ccxt 4.2.11 → 4.2.13

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 (392) hide show
  1. package/README.md +5 -5
  2. package/build.sh +2 -2
  3. package/dist/ccxt.browser.js +1347 -490
  4. package/dist/ccxt.browser.min.js +3 -3
  5. package/dist/cjs/_virtual/agent.js +7 -0
  6. package/dist/cjs/_virtual/parse-proxy-response.js +7 -0
  7. package/dist/cjs/_virtual/promisify.js +7 -0
  8. package/dist/cjs/ccxt.js +1 -1
  9. package/dist/cjs/js/ccxt.js +474 -0
  10. package/dist/cjs/js/src/abstract/ace.js +9 -0
  11. package/dist/cjs/js/src/abstract/alpaca.js +9 -0
  12. package/dist/cjs/js/src/abstract/ascendex.js +9 -0
  13. package/dist/cjs/js/src/abstract/bigone.js +9 -0
  14. package/dist/cjs/js/src/abstract/binance.js +9 -0
  15. package/dist/cjs/js/src/abstract/bingx.js +9 -0
  16. package/dist/cjs/js/src/abstract/bit2c.js +9 -0
  17. package/dist/cjs/js/src/abstract/bitbank.js +9 -0
  18. package/dist/cjs/js/src/abstract/bitbns.js +9 -0
  19. package/dist/cjs/js/src/abstract/bitfinex.js +9 -0
  20. package/dist/cjs/js/src/abstract/bitfinex2.js +9 -0
  21. package/dist/cjs/js/src/abstract/bitflyer.js +9 -0
  22. package/dist/cjs/js/src/abstract/bitforex.js +9 -0
  23. package/dist/cjs/js/src/abstract/bitget.js +9 -0
  24. package/dist/cjs/js/src/abstract/bithumb.js +9 -0
  25. package/dist/cjs/js/src/abstract/bitmart.js +9 -0
  26. package/dist/cjs/js/src/abstract/bitmex.js +9 -0
  27. package/dist/cjs/js/src/abstract/bitopro.js +9 -0
  28. package/dist/cjs/js/src/abstract/bitpanda.js +9 -0
  29. package/dist/cjs/js/src/abstract/bitrue.js +9 -0
  30. package/dist/cjs/js/src/abstract/bitso.js +9 -0
  31. package/dist/cjs/js/src/abstract/bitstamp.js +9 -0
  32. package/dist/cjs/js/src/abstract/bitteam.js +9 -0
  33. package/dist/cjs/js/src/abstract/bitvavo.js +9 -0
  34. package/dist/cjs/js/src/abstract/bl3p.js +9 -0
  35. package/dist/cjs/js/src/abstract/blockchaincom.js +9 -0
  36. package/dist/cjs/js/src/abstract/btcalpha.js +9 -0
  37. package/dist/cjs/js/src/abstract/btcbox.js +9 -0
  38. package/dist/cjs/js/src/abstract/btcmarkets.js +9 -0
  39. package/dist/cjs/js/src/abstract/btcturk.js +9 -0
  40. package/dist/cjs/js/src/abstract/bybit.js +9 -0
  41. package/dist/cjs/js/src/abstract/cex.js +9 -0
  42. package/dist/cjs/js/src/abstract/coinbase.js +9 -0
  43. package/dist/cjs/js/src/abstract/coinbasepro.js +9 -0
  44. package/dist/cjs/js/src/abstract/coincheck.js +9 -0
  45. package/dist/cjs/js/src/abstract/coinex.js +9 -0
  46. package/dist/cjs/js/src/abstract/coinlist.js +9 -0
  47. package/dist/cjs/js/src/abstract/coinmate.js +9 -0
  48. package/dist/cjs/js/src/abstract/coinone.js +9 -0
  49. package/dist/cjs/js/src/abstract/coinsph.js +9 -0
  50. package/dist/cjs/js/src/abstract/coinspot.js +9 -0
  51. package/dist/cjs/js/src/abstract/cryptocom.js +9 -0
  52. package/dist/cjs/js/src/abstract/currencycom.js +9 -0
  53. package/dist/cjs/js/src/abstract/delta.js +9 -0
  54. package/dist/cjs/js/src/abstract/deribit.js +9 -0
  55. package/dist/cjs/js/src/abstract/digifinex.js +9 -0
  56. package/dist/cjs/js/src/abstract/exmo.js +9 -0
  57. package/dist/cjs/js/src/abstract/gate.js +9 -0
  58. package/dist/cjs/js/src/abstract/gemini.js +9 -0
  59. package/dist/cjs/js/src/abstract/hitbtc.js +9 -0
  60. package/dist/cjs/js/src/abstract/hollaex.js +9 -0
  61. package/dist/cjs/js/src/abstract/htx.js +9 -0
  62. package/dist/cjs/js/src/abstract/huobijp.js +9 -0
  63. package/dist/cjs/js/src/abstract/idex.js +9 -0
  64. package/dist/cjs/js/src/abstract/independentreserve.js +9 -0
  65. package/dist/cjs/js/src/abstract/indodax.js +9 -0
  66. package/dist/cjs/js/src/abstract/kraken.js +9 -0
  67. package/dist/cjs/js/src/abstract/krakenfutures.js +9 -0
  68. package/dist/cjs/js/src/abstract/kucoin.js +9 -0
  69. package/dist/cjs/js/src/abstract/kucoinfutures.js +9 -0
  70. package/dist/cjs/js/src/abstract/kuna.js +9 -0
  71. package/dist/cjs/js/src/abstract/latoken.js +9 -0
  72. package/dist/cjs/js/src/abstract/lbank.js +9 -0
  73. package/dist/cjs/js/src/abstract/luno.js +9 -0
  74. package/dist/cjs/js/src/abstract/lykke.js +9 -0
  75. package/dist/cjs/js/src/abstract/mercado.js +9 -0
  76. package/dist/cjs/js/src/abstract/mexc.js +9 -0
  77. package/dist/cjs/js/src/abstract/ndax.js +9 -0
  78. package/dist/cjs/js/src/abstract/novadax.js +9 -0
  79. package/dist/cjs/js/src/abstract/oceanex.js +9 -0
  80. package/dist/cjs/js/src/abstract/okcoin.js +9 -0
  81. package/dist/cjs/js/src/abstract/okx.js +9 -0
  82. package/dist/cjs/js/src/abstract/p2b.js +9 -0
  83. package/dist/cjs/js/src/abstract/paymium.js +9 -0
  84. package/dist/cjs/js/src/abstract/phemex.js +9 -0
  85. package/dist/cjs/js/src/abstract/poloniex.js +9 -0
  86. package/dist/cjs/js/src/abstract/poloniexfutures.js +9 -0
  87. package/dist/cjs/js/src/abstract/probit.js +9 -0
  88. package/dist/cjs/js/src/abstract/timex.js +9 -0
  89. package/dist/cjs/js/src/abstract/tokocrypto.js +9 -0
  90. package/dist/cjs/js/src/abstract/upbit.js +9 -0
  91. package/dist/cjs/js/src/abstract/wavesexchange.js +9 -0
  92. package/dist/cjs/js/src/abstract/wazirx.js +9 -0
  93. package/dist/cjs/js/src/abstract/whitebit.js +9 -0
  94. package/dist/cjs/js/src/abstract/woo.js +9 -0
  95. package/dist/cjs/js/src/abstract/yobit.js +9 -0
  96. package/dist/cjs/js/src/abstract/zaif.js +9 -0
  97. package/dist/cjs/js/src/abstract/zonda.js +9 -0
  98. package/dist/cjs/js/src/ace.js +1058 -0
  99. package/dist/cjs/js/src/alpaca.js +1125 -0
  100. package/dist/cjs/js/src/ascendex.js +3360 -0
  101. package/dist/cjs/js/src/base/Exchange.js +5110 -0
  102. package/dist/cjs/js/src/base/Precise.js +263 -0
  103. package/dist/cjs/js/src/base/errors.js +299 -0
  104. package/dist/cjs/js/src/base/functions/crypto.js +78 -0
  105. package/dist/cjs/js/src/base/functions/encode.js +44 -0
  106. package/dist/cjs/js/src/base/functions/generic.js +193 -0
  107. package/dist/cjs/js/src/base/functions/misc.js +96 -0
  108. package/dist/cjs/js/src/base/functions/number.js +297 -0
  109. package/dist/cjs/js/src/base/functions/platform.js +28 -0
  110. package/dist/cjs/js/src/base/functions/rsa.js +34 -0
  111. package/dist/cjs/js/src/base/functions/string.js +48 -0
  112. package/dist/cjs/js/src/base/functions/throttle.js +66 -0
  113. package/dist/cjs/js/src/base/functions/time.js +187 -0
  114. package/dist/cjs/js/src/base/functions/totp.js +24 -0
  115. package/dist/cjs/js/src/base/functions/type.js +162 -0
  116. package/dist/cjs/js/src/base/functions.js +157 -0
  117. package/dist/cjs/js/src/base/ws/Cache.js +254 -0
  118. package/dist/cjs/js/src/base/ws/Client.js +299 -0
  119. package/dist/cjs/js/src/base/ws/Future.js +34 -0
  120. package/dist/cjs/js/src/base/ws/OrderBook.js +107 -0
  121. package/dist/cjs/js/src/base/ws/OrderBookSide.js +281 -0
  122. package/dist/cjs/js/src/base/ws/WsClient.js +69 -0
  123. package/dist/cjs/js/src/bequant.js +33 -0
  124. package/dist/cjs/js/src/bigone.js +2209 -0
  125. package/dist/cjs/js/src/binance.js +9736 -0
  126. package/dist/cjs/js/src/binancecoinm.js +45 -0
  127. package/dist/cjs/js/src/binanceus.js +84 -0
  128. package/dist/cjs/js/src/binanceusdm.js +58 -0
  129. package/dist/cjs/js/src/bingx.js +3807 -0
  130. package/dist/cjs/js/src/bit2c.js +916 -0
  131. package/dist/cjs/js/src/bitbank.js +1000 -0
  132. package/dist/cjs/js/src/bitbay.js +17 -0
  133. package/dist/cjs/js/src/bitbns.js +1220 -0
  134. package/dist/cjs/js/src/bitcoincom.js +17 -0
  135. package/dist/cjs/js/src/bitfinex.js +1670 -0
  136. package/dist/cjs/js/src/bitfinex2.js +2990 -0
  137. package/dist/cjs/js/src/bitflyer.js +1045 -0
  138. package/dist/cjs/js/src/bitforex.js +852 -0
  139. package/dist/cjs/js/src/bitget.js +8291 -0
  140. package/dist/cjs/js/src/bithumb.js +1090 -0
  141. package/dist/cjs/js/src/bitmart.js +4454 -0
  142. package/dist/cjs/js/src/bitmex.js +2884 -0
  143. package/dist/cjs/js/src/bitopro.js +1724 -0
  144. package/dist/cjs/js/src/bitpanda.js +2002 -0
  145. package/dist/cjs/js/src/bitrue.js +3253 -0
  146. package/dist/cjs/js/src/bitso.js +1753 -0
  147. package/dist/cjs/js/src/bitstamp.js +2188 -0
  148. package/dist/cjs/js/src/bitteam.js +2309 -0
  149. package/dist/cjs/js/src/bitvavo.js +1968 -0
  150. package/dist/cjs/js/src/bl3p.js +447 -0
  151. package/dist/cjs/js/src/blockchaincom.js +1160 -0
  152. package/dist/cjs/js/src/btcalpha.js +929 -0
  153. package/dist/cjs/js/src/btcbox.js +565 -0
  154. package/dist/cjs/js/src/btcmarkets.js +1237 -0
  155. package/dist/cjs/js/src/btcturk.js +929 -0
  156. package/dist/cjs/js/src/bybit.js +7646 -0
  157. package/dist/cjs/js/src/cex.js +1693 -0
  158. package/dist/cjs/js/src/coinbase.js +3424 -0
  159. package/dist/cjs/js/src/coinbasepro.js +1866 -0
  160. package/dist/cjs/js/src/coincheck.js +843 -0
  161. package/dist/cjs/js/src/coinex.js +5414 -0
  162. package/dist/cjs/js/src/coinlist.js +2329 -0
  163. package/dist/cjs/js/src/coinmate.js +989 -0
  164. package/dist/cjs/js/src/coinone.js +1185 -0
  165. package/dist/cjs/js/src/coinsph.js +1933 -0
  166. package/dist/cjs/js/src/coinspot.js +548 -0
  167. package/dist/cjs/js/src/cryptocom.js +3007 -0
  168. package/dist/cjs/js/src/currencycom.js +2015 -0
  169. package/dist/cjs/js/src/delta.js +3256 -0
  170. package/dist/cjs/js/src/deribit.js +3306 -0
  171. package/dist/cjs/js/src/digifinex.js +4307 -0
  172. package/dist/cjs/js/src/exmo.js +2645 -0
  173. package/dist/cjs/js/src/fmfwio.js +34 -0
  174. package/dist/cjs/js/src/gate.js +7072 -0
  175. package/dist/cjs/js/src/gateio.js +16 -0
  176. package/dist/cjs/js/src/gemini.js +1801 -0
  177. package/dist/cjs/js/src/hitbtc.js +3660 -0
  178. package/dist/cjs/js/src/hitbtc3.js +19 -0
  179. package/dist/cjs/js/src/hollaex.js +1882 -0
  180. package/dist/cjs/js/src/htx.js +9049 -0
  181. package/dist/cjs/js/src/huobi.js +16 -0
  182. package/dist/cjs/js/src/huobijp.js +1918 -0
  183. package/dist/cjs/js/src/idex.js +1770 -0
  184. package/dist/cjs/js/src/independentreserve.js +761 -0
  185. package/dist/cjs/js/src/indodax.js +1069 -0
  186. package/dist/cjs/js/src/kraken.js +2857 -0
  187. package/dist/cjs/js/src/krakenfutures.js +2407 -0
  188. package/dist/cjs/js/src/kucoin.js +4489 -0
  189. package/dist/cjs/js/src/kucoinfutures.js +2475 -0
  190. package/dist/cjs/js/src/kuna.js +1949 -0
  191. package/dist/cjs/js/src/latoken.js +1729 -0
  192. package/dist/cjs/js/src/lbank.js +2851 -0
  193. package/dist/cjs/js/src/luno.js +1044 -0
  194. package/dist/cjs/js/src/lykke.js +1303 -0
  195. package/dist/cjs/js/src/mercado.js +897 -0
  196. package/dist/cjs/js/src/mexc.js +5407 -0
  197. package/dist/cjs/js/src/ndax.js +2450 -0
  198. package/dist/cjs/js/src/novadax.js +1556 -0
  199. package/dist/cjs/js/src/oceanex.js +964 -0
  200. package/dist/cjs/js/src/okcoin.js +3115 -0
  201. package/dist/cjs/js/src/okx.js +7330 -0
  202. package/dist/cjs/js/src/p2b.js +1243 -0
  203. package/dist/cjs/js/src/paymium.js +597 -0
  204. package/dist/cjs/js/src/phemex.js +4722 -0
  205. package/dist/cjs/js/src/poloniex.js +2356 -0
  206. package/dist/cjs/js/src/poloniexfutures.js +1794 -0
  207. package/dist/cjs/js/src/pro/alpaca.js +714 -0
  208. package/dist/cjs/js/src/pro/ascendex.js +957 -0
  209. package/dist/cjs/js/src/pro/bequant.js +33 -0
  210. package/dist/cjs/js/src/pro/binance.js +2796 -0
  211. package/dist/cjs/js/src/pro/binancecoinm.js +23 -0
  212. package/dist/cjs/js/src/pro/binanceus.js +51 -0
  213. package/dist/cjs/js/src/pro/binanceusdm.js +32 -0
  214. package/dist/cjs/js/src/pro/bingx.js +944 -0
  215. package/dist/cjs/js/src/pro/bitcoincom.js +29 -0
  216. package/dist/cjs/js/src/pro/bitfinex.js +672 -0
  217. package/dist/cjs/js/src/pro/bitfinex2.js +1159 -0
  218. package/dist/cjs/js/src/pro/bitget.js +1733 -0
  219. package/dist/cjs/js/src/pro/bitmart.js +1486 -0
  220. package/dist/cjs/js/src/pro/bitmex.js +1576 -0
  221. package/dist/cjs/js/src/pro/bitopro.js +327 -0
  222. package/dist/cjs/js/src/pro/bitpanda.js +1341 -0
  223. package/dist/cjs/js/src/pro/bitrue.js +462 -0
  224. package/dist/cjs/js/src/pro/bitstamp.js +547 -0
  225. package/dist/cjs/js/src/pro/bitvavo.js +704 -0
  226. package/dist/cjs/js/src/pro/blockchaincom.js +794 -0
  227. package/dist/cjs/js/src/pro/bybit.js +1843 -0
  228. package/dist/cjs/js/src/pro/cex.js +1510 -0
  229. package/dist/cjs/js/src/pro/coinbase.js +561 -0
  230. package/dist/cjs/js/src/pro/coinbasepro.js +968 -0
  231. package/dist/cjs/js/src/pro/coinex.js +1095 -0
  232. package/dist/cjs/js/src/pro/cryptocom.js +1020 -0
  233. package/dist/cjs/js/src/pro/currencycom.js +563 -0
  234. package/dist/cjs/js/src/pro/deribit.js +825 -0
  235. package/dist/cjs/js/src/pro/exmo.js +658 -0
  236. package/dist/cjs/js/src/pro/gate.js +1316 -0
  237. package/dist/cjs/js/src/pro/gateio.js +16 -0
  238. package/dist/cjs/js/src/pro/gemini.js +649 -0
  239. package/dist/cjs/js/src/pro/hitbtc.js +1293 -0
  240. package/dist/cjs/js/src/pro/hollaex.js +597 -0
  241. package/dist/cjs/js/src/pro/htx.js +2383 -0
  242. package/dist/cjs/js/src/pro/huobi.js +16 -0
  243. package/dist/cjs/js/src/pro/huobijp.js +606 -0
  244. package/dist/cjs/js/src/pro/idex.js +714 -0
  245. package/dist/cjs/js/src/pro/independentreserve.js +280 -0
  246. package/dist/cjs/js/src/pro/kraken.js +1364 -0
  247. package/dist/cjs/js/src/pro/krakenfutures.js +1500 -0
  248. package/dist/cjs/js/src/pro/kucoin.js +1052 -0
  249. package/dist/cjs/js/src/pro/kucoinfutures.js +981 -0
  250. package/dist/cjs/js/src/pro/luno.js +322 -0
  251. package/dist/cjs/js/src/pro/mexc.js +1170 -0
  252. package/dist/cjs/js/src/pro/ndax.js +545 -0
  253. package/dist/cjs/js/src/pro/okcoin.js +760 -0
  254. package/dist/cjs/js/src/pro/okx.js +1608 -0
  255. package/dist/cjs/js/src/pro/phemex.js +1511 -0
  256. package/dist/cjs/js/src/pro/poloniex.js +1253 -0
  257. package/dist/cjs/js/src/pro/poloniexfutures.js +1014 -0
  258. package/dist/cjs/js/src/pro/probit.js +586 -0
  259. package/dist/cjs/js/src/pro/upbit.js +234 -0
  260. package/dist/cjs/js/src/pro/wazirx.js +776 -0
  261. package/dist/cjs/js/src/pro/whitebit.js +927 -0
  262. package/dist/cjs/js/src/pro/woo.js +769 -0
  263. package/dist/cjs/js/src/probit.js +1867 -0
  264. package/dist/cjs/js/src/static_dependencies/fflake/browser.js +401 -0
  265. package/dist/cjs/js/src/static_dependencies/jsencrypt/JSEncrypt.js +195 -0
  266. package/dist/cjs/js/src/static_dependencies/jsencrypt/JSEncryptRSAKey.js +308 -0
  267. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/asn1js/asn1.js +554 -0
  268. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/asn1js/base64.js +94 -0
  269. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/asn1js/hex.js +70 -0
  270. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/asn1js/int10.js +91 -0
  271. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/base64.js +16 -0
  272. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/jsbn.js +1760 -0
  273. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/prng4.js +52 -0
  274. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/rng.js +81 -0
  275. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/rsa.js +376 -0
  276. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/util.js +70 -0
  277. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsrsasign/asn1-1.0.js +1580 -0
  278. package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsrsasign/yahoo.js +74 -0
  279. package/dist/cjs/js/src/static_dependencies/noble-curves/_shortw_utils.js +24 -0
  280. package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/curve.js +158 -0
  281. package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/edwards.js +429 -0
  282. package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/hash-to-curve.js +176 -0
  283. package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/modular.js +324 -0
  284. package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/montgomery.js +163 -0
  285. package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/utils.js +245 -0
  286. package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/weierstrass.js +1018 -0
  287. package/dist/cjs/js/src/static_dependencies/noble-curves/ed25519.js +383 -0
  288. package/dist/cjs/js/src/static_dependencies/noble-curves/secp256k1.js +258 -0
  289. package/dist/cjs/js/src/static_dependencies/noble-hashes/_assert.js +53 -0
  290. package/dist/cjs/js/src/static_dependencies/noble-hashes/_sha2.js +120 -0
  291. package/dist/cjs/js/src/static_dependencies/noble-hashes/_u64.js +69 -0
  292. package/dist/cjs/js/src/static_dependencies/noble-hashes/crypto.js +7 -0
  293. package/dist/cjs/js/src/static_dependencies/noble-hashes/hmac.js +83 -0
  294. package/dist/cjs/js/src/static_dependencies/noble-hashes/md5.js +240 -0
  295. package/dist/cjs/js/src/static_dependencies/noble-hashes/sha1.js +91 -0
  296. package/dist/cjs/js/src/static_dependencies/noble-hashes/sha256.js +130 -0
  297. package/dist/cjs/js/src/static_dependencies/noble-hashes/sha3.js +214 -0
  298. package/dist/cjs/js/src/static_dependencies/noble-hashes/sha512.js +239 -0
  299. package/dist/cjs/js/src/static_dependencies/noble-hashes/utils.js +93 -0
  300. package/dist/cjs/js/src/static_dependencies/node-fetch/body.js +354 -0
  301. package/dist/cjs/js/src/static_dependencies/node-fetch/errors/abort-error.js +16 -0
  302. package/dist/cjs/js/src/static_dependencies/node-fetch/errors/base.js +20 -0
  303. package/dist/cjs/js/src/static_dependencies/node-fetch/errors/fetch-error.js +30 -0
  304. package/dist/cjs/js/src/static_dependencies/node-fetch/headers.js +239 -0
  305. package/dist/cjs/js/src/static_dependencies/node-fetch/index.js +372 -0
  306. package/dist/cjs/js/src/static_dependencies/node-fetch/request.js +273 -0
  307. package/dist/cjs/js/src/static_dependencies/node-fetch/response.js +139 -0
  308. package/dist/cjs/js/src/static_dependencies/node-fetch/utils/get-search.js +14 -0
  309. package/dist/cjs/js/src/static_dependencies/node-fetch/utils/is-redirect.js +16 -0
  310. package/dist/cjs/js/src/static_dependencies/node-fetch/utils/is.js +81 -0
  311. package/dist/cjs/js/src/static_dependencies/node-fetch/utils/referrer.js +292 -0
  312. package/dist/cjs/js/src/static_dependencies/proxies/agent-base/index.js +103 -0
  313. package/dist/cjs/js/src/static_dependencies/proxies/http-proxy-agent/index.js +140 -0
  314. package/dist/cjs/js/src/static_dependencies/proxies/https-proxy-agent/index.js +175 -0
  315. package/dist/cjs/js/src/static_dependencies/proxies/https-proxy-agent/parse-proxy-response.js +95 -0
  316. package/dist/cjs/js/src/static_dependencies/qs/index.cjs.js +7 -0
  317. package/dist/cjs/js/src/static_dependencies/scure-base/index.js +383 -0
  318. package/dist/cjs/js/src/timex.js +1562 -0
  319. package/dist/cjs/js/src/tokocrypto.js +2542 -0
  320. package/dist/cjs/js/src/upbit.js +1844 -0
  321. package/dist/cjs/js/src/wavesexchange.js +2607 -0
  322. package/dist/cjs/js/src/wazirx.js +953 -0
  323. package/dist/cjs/js/src/whitebit.js +2309 -0
  324. package/dist/cjs/js/src/woo.js +2765 -0
  325. package/dist/cjs/js/src/yobit.js +1314 -0
  326. package/dist/cjs/js/src/zaif.js +736 -0
  327. package/dist/cjs/js/src/zonda.js +1883 -0
  328. package/js/ccxt.d.ts +1 -1
  329. package/js/ccxt.js +1 -1
  330. package/js/src/abstract/bigone.d.ts +18 -0
  331. package/js/src/abstract/binance.d.ts +2 -0
  332. package/js/src/abstract/binancecoinm.d.ts +2 -0
  333. package/js/src/abstract/binanceus.d.ts +2 -0
  334. package/js/src/abstract/binanceusdm.d.ts +2 -0
  335. package/js/src/abstract/bingx.d.ts +2 -0
  336. package/js/src/abstract/bybit.d.ts +1 -0
  337. package/js/src/abstract/gate.d.ts +11 -0
  338. package/js/src/abstract/gateio.d.ts +11 -0
  339. package/js/src/abstract/okx.d.ts +1 -0
  340. package/js/src/alpaca.js +18 -18
  341. package/js/src/base/Exchange.d.ts +5 -1
  342. package/js/src/base/Exchange.js +101 -12
  343. package/js/src/bigone.d.ts +3 -2
  344. package/js/src/bigone.js +429 -167
  345. package/js/src/binance.js +48 -34
  346. package/js/src/bingx.js +115 -38
  347. package/js/src/bitfinex.d.ts +2 -2
  348. package/js/src/bitfinex.js +2 -3
  349. package/js/src/bitget.js +33 -13
  350. package/js/src/bitmart.d.ts +2 -2
  351. package/js/src/bitmart.js +5 -5
  352. package/js/src/bitmex.js +1 -0
  353. package/js/src/bybit.js +2 -0
  354. package/js/src/coinbase.d.ts +26 -3
  355. package/js/src/coinbase.js +176 -26
  356. package/js/src/coinlist.js +3 -4
  357. package/js/src/coinone.js +1 -1
  358. package/js/src/coinsph.js +2 -3
  359. package/js/src/deribit.js +1 -0
  360. package/js/src/gate.d.ts +4 -4
  361. package/js/src/gate.js +96 -59
  362. package/js/src/gemini.js +1 -1
  363. package/js/src/hitbtc.d.ts +4 -4
  364. package/js/src/hitbtc.js +2 -3
  365. package/js/src/htx.d.ts +1 -0
  366. package/js/src/htx.js +29 -7
  367. package/js/src/huobijp.js +2 -3
  368. package/js/src/independentreserve.js +7 -5
  369. package/js/src/kraken.js +3 -6
  370. package/js/src/lbank.js +59 -33
  371. package/js/src/mexc.js +2 -1
  372. package/js/src/oceanex.js +1 -1
  373. package/js/src/okx.js +14 -3
  374. package/js/src/phemex.js +9 -2
  375. package/js/src/pro/binance.d.ts +2 -23
  376. package/js/src/pro/binance.js +58 -22
  377. package/js/src/pro/coinbase.d.ts +2 -2
  378. package/js/src/pro/coinbase.js +4 -1
  379. package/js/src/pro/coinbasepro.d.ts +2 -2
  380. package/js/src/pro/hitbtc.d.ts +2 -2
  381. package/js/src/pro/kraken.js +1 -1
  382. package/js/src/pro/okx.d.ts +1 -0
  383. package/js/src/pro/okx.js +52 -2
  384. package/js/src/pro/poloniex.d.ts +2 -2
  385. package/js/src/probit.js +4 -2
  386. package/js/src/upbit.d.ts +3 -101
  387. package/js/src/upbit.js +12 -12
  388. package/js/src/wavesexchange.js +1 -1
  389. package/js/src/woo.d.ts +2 -0
  390. package/js/src/woo.js +52 -0
  391. package/package.json +1 -1
  392. package/skip-tests.json +5 -0
@@ -0,0 +1,4489 @@
1
+ 'use strict';
2
+
3
+ var kucoin$1 = require('./abstract/kucoin.js');
4
+ var errors = require('./base/errors.js');
5
+ var Precise = require('./base/Precise.js');
6
+ var number = require('./base/functions/number.js');
7
+ var sha256 = require('./static_dependencies/noble-hashes/sha256.js');
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * @class kucoin
13
+ * @augments Exchange
14
+ */
15
+ class kucoin extends kucoin$1 {
16
+ describe() {
17
+ return this.deepExtend(super.describe(), {
18
+ 'id': 'kucoin',
19
+ 'name': 'KuCoin',
20
+ 'countries': ['SC'],
21
+ 'rateLimit': 10,
22
+ 'version': 'v2',
23
+ 'certified': true,
24
+ 'pro': true,
25
+ 'comment': 'Platform 2.0',
26
+ 'quoteJsonNumbers': false,
27
+ 'has': {
28
+ 'CORS': undefined,
29
+ 'spot': true,
30
+ 'margin': true,
31
+ 'swap': false,
32
+ 'future': false,
33
+ 'option': false,
34
+ 'borrowCrossMargin': true,
35
+ 'borrowIsolatedMargin': true,
36
+ 'cancelAllOrders': true,
37
+ 'cancelOrder': true,
38
+ 'closeAllPositions': false,
39
+ 'closePosition': false,
40
+ 'createDepositAddress': true,
41
+ 'createMarketBuyOrderWithCost': true,
42
+ 'createMarketOrderWithCost': true,
43
+ 'createMarketSellOrderWithCost': true,
44
+ 'createOrder': true,
45
+ 'createOrders': true,
46
+ 'createPostOnlyOrder': true,
47
+ 'createStopLimitOrder': true,
48
+ 'createStopMarketOrder': true,
49
+ 'createStopOrder': true,
50
+ 'editOrder': true,
51
+ 'fetchAccounts': true,
52
+ 'fetchBalance': true,
53
+ 'fetchBorrowInterest': true,
54
+ 'fetchBorrowRateHistories': false,
55
+ 'fetchBorrowRateHistory': false,
56
+ 'fetchClosedOrders': true,
57
+ 'fetchCrossBorrowRate': false,
58
+ 'fetchCrossBorrowRates': false,
59
+ 'fetchCurrencies': true,
60
+ 'fetchDepositAddress': true,
61
+ 'fetchDepositAddressesByNetwork': true,
62
+ 'fetchDeposits': true,
63
+ 'fetchDepositWithdrawFee': true,
64
+ 'fetchDepositWithdrawFees': true,
65
+ 'fetchFundingHistory': false,
66
+ 'fetchFundingRate': false,
67
+ 'fetchFundingRateHistory': false,
68
+ 'fetchFundingRates': false,
69
+ 'fetchIndexOHLCV': false,
70
+ 'fetchIsolatedBorrowRate': false,
71
+ 'fetchIsolatedBorrowRates': false,
72
+ 'fetchL3OrderBook': true,
73
+ 'fetchLedger': true,
74
+ 'fetchLeverageTiers': false,
75
+ 'fetchMarginMode': false,
76
+ 'fetchMarketLeverageTiers': false,
77
+ 'fetchMarkets': true,
78
+ 'fetchMarkOHLCV': false,
79
+ 'fetchMyTrades': true,
80
+ 'fetchOHLCV': true,
81
+ 'fetchOpenInterest': false,
82
+ 'fetchOpenInterestHistory': false,
83
+ 'fetchOpenOrders': true,
84
+ 'fetchOrder': true,
85
+ 'fetchOrderBook': true,
86
+ 'fetchOrderBooks': false,
87
+ 'fetchOrdersByStatus': true,
88
+ 'fetchOrderTrades': true,
89
+ 'fetchPositionMode': false,
90
+ 'fetchPremiumIndexOHLCV': false,
91
+ 'fetchStatus': true,
92
+ 'fetchTicker': true,
93
+ 'fetchTickers': true,
94
+ 'fetchTime': true,
95
+ 'fetchTrades': true,
96
+ 'fetchTradingFee': true,
97
+ 'fetchTradingFees': false,
98
+ 'fetchTransactionFee': true,
99
+ 'fetchTransfers': false,
100
+ 'fetchWithdrawals': true,
101
+ 'repayCrossMargin': true,
102
+ 'repayIsolatedMargin': true,
103
+ 'setLeverage': false,
104
+ 'setMarginMode': false,
105
+ 'setPositionMode': false,
106
+ 'signIn': false,
107
+ 'transfer': true,
108
+ 'withdraw': true,
109
+ },
110
+ 'urls': {
111
+ 'logo': 'https://user-images.githubusercontent.com/51840849/87295558-132aaf80-c50e-11ea-9801-a2fb0c57c799.jpg',
112
+ 'referral': 'https://www.kucoin.com/ucenter/signup?rcode=E5wkqe',
113
+ 'api': {
114
+ 'public': 'https://api.kucoin.com',
115
+ 'private': 'https://api.kucoin.com',
116
+ 'futuresPrivate': 'https://api-futures.kucoin.com',
117
+ 'futuresPublic': 'https://api-futures.kucoin.com',
118
+ 'webExchange': 'https://kucoin.com/_api',
119
+ },
120
+ 'www': 'https://www.kucoin.com',
121
+ 'doc': [
122
+ 'https://docs.kucoin.com',
123
+ ],
124
+ },
125
+ 'requiredCredentials': {
126
+ 'apiKey': true,
127
+ 'secret': true,
128
+ 'password': true,
129
+ },
130
+ 'api': {
131
+ // level VIP0
132
+ // Spot => 3000/30s => 100/s
133
+ // Weight = x => 100/(100/x) = x
134
+ // Futures Management Public => 2000/30s => 200/3/s
135
+ // Weight = x => 100/(200/3/x) = x*1.5
136
+ 'public': {
137
+ 'get': {
138
+ // spot trading
139
+ 'currencies': 4.5,
140
+ 'currencies/{currency}': 4.5,
141
+ 'symbols': 6,
142
+ 'market/orderbook/level1': 3,
143
+ 'market/allTickers': 22.5,
144
+ 'market/stats': 22.5,
145
+ 'markets': 4.5,
146
+ 'market/orderbook/level{level}_{limit}': 6,
147
+ 'market/orderbook/level2_20': 3,
148
+ 'market/orderbook/level2_100': 6,
149
+ 'market/histories': 4.5,
150
+ 'market/candles': 4.5,
151
+ 'prices': 4.5,
152
+ 'timestamp': 4.5,
153
+ 'status': 4.5,
154
+ // margin trading
155
+ 'mark-price/{symbol}/current': 3,
156
+ 'margin/config': 25, // 25SW
157
+ },
158
+ 'post': {
159
+ // ws
160
+ 'bullet-public': 15, // 10PW
161
+ },
162
+ },
163
+ 'private': {
164
+ 'get': {
165
+ // account
166
+ 'user-info': 30,
167
+ 'accounts': 7.5,
168
+ 'accounts/{accountId}': 7.5,
169
+ 'accounts/ledgers': 3,
170
+ 'hf/accounts/ledgers': 2,
171
+ 'hf/margin/account/ledgers': 2,
172
+ 'transaction-history': 3,
173
+ 'sub/user': 30,
174
+ 'sub-accounts/{subUserId}': 22.5,
175
+ 'sub-accounts': 30,
176
+ 'sub/api-key': 30,
177
+ // funding
178
+ 'margin/account': 40,
179
+ 'margin/accounts': 15,
180
+ 'isolated/accounts': 15,
181
+ 'deposit-addresses': 7.5,
182
+ 'deposits': 7.5,
183
+ 'hist-deposits': 7.5,
184
+ 'withdrawals': 30,
185
+ 'hist-withdrawals': 30,
186
+ 'withdrawals/quotas': 30,
187
+ 'accounts/transferable': 30,
188
+ 'transfer-list': 30,
189
+ 'base-fee': 3,
190
+ 'trade-fees': 3,
191
+ // spot trading
192
+ 'market/orderbook/level{level}': 3,
193
+ 'market/orderbook/level2': 3,
194
+ 'market/orderbook/level3': 3,
195
+ 'hf/orders/active': 2,
196
+ 'hf/orders/active/symbols': 2,
197
+ 'hf/orders/done': 2,
198
+ 'hf/orders/{orderId}': 2,
199
+ 'hf/orders/client-order/{clientOid}': 2,
200
+ 'hf/orders/dead-cancel-all/query': 2,
201
+ 'hf/fills': 2,
202
+ 'orders': 2,
203
+ 'limit/orders': 3,
204
+ 'orders/{orderId}': 2,
205
+ 'order/client-order/{clientOid}': 3,
206
+ 'fills': 10,
207
+ 'limit/fills': 20,
208
+ 'stop-order': 8,
209
+ 'stop-order/{orderId}': 3,
210
+ 'stop-order/queryOrderByClientOid': 3,
211
+ 'oco/order/{orderId}': 2,
212
+ 'oco/order/details/{orderId}': 2,
213
+ 'oco/client-order/{clientOid}': 2,
214
+ 'oco/orders': 2,
215
+ // margin trading
216
+ 'hf/margin/orders/active': 4,
217
+ 'hf/margin/orders/done': 10,
218
+ 'hf/margin/orders/{orderId}': 4,
219
+ 'hf/margin/orders/client-order/{clientOid}': 5,
220
+ 'hf/margin/fills': 5,
221
+ 'etf/info': 25,
222
+ 'margin/currencies': 20,
223
+ 'risk/limit/strategy': 20,
224
+ 'isolated/symbols': 20,
225
+ 'isolated/account/{symbol}': 50,
226
+ 'margin/borrow': 15,
227
+ 'margin/repay': 15,
228
+ 'project/list': 10,
229
+ 'project/marketInterestRate': 7.5,
230
+ 'redeem/orders': 10,
231
+ 'purchase/orders': 10, // 10SW
232
+ },
233
+ 'post': {
234
+ // account
235
+ 'sub/user/created': 22.5,
236
+ 'sub/api-key': 30,
237
+ 'sub/api-key/update': 45,
238
+ // funding
239
+ 'deposit-addresses': 30,
240
+ 'withdrawals': 7.5,
241
+ 'accounts/universal-transfer': 6,
242
+ 'accounts/sub-transfer': 45,
243
+ 'accounts/inner-transfer': 15,
244
+ 'transfer-out': 30,
245
+ 'transfer-in': 30,
246
+ // spot trading
247
+ 'hf/orders': 1,
248
+ 'hf/orders/test': 1,
249
+ 'hf/orders/sync': 1,
250
+ 'hf/orders/multi': 1,
251
+ 'hf/orders/multi/sync': 1,
252
+ 'hf/orders/alter': 3,
253
+ 'hf/orders/dead-cancel-all': 2,
254
+ 'orders': 2,
255
+ 'orders/test': 2,
256
+ 'orders/multi': 3,
257
+ 'stop-order': 2,
258
+ 'oco/order': 2,
259
+ // margin trading
260
+ 'hf/margin/order': 5,
261
+ 'hf/margin/order/test': 5,
262
+ 'margin/order': 5,
263
+ 'margin/order/test': 5,
264
+ 'margin/borrow': 15,
265
+ 'margin/repay': 10,
266
+ 'purchase': 15,
267
+ 'redeem': 15,
268
+ 'lend/purchase/update': 10,
269
+ // ws
270
+ 'bullet-private': 10, // 10SW
271
+ },
272
+ 'delete': {
273
+ // account
274
+ 'sub/api-key': 45,
275
+ // funding
276
+ 'withdrawals/{withdrawalId}': 30,
277
+ // spot trading
278
+ 'hf/orders/{orderId}': 1,
279
+ 'hf/orders/sync/{orderId}': 1,
280
+ 'hf/orders/client-order/{clientOid}': 1,
281
+ 'hf/orders/sync/client-order/{clientOid}': 1,
282
+ 'hf/orders/cancel/{orderId}': 2,
283
+ 'hf/orders': 2,
284
+ 'hf/orders/cancelAll': 30,
285
+ 'orders/{orderId}': 3,
286
+ 'order/client-order/{clientOid}': 5,
287
+ 'orders': 20,
288
+ 'stop-order/{orderId}': 3,
289
+ 'stop-order/cancelOrderByClientOid': 5,
290
+ 'stop-order/cancel': 3,
291
+ 'oco/order/{orderId}': 3,
292
+ 'oco/client-order/{clientOid}': 3,
293
+ 'oco/orders': 3,
294
+ // margin trading
295
+ 'hf/margin/orders/{orderId}': 5,
296
+ 'hf/margin/orders/client-order/{clientOid}': 5,
297
+ 'hf/margin/orders': 10, // 10SW
298
+ },
299
+ },
300
+ 'futuresPublic': {
301
+ 'get': {
302
+ 'contracts/active': 4.5,
303
+ 'contracts/{symbol}': 4.5,
304
+ 'ticker': 3,
305
+ 'level2/snapshot': 4.5,
306
+ 'level2/depth20': 7.5,
307
+ 'level2/depth100': 15,
308
+ 'trade/history': 7.5,
309
+ 'kline/query': 4.5,
310
+ 'interest/query': 7.5,
311
+ 'index/query': 3,
312
+ 'mark-price/{symbol}/current': 4.5,
313
+ 'premium/query': 4.5,
314
+ 'trade-statistics': 4.5,
315
+ 'funding-rate/{symbol}/current': 3,
316
+ 'timestamp': 3,
317
+ 'status': 6,
318
+ // ?
319
+ 'level2/message/query': 1.3953,
320
+ },
321
+ 'post': {
322
+ // ws
323
+ 'bullet-public': 15, // 10PW
324
+ },
325
+ },
326
+ 'futuresPrivate': {
327
+ 'get': {
328
+ // account
329
+ 'transaction-history': 3,
330
+ // funding
331
+ 'account-overview': 7.5,
332
+ 'account-overview-all': 9,
333
+ 'transfer-list': 30,
334
+ // futures
335
+ 'orders': 3,
336
+ 'stopOrders': 9,
337
+ 'recentDoneOrders': 7.5,
338
+ 'orders/{orderId}': 7.5,
339
+ 'orders/byClientOid': 7.5,
340
+ 'fills': 7.5,
341
+ 'recentFills': 4.5,
342
+ 'openOrderStatistics': 15,
343
+ 'position': 3,
344
+ 'positions': 3,
345
+ 'contracts/risk-limit/{symbol}': 7.5,
346
+ 'funding-history': 7.5, // 5FW
347
+ },
348
+ 'post': {
349
+ // funding
350
+ 'transfer-out': 30,
351
+ 'transfer-in': 30,
352
+ // futures
353
+ 'orders': 3,
354
+ 'orders/test': 3,
355
+ 'position/margin/auto-deposit-status': 6,
356
+ 'position/margin/deposit-margin': 6,
357
+ 'position/risk-limit-level/change': 6,
358
+ // ws
359
+ 'bullet-private': 15, // 10FW
360
+ },
361
+ 'delete': {
362
+ 'orders/{orderId}': 1.5,
363
+ 'orders/client-order/{clientOid}': 1.5,
364
+ 'orders': 45,
365
+ 'stopOrders': 22.5, // 15FW
366
+ },
367
+ },
368
+ 'webExchange': {
369
+ 'get': {
370
+ 'currency/currency/chain-info': 1, // this is temporary from webApi
371
+ },
372
+ },
373
+ },
374
+ 'timeframes': {
375
+ '1m': '1min',
376
+ '3m': '3min',
377
+ '5m': '5min',
378
+ '15m': '15min',
379
+ '30m': '30min',
380
+ '1h': '1hour',
381
+ '2h': '2hour',
382
+ '4h': '4hour',
383
+ '6h': '6hour',
384
+ '8h': '8hour',
385
+ '12h': '12hour',
386
+ '1d': '1day',
387
+ '1w': '1week',
388
+ },
389
+ 'precisionMode': number.TICK_SIZE,
390
+ 'exceptions': {
391
+ 'exact': {
392
+ 'order not exist': errors.OrderNotFound,
393
+ 'order not exist.': errors.OrderNotFound,
394
+ 'order_not_exist': errors.OrderNotFound,
395
+ 'order_not_exist_or_not_allow_to_cancel': errors.InvalidOrder,
396
+ 'Order size below the minimum requirement.': errors.InvalidOrder,
397
+ 'The withdrawal amount is below the minimum requirement.': errors.ExchangeError,
398
+ 'Unsuccessful! Exceeded the max. funds out-transfer limit': errors.InsufficientFunds,
399
+ '400': errors.BadRequest,
400
+ '401': errors.AuthenticationError,
401
+ '403': errors.NotSupported,
402
+ '404': errors.NotSupported,
403
+ '405': errors.NotSupported,
404
+ '415': errors.NotSupported,
405
+ '429': errors.RateLimitExceeded,
406
+ '500': errors.ExchangeNotAvailable,
407
+ '503': errors.ExchangeNotAvailable,
408
+ '101030': errors.PermissionDenied,
409
+ '103000': errors.InvalidOrder,
410
+ '130101': errors.BadRequest,
411
+ '130102': errors.ExchangeError,
412
+ '130103': errors.OrderNotFound,
413
+ '130104': errors.ExchangeError,
414
+ '130105': errors.InsufficientFunds,
415
+ '130106': errors.NotSupported,
416
+ '130107': errors.ExchangeError,
417
+ '130108': errors.OrderNotFound,
418
+ '130201': errors.PermissionDenied,
419
+ '130202': errors.ExchangeError,
420
+ '130203': errors.InsufficientFunds,
421
+ '130204': errors.BadRequest,
422
+ '200004': errors.InsufficientFunds,
423
+ '210014': errors.InvalidOrder,
424
+ '210021': errors.InsufficientFunds,
425
+ '230003': errors.InsufficientFunds,
426
+ '260000': errors.InvalidAddress,
427
+ '260100': errors.InsufficientFunds,
428
+ '300000': errors.InvalidOrder,
429
+ '400000': errors.BadSymbol,
430
+ '400001': errors.AuthenticationError,
431
+ '400002': errors.InvalidNonce,
432
+ '400003': errors.AuthenticationError,
433
+ '400004': errors.AuthenticationError,
434
+ '400005': errors.AuthenticationError,
435
+ '400006': errors.AuthenticationError,
436
+ '400007': errors.AuthenticationError,
437
+ '400008': errors.NotSupported,
438
+ '400100': errors.BadRequest,
439
+ '400200': errors.InvalidOrder,
440
+ '400350': errors.InvalidOrder,
441
+ '400370': errors.InvalidOrder,
442
+ '400400': errors.BadRequest,
443
+ '400500': errors.InvalidOrder,
444
+ '400600': errors.BadSymbol,
445
+ '400760': errors.InvalidOrder,
446
+ '401000': errors.BadRequest,
447
+ '411100': errors.AccountSuspended,
448
+ '415000': errors.BadRequest,
449
+ '400303': errors.PermissionDenied,
450
+ '500000': errors.ExchangeNotAvailable,
451
+ '260220': errors.InvalidAddress,
452
+ '900014': errors.BadRequest, // {"code":"900014","msg":"Invalid chainId"}
453
+ },
454
+ 'broad': {
455
+ 'Exceeded the access frequency': errors.RateLimitExceeded,
456
+ 'require more permission': errors.PermissionDenied,
457
+ },
458
+ },
459
+ 'fees': {
460
+ 'trading': {
461
+ 'tierBased': true,
462
+ 'percentage': true,
463
+ 'taker': this.parseNumber('0.001'),
464
+ 'maker': this.parseNumber('0.001'),
465
+ 'tiers': {
466
+ 'taker': [
467
+ [this.parseNumber('0'), this.parseNumber('0.001')],
468
+ [this.parseNumber('50'), this.parseNumber('0.001')],
469
+ [this.parseNumber('200'), this.parseNumber('0.0009')],
470
+ [this.parseNumber('500'), this.parseNumber('0.0008')],
471
+ [this.parseNumber('1000'), this.parseNumber('0.0007')],
472
+ [this.parseNumber('2000'), this.parseNumber('0.0007')],
473
+ [this.parseNumber('4000'), this.parseNumber('0.0006')],
474
+ [this.parseNumber('8000'), this.parseNumber('0.0005')],
475
+ [this.parseNumber('15000'), this.parseNumber('0.00045')],
476
+ [this.parseNumber('25000'), this.parseNumber('0.0004')],
477
+ [this.parseNumber('40000'), this.parseNumber('0.00035')],
478
+ [this.parseNumber('60000'), this.parseNumber('0.0003')],
479
+ [this.parseNumber('80000'), this.parseNumber('0.00025')],
480
+ ],
481
+ 'maker': [
482
+ [this.parseNumber('0'), this.parseNumber('0.001')],
483
+ [this.parseNumber('50'), this.parseNumber('0.0009')],
484
+ [this.parseNumber('200'), this.parseNumber('0.0007')],
485
+ [this.parseNumber('500'), this.parseNumber('0.0005')],
486
+ [this.parseNumber('1000'), this.parseNumber('0.0003')],
487
+ [this.parseNumber('2000'), this.parseNumber('0')],
488
+ [this.parseNumber('4000'), this.parseNumber('0')],
489
+ [this.parseNumber('8000'), this.parseNumber('0')],
490
+ [this.parseNumber('15000'), this.parseNumber('-0.00005')],
491
+ [this.parseNumber('25000'), this.parseNumber('-0.00005')],
492
+ [this.parseNumber('40000'), this.parseNumber('-0.00005')],
493
+ [this.parseNumber('60000'), this.parseNumber('-0.00005')],
494
+ [this.parseNumber('80000'), this.parseNumber('-0.00005')],
495
+ ],
496
+ },
497
+ },
498
+ 'funding': {
499
+ 'tierBased': false,
500
+ 'percentage': false,
501
+ 'withdraw': {},
502
+ 'deposit': {},
503
+ },
504
+ },
505
+ 'commonCurrencies': {
506
+ 'BIFI': 'BIFIF',
507
+ 'VAI': 'VAIOT',
508
+ 'WAX': 'WAXP',
509
+ },
510
+ 'options': {
511
+ 'version': 'v1',
512
+ 'symbolSeparator': '-',
513
+ 'fetchMyTradesMethod': 'private_get_fills',
514
+ 'fetchCurrencies': {
515
+ 'webApiEnable': true,
516
+ 'webApiRetries': 1,
517
+ 'webApiMuteFailure': true,
518
+ },
519
+ 'fetchMarkets': {
520
+ 'fetchTickersFees': true,
521
+ },
522
+ 'withdraw': {
523
+ 'includeFee': false,
524
+ },
525
+ // endpoint versions
526
+ 'versions': {
527
+ 'public': {
528
+ 'GET': {
529
+ // spot trading
530
+ 'currencies': 'v3',
531
+ 'currencies/{currency}': 'v3',
532
+ 'symbols': 'v2',
533
+ },
534
+ },
535
+ 'private': {
536
+ 'GET': {
537
+ // account
538
+ 'user-info': 'v2',
539
+ 'hf/margin/account/ledgers': 'v3',
540
+ 'sub/user': 'v2',
541
+ 'sub-accounts': 'v2',
542
+ // funding
543
+ 'margin/accounts': 'v3',
544
+ 'isolated/accounts': 'v3',
545
+ // 'deposit-addresses': 'v2',
546
+ 'deposit-addresses': 'v1',
547
+ // spot trading
548
+ 'market/orderbook/level2': 'v3',
549
+ 'market/orderbook/level3': 'v3',
550
+ 'market/orderbook/level{level}': 'v3',
551
+ 'oco/order/{orderId}': 'v3',
552
+ 'oco/order/details/{orderId}': 'v3',
553
+ 'oco/client-order/{clientOid}': 'v3',
554
+ 'oco/orders': 'v3',
555
+ // margin trading
556
+ 'hf/margin/orders/active': 'v3',
557
+ 'hf/margin/orders/done': 'v3',
558
+ 'hf/margin/orders/{orderId}': 'v3',
559
+ 'hf/margin/orders/client-order/{clientOid}': 'v3',
560
+ 'hf/margin/fills': 'v3',
561
+ 'etf/info': 'v3',
562
+ 'margin/currencies': 'v3',
563
+ 'margin/borrow': 'v3',
564
+ 'margin/repay': 'v3',
565
+ 'project/list': 'v3',
566
+ 'project/marketInterestRate': 'v3',
567
+ 'redeem/orders': 'v3',
568
+ 'purchase/orders': 'v3',
569
+ },
570
+ 'POST': {
571
+ // account
572
+ 'sub/user/created': 'v2',
573
+ // funding
574
+ 'accounts/universal-transfer': 'v3',
575
+ 'accounts/sub-transfer': 'v2',
576
+ 'accounts/inner-transfer': 'v2',
577
+ 'transfer-out': 'v3',
578
+ // spot trading
579
+ 'oco/order': 'v3',
580
+ // margin trading
581
+ 'hf/margin/order': 'v3',
582
+ 'hf/margin/order/test': 'v3',
583
+ 'margin/borrow': 'v3',
584
+ 'margin/repay': 'v3',
585
+ 'purchase': 'v3',
586
+ 'redeem': 'v3',
587
+ 'lend/purchase/update': 'v3',
588
+ },
589
+ 'DELETE': {
590
+ // account
591
+ // funding
592
+ // spot trading
593
+ 'hf/margin/orders/{orderId}': 'v3',
594
+ 'hf/margin/orders/client-order/{clientOid}': 'v3',
595
+ 'hf/margin/orders': 'v3',
596
+ 'oco/order/{orderId}': 'v3',
597
+ 'oco/client-order/{clientOid}': 'v3',
598
+ 'oco/orders': 'v3',
599
+ // margin trading
600
+ },
601
+ },
602
+ 'futuresPrivate': {
603
+ 'POST': {
604
+ 'transfer-out': 'v3',
605
+ },
606
+ },
607
+ },
608
+ 'partner': {
609
+ // the support for spot and future exchanges as separate settings
610
+ 'spot': {
611
+ 'id': 'ccxt',
612
+ 'key': '9e58cc35-5b5e-4133-92ec-166e3f077cb8',
613
+ },
614
+ 'future': {
615
+ 'id': 'ccxtfutures',
616
+ 'key': '1b327198-f30c-4f14-a0ac-918871282f15',
617
+ },
618
+ // exchange-wide settings are also supported
619
+ // 'id': 'ccxt'
620
+ // 'key': '9e58cc35-5b5e-4133-92ec-166e3f077cb8',
621
+ },
622
+ 'accountsByType': {
623
+ 'spot': 'trade',
624
+ 'margin': 'margin',
625
+ 'cross': 'margin',
626
+ 'isolated': 'isolated',
627
+ 'main': 'main',
628
+ 'funding': 'main',
629
+ 'future': 'contract',
630
+ 'swap': 'contract',
631
+ 'mining': 'pool',
632
+ 'hf': 'trade_hf',
633
+ },
634
+ 'networks': {
635
+ 'BTC': 'btc',
636
+ 'BTCNATIVESEGWIT': 'bech32',
637
+ 'ERC20': 'eth',
638
+ 'TRC20': 'trx',
639
+ 'HRC20': 'heco',
640
+ 'MATIC': 'matic',
641
+ 'KCC': 'kcc',
642
+ 'SOL': 'sol',
643
+ 'ALGO': 'algo',
644
+ 'EOS': 'eos',
645
+ 'BEP20': 'bsc',
646
+ 'BEP2': 'bnb',
647
+ 'ARBONE': 'arbitrum',
648
+ 'AVAXX': 'avax',
649
+ 'AVAXC': 'avaxc',
650
+ 'TLOS': 'tlos',
651
+ 'CFX': 'cfx',
652
+ 'ACA': 'aca',
653
+ 'OPTIMISM': 'optimism',
654
+ 'ONT': 'ont',
655
+ 'GLMR': 'glmr',
656
+ 'CSPR': 'cspr',
657
+ 'KLAY': 'klay',
658
+ 'XRD': 'xrd',
659
+ 'RVN': 'rvn',
660
+ 'NEAR': 'near',
661
+ 'APT': 'aptos',
662
+ 'ETHW': 'ethw',
663
+ 'TON': 'ton',
664
+ 'BCH': 'bch',
665
+ 'BSV': 'bchsv',
666
+ 'BCHA': 'bchabc',
667
+ 'OSMO': 'osmo',
668
+ 'NANO': 'nano',
669
+ 'XLM': 'xlm',
670
+ 'VET': 'vet',
671
+ 'IOST': 'iost',
672
+ 'ZIL': 'zil',
673
+ 'XRP': 'xrp',
674
+ 'TOMO': 'tomo',
675
+ 'XMR': 'xmr',
676
+ 'COTI': 'coti',
677
+ 'XTZ': 'xtz',
678
+ 'ADA': 'ada',
679
+ 'WAX': 'waxp',
680
+ 'THETA': 'theta',
681
+ 'ONE': 'one',
682
+ 'IOTEX': 'iotx',
683
+ 'NULS': 'nuls',
684
+ 'KSM': 'ksm',
685
+ 'LTC': 'ltc',
686
+ 'WAVES': 'waves',
687
+ 'DOT': 'dot',
688
+ 'STEEM': 'steem',
689
+ 'QTUM': 'qtum',
690
+ 'DOGE': 'doge',
691
+ 'FIL': 'fil',
692
+ 'XYM': 'xym',
693
+ 'FLUX': 'flux',
694
+ 'ATOM': 'atom',
695
+ 'XDC': 'xdc',
696
+ 'KDA': 'kda',
697
+ 'ICP': 'icp',
698
+ 'CELO': 'celo',
699
+ 'LSK': 'lsk',
700
+ 'VSYS': 'vsys',
701
+ 'KAR': 'kar',
702
+ 'XCH': 'xch',
703
+ 'FLOW': 'flow',
704
+ 'BAND': 'band',
705
+ 'EGLD': 'egld',
706
+ 'HBAR': 'hbar',
707
+ 'XPR': 'xpr',
708
+ 'AR': 'ar',
709
+ 'FTM': 'ftm',
710
+ 'KAVA': 'kava',
711
+ 'KMA': 'kma',
712
+ 'XEC': 'xec',
713
+ 'IOTA': 'iota',
714
+ 'HNT': 'hnt',
715
+ 'ASTR': 'astr',
716
+ 'PDEX': 'pdex',
717
+ 'METIS': 'metis',
718
+ 'ZEC': 'zec',
719
+ 'POKT': 'pokt',
720
+ 'OASYS': 'oas',
721
+ 'OASIS': 'oasis',
722
+ 'ETC': 'etc',
723
+ 'AKT': 'akt',
724
+ 'FSN': 'fsn',
725
+ 'SCRT': 'scrt',
726
+ 'CFG': 'cfg',
727
+ 'ICX': 'icx',
728
+ 'KMD': 'kmd',
729
+ 'NEM': 'NEM',
730
+ 'STX': 'stx',
731
+ 'DGB': 'dgb',
732
+ 'DCR': 'dcr',
733
+ 'CKB': 'ckb',
734
+ 'ELA': 'ela',
735
+ 'HYDRA': 'hydra',
736
+ 'BTM': 'btm',
737
+ 'KARDIA': 'kai',
738
+ 'SXP': 'sxp',
739
+ 'NEBL': 'nebl',
740
+ 'ZEN': 'zen',
741
+ 'SDN': 'sdn',
742
+ 'LTO': 'lto',
743
+ 'WEMIX': 'wemix',
744
+ // 'BOBA': 'boba', // tbd
745
+ 'EVER': 'ever',
746
+ 'BNC': 'bnc',
747
+ 'BNCDOT': 'bncdot',
748
+ // 'CMP': 'cmp', // todo: after consensus
749
+ 'AION': 'aion',
750
+ 'GRIN': 'grin',
751
+ 'LOKI': 'loki',
752
+ 'QKC': 'qkc',
753
+ 'TT': 'TT',
754
+ 'PIVX': 'pivx',
755
+ 'SERO': 'sero',
756
+ 'METER': 'meter',
757
+ 'STATEMINE': 'statemine',
758
+ 'DVPN': 'dvpn',
759
+ 'XPRT': 'xprt',
760
+ 'MOVR': 'movr',
761
+ 'ERGO': 'ergo',
762
+ 'ABBC': 'abbc',
763
+ 'DIVI': 'divi',
764
+ 'PURA': 'pura',
765
+ 'DFI': 'dfi',
766
+ // 'NEO': 'neo', // tbd neo legacy
767
+ 'NEON3': 'neon3',
768
+ 'DOCK': 'dock',
769
+ 'TRUE': 'true',
770
+ 'CS': 'cs',
771
+ 'ORAI': 'orai',
772
+ // below will be uncommented after consensus
773
+ // 'BITCOINDIAMON': 'bcd',
774
+ // 'BITCOINGOLD': 'btg',
775
+ // 'HTR': 'htr',
776
+ // 'DEROHE': 'derohe',
777
+ // 'NDAU': 'ndau',
778
+ // 'HPB': 'hpb',
779
+ // 'AXE': 'axe',
780
+ // 'BITCOINPRIVATE': 'btcp',
781
+ // 'EDGEWARE': 'edg',
782
+ // 'JUPITER': 'jup',
783
+ // 'VELAS': 'vlx', // vlxevm is different
784
+ // // 'terra' luna lunc TBD
785
+ // 'DIGITALBITS': 'xdb',
786
+ // // fra is fra-emv on kucoin
787
+ // 'PASTEL': 'psl',
788
+ // // sysevm
789
+ // 'CONCORDIUM': 'ccd',
790
+ // 'AURORA': 'aurora',
791
+ // 'PHA': 'pha', // a.k.a. khala
792
+ // 'PAL': 'pal',
793
+ // 'RSK': 'rbtc',
794
+ // 'NIX': 'nix',
795
+ // 'NIM': 'nim',
796
+ // 'NRG': 'nrg',
797
+ // 'RFOX': 'rfox',
798
+ // 'PIONEER': 'neer',
799
+ // 'PIXIE': 'pix',
800
+ // 'ALEPHZERO': 'azero',
801
+ // 'ACHAIN': 'act', // actevm is different
802
+ // 'BOSCOIN': 'bos',
803
+ // 'ELECTRONEUM': 'etn',
804
+ // 'GOCHAIN': 'go',
805
+ // 'SOPHIATX': 'sphtx',
806
+ // 'WANCHAIN': 'wan',
807
+ // 'ZEEPIN': 'zpt',
808
+ // 'MATRIXAI': 'man',
809
+ // 'METADIUM': 'meta',
810
+ // 'METAHASH': 'mhc',
811
+ // // eosc --"eosforce" tbd
812
+ // 'IOTCHAIN': 'itc',
813
+ // 'CONTENTOS': 'cos',
814
+ // 'CPCHAIN': 'cpc',
815
+ // 'INTCHAIN': 'int',
816
+ // // 'DASH': 'dash', tbd digita-cash
817
+ // 'WALTONCHAIN': 'wtc',
818
+ // 'CONSTELLATION': 'dag',
819
+ // 'ONELEDGER': 'olt',
820
+ // 'AIRDAO': 'amb', // a.k.a. AMBROSUS
821
+ // 'ENERGYWEB': 'ewt',
822
+ // 'WAVESENTERPRISE': 'west',
823
+ // 'HYPERCASH': 'hc',
824
+ // 'ENECUUM': 'enq',
825
+ // 'HAVEN': 'xhv',
826
+ // 'CHAINX': 'pcx',
827
+ // // 'FLUXOLD': 'zel', // zel seems old chain (with uppercase FLUX in kucoin UI and with id 'zel')
828
+ // 'BUMO': 'bu',
829
+ // 'DEEPONION': 'onion',
830
+ // 'ULORD': 'ut',
831
+ // 'ASCH': 'xas',
832
+ // 'SOLARIS': 'xlr',
833
+ // 'APOLLO': 'apl',
834
+ // 'PIRATECHAIN': 'arrr',
835
+ // 'ULTRA': 'uos',
836
+ // 'EMONEY': 'ngm',
837
+ // 'AURORACHAIN': 'aoa',
838
+ // 'KLEVER': 'klv',
839
+ // undetermined: xns(insolar), rhoc, luk (luniverse), kts (klimatas), bchn (bitcoin cash node), god (shallow entry), lit (litmus),
840
+ },
841
+ 'marginModes': {
842
+ 'cross': 'MARGIN_TRADE',
843
+ 'isolated': 'MARGIN_ISOLATED_TRADE',
844
+ 'spot': 'TRADE',
845
+ },
846
+ },
847
+ });
848
+ }
849
+ nonce() {
850
+ return this.milliseconds();
851
+ }
852
+ async fetchTime(params = {}) {
853
+ /**
854
+ * @method
855
+ * @name kucoin#fetchTime
856
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
857
+ * @see https://docs.kucoin.com/#server-time
858
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
859
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
860
+ */
861
+ const response = await this.publicGetTimestamp(params);
862
+ //
863
+ // {
864
+ // "code":"200000",
865
+ // "msg":"success",
866
+ // "data":1546837113087
867
+ // }
868
+ //
869
+ return this.safeInteger(response, 'data');
870
+ }
871
+ async fetchStatus(params = {}) {
872
+ /**
873
+ * @method
874
+ * @name kucoin#fetchStatus
875
+ * @description the latest known information on the availability of the exchange API
876
+ * @see https://docs.kucoin.com/#service-status
877
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
878
+ * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
879
+ */
880
+ const response = await this.publicGetStatus(params);
881
+ //
882
+ // {
883
+ // "code":"200000",
884
+ // "data":{
885
+ // "status":"open", //open, close, cancelonly
886
+ // "msg":"upgrade match engine" //remark for operation
887
+ // }
888
+ // }
889
+ //
890
+ const data = this.safeValue(response, 'data', {});
891
+ const status = this.safeString(data, 'status');
892
+ return {
893
+ 'status': (status === 'open') ? 'ok' : 'maintenance',
894
+ 'updated': undefined,
895
+ 'eta': undefined,
896
+ 'url': undefined,
897
+ 'info': response,
898
+ };
899
+ }
900
+ async fetchMarkets(params = {}) {
901
+ /**
902
+ * @method
903
+ * @name kucoin#fetchMarkets
904
+ * @description retrieves data on all markets for kucoin
905
+ * @see https://docs.kucoin.com/#get-symbols-list-deprecated
906
+ * @see https://docs.kucoin.com/#get-all-tickers
907
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
908
+ * @returns {object[]} an array of objects representing market data
909
+ */
910
+ const response = await this.publicGetSymbols(params);
911
+ //
912
+ // {
913
+ // "code": "200000",
914
+ // "data": [
915
+ // {
916
+ // "symbol": "XLM-USDT",
917
+ // "name": "XLM-USDT",
918
+ // "baseCurrency": "XLM",
919
+ // "quoteCurrency": "USDT",
920
+ // "feeCurrency": "USDT",
921
+ // "market": "USDS",
922
+ // "baseMinSize": "0.1",
923
+ // "quoteMinSize": "0.01",
924
+ // "baseMaxSize": "10000000000",
925
+ // "quoteMaxSize": "99999999",
926
+ // "baseIncrement": "0.0001",
927
+ // "quoteIncrement": "0.000001",
928
+ // "priceIncrement": "0.000001",
929
+ // "priceLimitRate": "0.1",
930
+ // "isMarginEnabled": true,
931
+ // "enableTrading": true
932
+ // },
933
+ // ]
934
+ // }
935
+ //
936
+ const data = this.safeValue(response, 'data');
937
+ const options = this.safeValue(this.options, 'fetchMarkets', {});
938
+ const fetchTickersFees = this.safeValue(options, 'fetchTickersFees', true);
939
+ let tickersResponse = {};
940
+ if (fetchTickersFees) {
941
+ tickersResponse = await this.publicGetMarketAllTickers(params);
942
+ }
943
+ //
944
+ // {
945
+ // "code": "200000",
946
+ // "data": {
947
+ // "time":1602832092060,
948
+ // "ticker":[
949
+ // {
950
+ // "symbol": "BTC-USDT", // symbol
951
+ // "symbolName":"BTC-USDT", // Name of trading pairs, it would change after renaming
952
+ // "buy": "11328.9", // bestAsk
953
+ // "sell": "11329", // bestBid
954
+ // "changeRate": "-0.0055", // 24h change rate
955
+ // "changePrice": "-63.6", // 24h change price
956
+ // "high": "11610", // 24h highest price
957
+ // "low": "11200", // 24h lowest price
958
+ // "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
959
+ // "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
960
+ // "last": "11328.9", // last price
961
+ // "averagePrice": "11360.66065903", // 24h average transaction price yesterday
962
+ // "takerFeeRate": "0.001", // Basic Taker Fee
963
+ // "makerFeeRate": "0.001", // Basic Maker Fee
964
+ // "takerCoefficient": "1", // Taker Fee Coefficient
965
+ // "makerCoefficient": "1" // Maker Fee Coefficient
966
+ // }
967
+ // ]
968
+ // }
969
+ // }
970
+ //
971
+ const tickersData = this.safeValue(tickersResponse, 'data', {});
972
+ const tickers = this.safeValue(tickersData, 'ticker', []);
973
+ const tickersByMarketId = this.indexBy(tickers, 'symbol');
974
+ const result = [];
975
+ for (let i = 0; i < data.length; i++) {
976
+ const market = data[i];
977
+ const id = this.safeString(market, 'symbol');
978
+ const [baseId, quoteId] = id.split('-');
979
+ const base = this.safeCurrencyCode(baseId);
980
+ const quote = this.safeCurrencyCode(quoteId);
981
+ // const quoteIncrement = this.safeNumber (market, 'quoteIncrement');
982
+ const ticker = this.safeValue(tickersByMarketId, id, {});
983
+ const makerFeeRate = this.safeString(ticker, 'makerFeeRate');
984
+ const takerFeeRate = this.safeString(ticker, 'takerFeeRate');
985
+ const makerCoefficient = this.safeString(ticker, 'makerCoefficient');
986
+ const takerCoefficient = this.safeString(ticker, 'takerCoefficient');
987
+ result.push({
988
+ 'id': id,
989
+ 'symbol': base + '/' + quote,
990
+ 'base': base,
991
+ 'quote': quote,
992
+ 'settle': undefined,
993
+ 'baseId': baseId,
994
+ 'quoteId': quoteId,
995
+ 'settleId': undefined,
996
+ 'type': 'spot',
997
+ 'spot': true,
998
+ 'margin': this.safeValue(market, 'isMarginEnabled'),
999
+ 'swap': false,
1000
+ 'future': false,
1001
+ 'option': false,
1002
+ 'active': this.safeValue(market, 'enableTrading'),
1003
+ 'contract': false,
1004
+ 'linear': undefined,
1005
+ 'inverse': undefined,
1006
+ 'taker': this.parseNumber(Precise["default"].stringMul(takerFeeRate, takerCoefficient)),
1007
+ 'maker': this.parseNumber(Precise["default"].stringMul(makerFeeRate, makerCoefficient)),
1008
+ 'contractSize': undefined,
1009
+ 'expiry': undefined,
1010
+ 'expiryDatetime': undefined,
1011
+ 'strike': undefined,
1012
+ 'optionType': undefined,
1013
+ 'precision': {
1014
+ 'amount': this.safeNumber(market, 'baseIncrement'),
1015
+ 'price': this.safeNumber(market, 'priceIncrement'),
1016
+ },
1017
+ 'limits': {
1018
+ 'leverage': {
1019
+ 'min': undefined,
1020
+ 'max': undefined,
1021
+ },
1022
+ 'amount': {
1023
+ 'min': this.safeNumber(market, 'baseMinSize'),
1024
+ 'max': this.safeNumber(market, 'baseMaxSize'),
1025
+ },
1026
+ 'price': {
1027
+ 'min': undefined,
1028
+ 'max': undefined,
1029
+ },
1030
+ 'cost': {
1031
+ 'min': this.safeNumber(market, 'quoteMinSize'),
1032
+ 'max': this.safeNumber(market, 'quoteMaxSize'),
1033
+ },
1034
+ },
1035
+ 'created': undefined,
1036
+ 'info': market,
1037
+ });
1038
+ }
1039
+ return result;
1040
+ }
1041
+ async fetchCurrencies(params = {}) {
1042
+ /**
1043
+ * @method
1044
+ * @name kucoin#fetchCurrencies
1045
+ * @description fetches all available currencies on an exchange
1046
+ * @see https://docs.kucoin.com/#get-currencies
1047
+ * @param {object} params extra parameters specific to the exchange API endpoint
1048
+ * @returns {object} an associative dictionary of currencies
1049
+ */
1050
+ const promises = [];
1051
+ promises.push(this.publicGetCurrencies(params));
1052
+ //
1053
+ // {
1054
+ // "code":"200000",
1055
+ // "data":[
1056
+ // {
1057
+ // "currency":"CSP",
1058
+ // "name":"CSP",
1059
+ // "fullName":"Caspian",
1060
+ // "precision":8,
1061
+ // "confirms":null,
1062
+ // "contractAddress":null,
1063
+ // "isMarginEnabled":false,
1064
+ // "isDebitEnabled":false,
1065
+ // "chains":[
1066
+ // {
1067
+ // "chainName":"ERC20",
1068
+ // "chain":"eth",
1069
+ // "withdrawalMinSize":"2999",
1070
+ // "withdrawalMinFee":"2999",
1071
+ // "isWithdrawEnabled":false,
1072
+ // "isDepositEnabled":false,
1073
+ // "confirms":12,
1074
+ // "preConfirms":12,
1075
+ // "contractAddress":"0xa6446d655a0c34bc4f05042ee88170d056cbaf45",
1076
+ // "depositFeeRate": "0.001", // present for some currencies/networks
1077
+ // }
1078
+ // ]
1079
+ // },
1080
+ // }
1081
+ //
1082
+ promises.push(this.fetchWebEndpoint('fetchCurrencies', 'webExchangeGetCurrencyCurrencyChainInfo', true));
1083
+ //
1084
+ // {
1085
+ // "success": true,
1086
+ // "code": "200",
1087
+ // "msg": "success",
1088
+ // "retry": false,
1089
+ // "data": [
1090
+ // {
1091
+ // "status": "enabled",
1092
+ // "currency": "BTC",
1093
+ // "isChainEnabled": "true",
1094
+ // "chain": "btc",
1095
+ // "chainName": "BTC",
1096
+ // "chainFullName": "Bitcoin",
1097
+ // "walletPrecision": "8",
1098
+ // "isDepositEnabled": "true",
1099
+ // "depositMinSize": "0.00005",
1100
+ // "confirmationCount": "2",
1101
+ // "isWithdrawEnabled": "true",
1102
+ // "withdrawMinSize": "0.001",
1103
+ // "withdrawMinFee": "0.0005",
1104
+ // "withdrawFeeRate": "0",
1105
+ // "depositDisabledTip": "Wallet Maintenance",
1106
+ // "preDepositTipEnabled": "true",
1107
+ // "preDepositTip": "Do not transfer from ETH network directly",
1108
+ // "withdrawDisabledTip": "",
1109
+ // "preWithdrawTipEnabled": "false",
1110
+ // "preWithdrawTip": "",
1111
+ // "orgAddress": "",
1112
+ // "userAddressName": "Memo",
1113
+ // },
1114
+ // ]
1115
+ // }
1116
+ //
1117
+ const responses = await Promise.all(promises);
1118
+ const currenciesResponse = this.safeValue(responses, 0, {});
1119
+ const currenciesData = this.safeValue(currenciesResponse, 'data', []);
1120
+ const additionalResponse = this.safeValue(responses, 1, {});
1121
+ const additionalData = this.safeValue(additionalResponse, 'data', []);
1122
+ const additionalDataGrouped = this.groupBy(additionalData, 'currency');
1123
+ const result = {};
1124
+ for (let i = 0; i < currenciesData.length; i++) {
1125
+ const entry = currenciesData[i];
1126
+ const id = this.safeString(entry, 'currency');
1127
+ const name = this.safeString(entry, 'fullName');
1128
+ const code = this.safeCurrencyCode(id);
1129
+ let isWithdrawEnabled = undefined;
1130
+ let isDepositEnabled = undefined;
1131
+ const networks = {};
1132
+ const chains = this.safeValue(entry, 'chains', []);
1133
+ const extraChainsData = this.indexBy(this.safeValue(additionalDataGrouped, id, []), 'chain');
1134
+ const rawPrecision = this.safeString(entry, 'precision');
1135
+ const precision = this.parseNumber(this.parsePrecision(rawPrecision));
1136
+ const chainsLength = chains.length;
1137
+ if (!chainsLength) {
1138
+ // https://t.me/KuCoin_API/173118
1139
+ isWithdrawEnabled = false;
1140
+ isDepositEnabled = false;
1141
+ }
1142
+ for (let j = 0; j < chainsLength; j++) {
1143
+ const chain = chains[j];
1144
+ const chainId = this.safeString(chain, 'chainId');
1145
+ const networkCode = this.networkIdToCode(chainId);
1146
+ const chainWithdrawEnabled = this.safeValue(chain, 'isWithdrawEnabled', false);
1147
+ if (isWithdrawEnabled === undefined) {
1148
+ isWithdrawEnabled = chainWithdrawEnabled;
1149
+ }
1150
+ else {
1151
+ isWithdrawEnabled = isWithdrawEnabled || chainWithdrawEnabled;
1152
+ }
1153
+ const chainDepositEnabled = this.safeValue(chain, 'isDepositEnabled', false);
1154
+ if (isDepositEnabled === undefined) {
1155
+ isDepositEnabled = chainDepositEnabled;
1156
+ }
1157
+ else {
1158
+ isDepositEnabled = isDepositEnabled || chainDepositEnabled;
1159
+ }
1160
+ const chainExtraData = this.safeValue(extraChainsData, chainId, {});
1161
+ networks[networkCode] = {
1162
+ 'info': chain,
1163
+ 'id': chainId,
1164
+ 'name': this.safeString(chain, 'chainName'),
1165
+ 'code': networkCode,
1166
+ 'active': chainWithdrawEnabled && chainDepositEnabled,
1167
+ 'fee': this.safeNumber(chain, 'withdrawalMinFee'),
1168
+ 'deposit': chainDepositEnabled,
1169
+ 'withdraw': chainWithdrawEnabled,
1170
+ 'precision': this.parseNumber(this.parsePrecision(this.safeString(chainExtraData, 'walletPrecision'))),
1171
+ 'limits': {
1172
+ 'withdraw': {
1173
+ 'min': this.safeNumber(chain, 'withdrawalMinSize'),
1174
+ 'max': undefined,
1175
+ },
1176
+ 'deposit': {
1177
+ 'min': this.safeNumber(chainExtraData, 'depositMinSize'),
1178
+ 'max': undefined,
1179
+ },
1180
+ },
1181
+ };
1182
+ }
1183
+ // kucoin has determined 'fiat' currencies with below logic
1184
+ const isFiat = (rawPrecision === '2') && (chainsLength === 0);
1185
+ result[code] = {
1186
+ 'id': id,
1187
+ 'name': name,
1188
+ 'code': code,
1189
+ 'type': isFiat ? 'fiat' : 'crypto',
1190
+ 'precision': precision,
1191
+ 'info': entry,
1192
+ 'active': (isDepositEnabled || isWithdrawEnabled),
1193
+ 'deposit': isDepositEnabled,
1194
+ 'withdraw': isWithdrawEnabled,
1195
+ 'fee': undefined,
1196
+ 'limits': this.limits,
1197
+ 'networks': networks,
1198
+ };
1199
+ }
1200
+ return result;
1201
+ }
1202
+ async fetchAccounts(params = {}) {
1203
+ /**
1204
+ * @method
1205
+ * @name kucoin#fetchAccounts
1206
+ * @description fetch all the accounts associated with a profile
1207
+ * @see https://docs.kucoin.com/#list-accounts
1208
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1209
+ * @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type
1210
+ */
1211
+ const response = await this.privateGetAccounts(params);
1212
+ //
1213
+ // {
1214
+ // "code": "200000",
1215
+ // "data": [
1216
+ // {
1217
+ // "balance": "0.00009788",
1218
+ // "available": "0.00009788",
1219
+ // "holds": "0",
1220
+ // "currency": "BTC",
1221
+ // "id": "5c6a4fd399a1d81c4f9cc4d0",
1222
+ // "type": "trade"
1223
+ // },
1224
+ // {
1225
+ // "balance": "0.00000001",
1226
+ // "available": "0.00000001",
1227
+ // "holds": "0",
1228
+ // "currency": "ETH",
1229
+ // "id": "5c6a49ec99a1d819392e8e9f",
1230
+ // "type": "trade"
1231
+ // }
1232
+ // ]
1233
+ // }
1234
+ //
1235
+ const data = this.safeValue(response, 'data', []);
1236
+ const result = [];
1237
+ for (let i = 0; i < data.length; i++) {
1238
+ const account = data[i];
1239
+ const accountId = this.safeString(account, 'id');
1240
+ const currencyId = this.safeString(account, 'currency');
1241
+ const code = this.safeCurrencyCode(currencyId);
1242
+ const type = this.safeString(account, 'type'); // main or trade
1243
+ result.push({
1244
+ 'id': accountId,
1245
+ 'type': type,
1246
+ 'currency': code,
1247
+ 'code': code,
1248
+ 'info': account,
1249
+ });
1250
+ }
1251
+ return result;
1252
+ }
1253
+ async fetchTransactionFee(code, params = {}) {
1254
+ /**
1255
+ * @method
1256
+ * @name kucoin#fetchTransactionFee
1257
+ * @description *DEPRECATED* please use fetchDepositWithdrawFee instead
1258
+ * @see https://docs.kucoin.com/#get-withdrawal-quotas
1259
+ * @param {string} code unified currency code
1260
+ * @param {object} params extra parameters specific to the exchange API endpoint
1261
+ * @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
1262
+ */
1263
+ await this.loadMarkets();
1264
+ const currency = this.currency(code);
1265
+ const request = {
1266
+ 'currency': currency['id'],
1267
+ };
1268
+ let networkCode = undefined;
1269
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
1270
+ if (networkCode !== undefined) {
1271
+ request['chain'] = this.networkCodeToId(networkCode).toLowerCase();
1272
+ }
1273
+ const response = await this.privateGetWithdrawalsQuotas(this.extend(request, params));
1274
+ const data = this.safeValue(response, 'data');
1275
+ const withdrawFees = {};
1276
+ withdrawFees[code] = this.safeNumber(data, 'withdrawMinFee');
1277
+ return {
1278
+ 'info': response,
1279
+ 'withdraw': withdrawFees,
1280
+ 'deposit': {},
1281
+ };
1282
+ }
1283
+ async fetchDepositWithdrawFee(code, params = {}) {
1284
+ /**
1285
+ * @method
1286
+ * @name kucoin#fetchDepositWithdrawFee
1287
+ * @description fetch the fee for deposits and withdrawals
1288
+ * @see https://docs.kucoin.com/#get-withdrawal-quotas
1289
+ * @param {string} code unified currency code
1290
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1291
+ * @param {string} [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
1292
+ * @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
1293
+ */
1294
+ await this.loadMarkets();
1295
+ const currency = this.currency(code);
1296
+ const request = {
1297
+ 'currency': currency['id'],
1298
+ };
1299
+ let networkCode = undefined;
1300
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
1301
+ if (networkCode !== undefined) {
1302
+ request['chain'] = this.networkCodeToId(networkCode).toLowerCase();
1303
+ }
1304
+ const response = await this.privateGetWithdrawalsQuotas(this.extend(request, params));
1305
+ //
1306
+ // {
1307
+ // "code": "200000",
1308
+ // "data": {
1309
+ // "currency": "USDT",
1310
+ // "limitBTCAmount": "1.00000000",
1311
+ // "usedBTCAmount": "0.00000000",
1312
+ // "remainAmount": "16548.072149",
1313
+ // "availableAmount": "0",
1314
+ // "withdrawMinFee": "25",
1315
+ // "innerWithdrawMinFee": "0",
1316
+ // "withdrawMinSize": "50",
1317
+ // "isWithdrawEnabled": true,
1318
+ // "precision": 6,
1319
+ // "chain": "ERC20"
1320
+ // }
1321
+ // }
1322
+ //
1323
+ const data = this.safeValue(response, 'data');
1324
+ return this.parseDepositWithdrawFee(data, currency);
1325
+ }
1326
+ parseDepositWithdrawFee(fee, currency = undefined) {
1327
+ //
1328
+ // {
1329
+ // "currency": "USDT",
1330
+ // "limitBTCAmount": "1.00000000",
1331
+ // "usedBTCAmount": "0.00000000",
1332
+ // "remainAmount": "16548.072149",
1333
+ // "availableAmount": "0",
1334
+ // "withdrawMinFee": "25",
1335
+ // "innerWithdrawMinFee": "0",
1336
+ // "withdrawMinSize": "50",
1337
+ // "isWithdrawEnabled": true,
1338
+ // "precision": 6,
1339
+ // "chain": "ERC20"
1340
+ // }
1341
+ //
1342
+ const result = {
1343
+ 'info': fee,
1344
+ 'withdraw': {
1345
+ 'fee': undefined,
1346
+ 'percentage': undefined,
1347
+ },
1348
+ 'deposit': {
1349
+ 'fee': undefined,
1350
+ 'percentage': undefined,
1351
+ },
1352
+ 'networks': {},
1353
+ };
1354
+ const isWithdrawEnabled = this.safeValue(fee, 'isWithdrawEnabled');
1355
+ if (isWithdrawEnabled) {
1356
+ result['withdraw']['fee'] = this.safeNumber2(fee, 'withdrawalMinFee', 'withdrawMinFee');
1357
+ result['withdraw']['percentage'] = false;
1358
+ const networkId = this.safeString(fee, 'chain');
1359
+ if (networkId) {
1360
+ const networkCode = this.networkIdToCode(networkId, this.safeString(currency, 'code'));
1361
+ result['networks'][networkCode] = {
1362
+ 'withdraw': result['withdraw'],
1363
+ 'deposit': {
1364
+ 'fee': undefined,
1365
+ 'percentage': undefined,
1366
+ },
1367
+ };
1368
+ }
1369
+ }
1370
+ return result;
1371
+ }
1372
+ isFuturesMethod(methodName, params) {
1373
+ //
1374
+ // Helper
1375
+ // @methodName (string): The name of the method
1376
+ // @params (dict): The parameters passed into {methodName}
1377
+ // @return: true if the method used is meant for futures trading, false otherwise
1378
+ //
1379
+ const defaultType = this.safeString2(this.options, methodName, 'defaultType', 'trade');
1380
+ const requestedType = this.safeString(params, 'type', defaultType);
1381
+ const accountsByType = this.safeValue(this.options, 'accountsByType');
1382
+ const type = this.safeString(accountsByType, requestedType);
1383
+ if (type === undefined) {
1384
+ const keys = Object.keys(accountsByType);
1385
+ throw new errors.ExchangeError(this.id + ' isFuturesMethod() type must be one of ' + keys.join(', '));
1386
+ }
1387
+ params = this.omit(params, 'type');
1388
+ return (type === 'contract') || (type === 'future') || (type === 'futures'); // * (type === 'futures') deprecated, use (type === 'future')
1389
+ }
1390
+ parseTicker(ticker, market = undefined) {
1391
+ //
1392
+ // {
1393
+ // "symbol": "BTC-USDT", // symbol
1394
+ // "symbolName":"BTC-USDT", // Name of trading pairs, it would change after renaming
1395
+ // "buy": "11328.9", // bestAsk
1396
+ // "sell": "11329", // bestBid
1397
+ // "changeRate": "-0.0055", // 24h change rate
1398
+ // "changePrice": "-63.6", // 24h change price
1399
+ // "high": "11610", // 24h highest price
1400
+ // "low": "11200", // 24h lowest price
1401
+ // "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
1402
+ // "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
1403
+ // "last": "11328.9", // last price
1404
+ // "averagePrice": "11360.66065903", // 24h average transaction price yesterday
1405
+ // "takerFeeRate": "0.001", // Basic Taker Fee
1406
+ // "makerFeeRate": "0.001", // Basic Maker Fee
1407
+ // "takerCoefficient": "1", // Taker Fee Coefficient
1408
+ // "makerCoefficient": "1" // Maker Fee Coefficient
1409
+ // }
1410
+ //
1411
+ // {
1412
+ // "trading": true,
1413
+ // "symbol": "KCS-BTC",
1414
+ // "buy": 0.00011,
1415
+ // "sell": 0.00012,
1416
+ // "sort": 100,
1417
+ // "volValue": 3.13851792584, //total
1418
+ // "baseCurrency": "KCS",
1419
+ // "market": "BTC",
1420
+ // "quoteCurrency": "BTC",
1421
+ // "symbolCode": "KCS-BTC",
1422
+ // "datetime": 1548388122031,
1423
+ // "high": 0.00013,
1424
+ // "vol": 27514.34842,
1425
+ // "low": 0.0001,
1426
+ // "changePrice": -1.0e-5,
1427
+ // "changeRate": -0.0769,
1428
+ // "lastTradedPrice": 0.00012,
1429
+ // "board": 0,
1430
+ // "mark": 0
1431
+ // }
1432
+ //
1433
+ // market/ticker ws subscription
1434
+ //
1435
+ // {
1436
+ // "bestAsk": "62258.9",
1437
+ // "bestAskSize": "0.38579986",
1438
+ // "bestBid": "62258.8",
1439
+ // "bestBidSize": "0.0078381",
1440
+ // "price": "62260.7",
1441
+ // "sequence": "1621383297064",
1442
+ // "size": "0.00002841",
1443
+ // "time": 1634641777363
1444
+ // }
1445
+ //
1446
+ let percentage = this.safeString(ticker, 'changeRate');
1447
+ if (percentage !== undefined) {
1448
+ percentage = Precise["default"].stringMul(percentage, '100');
1449
+ }
1450
+ let last = this.safeString2(ticker, 'last', 'lastTradedPrice');
1451
+ last = this.safeString(ticker, 'price', last);
1452
+ const marketId = this.safeString(ticker, 'symbol');
1453
+ market = this.safeMarket(marketId, market, '-');
1454
+ const symbol = market['symbol'];
1455
+ const baseVolume = this.safeString(ticker, 'vol');
1456
+ const quoteVolume = this.safeString(ticker, 'volValue');
1457
+ const timestamp = this.safeInteger2(ticker, 'time', 'datetime');
1458
+ return this.safeTicker({
1459
+ 'symbol': symbol,
1460
+ 'timestamp': timestamp,
1461
+ 'datetime': this.iso8601(timestamp),
1462
+ 'high': this.safeString(ticker, 'high'),
1463
+ 'low': this.safeString(ticker, 'low'),
1464
+ 'bid': this.safeString2(ticker, 'buy', 'bestBid'),
1465
+ 'bidVolume': this.safeString(ticker, 'bestBidSize'),
1466
+ 'ask': this.safeString2(ticker, 'sell', 'bestAsk'),
1467
+ 'askVolume': this.safeString(ticker, 'bestAskSize'),
1468
+ 'vwap': undefined,
1469
+ 'open': this.safeString(ticker, 'open'),
1470
+ 'close': last,
1471
+ 'last': last,
1472
+ 'previousClose': undefined,
1473
+ 'change': this.safeString(ticker, 'changePrice'),
1474
+ 'percentage': percentage,
1475
+ 'average': this.safeString(ticker, 'averagePrice'),
1476
+ 'baseVolume': baseVolume,
1477
+ 'quoteVolume': quoteVolume,
1478
+ 'info': ticker,
1479
+ }, market);
1480
+ }
1481
+ async fetchTickers(symbols = undefined, params = {}) {
1482
+ /**
1483
+ * @method
1484
+ * @name kucoin#fetchTickers
1485
+ * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1486
+ * @see https://docs.kucoin.com/#get-all-tickers
1487
+ * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1488
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1489
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1490
+ */
1491
+ await this.loadMarkets();
1492
+ symbols = this.marketSymbols(symbols);
1493
+ const response = await this.publicGetMarketAllTickers(params);
1494
+ //
1495
+ // {
1496
+ // "code": "200000",
1497
+ // "data": {
1498
+ // "time":1602832092060,
1499
+ // "ticker":[
1500
+ // {
1501
+ // "symbol": "BTC-USDT", // symbol
1502
+ // "symbolName":"BTC-USDT", // Name of trading pairs, it would change after renaming
1503
+ // "buy": "11328.9", // bestAsk
1504
+ // "sell": "11329", // bestBid
1505
+ // "changeRate": "-0.0055", // 24h change rate
1506
+ // "changePrice": "-63.6", // 24h change price
1507
+ // "high": "11610", // 24h highest price
1508
+ // "low": "11200", // 24h lowest price
1509
+ // "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
1510
+ // "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
1511
+ // "last": "11328.9", // last price
1512
+ // "averagePrice": "11360.66065903", // 24h average transaction price yesterday
1513
+ // "takerFeeRate": "0.001", // Basic Taker Fee
1514
+ // "makerFeeRate": "0.001", // Basic Maker Fee
1515
+ // "takerCoefficient": "1", // Taker Fee Coefficient
1516
+ // "makerCoefficient": "1" // Maker Fee Coefficient
1517
+ // }
1518
+ // ]
1519
+ // }
1520
+ // }
1521
+ //
1522
+ const data = this.safeValue(response, 'data', {});
1523
+ const tickers = this.safeValue(data, 'ticker', []);
1524
+ const time = this.safeInteger(data, 'time');
1525
+ const result = {};
1526
+ for (let i = 0; i < tickers.length; i++) {
1527
+ tickers[i]['time'] = time;
1528
+ const ticker = this.parseTicker(tickers[i]);
1529
+ const symbol = this.safeString(ticker, 'symbol');
1530
+ if (symbol !== undefined) {
1531
+ result[symbol] = ticker;
1532
+ }
1533
+ }
1534
+ return this.filterByArrayTickers(result, 'symbol', symbols);
1535
+ }
1536
+ async fetchTicker(symbol, params = {}) {
1537
+ /**
1538
+ * @method
1539
+ * @name kucoin#fetchTicker
1540
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1541
+ * @see https://docs.kucoin.com/#get-24hr-stats
1542
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
1543
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1544
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1545
+ */
1546
+ await this.loadMarkets();
1547
+ const market = this.market(symbol);
1548
+ const request = {
1549
+ 'symbol': market['id'],
1550
+ };
1551
+ const response = await this.publicGetMarketStats(this.extend(request, params));
1552
+ //
1553
+ // {
1554
+ // "code": "200000",
1555
+ // "data": {
1556
+ // "time": 1602832092060, // time
1557
+ // "symbol": "BTC-USDT", // symbol
1558
+ // "buy": "11328.9", // bestAsk
1559
+ // "sell": "11329", // bestBid
1560
+ // "changeRate": "-0.0055", // 24h change rate
1561
+ // "changePrice": "-63.6", // 24h change price
1562
+ // "high": "11610", // 24h highest price
1563
+ // "low": "11200", // 24h lowest price
1564
+ // "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
1565
+ // "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
1566
+ // "last": "11328.9", // last price
1567
+ // "averagePrice": "11360.66065903", // 24h average transaction price yesterday
1568
+ // "takerFeeRate": "0.001", // Basic Taker Fee
1569
+ // "makerFeeRate": "0.001", // Basic Maker Fee
1570
+ // "takerCoefficient": "1", // Taker Fee Coefficient
1571
+ // "makerCoefficient": "1" // Maker Fee Coefficient
1572
+ // }
1573
+ // }
1574
+ //
1575
+ return this.parseTicker(response['data'], market);
1576
+ }
1577
+ parseOHLCV(ohlcv, market = undefined) {
1578
+ //
1579
+ // [
1580
+ // "1545904980", // Start time of the candle cycle
1581
+ // "0.058", // opening price
1582
+ // "0.049", // closing price
1583
+ // "0.058", // highest price
1584
+ // "0.049", // lowest price
1585
+ // "0.018", // base volume
1586
+ // "0.000945", // quote volume
1587
+ // ]
1588
+ //
1589
+ return [
1590
+ this.safeTimestamp(ohlcv, 0),
1591
+ this.safeNumber(ohlcv, 1),
1592
+ this.safeNumber(ohlcv, 3),
1593
+ this.safeNumber(ohlcv, 4),
1594
+ this.safeNumber(ohlcv, 2),
1595
+ this.safeNumber(ohlcv, 5),
1596
+ ];
1597
+ }
1598
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1599
+ /**
1600
+ * @method
1601
+ * @name kucoin#fetchOHLCV
1602
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1603
+ * @see https://docs.kucoin.com/#get-klines
1604
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1605
+ * @param {string} timeframe the length of time each candle represents
1606
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
1607
+ * @param {int} [limit] the maximum amount of candles to fetch
1608
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1609
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1610
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1611
+ */
1612
+ await this.loadMarkets();
1613
+ let paginate = false;
1614
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'paginate');
1615
+ if (paginate) {
1616
+ return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1500);
1617
+ }
1618
+ const market = this.market(symbol);
1619
+ const marketId = market['id'];
1620
+ const request = {
1621
+ 'symbol': marketId,
1622
+ 'type': this.safeString(this.timeframes, timeframe, timeframe),
1623
+ };
1624
+ const duration = this.parseTimeframe(timeframe) * 1000;
1625
+ let endAt = this.milliseconds(); // required param
1626
+ if (since !== undefined) {
1627
+ request['startAt'] = this.parseToInt(Math.floor(since / 1000));
1628
+ if (limit === undefined) {
1629
+ // https://docs.kucoin.com/#get-klines
1630
+ // https://docs.kucoin.com/#details
1631
+ // For each query, the system would return at most 1500 pieces of data.
1632
+ // To obtain more data, please page the data by time.
1633
+ limit = this.safeInteger(this.options, 'fetchOHLCVLimit', 1500);
1634
+ }
1635
+ endAt = this.sum(since, limit * duration);
1636
+ }
1637
+ else if (limit !== undefined) {
1638
+ since = endAt - limit * duration;
1639
+ request['startAt'] = this.parseToInt(Math.floor(since / 1000));
1640
+ }
1641
+ request['endAt'] = this.parseToInt(Math.floor(endAt / 1000));
1642
+ const response = await this.publicGetMarketCandles(this.extend(request, params));
1643
+ //
1644
+ // {
1645
+ // "code":"200000",
1646
+ // "data":[
1647
+ // ["1591517700","0.025078","0.025069","0.025084","0.025064","18.9883256","0.4761861079404"],
1648
+ // ["1591516800","0.025089","0.025079","0.025089","0.02506","99.4716622","2.494143499081"],
1649
+ // ["1591515900","0.025079","0.02509","0.025091","0.025068","59.83701271","1.50060885172798"],
1650
+ // ]
1651
+ // }
1652
+ //
1653
+ const data = this.safeValue(response, 'data', []);
1654
+ return this.parseOHLCVs(data, market, timeframe, since, limit);
1655
+ }
1656
+ async createDepositAddress(code, params = {}) {
1657
+ /**
1658
+ * @method
1659
+ * @name kucoin#createDepositAddress
1660
+ * @see https://docs.kucoin.com/#create-deposit-address
1661
+ * @description create a currency deposit address
1662
+ * @param {string} code unified currency code of the currency for the deposit address
1663
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1664
+ * @param {string} [params.network] the blockchain network name
1665
+ * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
1666
+ */
1667
+ await this.loadMarkets();
1668
+ const currency = this.currency(code);
1669
+ const request = {
1670
+ 'currency': currency['id'],
1671
+ };
1672
+ let networkCode = undefined;
1673
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
1674
+ if (networkCode !== undefined) {
1675
+ request['chain'] = this.networkCodeToId(networkCode).toLowerCase();
1676
+ }
1677
+ const response = await this.privatePostDepositAddresses(this.extend(request, params));
1678
+ // {"code":"260000","msg":"Deposit address already exists."}
1679
+ // BCH {"code":"200000","data":{"address":"bitcoincash:qza3m4nj9rx7l9r0cdadfqxts6f92shvhvr5ls4q7z","memo":""}}
1680
+ // BTC {"code":"200000","data":{"address":"36SjucKqQpQSvsak9A7h6qzFjrVXpRNZhE","memo":""}}
1681
+ const data = this.safeValue(response, 'data', {});
1682
+ return this.parseDepositAddress(data, currency);
1683
+ }
1684
+ async fetchDepositAddress(code, params = {}) {
1685
+ /**
1686
+ * @method
1687
+ * @name kucoin#fetchDepositAddress
1688
+ * @description fetch the deposit address for a currency associated with this account
1689
+ * @see https://docs.kucoin.com/#get-deposit-addresses-v2
1690
+ * @param {string} code unified currency code
1691
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1692
+ * @param {string} [params.network] the blockchain network name
1693
+ * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
1694
+ */
1695
+ await this.loadMarkets();
1696
+ const currency = this.currency(code);
1697
+ const request = {
1698
+ 'currency': currency['id'],
1699
+ // for USDT - OMNI, ERC20, TRC20, default is ERC20
1700
+ // for BTC - Native, Segwit, TRC20, the parameters are bech32, btc, trx, default is Native
1701
+ // 'chain': 'ERC20', // optional
1702
+ };
1703
+ let networkCode = undefined;
1704
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
1705
+ if (networkCode !== undefined) {
1706
+ request['chain'] = this.networkCodeToId(networkCode).toLowerCase();
1707
+ }
1708
+ const version = this.options['versions']['private']['GET']['deposit-addresses'];
1709
+ this.options['versions']['private']['GET']['deposit-addresses'] = 'v1';
1710
+ const response = await this.privateGetDepositAddresses(this.extend(request, params));
1711
+ // BCH {"code":"200000","data":{"address":"bitcoincash:qza3m4nj9rx7l9r0cdadfqxts6f92shvhvr5ls4q7z","memo":""}}
1712
+ // BTC {"code":"200000","data":{"address":"36SjucKqQpQSvsak9A7h6qzFjrVXpRNZhE","memo":""}}
1713
+ this.options['versions']['private']['GET']['deposit-addresses'] = version;
1714
+ const data = this.safeValue(response, 'data');
1715
+ if (data === undefined) {
1716
+ throw new errors.ExchangeError(this.id + ' fetchDepositAddress() returned an empty response, you might try to run createDepositAddress() first and try again');
1717
+ }
1718
+ return this.parseDepositAddress(data, currency);
1719
+ }
1720
+ parseDepositAddress(depositAddress, currency = undefined) {
1721
+ let address = this.safeString(depositAddress, 'address');
1722
+ // BCH/BSV is returned with a "bitcoincash:" prefix, which we cut off here and only keep the address
1723
+ if (address !== undefined) {
1724
+ address = address.replace('bitcoincash:', '');
1725
+ }
1726
+ let code = undefined;
1727
+ if (currency !== undefined) {
1728
+ code = currency['id'];
1729
+ if (code !== 'NIM') {
1730
+ // contains spaces
1731
+ this.checkAddress(address);
1732
+ }
1733
+ }
1734
+ return {
1735
+ 'info': depositAddress,
1736
+ 'currency': code,
1737
+ 'address': address,
1738
+ 'tag': this.safeString(depositAddress, 'memo'),
1739
+ 'network': this.networkIdToCode(this.safeString(depositAddress, 'chain')),
1740
+ };
1741
+ }
1742
+ async fetchDepositAddressesByNetwork(code, params = {}) {
1743
+ /**
1744
+ * @method
1745
+ * @name kucoin#fetchDepositAddressesByNetwork
1746
+ * @see https://docs.kucoin.com/#get-deposit-addresses-v2
1747
+ * @description fetch the deposit address for a currency associated with this account
1748
+ * @param {string} code unified currency code
1749
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1750
+ * @returns {object} an array of [address structures]{@link https://docs.ccxt.com/#/?id=address-structure}
1751
+ */
1752
+ await this.loadMarkets();
1753
+ const currency = this.currency(code);
1754
+ const request = {
1755
+ 'currency': currency['id'],
1756
+ };
1757
+ const version = this.options['versions']['private']['GET']['deposit-addresses'];
1758
+ this.options['versions']['private']['GET']['deposit-addresses'] = 'v2';
1759
+ const response = await this.privateGetDepositAddresses(this.extend(request, params));
1760
+ //
1761
+ // {
1762
+ // "code": "200000",
1763
+ // "data": [
1764
+ // {
1765
+ // "address": "fr1qvus7d4d5fgxj5e7zvqe6yhxd7txm95h2and69r",
1766
+ // "memo": "",
1767
+ // "chain": "BTC-Segwit",
1768
+ // "contractAddress": ""
1769
+ // },
1770
+ // {"address":"37icNMEWbiF8ZkwUMxmfzMxi2A1MQ44bMn","memo":"","chain":"BTC","contractAddress":""},
1771
+ // {"address":"Deposit temporarily blocked","memo":"","chain":"TRC20","contractAddress":""}
1772
+ // ]
1773
+ // }
1774
+ //
1775
+ this.options['versions']['private']['GET']['deposit-addresses'] = version;
1776
+ const chains = this.safeValue(response, 'data', []);
1777
+ const parsed = this.parseDepositAddresses(chains, [currency['code']], false, {
1778
+ 'currency': currency['id'],
1779
+ });
1780
+ return this.indexBy(parsed, 'network');
1781
+ }
1782
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
1783
+ /**
1784
+ * @method
1785
+ * @name kucoin#fetchOrderBook
1786
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1787
+ * @see https://www.kucoin.com/docs/rest/spot-trading/market-data/get-part-order-book-aggregated-
1788
+ * @see https://www.kucoin.com/docs/rest/spot-trading/market-data/get-full-order-book-aggregated-
1789
+ * @param {string} symbol unified symbol of the market to fetch the order book for
1790
+ * @param {int} [limit] the maximum amount of order book entries to return
1791
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1792
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
1793
+ */
1794
+ await this.loadMarkets();
1795
+ const market = this.market(symbol);
1796
+ const level = this.safeInteger(params, 'level', 2);
1797
+ const request = { 'symbol': market['id'] };
1798
+ const isAuthenticated = this.checkRequiredCredentials(false);
1799
+ let response = undefined;
1800
+ if (!isAuthenticated || limit !== undefined) {
1801
+ if (level === 2) {
1802
+ request['level'] = level;
1803
+ if (limit !== undefined) {
1804
+ if ((limit === 20) || (limit === 100)) {
1805
+ request['limit'] = limit;
1806
+ }
1807
+ else {
1808
+ throw new errors.ExchangeError(this.id + ' fetchOrderBook() limit argument must be 20 or 100');
1809
+ }
1810
+ }
1811
+ request['limit'] = limit ? limit : 100;
1812
+ }
1813
+ response = await this.publicGetMarketOrderbookLevelLevelLimit(this.extend(request, params));
1814
+ }
1815
+ else {
1816
+ response = await this.privateGetMarketOrderbookLevel2(this.extend(request, params));
1817
+ }
1818
+ //
1819
+ // public (v1) market/orderbook/level2_20 and market/orderbook/level2_100
1820
+ //
1821
+ // {
1822
+ // "sequence": "3262786978",
1823
+ // "time": 1550653727731,
1824
+ // "bids": [
1825
+ // ["6500.12", "0.45054140"],
1826
+ // ["6500.11", "0.45054140"],
1827
+ // ],
1828
+ // "asks": [
1829
+ // ["6500.16", "0.57753524"],
1830
+ // ["6500.15", "0.57753524"],
1831
+ // ]
1832
+ // }
1833
+ //
1834
+ // private (v3) market/orderbook/level2
1835
+ //
1836
+ // {
1837
+ // "sequence": "3262786978",
1838
+ // "time": 1550653727731,
1839
+ // "bids": [
1840
+ // ["6500.12", "0.45054140"],
1841
+ // ["6500.11", "0.45054140"],
1842
+ // ],
1843
+ // "asks": [
1844
+ // ["6500.16", "0.57753524"],
1845
+ // ["6500.15", "0.57753524"],
1846
+ // ]
1847
+ // }
1848
+ //
1849
+ const data = this.safeValue(response, 'data', {});
1850
+ const timestamp = this.safeInteger(data, 'time');
1851
+ const orderbook = this.parseOrderBook(data, market['symbol'], timestamp, 'bids', 'asks', level - 2, level - 1);
1852
+ orderbook['nonce'] = this.safeInteger(data, 'sequence');
1853
+ return orderbook;
1854
+ }
1855
+ handleTriggerPrices(params) {
1856
+ const triggerPrice = this.safeValue2(params, 'triggerPrice', 'stopPrice');
1857
+ const stopLossPrice = this.safeValue(params, 'stopLossPrice');
1858
+ const takeProfitPrice = this.safeValue(params, 'takeProfitPrice');
1859
+ const isStopLoss = stopLossPrice !== undefined;
1860
+ const isTakeProfit = takeProfitPrice !== undefined;
1861
+ if ((isStopLoss && isTakeProfit) || (triggerPrice && stopLossPrice) || (triggerPrice && isTakeProfit)) {
1862
+ throw new errors.ExchangeError(this.id + ' createOrder() - you should use either triggerPrice or stopLossPrice or takeProfitPrice');
1863
+ }
1864
+ return [triggerPrice, stopLossPrice, takeProfitPrice];
1865
+ }
1866
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1867
+ /**
1868
+ * @method
1869
+ * @name kucoin#createOrder
1870
+ * @description Create an order on the exchange
1871
+ * @see https://docs.kucoin.com/spot#place-a-new-order
1872
+ * @see https://docs.kucoin.com/spot#place-a-new-order-2
1873
+ * @see https://docs.kucoin.com/spot#place-a-margin-order
1874
+ * @see https://docs.kucoin.com/spot-hf/#place-hf-order
1875
+ * @see https://www.kucoin.com/docs/rest/spot-trading/orders/place-order-test
1876
+ * @see https://www.kucoin.com/docs/rest/margin-trading/orders/place-margin-order-test
1877
+ * @param {string} symbol Unified CCXT market symbol
1878
+ * @param {string} type 'limit' or 'market'
1879
+ * @param {string} side 'buy' or 'sell'
1880
+ * @param {float} amount the amount of currency to trade
1881
+ * @param {float} [price] *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
1882
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1883
+ * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
1884
+ * @param {string} [params.marginMode] 'cross', // cross (cross mode) and isolated (isolated mode), set to cross by default, the isolated mode will be released soon, stay tuned
1885
+ * @param {string} [params.timeInForce] GTC, GTT, IOC, or FOK, default is GTC, limit orders only
1886
+ * @param {string} [params.postOnly] Post only flag, invalid when timeInForce is IOC or FOK
1887
+ *
1888
+ * EXCHANGE SPECIFIC PARAMETERS
1889
+ * @param {string} [params.clientOid] client order id, defaults to uuid if not passed
1890
+ * @param {string} [params.remark] remark for the order, length cannot exceed 100 utf8 characters
1891
+ * @param {string} [params.tradeType] 'TRADE', // TRADE, MARGIN_TRADE // not used with margin orders
1892
+ * limit orders ---------------------------------------------------
1893
+ * @param {float} [params.cancelAfter] long, // cancel after n seconds, requires timeInForce to be GTT
1894
+ * @param {bool} [params.hidden] false, // Order will not be displayed in the order book
1895
+ * @param {bool} [params.iceberg] false, // Only a portion of the order is displayed in the order book
1896
+ * @param {string} [params.visibleSize] this.amountToPrecision (symbol, visibleSize), // The maximum visible size of an iceberg order
1897
+ * market orders --------------------------------------------------
1898
+ * @param {string} [params.funds] // Amount of quote currency to use
1899
+ * stop orders ----------------------------------------------------
1900
+ * @param {string} [params.stop] Either loss or entry, the default is loss. Requires stopPrice to be defined
1901
+ * margin orders --------------------------------------------------
1902
+ * @param {float} [params.leverage] Leverage size of the order
1903
+ * @param {string} [params.stp] '', // self trade prevention, CN, CO, CB or DC
1904
+ * @param {bool} [params.autoBorrow] false, // The system will first borrow you funds at the optimal interest rate and then place an order for you
1905
+ * @param {bool} [params.hf] false, // true for hf order
1906
+ * @param {bool} [params.test] set to true to test an order, no order will be created but the request will be validated
1907
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1908
+ */
1909
+ await this.loadMarkets();
1910
+ const market = this.market(symbol);
1911
+ const testOrder = this.safeValue(params, 'test', false);
1912
+ params = this.omit(params, 'test');
1913
+ const isHf = this.safeValue(params, 'hf', false);
1914
+ const [triggerPrice, stopLossPrice, takeProfitPrice] = this.handleTriggerPrices(params);
1915
+ const tradeType = this.safeString(params, 'tradeType'); // keep it for backward compatibility
1916
+ const isTriggerOrder = (triggerPrice || stopLossPrice || takeProfitPrice);
1917
+ const marginResult = this.handleMarginModeAndParams('createOrder', params);
1918
+ const marginMode = this.safeString(marginResult, 0);
1919
+ const isMarginOrder = tradeType === 'MARGIN_TRADE' || marginMode !== undefined;
1920
+ // don't omit anything before calling createOrderRequest
1921
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
1922
+ let response = undefined;
1923
+ if (testOrder) {
1924
+ if (isMarginOrder) {
1925
+ response = await this.privatePostMarginOrderTest(orderRequest);
1926
+ }
1927
+ else {
1928
+ response = await this.privatePostOrdersTest(orderRequest);
1929
+ }
1930
+ }
1931
+ else if (isHf) {
1932
+ response = await this.privatePostHfOrders(orderRequest);
1933
+ }
1934
+ else if (isTriggerOrder) {
1935
+ response = await this.privatePostStopOrder(orderRequest);
1936
+ }
1937
+ else if (isMarginOrder) {
1938
+ response = await this.privatePostMarginOrder(orderRequest);
1939
+ }
1940
+ else {
1941
+ response = await this.privatePostOrders(orderRequest);
1942
+ }
1943
+ //
1944
+ // {
1945
+ // "code": "200000",
1946
+ // "data": {
1947
+ // "orderId": "5bd6e9286d99522a52e458de"
1948
+ // }
1949
+ // }
1950
+ //
1951
+ const data = this.safeValue(response, 'data', {});
1952
+ return this.parseOrder(data, market);
1953
+ }
1954
+ async createMarketOrderWithCost(symbol, side, cost, params = {}) {
1955
+ /**
1956
+ * @method
1957
+ * @name kucoin#createMarketOrderWithCost
1958
+ * @description create a market order by providing the symbol, side and cost
1959
+ * @see https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
1960
+ * @param {string} symbol unified symbol of the market to create an order in
1961
+ * @param {string} side 'buy' or 'sell'
1962
+ * @param {float} cost how much you want to trade in units of the quote currency
1963
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1964
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1965
+ */
1966
+ await this.loadMarkets();
1967
+ params['cost'] = cost;
1968
+ return await this.createOrder(symbol, 'market', side, cost, undefined, params);
1969
+ }
1970
+ async createMarketBuyOrderWithCost(symbol, cost, params = {}) {
1971
+ /**
1972
+ * @method
1973
+ * @name kucoin#createMarketBuyOrderWithCost
1974
+ * @description create a market buy order by providing the symbol and cost
1975
+ * @see https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
1976
+ * @param {string} symbol unified symbol of the market to create an order in
1977
+ * @param {float} cost how much you want to trade in units of the quote currency
1978
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1979
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1980
+ */
1981
+ await this.loadMarkets();
1982
+ return await this.createMarketOrderWithCost(symbol, 'buy', cost, params);
1983
+ }
1984
+ async createMarketSellOrderWithCost(symbol, cost, params = {}) {
1985
+ /**
1986
+ * @method
1987
+ * @name kucoin#createMarketSellOrderWithCost
1988
+ * @description create a market sell order by providing the symbol and cost
1989
+ * @see https://www.kucoin.com/docs/rest/spot-trading/orders/place-order
1990
+ * @param {string} symbol unified symbol of the market to create an order in
1991
+ * @param {float} cost how much you want to trade in units of the quote currency
1992
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1993
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1994
+ */
1995
+ await this.loadMarkets();
1996
+ return await this.createMarketOrderWithCost(symbol, 'sell', cost, params);
1997
+ }
1998
+ async createOrders(orders, params = {}) {
1999
+ /**
2000
+ * @method
2001
+ * @name kucoin#createOrders
2002
+ * @description create a list of trade orders
2003
+ * @see https://www.kucoin.com/docs/rest/spot-trading/orders/place-multiple-orders
2004
+ * @see https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/place-multiple-hf-orders
2005
+ * @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
2006
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2007
+ * @param {bool} [params.hf] false, // true for hf orders
2008
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2009
+ */
2010
+ await this.loadMarkets();
2011
+ const ordersRequests = [];
2012
+ let symbol = undefined;
2013
+ for (let i = 0; i < orders.length; i++) {
2014
+ const rawOrder = orders[i];
2015
+ const marketId = this.safeString(rawOrder, 'symbol');
2016
+ if (symbol === undefined) {
2017
+ symbol = marketId;
2018
+ }
2019
+ else {
2020
+ if (symbol !== marketId) {
2021
+ throw new errors.BadRequest(this.id + ' createOrders() requires all orders to have the same symbol');
2022
+ }
2023
+ }
2024
+ const type = this.safeString(rawOrder, 'type');
2025
+ if (type !== 'limit') {
2026
+ throw new errors.BadRequest(this.id + ' createOrders() only supports limit orders');
2027
+ }
2028
+ const side = this.safeString(rawOrder, 'side');
2029
+ const amount = this.safeValue(rawOrder, 'amount');
2030
+ const price = this.safeValue(rawOrder, 'price');
2031
+ const orderParams = this.safeValue(rawOrder, 'params', {});
2032
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
2033
+ ordersRequests.push(orderRequest);
2034
+ }
2035
+ const market = this.market(symbol);
2036
+ const request = {
2037
+ 'symbol': market['id'],
2038
+ 'orderList': ordersRequests,
2039
+ };
2040
+ const hf = this.safeValue(params, 'hf', false);
2041
+ params = this.omit(params, 'hf');
2042
+ let response = undefined;
2043
+ if (hf) {
2044
+ response = await this.privatePostHfOrdersMulti(this.extend(request, params));
2045
+ }
2046
+ else {
2047
+ response = await this.privatePostOrdersMulti(this.extend(request, params));
2048
+ }
2049
+ //
2050
+ // {
2051
+ // "code": "200000",
2052
+ // "data": {
2053
+ // "data": [
2054
+ // {
2055
+ // "symbol": "LTC-USDT",
2056
+ // "type": "limit",
2057
+ // "side": "sell",
2058
+ // "price": "90",
2059
+ // "size": "0.1",
2060
+ // "funds": null,
2061
+ // "stp": "",
2062
+ // "stop": "",
2063
+ // "stopPrice": null,
2064
+ // "timeInForce": "GTC",
2065
+ // "cancelAfter": 0,
2066
+ // "postOnly": false,
2067
+ // "hidden": false,
2068
+ // "iceberge": false,
2069
+ // "iceberg": false,
2070
+ // "visibleSize": null,
2071
+ // "channel": "API",
2072
+ // "id": "6539148443fcf500079d15e5",
2073
+ // "status": "success",
2074
+ // "failMsg": null,
2075
+ // "clientOid": "5c4c5398-8ab2-4b4e-af8a-e2d90ad2488f"
2076
+ // },
2077
+ // }
2078
+ //
2079
+ let data = this.safeValue(response, 'data', {});
2080
+ data = this.safeValue(data, 'data', []);
2081
+ return this.parseOrders(data);
2082
+ }
2083
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
2084
+ const market = this.market(symbol);
2085
+ // required param, cannot be used twice
2086
+ const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId', this.uuid());
2087
+ params = this.omit(params, ['clientOid', 'clientOrderId']);
2088
+ const request = {
2089
+ 'clientOid': clientOrderId,
2090
+ 'side': side,
2091
+ 'symbol': market['id'],
2092
+ 'type': type, // limit or market
2093
+ };
2094
+ const quoteAmount = this.safeNumber2(params, 'cost', 'funds');
2095
+ let amountString = undefined;
2096
+ let costString = undefined;
2097
+ let marginMode = undefined;
2098
+ [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
2099
+ if (type === 'market') {
2100
+ if (quoteAmount !== undefined) {
2101
+ params = this.omit(params, ['cost', 'funds']);
2102
+ // kucoin uses base precision even for quote values
2103
+ costString = this.amountToPrecision(symbol, quoteAmount);
2104
+ request['funds'] = costString;
2105
+ }
2106
+ else {
2107
+ amountString = this.amountToPrecision(symbol, amount);
2108
+ request['size'] = this.amountToPrecision(symbol, amount);
2109
+ }
2110
+ }
2111
+ else {
2112
+ amountString = this.amountToPrecision(symbol, amount);
2113
+ request['size'] = amountString;
2114
+ request['price'] = this.priceToPrecision(symbol, price);
2115
+ }
2116
+ const tradeType = this.safeString(params, 'tradeType'); // keep it for backward compatibility
2117
+ const [triggerPrice, stopLossPrice, takeProfitPrice] = this.handleTriggerPrices(params);
2118
+ const isTriggerOrder = (triggerPrice || stopLossPrice || takeProfitPrice);
2119
+ const isMarginOrder = tradeType === 'MARGIN_TRADE' || marginMode !== undefined;
2120
+ params = this.omit(params, ['stopLossPrice', 'takeProfitPrice', 'triggerPrice', 'stopPrice']);
2121
+ if (isTriggerOrder) {
2122
+ if (triggerPrice) {
2123
+ request['stopPrice'] = this.priceToPrecision(symbol, triggerPrice);
2124
+ }
2125
+ else if (stopLossPrice || takeProfitPrice) {
2126
+ if (stopLossPrice) {
2127
+ request['stop'] = (side === 'buy') ? 'entry' : 'loss';
2128
+ request['stopPrice'] = this.priceToPrecision(symbol, stopLossPrice);
2129
+ }
2130
+ else {
2131
+ request['stop'] = (side === 'buy') ? 'loss' : 'entry';
2132
+ request['stopPrice'] = this.priceToPrecision(symbol, takeProfitPrice);
2133
+ }
2134
+ }
2135
+ if (marginMode === 'isolated') {
2136
+ throw new errors.BadRequest(this.id + ' createOrder does not support isolated margin for stop orders');
2137
+ }
2138
+ else if (marginMode === 'cross') {
2139
+ request['tradeType'] = this.options['marginModes'][marginMode];
2140
+ }
2141
+ }
2142
+ else if (isMarginOrder) {
2143
+ if (marginMode === 'isolated') {
2144
+ request['marginModel'] = 'isolated';
2145
+ }
2146
+ }
2147
+ let postOnly = undefined;
2148
+ [postOnly, params] = this.handlePostOnly(type === 'market', false, params);
2149
+ if (postOnly) {
2150
+ request['postOnly'] = true;
2151
+ }
2152
+ return this.extend(request, params);
2153
+ }
2154
+ async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
2155
+ /**
2156
+ * @method
2157
+ * @name kucoin#editOrder
2158
+ * @description edit an order, kucoin currently only supports the modification of HF orders
2159
+ * @see https://docs.kucoin.com/spot-hf/#modify-order
2160
+ * @param {string} id order id
2161
+ * @param {string} symbol unified symbol of the market to create an order in
2162
+ * @param {string} type not used
2163
+ * @param {string} side not used
2164
+ * @param {float} amount how much of the currency you want to trade in units of the base currency
2165
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
2166
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2167
+ * @param {string} [params.clientOrderId] client order id, defaults to id if not passed
2168
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2169
+ */
2170
+ await this.loadMarkets();
2171
+ const market = this.market(symbol);
2172
+ const request = {
2173
+ 'symbol': market['id'],
2174
+ };
2175
+ const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId');
2176
+ if (clientOrderId !== undefined) {
2177
+ request['clientOid'] = clientOrderId;
2178
+ }
2179
+ else {
2180
+ request['orderId'] = id;
2181
+ }
2182
+ if (amount !== undefined) {
2183
+ request['newSize'] = this.amountToPrecision(symbol, amount);
2184
+ }
2185
+ if (price !== undefined) {
2186
+ request['newPrice'] = this.priceToPrecision(symbol, price);
2187
+ }
2188
+ const response = await this.privatePostHfOrdersAlter(this.extend(request, params));
2189
+ //
2190
+ // {
2191
+ // "code":"200000",
2192
+ // "data":{
2193
+ // "newOrderId":"6478d7a6c883280001e92d8b"
2194
+ // }
2195
+ // }
2196
+ //
2197
+ const data = this.safeValue(response, 'data', {});
2198
+ return this.parseOrder(data, market);
2199
+ }
2200
+ async cancelOrder(id, symbol = undefined, params = {}) {
2201
+ /**
2202
+ * @method
2203
+ * @name kucoin#cancelOrder
2204
+ * @description cancels an open order
2205
+ * @see https://docs.kucoin.com/spot#cancel-an-order
2206
+ * @see https://docs.kucoin.com/spot#cancel-an-order-2
2207
+ * @see https://docs.kucoin.com/spot#cancel-single-order-by-clientoid
2208
+ * @see https://docs.kucoin.com/spot#cancel-single-order-by-clientoid-2
2209
+ * @see https://docs.kucoin.com/spot-hf/#cancel-orders-by-orderid
2210
+ * @see https://docs.kucoin.com/spot-hf/#cancel-order-by-clientoid
2211
+ * @param {string} id order id
2212
+ * @param {string} symbol unified symbol of the market the order was made in
2213
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2214
+ * @param {bool} [params.stop] True if cancelling a stop order
2215
+ * @param {bool} [params.hf] false, // true for hf order
2216
+ * @returns Response from the exchange
2217
+ */
2218
+ await this.loadMarkets();
2219
+ const request = {};
2220
+ const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId');
2221
+ const stop = this.safeValue2(params, 'stop', 'trigger', false);
2222
+ const hf = this.safeValue(params, 'hf', false);
2223
+ if (hf) {
2224
+ if (symbol === undefined) {
2225
+ throw new errors.ArgumentsRequired(this.id + ' cancelOrder() requires a symbol parameter for hf orders');
2226
+ }
2227
+ const market = this.market(symbol);
2228
+ request['symbol'] = market['id'];
2229
+ }
2230
+ let response = undefined;
2231
+ params = this.omit(params, ['clientOid', 'clientOrderId', 'stop', 'hf', 'trigger']);
2232
+ if (clientOrderId !== undefined) {
2233
+ request['clientOid'] = clientOrderId;
2234
+ if (stop) {
2235
+ response = await this.privateDeleteStopOrderCancelOrderByClientOid(this.extend(request, params));
2236
+ }
2237
+ else if (hf) {
2238
+ response = await this.privateDeleteHfOrdersClientOrderClientOid(this.extend(request, params));
2239
+ }
2240
+ else {
2241
+ response = await this.privateDeleteOrderClientOrderClientOid(this.extend(request, params));
2242
+ }
2243
+ }
2244
+ else {
2245
+ request['orderId'] = id;
2246
+ if (stop) {
2247
+ response = await this.privateDeleteStopOrderOrderId(this.extend(request, params));
2248
+ }
2249
+ else if (hf) {
2250
+ response = await this.privateDeleteHfOrdersOrderId(this.extend(request, params));
2251
+ }
2252
+ else {
2253
+ response = await this.privateDeleteOrdersOrderId(this.extend(request, params));
2254
+ }
2255
+ }
2256
+ return response;
2257
+ }
2258
+ async cancelAllOrders(symbol = undefined, params = {}) {
2259
+ /**
2260
+ * @method
2261
+ * @name kucoin#cancelAllOrders
2262
+ * @description cancel all open orders
2263
+ * @see https://docs.kucoin.com/spot#cancel-all-orders
2264
+ * @see https://docs.kucoin.com/spot#cancel-orders
2265
+ * @see https://docs.kucoin.com/spot-hf/#cancel-all-hf-orders-by-symbol
2266
+ * @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
2267
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2268
+ * @param {bool} [params.stop] *invalid for isolated margin* true if cancelling all stop orders
2269
+ * @param {string} [params.marginMode] 'cross' or 'isolated'
2270
+ * @param {string} [params.orderIds] *stop orders only* Comma seperated order IDs
2271
+ * @param {bool} [params.stop] True if cancelling a stop order
2272
+ * @param {bool} [params.hf] false, // true for hf order
2273
+ * @returns Response from the exchange
2274
+ */
2275
+ await this.loadMarkets();
2276
+ const request = {};
2277
+ const stop = this.safeValue(params, 'stop', false);
2278
+ const hf = this.safeValue(params, 'hf', false);
2279
+ params = this.omit(params, ['stop', 'hf']);
2280
+ const [marginMode, query] = this.handleMarginModeAndParams('cancelAllOrders', params);
2281
+ if (symbol !== undefined) {
2282
+ request['symbol'] = this.marketId(symbol);
2283
+ }
2284
+ if (marginMode !== undefined) {
2285
+ request['tradeType'] = this.options['marginModes'][marginMode];
2286
+ if (marginMode === 'isolated' && stop) {
2287
+ throw new errors.BadRequest(this.id + ' cancelAllOrders does not support isolated margin for stop orders');
2288
+ }
2289
+ }
2290
+ let response = undefined;
2291
+ if (stop) {
2292
+ response = await this.privateDeleteStopOrderCancel(this.extend(request, query));
2293
+ }
2294
+ else if (hf) {
2295
+ if (symbol === undefined) {
2296
+ response = await this.privateDeleteHfOrdersCancelAll(this.extend(request, query));
2297
+ }
2298
+ else {
2299
+ response = await this.privateDeleteHfOrders(this.extend(request, query));
2300
+ }
2301
+ }
2302
+ else {
2303
+ response = await this.privateDeleteOrders(this.extend(request, query));
2304
+ }
2305
+ return response;
2306
+ }
2307
+ async fetchOrdersByStatus(status, symbol = undefined, since = undefined, limit = undefined, params = {}) {
2308
+ /**
2309
+ * @method
2310
+ * @name kucoin#fetchOrdersByStatus
2311
+ * @description fetch a list of orders
2312
+ * @see https://docs.kucoin.com/spot#list-orders
2313
+ * @see https://docs.kucoin.com/spot#list-stop-orders
2314
+ * @see https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2315
+ * @see https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2316
+ * @param {string} status *not used for stop orders* 'open' or 'closed'
2317
+ * @param {string} symbol unified market symbol
2318
+ * @param {int} [since] timestamp in ms of the earliest order
2319
+ * @param {int} [limit] max number of orders to return
2320
+ * @param {object} [params] exchange specific params
2321
+ * @param {int} [params.until] end time in ms
2322
+ * @param {bool} [params.stop] true if fetching stop orders
2323
+ * @param {string} [params.side] buy or sell
2324
+ * @param {string} [params.type] limit, market, limit_stop or market_stop
2325
+ * @param {string} [params.tradeType] TRADE for spot trading, MARGIN_TRADE for Margin Trading
2326
+ * @param {int} [params.currentPage] *stop orders only* current page
2327
+ * @param {string} [params.orderIds] *stop orders only* comma seperated order ID list
2328
+ * @param {bool} [params.stop] True if fetching a stop order
2329
+ * @param {bool} [params.hf] false, // true for hf order
2330
+ * @returns An [array of order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2331
+ */
2332
+ await this.loadMarkets();
2333
+ let lowercaseStatus = status.toLowerCase();
2334
+ const until = this.safeInteger2(params, 'until', 'till');
2335
+ const stop = this.safeValue(params, 'stop', false);
2336
+ const hf = this.safeValue(params, 'hf', false);
2337
+ params = this.omit(params, ['stop', 'hf', 'till', 'until']);
2338
+ const [marginMode, query] = this.handleMarginModeAndParams('fetchOrdersByStatus', params);
2339
+ if (lowercaseStatus === 'open') {
2340
+ lowercaseStatus = 'active';
2341
+ }
2342
+ else if (lowercaseStatus === 'closed') {
2343
+ lowercaseStatus = 'done';
2344
+ }
2345
+ const request = {
2346
+ 'status': lowercaseStatus,
2347
+ };
2348
+ let market = undefined;
2349
+ if (symbol !== undefined) {
2350
+ market = this.market(symbol);
2351
+ request['symbol'] = market['id'];
2352
+ }
2353
+ if (since !== undefined) {
2354
+ request['startAt'] = since;
2355
+ }
2356
+ if (limit !== undefined) {
2357
+ request['pageSize'] = limit;
2358
+ }
2359
+ if (until) {
2360
+ request['endAt'] = until;
2361
+ }
2362
+ request['tradeType'] = this.safeString(this.options['marginModes'], marginMode, 'TRADE');
2363
+ let response = undefined;
2364
+ if (stop) {
2365
+ response = await this.privateGetStopOrder(this.extend(request, query));
2366
+ }
2367
+ else if (hf) {
2368
+ if (lowercaseStatus === 'active') {
2369
+ response = await this.privateGetHfOrdersActive(this.extend(request, query));
2370
+ }
2371
+ else if (lowercaseStatus === 'done') {
2372
+ response = await this.privateGetHfOrdersDone(this.extend(request, query));
2373
+ }
2374
+ }
2375
+ else {
2376
+ response = await this.privateGetOrders(this.extend(request, query));
2377
+ }
2378
+ //
2379
+ // {
2380
+ // "code": "200000",
2381
+ // "data": {
2382
+ // "currentPage": 1,
2383
+ // "pageSize": 1,
2384
+ // "totalNum": 153408,
2385
+ // "totalPage": 153408,
2386
+ // "items": [
2387
+ // {
2388
+ // "id": "5c35c02703aa673ceec2a168", //orderid
2389
+ // "symbol": "BTC-USDT", //symbol
2390
+ // "opType": "DEAL", // operation type,deal is pending order,cancel is cancel order
2391
+ // "type": "limit", // order type,e.g. limit,markrt,stop_limit.
2392
+ // "side": "buy", // transaction direction,include buy and sell
2393
+ // "price": "10", // order price
2394
+ // "size": "2", // order quantity
2395
+ // "funds": "0", // order funds
2396
+ // "dealFunds": "0.166", // deal funds
2397
+ // "dealSize": "2", // deal quantity
2398
+ // "fee": "0", // fee
2399
+ // "feeCurrency": "USDT", // charge fee currency
2400
+ // "stp": "", // self trade prevention,include CN,CO,DC,CB
2401
+ // "stop": "", // stop type
2402
+ // "stopTriggered": false, // stop order is triggered
2403
+ // "stopPrice": "0", // stop price
2404
+ // "timeInForce": "GTC", // time InForce,include GTC,GTT,IOC,FOK
2405
+ // "postOnly": false, // postOnly
2406
+ // "hidden": false, // hidden order
2407
+ // "iceberg": false, // iceberg order
2408
+ // "visibleSize": "0", // display quantity for iceberg order
2409
+ // "cancelAfter": 0, // cancel orders time,requires timeInForce to be GTT
2410
+ // "channel": "IOS", // order source
2411
+ // "clientOid": "", // user-entered order unique mark
2412
+ // "remark": "", // remark
2413
+ // "tags": "", // tag order source
2414
+ // "isActive": false, // status before unfilled or uncancelled
2415
+ // "cancelExist": false, // order cancellation transaction record
2416
+ // "createdAt": 1547026471000 // time
2417
+ // },
2418
+ // ]
2419
+ // }
2420
+ // }
2421
+ const responseData = this.safeValue(response, 'data', {});
2422
+ const orders = this.safeValue(responseData, 'items', responseData);
2423
+ return this.parseOrders(orders, market, since, limit);
2424
+ }
2425
+ async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2426
+ /**
2427
+ * @method
2428
+ * @name kucoin#fetchClosedOrders
2429
+ * @description fetches information on multiple closed orders made by the user
2430
+ * @see https://docs.kucoin.com/spot#list-orders
2431
+ * @see https://docs.kucoin.com/spot#list-stop-orders
2432
+ * @see https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2433
+ * @see https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2434
+ * @param {string} symbol unified market symbol of the market orders were made in
2435
+ * @param {int} [since] the earliest time in ms to fetch orders for
2436
+ * @param {int} [limit] the maximum number of order structures to retrieve
2437
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2438
+ * @param {int} [params.till] end time in ms
2439
+ * @param {string} [params.side] buy or sell
2440
+ * @param {string} [params.type] limit, market, limit_stop or market_stop
2441
+ * @param {string} [params.tradeType] TRADE for spot trading, MARGIN_TRADE for Margin Trading
2442
+ * @param {bool} [params.stop] True if fetching a stop order
2443
+ * @param {bool} [params.hf] false, // true for hf order
2444
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2445
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2446
+ */
2447
+ await this.loadMarkets();
2448
+ let paginate = false;
2449
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchClosedOrders', 'paginate');
2450
+ if (paginate) {
2451
+ return await this.fetchPaginatedCallDynamic('fetchClosedOrders', symbol, since, limit, params);
2452
+ }
2453
+ return await this.fetchOrdersByStatus('done', symbol, since, limit, params);
2454
+ }
2455
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2456
+ /**
2457
+ * @method
2458
+ * @name kucoin#fetchOpenOrders
2459
+ * @description fetch all unfilled currently open orders
2460
+ * @see https://docs.kucoin.com/spot#list-orders
2461
+ * @see https://docs.kucoin.com/spot#list-stop-orders
2462
+ * @see https://docs.kucoin.com/spot-hf/#obtain-list-of-active-hf-orders
2463
+ * @see https://docs.kucoin.com/spot-hf/#obtain-list-of-filled-hf-orders
2464
+ * @param {string} symbol unified market symbol
2465
+ * @param {int} [since] the earliest time in ms to fetch open orders for
2466
+ * @param {int} [limit] the maximum number of open orders structures to retrieve
2467
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2468
+ * @param {int} [params.till] end time in ms
2469
+ * @param {bool} [params.stop] true if fetching stop orders
2470
+ * @param {string} [params.side] buy or sell
2471
+ * @param {string} [params.type] limit, market, limit_stop or market_stop
2472
+ * @param {string} [params.tradeType] TRADE for spot trading, MARGIN_TRADE for Margin Trading
2473
+ * @param {int} [params.currentPage] *stop orders only* current page
2474
+ * @param {string} [params.orderIds] *stop orders only* comma seperated order ID list
2475
+ * @param {bool} [params.stop] True if fetching a stop order
2476
+ * @param {bool} [params.hf] false, // true for hf order
2477
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2478
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2479
+ */
2480
+ await this.loadMarkets();
2481
+ let paginate = false;
2482
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchOpenOrders', 'paginate');
2483
+ if (paginate) {
2484
+ return await this.fetchPaginatedCallDynamic('fetchOpenOrders', symbol, since, limit, params);
2485
+ }
2486
+ return await this.fetchOrdersByStatus('active', symbol, since, limit, params);
2487
+ }
2488
+ async fetchOrder(id, symbol = undefined, params = {}) {
2489
+ /**
2490
+ * @method
2491
+ * @name kucoin#fetchOrder
2492
+ * @description fetch an order
2493
+ * @see https://docs.kucoin.com/spot#get-an-order
2494
+ * @see https://docs.kucoin.com/spot#get-single-active-order-by-clientoid
2495
+ * @see https://docs.kucoin.com/spot#get-single-order-info
2496
+ * @see https://docs.kucoin.com/spot#get-single-order-by-clientoid
2497
+ * @see https://docs.kucoin.com/spot-hf/#details-of-a-single-hf-order
2498
+ * @see https://docs.kucoin.com/spot-hf/#obtain-details-of-a-single-hf-order-using-clientoid
2499
+ * @param {string} id Order id
2500
+ * @param {string} symbol not sent to exchange except for stop orders with clientOid, but used internally by CCXT to filter
2501
+ * @param {object} [params] exchange specific parameters
2502
+ * @param {bool} [params.stop] true if fetching a stop order
2503
+ * @param {bool} [params.hf] false, // true for hf order
2504
+ * @param {bool} [params.clientOid] unique order id created by users to identify their orders
2505
+ * @returns An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2506
+ */
2507
+ await this.loadMarkets();
2508
+ const request = {};
2509
+ const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId');
2510
+ const stop = this.safeValue(params, 'stop', false);
2511
+ const hf = this.safeValue(params, 'hf', false);
2512
+ let market = undefined;
2513
+ if (symbol !== undefined) {
2514
+ market = this.market(symbol);
2515
+ }
2516
+ if (hf) {
2517
+ if (symbol === undefined) {
2518
+ throw new errors.ArgumentsRequired(this.id + ' fetchOrder() requires a symbol parameter for hf orders');
2519
+ }
2520
+ request['symbol'] = market['id'];
2521
+ }
2522
+ params = this.omit(params, ['stop', 'hf', 'clientOid', 'clientOrderId']);
2523
+ let response = undefined;
2524
+ if (clientOrderId !== undefined) {
2525
+ request['clientOid'] = clientOrderId;
2526
+ if (stop) {
2527
+ if (symbol !== undefined) {
2528
+ request['symbol'] = market['id'];
2529
+ }
2530
+ response = await this.privateGetStopOrderQueryOrderByClientOid(this.extend(request, params));
2531
+ }
2532
+ else if (hf) {
2533
+ response = await this.privateGetHfOrdersClientOrderClientOid(this.extend(request, params));
2534
+ }
2535
+ else {
2536
+ response = await this.privateGetOrderClientOrderClientOid(this.extend(request, params));
2537
+ }
2538
+ }
2539
+ else {
2540
+ // a special case for undefined ids
2541
+ // otherwise a wrong endpoint for all orders will be triggered
2542
+ // https://github.com/ccxt/ccxt/issues/7234
2543
+ if (id === undefined) {
2544
+ throw new errors.InvalidOrder(this.id + ' fetchOrder() requires an order id');
2545
+ }
2546
+ request['orderId'] = id;
2547
+ if (stop) {
2548
+ response = await this.privateGetStopOrderOrderId(this.extend(request, params));
2549
+ }
2550
+ else if (hf) {
2551
+ response = await this.privateGetHfOrdersOrderId(this.extend(request, params));
2552
+ }
2553
+ else {
2554
+ response = await this.privateGetOrdersOrderId(this.extend(request, params));
2555
+ }
2556
+ }
2557
+ let responseData = this.safeValue(response, 'data', {});
2558
+ if (Array.isArray(responseData)) {
2559
+ responseData = this.safeValue(responseData, 0);
2560
+ }
2561
+ return this.parseOrder(responseData, market);
2562
+ }
2563
+ parseOrder(order, market = undefined) {
2564
+ //
2565
+ // createOrder
2566
+ //
2567
+ // {
2568
+ // "orderId": "63c97e47d686c5000159a656"
2569
+ // }
2570
+ //
2571
+ // cancelOrder
2572
+ //
2573
+ // {
2574
+ // "cancelledOrderIds": [ "63c97e47d686c5000159a656" ]
2575
+ // }
2576
+ //
2577
+ // fetchOpenOrders, fetchClosedOrders
2578
+ //
2579
+ // {
2580
+ // "id": "63c97ce8d686c500015793bb",
2581
+ // "symbol": "USDC-USDT",
2582
+ // "opType": "DEAL",
2583
+ // "type": "limit",
2584
+ // "side": "sell",
2585
+ // "price": "1.05",
2586
+ // "size": "1",
2587
+ // "funds": "0",
2588
+ // "dealFunds": "0",
2589
+ // "dealSize": "0",
2590
+ // "fee": "0",
2591
+ // "feeCurrency": "USDT",
2592
+ // "stp": "",
2593
+ // "stop": "",
2594
+ // "stopTriggered": false,
2595
+ // "stopPrice": "0",
2596
+ // "timeInForce": "GTC",
2597
+ // "postOnly": false,
2598
+ // "hidden": false,
2599
+ // "iceberg": false,
2600
+ // "visibleSize": "0",
2601
+ // "cancelAfter": 0,
2602
+ // "channel": "API",
2603
+ // "clientOid": "d602d73f-5424-4751-bef0-8debce8f0a82",
2604
+ // "remark": null,
2605
+ // "tags": "partner:ccxt",
2606
+ // "isActive": true,
2607
+ // "cancelExist": false,
2608
+ // "createdAt": 1674149096927,
2609
+ // "tradeType": "TRADE"
2610
+ // }
2611
+ //
2612
+ // stop orders (fetchOpenOrders, fetchClosedOrders)
2613
+ //
2614
+ // {
2615
+ // "id": "vs9f6ou9e864rgq8000t4qnm",
2616
+ // "symbol": "USDC-USDT",
2617
+ // "userId": "613a896885d8660006151f01",
2618
+ // "status": "NEW",
2619
+ // "type": "market",
2620
+ // "side": "sell",
2621
+ // "price": null,
2622
+ // "size": "1.00000000000000000000",
2623
+ // "funds": null,
2624
+ // "stp": null,
2625
+ // "timeInForce": "GTC",
2626
+ // "cancelAfter": -1,
2627
+ // "postOnly": false,
2628
+ // "hidden": false,
2629
+ // "iceberg": false,
2630
+ // "visibleSize": null,
2631
+ // "channel": "API",
2632
+ // "clientOid": "5d3fd727-6456-438d-9550-40d9d85eee0b",
2633
+ // "remark": null,
2634
+ // "tags": "partner:ccxt",
2635
+ // "relatedNo": null,
2636
+ // "orderTime": 1674146316994000028,
2637
+ // "domainId": "kucoin",
2638
+ // "tradeSource": "USER",
2639
+ // "tradeType": "MARGIN_TRADE",
2640
+ // "feeCurrency": "USDT",
2641
+ // "takerFeeRate": "0.00100000000000000000",
2642
+ // "makerFeeRate": "0.00100000000000000000",
2643
+ // "createdAt": 1674146316994,
2644
+ // "stop": "loss",
2645
+ // "stopTriggerTime": null,
2646
+ // "stopPrice": "0.97000000000000000000"
2647
+ // }
2648
+ // hf order
2649
+ // {
2650
+ // "id":"6478cf1439bdfc0001528a1d",
2651
+ // "symbol":"LTC-USDT",
2652
+ // "opType":"DEAL",
2653
+ // "type":"limit",
2654
+ // "side":"buy",
2655
+ // "price":"50",
2656
+ // "size":"0.1",
2657
+ // "funds":"5",
2658
+ // "dealSize":"0",
2659
+ // "dealFunds":"0",
2660
+ // "fee":"0",
2661
+ // "feeCurrency":"USDT",
2662
+ // "stp":null,
2663
+ // "timeInForce":"GTC",
2664
+ // "postOnly":false,
2665
+ // "hidden":false,
2666
+ // "iceberg":false,
2667
+ // "visibleSize":"0",
2668
+ // "cancelAfter":0,
2669
+ // "channel":"API",
2670
+ // "clientOid":"d4d2016b-8e3a-445c-aa5d-dc6df5d1678d",
2671
+ // "remark":null,
2672
+ // "tags":"partner:ccxt",
2673
+ // "cancelExist":false,
2674
+ // "createdAt":1685638932074,
2675
+ // "lastUpdatedAt":1685639013735,
2676
+ // "tradeType":"TRADE",
2677
+ // "inOrderBook":true,
2678
+ // "cancelledSize":"0",
2679
+ // "cancelledFunds":"0",
2680
+ // "remainSize":"0.1",
2681
+ // "remainFunds":"5",
2682
+ // "active":true
2683
+ // }
2684
+ //
2685
+ const marketId = this.safeString(order, 'symbol');
2686
+ const timestamp = this.safeInteger(order, 'createdAt');
2687
+ const feeCurrencyId = this.safeString(order, 'feeCurrency');
2688
+ const cancelExist = this.safeValue(order, 'cancelExist', false);
2689
+ const responseStop = this.safeString(order, 'stop');
2690
+ const stop = responseStop !== undefined;
2691
+ const stopTriggered = this.safeValue(order, 'stopTriggered', false);
2692
+ const isActive = this.safeValue2(order, 'isActive', 'active');
2693
+ const responseStatus = this.safeString(order, 'status');
2694
+ let status = undefined;
2695
+ if (isActive !== undefined) {
2696
+ if (isActive === true) {
2697
+ status = 'open';
2698
+ }
2699
+ else {
2700
+ status = 'closed';
2701
+ }
2702
+ }
2703
+ if (stop) {
2704
+ if (responseStatus === 'NEW') {
2705
+ status = 'open';
2706
+ }
2707
+ else if (!isActive && !stopTriggered) {
2708
+ status = 'cancelled';
2709
+ }
2710
+ }
2711
+ if (cancelExist) {
2712
+ status = 'canceled';
2713
+ }
2714
+ if (responseStatus === 'fail') {
2715
+ status = 'rejected';
2716
+ }
2717
+ const stopPrice = this.safeNumber(order, 'stopPrice');
2718
+ return this.safeOrder({
2719
+ 'info': order,
2720
+ 'id': this.safeStringN(order, ['id', 'orderId', 'newOrderId']),
2721
+ 'clientOrderId': this.safeString(order, 'clientOid'),
2722
+ 'symbol': this.safeSymbol(marketId, market, '-'),
2723
+ 'type': this.safeString(order, 'type'),
2724
+ 'timeInForce': this.safeString(order, 'timeInForce'),
2725
+ 'postOnly': this.safeValue(order, 'postOnly'),
2726
+ 'side': this.safeString(order, 'side'),
2727
+ 'amount': this.safeString(order, 'size'),
2728
+ 'price': this.safeString(order, 'price'),
2729
+ 'stopPrice': stopPrice,
2730
+ 'triggerPrice': stopPrice,
2731
+ 'cost': this.safeString(order, 'dealFunds'),
2732
+ 'filled': this.safeString(order, 'dealSize'),
2733
+ 'remaining': undefined,
2734
+ 'timestamp': timestamp,
2735
+ 'datetime': this.iso8601(timestamp),
2736
+ 'fee': {
2737
+ 'currency': this.safeCurrencyCode(feeCurrencyId),
2738
+ 'cost': this.safeNumber(order, 'fee'),
2739
+ },
2740
+ 'status': status,
2741
+ 'lastTradeTimestamp': undefined,
2742
+ 'average': undefined,
2743
+ 'trades': undefined,
2744
+ }, market);
2745
+ }
2746
+ async fetchOrderTrades(id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
2747
+ /**
2748
+ * @method
2749
+ * @name kucoin#fetchOrderTrades
2750
+ * @description fetch all the trades made from a single order
2751
+ * @see https://docs.kucoin.com/#list-fills
2752
+ * @see https://docs.kucoin.com/spot-hf/#transaction-details
2753
+ * @param {string} id order id
2754
+ * @param {string} symbol unified market symbol
2755
+ * @param {int} [since] the earliest time in ms to fetch trades for
2756
+ * @param {int} [limit] the maximum number of trades to retrieve
2757
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2758
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
2759
+ */
2760
+ const request = {
2761
+ 'orderId': id,
2762
+ };
2763
+ return await this.fetchMyTrades(symbol, since, limit, this.extend(request, params));
2764
+ }
2765
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2766
+ /**
2767
+ * @method
2768
+ * @name kucoin#fetchMyTrades
2769
+ * @see https://docs.kucoin.com/#list-fills
2770
+ * @see https://docs.kucoin.com/spot-hf/#transaction-details
2771
+ * @description fetch all trades made by the user
2772
+ * @param {string} symbol unified market symbol
2773
+ * @param {int} [since] the earliest time in ms to fetch trades for
2774
+ * @param {int} [limit] the maximum number of trades structures to retrieve
2775
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2776
+ * @param {int} [params.until] the latest time in ms to fetch entries for
2777
+ * @param {bool} [params.hf] false, // true for hf order
2778
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2779
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
2780
+ */
2781
+ await this.loadMarkets();
2782
+ let paginate = false;
2783
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchMyTrades', 'paginate');
2784
+ if (paginate) {
2785
+ return await this.fetchPaginatedCallDynamic('fetchMyTrades', symbol, since, limit, params);
2786
+ }
2787
+ let request = {};
2788
+ const hf = this.safeValue(params, 'hf', false);
2789
+ if (hf && symbol === undefined) {
2790
+ throw new errors.ArgumentsRequired(this.id + ' fetchMyTrades() requires a symbol parameter for hf orders');
2791
+ }
2792
+ let market = undefined;
2793
+ if (symbol !== undefined) {
2794
+ market = this.market(symbol);
2795
+ request['symbol'] = market['id'];
2796
+ }
2797
+ if (limit !== undefined) {
2798
+ request['pageSize'] = limit;
2799
+ }
2800
+ const method = this.options['fetchMyTradesMethod'];
2801
+ let parseResponseData = false;
2802
+ let response = undefined;
2803
+ [request, params] = this.handleUntilOption('endAt', request, params);
2804
+ if (hf) {
2805
+ response = await this.privateGetHfFills(this.extend(request, params));
2806
+ }
2807
+ else if (method === 'private_get_fills') {
2808
+ // does not return trades earlier than 2019-02-18T00:00:00Z
2809
+ if (since !== undefined) {
2810
+ // only returns trades up to one week after the since param
2811
+ request['startAt'] = since;
2812
+ }
2813
+ response = await this.privateGetFills(this.extend(request, params));
2814
+ }
2815
+ else if (method === 'private_get_limit_fills') {
2816
+ // does not return trades earlier than 2019-02-18T00:00:00Z
2817
+ // takes no params
2818
+ // only returns first 1000 trades (not only "in the last 24 hours" as stated in the docs)
2819
+ parseResponseData = true;
2820
+ response = await this.privateGetLimitFills(this.extend(request, params));
2821
+ }
2822
+ else {
2823
+ throw new errors.ExchangeError(this.id + ' fetchMyTradesMethod() invalid method');
2824
+ }
2825
+ //
2826
+ // {
2827
+ // "currentPage": 1,
2828
+ // "pageSize": 50,
2829
+ // "totalNum": 1,
2830
+ // "totalPage": 1,
2831
+ // "items": [
2832
+ // {
2833
+ // "symbol":"BTC-USDT", // symbol
2834
+ // "tradeId":"5c35c02709e4f67d5266954e", // trade id
2835
+ // "orderId":"5c35c02703aa673ceec2a168", // order id
2836
+ // "counterOrderId":"5c1ab46003aa676e487fa8e3", // counter order id
2837
+ // "side":"buy", // transaction direction,include buy and sell
2838
+ // "liquidity":"taker", // include taker and maker
2839
+ // "forceTaker":true, // forced to become taker
2840
+ // "price":"0.083", // order price
2841
+ // "size":"0.8424304", // order quantity
2842
+ // "funds":"0.0699217232", // order funds
2843
+ // "fee":"0", // fee
2844
+ // "feeRate":"0", // fee rate
2845
+ // "feeCurrency":"USDT", // charge fee currency
2846
+ // "stop":"", // stop type
2847
+ // "type":"limit", // order type, e.g. limit, market, stop_limit.
2848
+ // "createdAt":1547026472000 // time
2849
+ // },
2850
+ // //------------------------------------------------------
2851
+ // // v1 (historical) trade response structure
2852
+ // {
2853
+ // "symbol": "SNOV-ETH",
2854
+ // "dealPrice": "0.0000246",
2855
+ // "dealValue": "0.018942",
2856
+ // "amount": "770",
2857
+ // "fee": "0.00001137",
2858
+ // "side": "sell",
2859
+ // "createdAt": 1540080199
2860
+ // "id":"5c4d389e4c8c60413f78e2e5",
2861
+ // }
2862
+ // ]
2863
+ // }
2864
+ //
2865
+ const data = this.safeValue(response, 'data', {});
2866
+ let trades = undefined;
2867
+ if (parseResponseData) {
2868
+ trades = data;
2869
+ }
2870
+ else {
2871
+ trades = this.safeValue(data, 'items', []);
2872
+ }
2873
+ return this.parseTrades(trades, market, since, limit);
2874
+ }
2875
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
2876
+ /**
2877
+ * @method
2878
+ * @name kucoin#fetchTrades
2879
+ * @description get the list of most recent trades for a particular symbol
2880
+ * @see https://docs.kucoin.com/#get-trade-histories
2881
+ * @param {string} symbol unified symbol of the market to fetch trades for
2882
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
2883
+ * @param {int} [limit] the maximum amount of trades to fetch
2884
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2885
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
2886
+ */
2887
+ await this.loadMarkets();
2888
+ const market = this.market(symbol);
2889
+ const request = {
2890
+ 'symbol': market['id'],
2891
+ };
2892
+ // pagination is not supported on the exchange side anymore
2893
+ // if (since !== undefined) {
2894
+ // request['startAt'] = Math.floor (since / 1000);
2895
+ // }
2896
+ // if (limit !== undefined) {
2897
+ // request['pageSize'] = limit;
2898
+ // }
2899
+ const response = await this.publicGetMarketHistories(this.extend(request, params));
2900
+ //
2901
+ // {
2902
+ // "code": "200000",
2903
+ // "data": [
2904
+ // {
2905
+ // "sequence": "1548764654235",
2906
+ // "side": "sell",
2907
+ // "size":"0.6841354",
2908
+ // "price":"0.03202",
2909
+ // "time":1548848575203567174
2910
+ // }
2911
+ // ]
2912
+ // }
2913
+ //
2914
+ const trades = this.safeValue(response, 'data', []);
2915
+ return this.parseTrades(trades, market, since, limit);
2916
+ }
2917
+ parseTrade(trade, market = undefined) {
2918
+ //
2919
+ // fetchTrades (public)
2920
+ //
2921
+ // {
2922
+ // "sequence": "1548764654235",
2923
+ // "side": "sell",
2924
+ // "size":"0.6841354",
2925
+ // "price":"0.03202",
2926
+ // "time":1548848575203567174
2927
+ // }
2928
+ //
2929
+ // {
2930
+ // "sequence": "1568787654360",
2931
+ // "symbol": "BTC-USDT",
2932
+ // "side": "buy",
2933
+ // "size": "0.00536577",
2934
+ // "price": "9345",
2935
+ // "takerOrderId": "5e356c4a9f1a790008f8d921",
2936
+ // "time": "1580559434436443257",
2937
+ // "type": "match",
2938
+ // "makerOrderId": "5e356bffedf0010008fa5d7f",
2939
+ // "tradeId": "5e356c4aeefabd62c62a1ece"
2940
+ // }
2941
+ //
2942
+ // fetchMyTrades (private) v2
2943
+ //
2944
+ // {
2945
+ // "symbol":"BTC-USDT",
2946
+ // "tradeId":"5c35c02709e4f67d5266954e",
2947
+ // "orderId":"5c35c02703aa673ceec2a168",
2948
+ // "counterOrderId":"5c1ab46003aa676e487fa8e3",
2949
+ // "side":"buy",
2950
+ // "liquidity":"taker",
2951
+ // "forceTaker":true,
2952
+ // "price":"0.083",
2953
+ // "size":"0.8424304",
2954
+ // "funds":"0.0699217232",
2955
+ // "fee":"0",
2956
+ // "feeRate":"0",
2957
+ // "feeCurrency":"USDT",
2958
+ // "stop":"",
2959
+ // "type":"limit",
2960
+ // "createdAt":1547026472000
2961
+ // }
2962
+ //
2963
+ // fetchMyTrades v2 alternative format since 2019-05-21 https://github.com/ccxt/ccxt/pull/5162
2964
+ //
2965
+ // {
2966
+ // "symbol": "OPEN-BTC",
2967
+ // "forceTaker": false,
2968
+ // "orderId": "5ce36420054b4663b1fff2c9",
2969
+ // "fee": "0",
2970
+ // "feeCurrency": "",
2971
+ // "type": "",
2972
+ // "feeRate": "0",
2973
+ // "createdAt": 1558417615000,
2974
+ // "size": "12.8206",
2975
+ // "stop": "",
2976
+ // "price": "0",
2977
+ // "funds": "0",
2978
+ // "tradeId": "5ce390cf6e0db23b861c6e80"
2979
+ // }
2980
+ //
2981
+ // fetchMyTrades (private) v1 (historical)
2982
+ //
2983
+ // {
2984
+ // "symbol": "SNOV-ETH",
2985
+ // "dealPrice": "0.0000246",
2986
+ // "dealValue": "0.018942",
2987
+ // "amount": "770",
2988
+ // "fee": "0.00001137",
2989
+ // "side": "sell",
2990
+ // "createdAt": 1540080199
2991
+ // "id":"5c4d389e4c8c60413f78e2e5",
2992
+ // }
2993
+ //
2994
+ const marketId = this.safeString(trade, 'symbol');
2995
+ market = this.safeMarket(marketId, market, '-');
2996
+ const id = this.safeString2(trade, 'tradeId', 'id');
2997
+ const orderId = this.safeString(trade, 'orderId');
2998
+ const takerOrMaker = this.safeString(trade, 'liquidity');
2999
+ let timestamp = this.safeInteger(trade, 'time');
3000
+ if (timestamp !== undefined) {
3001
+ timestamp = this.parseToInt(timestamp / 1000000);
3002
+ }
3003
+ else {
3004
+ timestamp = this.safeInteger(trade, 'createdAt');
3005
+ // if it's a historical v1 trade, the exchange returns timestamp in seconds
3006
+ if (('dealValue' in trade) && (timestamp !== undefined)) {
3007
+ timestamp = timestamp * 1000;
3008
+ }
3009
+ }
3010
+ const priceString = this.safeString2(trade, 'price', 'dealPrice');
3011
+ const amountString = this.safeString2(trade, 'size', 'amount');
3012
+ const side = this.safeString(trade, 'side');
3013
+ let fee = undefined;
3014
+ const feeCostString = this.safeString(trade, 'fee');
3015
+ if (feeCostString !== undefined) {
3016
+ const feeCurrencyId = this.safeString(trade, 'feeCurrency');
3017
+ let feeCurrency = this.safeCurrencyCode(feeCurrencyId);
3018
+ if (feeCurrency === undefined) {
3019
+ feeCurrency = (side === 'sell') ? market['quote'] : market['base'];
3020
+ }
3021
+ fee = {
3022
+ 'cost': feeCostString,
3023
+ 'currency': feeCurrency,
3024
+ 'rate': this.safeString(trade, 'feeRate'),
3025
+ };
3026
+ }
3027
+ let type = this.safeString(trade, 'type');
3028
+ if (type === 'match') {
3029
+ type = undefined;
3030
+ }
3031
+ const costString = this.safeString2(trade, 'funds', 'dealValue');
3032
+ return this.safeTrade({
3033
+ 'info': trade,
3034
+ 'id': id,
3035
+ 'order': orderId,
3036
+ 'timestamp': timestamp,
3037
+ 'datetime': this.iso8601(timestamp),
3038
+ 'symbol': market['symbol'],
3039
+ 'type': type,
3040
+ 'takerOrMaker': takerOrMaker,
3041
+ 'side': side,
3042
+ 'price': priceString,
3043
+ 'amount': amountString,
3044
+ 'cost': costString,
3045
+ 'fee': fee,
3046
+ }, market);
3047
+ }
3048
+ async fetchTradingFee(symbol, params = {}) {
3049
+ /**
3050
+ * @method
3051
+ * @name kucoin#fetchTradingFee
3052
+ * @description fetch the trading fees for a market
3053
+ * @see https://docs.kucoin.com/#actual-fee-rate-of-the-trading-pair
3054
+ * @param {string} symbol unified market symbol
3055
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3056
+ * @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
3057
+ */
3058
+ await this.loadMarkets();
3059
+ const market = this.market(symbol);
3060
+ const request = {
3061
+ 'symbols': market['id'],
3062
+ };
3063
+ const response = await this.privateGetTradeFees(this.extend(request, params));
3064
+ //
3065
+ // {
3066
+ // "code": "200000",
3067
+ // "data": [
3068
+ // {
3069
+ // "symbol": "BTC-USDT",
3070
+ // "takerFeeRate": "0.001",
3071
+ // "makerFeeRate": "0.001"
3072
+ // }
3073
+ // ]
3074
+ // }
3075
+ //
3076
+ const data = this.safeValue(response, 'data', []);
3077
+ const first = this.safeValue(data, 0);
3078
+ const marketId = this.safeString(first, 'symbol');
3079
+ return {
3080
+ 'info': response,
3081
+ 'symbol': this.safeSymbol(marketId, market),
3082
+ 'maker': this.safeNumber(first, 'makerFeeRate'),
3083
+ 'taker': this.safeNumber(first, 'takerFeeRate'),
3084
+ 'percentage': true,
3085
+ 'tierBased': true,
3086
+ };
3087
+ }
3088
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
3089
+ /**
3090
+ * @method
3091
+ * @name kucoin#withdraw
3092
+ * @description make a withdrawal
3093
+ * @see https://docs.kucoin.com/#apply-withdraw-2
3094
+ * @param {string} code unified currency code
3095
+ * @param {float} amount the amount to withdraw
3096
+ * @param {string} address the address to withdraw to
3097
+ * @param {string} tag
3098
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3099
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
3100
+ */
3101
+ [tag, params] = this.handleWithdrawTagAndParams(tag, params);
3102
+ await this.loadMarkets();
3103
+ this.checkAddress(address);
3104
+ const currency = this.currency(code);
3105
+ const request = {
3106
+ 'currency': currency['id'],
3107
+ 'address': address,
3108
+ 'amount': amount,
3109
+ // 'memo': tag,
3110
+ // 'isInner': false, // internal transfer or external withdrawal
3111
+ // 'remark': 'optional',
3112
+ // 'chain': 'OMNI', // 'ERC20', 'TRC20', default is ERC20, This only apply for multi-chain currency, and there is no need for single chain currency.
3113
+ };
3114
+ if (tag !== undefined) {
3115
+ request['memo'] = tag;
3116
+ }
3117
+ let networkCode = undefined;
3118
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
3119
+ if (networkCode !== undefined) {
3120
+ request['chain'] = this.networkCodeToId(networkCode).toLowerCase();
3121
+ }
3122
+ let includeFee = undefined;
3123
+ [includeFee, params] = this.handleOptionAndParams(params, 'withdraw', 'includeFee', false);
3124
+ if (includeFee) {
3125
+ request['feeDeductType'] = 'INTERNAL';
3126
+ }
3127
+ const response = await this.privatePostWithdrawals(this.extend(request, params));
3128
+ //
3129
+ // https://github.com/ccxt/ccxt/issues/5558
3130
+ //
3131
+ // {
3132
+ // "code": 200000,
3133
+ // "data": {
3134
+ // "withdrawalId": "5bffb63303aa675e8bbe18f9"
3135
+ // }
3136
+ // }
3137
+ //
3138
+ const data = this.safeValue(response, 'data', {});
3139
+ return this.parseTransaction(data, currency);
3140
+ }
3141
+ parseTransactionStatus(status) {
3142
+ const statuses = {
3143
+ 'SUCCESS': 'ok',
3144
+ 'PROCESSING': 'pending',
3145
+ 'WALLET_PROCESSING': 'pending',
3146
+ 'FAILURE': 'failed',
3147
+ };
3148
+ return this.safeString(statuses, status, status);
3149
+ }
3150
+ parseTransaction(transaction, currency = undefined) {
3151
+ //
3152
+ // fetchDeposits
3153
+ //
3154
+ // {
3155
+ // "address": "0x5f047b29041bcfdbf0e4478cdfa753a336ba6989",
3156
+ // "memo": "5c247c8a03aa677cea2a251d",
3157
+ // "amount": 1,
3158
+ // "fee": 0.0001,
3159
+ // "currency": "KCS",
3160
+ // "chain": "",
3161
+ // "isInner": false,
3162
+ // "walletTxId": "5bbb57386d99522d9f954c5a@test004",
3163
+ // "status": "SUCCESS",
3164
+ // "createdAt": 1544178843000,
3165
+ // "updatedAt": 1544178891000
3166
+ // "remark":"foobar"
3167
+ // }
3168
+ //
3169
+ // fetchWithdrawals
3170
+ //
3171
+ // {
3172
+ // "id": "5c2dc64e03aa675aa263f1ac",
3173
+ // "address": "0x5bedb060b8eb8d823e2414d82acce78d38be7fe9",
3174
+ // "memo": "",
3175
+ // "currency": "ETH",
3176
+ // "chain": "",
3177
+ // "amount": 1.0000000,
3178
+ // "fee": 0.0100000,
3179
+ // "walletTxId": "3e2414d82acce78d38be7fe9",
3180
+ // "isInner": false,
3181
+ // "status": "FAILURE",
3182
+ // "createdAt": 1546503758000,
3183
+ // "updatedAt": 1546504603000
3184
+ // "remark":"foobar"
3185
+ // }
3186
+ //
3187
+ // withdraw
3188
+ //
3189
+ // {
3190
+ // "withdrawalId": "5bffb63303aa675e8bbe18f9"
3191
+ // }
3192
+ //
3193
+ const currencyId = this.safeString(transaction, 'currency');
3194
+ const code = this.safeCurrencyCode(currencyId, currency);
3195
+ let address = this.safeString(transaction, 'address');
3196
+ const amount = this.safeString(transaction, 'amount');
3197
+ let txid = this.safeString(transaction, 'walletTxId');
3198
+ if (txid !== undefined) {
3199
+ const txidParts = txid.split('@');
3200
+ const numTxidParts = txidParts.length;
3201
+ if (numTxidParts > 1) {
3202
+ if (address === undefined) {
3203
+ if (txidParts[1].length > 1) {
3204
+ address = txidParts[1];
3205
+ }
3206
+ }
3207
+ }
3208
+ txid = txidParts[0];
3209
+ }
3210
+ let type = (txid === undefined) ? 'withdrawal' : 'deposit';
3211
+ const rawStatus = this.safeString(transaction, 'status');
3212
+ let fee = undefined;
3213
+ const feeCost = this.safeString(transaction, 'fee');
3214
+ if (feeCost !== undefined) {
3215
+ let rate = undefined;
3216
+ if (amount !== undefined) {
3217
+ rate = Precise["default"].stringDiv(feeCost, amount);
3218
+ }
3219
+ fee = {
3220
+ 'cost': this.parseNumber(feeCost),
3221
+ 'rate': this.parseNumber(rate),
3222
+ 'currency': code,
3223
+ };
3224
+ }
3225
+ let timestamp = this.safeInteger2(transaction, 'createdAt', 'createAt');
3226
+ let updated = this.safeInteger(transaction, 'updatedAt');
3227
+ const isV1 = !('createdAt' in transaction);
3228
+ // if it's a v1 structure
3229
+ if (isV1) {
3230
+ type = ('address' in transaction) ? 'withdrawal' : 'deposit';
3231
+ if (timestamp !== undefined) {
3232
+ timestamp = timestamp * 1000;
3233
+ }
3234
+ if (updated !== undefined) {
3235
+ updated = updated * 1000;
3236
+ }
3237
+ }
3238
+ const internal = this.safeValue(transaction, 'isInner');
3239
+ const tag = this.safeString(transaction, 'memo');
3240
+ return {
3241
+ 'info': transaction,
3242
+ 'id': this.safeString2(transaction, 'id', 'withdrawalId'),
3243
+ 'timestamp': timestamp,
3244
+ 'datetime': this.iso8601(timestamp),
3245
+ 'network': this.networkIdToCode(this.safeString(transaction, 'chain')),
3246
+ 'address': address,
3247
+ 'addressTo': address,
3248
+ 'addressFrom': undefined,
3249
+ 'tag': tag,
3250
+ 'tagTo': tag,
3251
+ 'tagFrom': undefined,
3252
+ 'currency': code,
3253
+ 'amount': this.parseNumber(amount),
3254
+ 'txid': txid,
3255
+ 'type': type,
3256
+ 'status': this.parseTransactionStatus(rawStatus),
3257
+ 'comment': this.safeString(transaction, 'remark'),
3258
+ 'internal': internal,
3259
+ 'fee': fee,
3260
+ 'updated': updated,
3261
+ };
3262
+ }
3263
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
3264
+ /**
3265
+ * @method
3266
+ * @name kucoin#fetchDeposits
3267
+ * @description fetch all deposits made to an account
3268
+ * @see https://docs.kucoin.com/#get-deposit-list
3269
+ * @see https://docs.kucoin.com/#get-v1-historical-deposits-list
3270
+ * @param {string} code unified currency code
3271
+ * @param {int} [since] the earliest time in ms to fetch deposits for
3272
+ * @param {int} [limit] the maximum number of deposits structures to retrieve
3273
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3274
+ * @param {int} [params.until] the latest time in ms to fetch entries for
3275
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3276
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
3277
+ */
3278
+ await this.loadMarkets();
3279
+ let paginate = false;
3280
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchDeposits', 'paginate');
3281
+ if (paginate) {
3282
+ return await this.fetchPaginatedCallDynamic('fetchDeposits', code, since, limit, params);
3283
+ }
3284
+ let request = {};
3285
+ let currency = undefined;
3286
+ if (code !== undefined) {
3287
+ currency = this.currency(code);
3288
+ request['currency'] = currency['id'];
3289
+ }
3290
+ if (limit !== undefined) {
3291
+ request['pageSize'] = limit;
3292
+ }
3293
+ [request, params] = this.handleUntilOption('endAt', request, params);
3294
+ let response = undefined;
3295
+ if (since !== undefined && since < 1550448000000) {
3296
+ // if since is earlier than 2019-02-18T00:00:00Z
3297
+ request['startAt'] = this.parseToInt(since / 1000);
3298
+ response = await this.privateGetHistDeposits(this.extend(request, params));
3299
+ }
3300
+ else {
3301
+ if (since !== undefined) {
3302
+ request['startAt'] = since;
3303
+ }
3304
+ response = await this.privateGetDeposits(this.extend(request, params));
3305
+ }
3306
+ //
3307
+ // {
3308
+ // "code": "200000",
3309
+ // "data": {
3310
+ // "currentPage": 1,
3311
+ // "pageSize": 5,
3312
+ // "totalNum": 2,
3313
+ // "totalPage": 1,
3314
+ // "items": [
3315
+ // //--------------------------------------------------
3316
+ // // version 2 deposit response structure
3317
+ // {
3318
+ // "address": "0x5f047b29041bcfdbf0e4478cdfa753a336ba6989",
3319
+ // "memo": "5c247c8a03aa677cea2a251d",
3320
+ // "amount": 1,
3321
+ // "fee": 0.0001,
3322
+ // "currency": "KCS",
3323
+ // "isInner": false,
3324
+ // "walletTxId": "5bbb57386d99522d9f954c5a@test004",
3325
+ // "status": "SUCCESS",
3326
+ // "createdAt": 1544178843000,
3327
+ // "updatedAt": 1544178891000
3328
+ // "remark":"foobar"
3329
+ // },
3330
+ // //--------------------------------------------------
3331
+ // // version 1 (historical) deposit response structure
3332
+ // {
3333
+ // "currency": "BTC",
3334
+ // "createAt": 1528536998,
3335
+ // "amount": "0.03266638",
3336
+ // "walletTxId": "55c643bc2c68d6f17266383ac1be9e454038864b929ae7cee0bc408cc5c869e8@12ffGWmMMD1zA1WbFm7Ho3JZ1w6NYXjpFk@234",
3337
+ // "isInner": false,
3338
+ // "status": "SUCCESS",
3339
+ // }
3340
+ // ]
3341
+ // }
3342
+ // }
3343
+ //
3344
+ const responseData = response['data']['items'];
3345
+ return this.parseTransactions(responseData, currency, since, limit, { 'type': 'deposit' });
3346
+ }
3347
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
3348
+ /**
3349
+ * @method
3350
+ * @name kucoin#fetchWithdrawals
3351
+ * @description fetch all withdrawals made from an account
3352
+ * @see https://docs.kucoin.com/#get-withdrawals-list
3353
+ * @see https://docs.kucoin.com/#get-v1-historical-withdrawals-list
3354
+ * @param {string} code unified currency code
3355
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
3356
+ * @param {int} [limit] the maximum number of withdrawals structures to retrieve
3357
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3358
+ * @param {int} [params.until] the latest time in ms to fetch entries for
3359
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3360
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
3361
+ */
3362
+ await this.loadMarkets();
3363
+ let paginate = false;
3364
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchWithdrawals', 'paginate');
3365
+ if (paginate) {
3366
+ return await this.fetchPaginatedCallDynamic('fetchWithdrawals', code, since, limit, params);
3367
+ }
3368
+ let request = {};
3369
+ let currency = undefined;
3370
+ if (code !== undefined) {
3371
+ currency = this.currency(code);
3372
+ request['currency'] = currency['id'];
3373
+ }
3374
+ if (limit !== undefined) {
3375
+ request['pageSize'] = limit;
3376
+ }
3377
+ [request, params] = this.handleUntilOption('endAt', request, params);
3378
+ let response = undefined;
3379
+ if (since !== undefined && since < 1550448000000) {
3380
+ // if since is earlier than 2019-02-18T00:00:00Z
3381
+ request['startAt'] = this.parseToInt(since / 1000);
3382
+ response = await this.privateGetHistWithdrawals(this.extend(request, params));
3383
+ }
3384
+ else {
3385
+ if (since !== undefined) {
3386
+ request['startAt'] = since;
3387
+ }
3388
+ response = await this.privateGetWithdrawals(this.extend(request, params));
3389
+ }
3390
+ //
3391
+ // {
3392
+ // "code": "200000",
3393
+ // "data": {
3394
+ // "currentPage": 1,
3395
+ // "pageSize": 5,
3396
+ // "totalNum": 2,
3397
+ // "totalPage": 1,
3398
+ // "items": [
3399
+ // //--------------------------------------------------
3400
+ // // version 2 withdrawal response structure
3401
+ // {
3402
+ // "id": "5c2dc64e03aa675aa263f1ac",
3403
+ // "address": "0x5bedb060b8eb8d823e2414d82acce78d38be7fe9",
3404
+ // "memo": "",
3405
+ // "currency": "ETH",
3406
+ // "amount": 1.0000000,
3407
+ // "fee": 0.0100000,
3408
+ // "walletTxId": "3e2414d82acce78d38be7fe9",
3409
+ // "isInner": false,
3410
+ // "status": "FAILURE",
3411
+ // "createdAt": 1546503758000,
3412
+ // "updatedAt": 1546504603000
3413
+ // },
3414
+ // //--------------------------------------------------
3415
+ // // version 1 (historical) withdrawal response structure
3416
+ // {
3417
+ // "currency": "BTC",
3418
+ // "createAt": 1526723468,
3419
+ // "amount": "0.534",
3420
+ // "address": "33xW37ZSW4tQvg443Pc7NLCAs167Yc2XUV",
3421
+ // "walletTxId": "aeacea864c020acf58e51606169240e96774838dcd4f7ce48acf38e3651323f4",
3422
+ // "isInner": false,
3423
+ // "status": "SUCCESS"
3424
+ // }
3425
+ // ]
3426
+ // }
3427
+ // }
3428
+ //
3429
+ const responseData = response['data']['items'];
3430
+ return this.parseTransactions(responseData, currency, since, limit, { 'type': 'withdrawal' });
3431
+ }
3432
+ parseBalanceHelper(entry) {
3433
+ const account = this.account();
3434
+ account['used'] = this.safeString(entry, 'holdBalance');
3435
+ account['free'] = this.safeString(entry, 'availableBalance');
3436
+ account['total'] = this.safeString(entry, 'totalBalance');
3437
+ const debt = this.safeString(entry, 'liability');
3438
+ const interest = this.safeString(entry, 'interest');
3439
+ account['debt'] = Precise["default"].stringAdd(debt, interest);
3440
+ return account;
3441
+ }
3442
+ async fetchBalance(params = {}) {
3443
+ /**
3444
+ * @method
3445
+ * @name kucoin#fetchBalance
3446
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
3447
+ * @see https://docs.kucoin.com/#list-accounts
3448
+ * @see https://www.kucoin.com/docs/rest/account/basic-info/get-account-list-spot-margin-trade_hf
3449
+ * @see https://docs.kucoin.com/#query-isolated-margin-account-info
3450
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3451
+ * @param {object} [params.marginMode] 'cross' or 'isolated', margin type for fetching margin balance
3452
+ * @param {object} [params.type] extra parameters specific to the exchange API endpoint
3453
+ * @param {object} [params.hf] *default if false* if true, the result includes the balance of the high frequency account
3454
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
3455
+ */
3456
+ await this.loadMarkets();
3457
+ const code = this.safeString(params, 'code');
3458
+ let currency = undefined;
3459
+ if (code !== undefined) {
3460
+ currency = this.currency(code);
3461
+ }
3462
+ const defaultType = this.safeString2(this.options, 'fetchBalance', 'defaultType', 'spot');
3463
+ const requestedType = this.safeString(params, 'type', defaultType);
3464
+ const accountsByType = this.safeValue(this.options, 'accountsByType');
3465
+ let type = this.safeString(accountsByType, requestedType, requestedType);
3466
+ params = this.omit(params, 'type');
3467
+ const isHf = this.safeValue(params, 'hf', false);
3468
+ if (isHf) {
3469
+ type = 'trade_hf';
3470
+ }
3471
+ params = this.omit(params, 'hf');
3472
+ const [marginMode, query] = this.handleMarginModeAndParams('fetchBalance', params);
3473
+ let response = undefined;
3474
+ const request = {};
3475
+ const isolated = (marginMode === 'isolated') || (type === 'isolated');
3476
+ const cross = (marginMode === 'cross') || (type === 'cross');
3477
+ if (isolated) {
3478
+ if (currency !== undefined) {
3479
+ request['balanceCurrency'] = currency['id'];
3480
+ }
3481
+ response = await this.privateGetIsolatedAccounts(this.extend(request, query));
3482
+ }
3483
+ else if (cross) {
3484
+ response = await this.privateGetMarginAccount(this.extend(request, query));
3485
+ }
3486
+ else {
3487
+ if (currency !== undefined) {
3488
+ request['currency'] = currency['id'];
3489
+ }
3490
+ request['type'] = type;
3491
+ response = await this.privateGetAccounts(this.extend(request, query));
3492
+ }
3493
+ //
3494
+ // Spot and Cross
3495
+ //
3496
+ // {
3497
+ // "code": "200000",
3498
+ // "data": [
3499
+ // {
3500
+ // "balance": "0.00009788",
3501
+ // "available": "0.00009788",
3502
+ // "holds": "0",
3503
+ // "currency": "BTC",
3504
+ // "id": "5c6a4fd399a1d81c4f9cc4d0",
3505
+ // "type": "trade",
3506
+ // },
3507
+ // ]
3508
+ // }
3509
+ //
3510
+ // Isolated
3511
+ //
3512
+ // {
3513
+ // "code": "200000",
3514
+ // "data": {
3515
+ // "totalConversionBalance": "0",
3516
+ // "liabilityConversionBalance": "0",
3517
+ // "assets": [
3518
+ // {
3519
+ // "symbol": "MANA-USDT",
3520
+ // "status": "CLEAR",
3521
+ // "debtRatio": "0",
3522
+ // "baseAsset": {
3523
+ // "currency": "MANA",
3524
+ // "totalBalance": "0",
3525
+ // "holdBalance": "0",
3526
+ // "availableBalance": "0",
3527
+ // "liability": "0",
3528
+ // "interest": "0",
3529
+ // "borrowableAmount": "0"
3530
+ // },
3531
+ // "quoteAsset": {
3532
+ // "currency": "USDT",
3533
+ // "totalBalance": "0",
3534
+ // "holdBalance": "0",
3535
+ // "availableBalance": "0",
3536
+ // "liability": "0",
3537
+ // "interest": "0",
3538
+ // "borrowableAmount": "0"
3539
+ // }
3540
+ // },
3541
+ // ...
3542
+ // ]
3543
+ // }
3544
+ // }
3545
+ //
3546
+ const data = this.safeValue(response, 'data', []);
3547
+ const result = {
3548
+ 'info': response,
3549
+ 'timestamp': undefined,
3550
+ 'datetime': undefined,
3551
+ };
3552
+ if (isolated) {
3553
+ const assets = this.safeValue(data, 'assets', data);
3554
+ for (let i = 0; i < assets.length; i++) {
3555
+ const entry = assets[i];
3556
+ const marketId = this.safeString(entry, 'symbol');
3557
+ const symbol = this.safeSymbol(marketId, undefined, '_');
3558
+ const base = this.safeValue(entry, 'baseAsset', {});
3559
+ const quote = this.safeValue(entry, 'quoteAsset', {});
3560
+ const baseCode = this.safeCurrencyCode(this.safeString(base, 'currency'));
3561
+ const quoteCode = this.safeCurrencyCode(this.safeString(quote, 'currency'));
3562
+ const subResult = {};
3563
+ subResult[baseCode] = this.parseBalanceHelper(base);
3564
+ subResult[quoteCode] = this.parseBalanceHelper(quote);
3565
+ result[symbol] = this.safeBalance(subResult);
3566
+ }
3567
+ }
3568
+ else if (cross) {
3569
+ const accounts = this.safeValue(data, 'accounts', []);
3570
+ for (let i = 0; i < accounts.length; i++) {
3571
+ const balance = accounts[i];
3572
+ const currencyId = this.safeString(balance, 'currency');
3573
+ const codeInner = this.safeCurrencyCode(currencyId);
3574
+ result[codeInner] = this.parseBalanceHelper(balance);
3575
+ }
3576
+ }
3577
+ else {
3578
+ for (let i = 0; i < data.length; i++) {
3579
+ const balance = data[i];
3580
+ const balanceType = this.safeString(balance, 'type');
3581
+ if (balanceType === type) {
3582
+ const currencyId = this.safeString(balance, 'currency');
3583
+ const codeInner2 = this.safeCurrencyCode(currencyId);
3584
+ const account = this.account();
3585
+ account['total'] = this.safeString(balance, 'balance');
3586
+ account['free'] = this.safeString(balance, 'available');
3587
+ account['used'] = this.safeString(balance, 'holds');
3588
+ result[codeInner2] = account;
3589
+ }
3590
+ }
3591
+ }
3592
+ const returnType = isolated ? result : this.safeBalance(result);
3593
+ return returnType;
3594
+ }
3595
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
3596
+ /**
3597
+ * @method
3598
+ * @name kucoin#transfer
3599
+ * @description transfer currency internally between wallets on the same account
3600
+ * @see https://docs.kucoin.com/#inner-transfer
3601
+ * @see https://docs.kucoin.com/futures/#transfer-funds-to-kucoin-main-account-2
3602
+ * @see https://docs.kucoin.com/spot-hf/#internal-funds-transfers-in-high-frequency-trading-accounts
3603
+ * @param {string} code unified currency code
3604
+ * @param {float} amount amount to transfer
3605
+ * @param {string} fromAccount account to transfer from
3606
+ * @param {string} toAccount account to transfer to
3607
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3608
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
3609
+ */
3610
+ await this.loadMarkets();
3611
+ const currency = this.currency(code);
3612
+ const requestedAmount = this.currencyToPrecision(code, amount);
3613
+ let fromId = this.convertTypeToAccount(fromAccount);
3614
+ let toId = this.convertTypeToAccount(toAccount);
3615
+ const fromIsolated = this.inArray(fromId, this.ids);
3616
+ const toIsolated = this.inArray(toId, this.ids);
3617
+ if (fromId === 'contract') {
3618
+ if (toId !== 'main') {
3619
+ throw new errors.ExchangeError(this.id + ' transfer() only supports transferring from futures account to main account');
3620
+ }
3621
+ const request = {
3622
+ 'currency': currency['id'],
3623
+ 'amount': requestedAmount,
3624
+ };
3625
+ if (!('bizNo' in params)) {
3626
+ // it doesn't like more than 24 characters
3627
+ request['bizNo'] = this.uuid22();
3628
+ }
3629
+ const response = await this.futuresPrivatePostTransferOut(this.extend(request, params));
3630
+ //
3631
+ // {
3632
+ // "code": "200000",
3633
+ // "data": {
3634
+ // "applyId": "605a87217dff1500063d485d",
3635
+ // "bizNo": "bcd6e5e1291f4905af84dc",
3636
+ // "payAccountType": "CONTRACT",
3637
+ // "payTag": "DEFAULT",
3638
+ // "remark": '',
3639
+ // "recAccountType": "MAIN",
3640
+ // "recTag": "DEFAULT",
3641
+ // "recRemark": '',
3642
+ // "recSystem": "KUCOIN",
3643
+ // "status": "PROCESSING",
3644
+ // "currency": "XBT",
3645
+ // "amount": "0.00001",
3646
+ // "fee": "0",
3647
+ // "sn": "573688685663948",
3648
+ // "reason": '',
3649
+ // "createdAt": 1616545569000,
3650
+ // "updatedAt": 1616545569000
3651
+ // }
3652
+ // }
3653
+ //
3654
+ const data = this.safeValue(response, 'data');
3655
+ return this.parseTransfer(data, currency);
3656
+ }
3657
+ else {
3658
+ const request = {
3659
+ 'currency': currency['id'],
3660
+ 'amount': requestedAmount,
3661
+ };
3662
+ if (fromIsolated || toIsolated) {
3663
+ if (this.inArray(fromId, this.ids)) {
3664
+ request['fromTag'] = fromId;
3665
+ fromId = 'isolated';
3666
+ }
3667
+ if (this.inArray(toId, this.ids)) {
3668
+ request['toTag'] = toId;
3669
+ toId = 'isolated';
3670
+ }
3671
+ }
3672
+ request['from'] = fromId;
3673
+ request['to'] = toId;
3674
+ if (!('clientOid' in params)) {
3675
+ request['clientOid'] = this.uuid();
3676
+ }
3677
+ const response = await this.privatePostAccountsInnerTransfer(this.extend(request, params));
3678
+ //
3679
+ // {
3680
+ // "code": "200000",
3681
+ // "data": {
3682
+ // "orderId": "605a6211e657f00006ad0ad6"
3683
+ // }
3684
+ // }
3685
+ //
3686
+ const data = this.safeValue(response, 'data');
3687
+ return this.parseTransfer(data, currency);
3688
+ }
3689
+ }
3690
+ parseTransfer(transfer, currency = undefined) {
3691
+ //
3692
+ // transfer (spot)
3693
+ //
3694
+ // {
3695
+ // "orderId": "605a6211e657f00006ad0ad6"
3696
+ // }
3697
+ //
3698
+ // {
3699
+ // "code": "200000",
3700
+ // "msg": "Failed to transfer out. The amount exceeds the upper limit"
3701
+ // }
3702
+ //
3703
+ // transfer (futures)
3704
+ //
3705
+ // {
3706
+ // "applyId": "605a87217dff1500063d485d",
3707
+ // "bizNo": "bcd6e5e1291f4905af84dc",
3708
+ // "payAccountType": "CONTRACT",
3709
+ // "payTag": "DEFAULT",
3710
+ // "remark": '',
3711
+ // "recAccountType": "MAIN",
3712
+ // "recTag": "DEFAULT",
3713
+ // "recRemark": '',
3714
+ // "recSystem": "KUCOIN",
3715
+ // "status": "PROCESSING",
3716
+ // "currency": "XBT",
3717
+ // "amount": "0.00001",
3718
+ // "fee": "0",
3719
+ // "sn": "573688685663948",
3720
+ // "reason": '',
3721
+ // "createdAt": 1616545569000,
3722
+ // "updatedAt": 1616545569000
3723
+ // }
3724
+ //
3725
+ const timestamp = this.safeInteger(transfer, 'createdAt');
3726
+ const currencyId = this.safeString(transfer, 'currency');
3727
+ const rawStatus = this.safeString(transfer, 'status');
3728
+ const accountFromRaw = this.safeStringLower(transfer, 'payAccountType');
3729
+ const accountToRaw = this.safeStringLower(transfer, 'recAccountType');
3730
+ const accountsByType = this.safeValue(this.options, 'accountsByType');
3731
+ const accountFrom = this.safeString(accountsByType, accountFromRaw, accountFromRaw);
3732
+ const accountTo = this.safeString(accountsByType, accountToRaw, accountToRaw);
3733
+ return {
3734
+ 'id': this.safeString2(transfer, 'applyId', 'orderId'),
3735
+ 'currency': this.safeCurrencyCode(currencyId, currency),
3736
+ 'timestamp': timestamp,
3737
+ 'datetime': this.iso8601(timestamp),
3738
+ 'amount': this.safeNumber(transfer, 'amount'),
3739
+ 'fromAccount': accountFrom,
3740
+ 'toAccount': accountTo,
3741
+ 'status': this.parseTransferStatus(rawStatus),
3742
+ 'info': transfer,
3743
+ };
3744
+ }
3745
+ parseTransferStatus(status) {
3746
+ const statuses = {
3747
+ 'PROCESSING': 'pending',
3748
+ };
3749
+ return this.safeString(statuses, status, status);
3750
+ }
3751
+ parseLedgerEntryType(type) {
3752
+ const types = {
3753
+ 'Assets Transferred in After Upgrading': 'transfer',
3754
+ 'Deposit': 'transaction',
3755
+ 'Withdrawal': 'transaction',
3756
+ 'Transfer': 'transfer',
3757
+ 'Trade_Exchange': 'trade',
3758
+ // 'Vote for Coin': 'Vote for Coin', // Vote for Coin
3759
+ 'KuCoin Bonus': 'bonus',
3760
+ 'Referral Bonus': 'referral',
3761
+ 'Rewards': 'bonus',
3762
+ // 'Distribution': 'Distribution', // Distribution, such as get GAS by holding NEO
3763
+ 'Airdrop/Fork': 'airdrop',
3764
+ 'Other rewards': 'bonus',
3765
+ 'Fee Rebate': 'rebate',
3766
+ 'Buy Crypto': 'trade',
3767
+ 'Sell Crypto': 'sell',
3768
+ 'Public Offering Purchase': 'trade',
3769
+ // 'Send red envelope': 'Send red envelope', // Send red envelope
3770
+ // 'Open red envelope': 'Open red envelope', // Open red envelope
3771
+ // 'Staking': 'Staking', // Staking
3772
+ // 'LockDrop Vesting': 'LockDrop Vesting', // LockDrop Vesting
3773
+ // 'Staking Profits': 'Staking Profits', // Staking Profits
3774
+ // 'Redemption': 'Redemption', // Redemption
3775
+ 'Refunded Fees': 'fee',
3776
+ 'KCS Pay Fees': 'fee',
3777
+ 'Margin Trade': 'trade',
3778
+ 'Loans': 'Loans',
3779
+ // 'Borrowings': 'Borrowings', // Borrowings
3780
+ // 'Debt Repayment': 'Debt Repayment', // Debt Repayment
3781
+ // 'Loans Repaid': 'Loans Repaid', // Loans Repaid
3782
+ // 'Lendings': 'Lendings', // Lendings
3783
+ // 'Pool transactions': 'Pool transactions', // Pool-X transactions
3784
+ 'Instant Exchange': 'trade',
3785
+ 'Sub-account transfer': 'transfer',
3786
+ 'Liquidation Fees': 'fee', // Liquidation Fees
3787
+ // 'Soft Staking Profits': 'Soft Staking Profits', // Soft Staking Profits
3788
+ // 'Voting Earnings': 'Voting Earnings', // Voting Earnings on Pool-X
3789
+ // 'Redemption of Voting': 'Redemption of Voting', // Redemption of Voting on Pool-X
3790
+ // 'Voting': 'Voting', // Voting on Pool-X
3791
+ // 'Convert to KCS': 'Convert to KCS', // Convert to KCS
3792
+ };
3793
+ return this.safeString(types, type, type);
3794
+ }
3795
+ parseLedgerEntry(item, currency = undefined) {
3796
+ //
3797
+ // {
3798
+ // "id": "611a1e7c6a053300067a88d9", //unique key for each ledger entry
3799
+ // "currency": "USDT", //Currency
3800
+ // "amount": "10.00059547", //The total amount of assets (fees included) involved in assets changes such as transaction, withdrawal and bonus distribution.
3801
+ // "fee": "0", //Deposit or withdrawal fee
3802
+ // "balance": "0", //Total assets of a currency remaining funds after transaction
3803
+ // "accountType": "MAIN", //Account Type
3804
+ // "bizType": "Loans Repaid", //business type
3805
+ // "direction": "in", //side, in or out
3806
+ // "createdAt": 1629101692950, //Creation time
3807
+ // "context": "{\"borrowerUserId\":\"601ad03e50dc810006d242ea\",\"loanRepayDetailNo\":\"611a1e7cc913d000066cf7ec\"}" //Business core parameters
3808
+ // }
3809
+ //
3810
+ const id = this.safeString(item, 'id');
3811
+ const currencyId = this.safeString(item, 'currency');
3812
+ const code = this.safeCurrencyCode(currencyId, currency);
3813
+ const amount = this.safeNumber(item, 'amount');
3814
+ const balanceAfter = undefined;
3815
+ // const balanceAfter = this.safeNumber (item, 'balance'); only returns zero string
3816
+ const bizType = this.safeString(item, 'bizType');
3817
+ const type = this.parseLedgerEntryType(bizType);
3818
+ const direction = this.safeString(item, 'direction');
3819
+ const timestamp = this.safeInteger(item, 'createdAt');
3820
+ const datetime = this.iso8601(timestamp);
3821
+ const account = this.safeString(item, 'accountType'); // MAIN, TRADE, MARGIN, or CONTRACT
3822
+ const context = this.safeString(item, 'context'); // contains other information about the ledger entry
3823
+ //
3824
+ // withdrawal transaction
3825
+ //
3826
+ // "{\"orderId\":\"617bb2d09e7b3b000196dac8\",\"txId\":\"0x79bb9855f86b351a45cab4dc69d78ca09586a94c45dde49475722b98f401b054\"}"
3827
+ //
3828
+ // deposit to MAIN, trade via MAIN
3829
+ //
3830
+ // "{\"orderId\":\"617ab9949e7b3b0001948081\",\"txId\":\"0x7a06b16bbd6b03dbc3d96df5683b15229fc35e7184fd7179a5f3a310bd67d1fa@default@0\"}"
3831
+ //
3832
+ // sell trade
3833
+ //
3834
+ // "{\"symbol\":\"ETH-USDT\",\"orderId\":\"617adcd1eb3fa20001dd29a1\",\"tradeId\":\"617adcd12e113d2b91222ff9\"}"
3835
+ //
3836
+ let referenceId = undefined;
3837
+ if (context !== undefined && context !== '') {
3838
+ try {
3839
+ const parsed = JSON.parse(context);
3840
+ const orderId = this.safeString(parsed, 'orderId');
3841
+ const tradeId = this.safeString(parsed, 'tradeId');
3842
+ // transactions only have an orderId but for trades we wish to use tradeId
3843
+ if (tradeId !== undefined) {
3844
+ referenceId = tradeId;
3845
+ }
3846
+ else {
3847
+ referenceId = orderId;
3848
+ }
3849
+ }
3850
+ catch (exc) {
3851
+ referenceId = context;
3852
+ }
3853
+ }
3854
+ let fee = undefined;
3855
+ const feeCost = this.safeNumber(item, 'fee');
3856
+ let feeCurrency = undefined;
3857
+ if (feeCost !== 0) {
3858
+ feeCurrency = code;
3859
+ fee = { 'cost': feeCost, 'currency': feeCurrency };
3860
+ }
3861
+ return {
3862
+ 'id': id,
3863
+ 'direction': direction,
3864
+ 'account': account,
3865
+ 'referenceId': referenceId,
3866
+ 'referenceAccount': account,
3867
+ 'type': type,
3868
+ 'currency': code,
3869
+ 'amount': amount,
3870
+ 'timestamp': timestamp,
3871
+ 'datetime': datetime,
3872
+ 'before': undefined,
3873
+ 'after': balanceAfter,
3874
+ 'status': undefined,
3875
+ 'fee': fee,
3876
+ 'info': item,
3877
+ };
3878
+ }
3879
+ async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
3880
+ /**
3881
+ * @method
3882
+ * @name kucoin#fetchLedger
3883
+ * @see https://docs.kucoin.com/#get-account-ledgers
3884
+ * @see https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-trade_hf
3885
+ * @see https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-margin_hf
3886
+ * @description fetch the history of changes, actions done by the user or operations that altered balance of the user
3887
+ * @param {string} code unified currency code, default is undefined
3888
+ * @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
3889
+ * @param {int} [limit] max number of ledger entrys to return, default is undefined
3890
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3891
+ * @param {boolean} [params.hf] default false, when true will fetch ledger entries for the high frequency trading account
3892
+ * @param {int} [params.until] the latest time in ms to fetch entries for
3893
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3894
+ * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger-structure}
3895
+ */
3896
+ await this.loadMarkets();
3897
+ await this.loadAccounts();
3898
+ let paginate = false;
3899
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchLedger', 'paginate');
3900
+ const isHf = this.safeValue(params, 'hf');
3901
+ params = this.omit(params, 'hf');
3902
+ if (paginate) {
3903
+ return await this.fetchPaginatedCallDynamic('fetchLedger', code, since, limit, params);
3904
+ }
3905
+ let request = {
3906
+ // 'currency': currency['id'], // can choose up to 10, if not provided returns for all currencies by default
3907
+ // 'direction': 'in', // 'out'
3908
+ // 'bizType': 'DEPOSIT', // DEPOSIT, WITHDRAW, TRANSFER, SUB_TRANSFER,TRADE_EXCHANGE, MARGIN_EXCHANGE, KUCOIN_BONUS (optional)
3909
+ // 'startAt': since,
3910
+ // 'endAt': exchange.milliseconds (),
3911
+ };
3912
+ if (since !== undefined) {
3913
+ request['startAt'] = since;
3914
+ }
3915
+ // atm only single currency retrieval is supported
3916
+ let currency = undefined;
3917
+ if (code !== undefined) {
3918
+ currency = this.currency(code);
3919
+ request['currency'] = currency['id'];
3920
+ }
3921
+ [request, params] = this.handleUntilOption('endAt', request, params);
3922
+ let marginMode = undefined;
3923
+ [marginMode, params] = this.handleMarginModeAndParams('fetchLedger', params);
3924
+ let response = undefined;
3925
+ if (isHf) {
3926
+ if (marginMode !== undefined) {
3927
+ response = await this.privateGetHfMarginAccountLedgers(this.extend(request, params));
3928
+ }
3929
+ else {
3930
+ response = await this.privateGetHfAccountsLedgers(this.extend(request, params));
3931
+ }
3932
+ }
3933
+ else {
3934
+ response = await this.privateGetAccountsLedgers(this.extend(request, params));
3935
+ }
3936
+ //
3937
+ // {
3938
+ // "code":"200000",
3939
+ // "data":{
3940
+ // "currentPage":1,
3941
+ // "pageSize":50,
3942
+ // "totalNum":1,
3943
+ // "totalPage":1,
3944
+ // "items":[
3945
+ // {
3946
+ // "id":"617cc528729f5f0001c03ceb",
3947
+ // "currency":"GAS",
3948
+ // "amount":"0.00000339",
3949
+ // "fee":"0",
3950
+ // "balance":"0",
3951
+ // "accountType":"MAIN",
3952
+ // "bizType":"Distribution",
3953
+ // "direction":"in",
3954
+ // "createdAt":1635566888183,
3955
+ // "context":"{\"orderId\":\"617cc47a1c47ed0001ce3606\",\"description\":\"Holding NEO,distribute GAS(2021/10/30)\"}"
3956
+ // }
3957
+ // {
3958
+ // "id": "611a1e7c6a053300067a88d9",//unique key
3959
+ // "currency": "USDT", //Currency
3960
+ // "amount": "10.00059547", //Change amount of the funds
3961
+ // "fee": "0", //Deposit or withdrawal fee
3962
+ // "balance": "0", //Total assets of a currency
3963
+ // "accountType": "MAIN", //Account Type
3964
+ // "bizType": "Loans Repaid", //business type
3965
+ // "direction": "in", //side, in or out
3966
+ // "createdAt": 1629101692950, //Creation time
3967
+ // "context": "{\"borrowerUserId\":\"601ad03e50dc810006d242ea\",\"loanRepayDetailNo\":\"611a1e7cc913d000066cf7ec\"}"
3968
+ // },
3969
+ // ]
3970
+ // }
3971
+ // }
3972
+ //
3973
+ const data = this.safeValue(response, 'data');
3974
+ const items = this.safeValue(data, 'items', data);
3975
+ return this.parseLedger(items, currency, since, limit);
3976
+ }
3977
+ calculateRateLimiterCost(api, method, path, params, config = {}) {
3978
+ const versions = this.safeValue(this.options, 'versions', {});
3979
+ const apiVersions = this.safeValue(versions, api, {});
3980
+ const methodVersions = this.safeValue(apiVersions, method, {});
3981
+ const defaultVersion = this.safeString(methodVersions, path, this.options['version']);
3982
+ const version = this.safeString(params, 'version', defaultVersion);
3983
+ if (version === 'v3' && ('v3' in config)) {
3984
+ return config['v3'];
3985
+ }
3986
+ else if (version === 'v2' && ('v2' in config)) {
3987
+ return config['v2'];
3988
+ }
3989
+ else if (version === 'v1' && ('v1' in config)) {
3990
+ return config['v1'];
3991
+ }
3992
+ return this.safeValue(config, 'cost', 1);
3993
+ }
3994
+ parseBorrowRateHistory(response, code, since, limit) {
3995
+ const result = [];
3996
+ for (let i = 0; i < response.length; i++) {
3997
+ const item = response[i];
3998
+ const borrowRate = this.parseBorrowRate(item);
3999
+ result.push(borrowRate);
4000
+ }
4001
+ const sorted = this.sortBy(result, 'timestamp');
4002
+ return this.filterByCurrencySinceLimit(sorted, code, since, limit);
4003
+ }
4004
+ parseBorrowRate(info, currency = undefined) {
4005
+ //
4006
+ // {
4007
+ // "tradeId": "62db2dcaff219600012b56cd",
4008
+ // "currency": "USDT",
4009
+ // "size": "10",
4010
+ // "dailyIntRate": "0.00003",
4011
+ // "term": 7,
4012
+ // "timestamp": 1658531274508488480
4013
+ // },
4014
+ //
4015
+ const timestampId = this.safeString(info, 'timestamp');
4016
+ const timestamp = Precise["default"].stringMul(timestampId, '0.000001');
4017
+ const currencyId = this.safeString(info, 'currency');
4018
+ return {
4019
+ 'currency': this.safeCurrencyCode(currencyId, currency),
4020
+ 'rate': this.safeNumber(info, 'dailyIntRate'),
4021
+ 'period': 86400000,
4022
+ 'timestamp': timestamp,
4023
+ 'datetime': this.iso8601(timestamp),
4024
+ 'info': info,
4025
+ };
4026
+ }
4027
+ async fetchBorrowInterest(code = undefined, symbol = undefined, since = undefined, limit = undefined, params = {}) {
4028
+ /**
4029
+ * @method
4030
+ * @name kucoin#fetchBorrowInterest
4031
+ * @description fetch the interest owed by the user for borrowing currency for margin trading
4032
+ * @see https://docs.kucoin.com/#get-repay-record
4033
+ * @see https://docs.kucoin.com/#query-isolated-margin-account-info
4034
+ * @param {string} code unified currency code
4035
+ * @param {string} symbol unified market symbol, required for isolated margin
4036
+ * @param {int} [since] the earliest time in ms to fetch borrrow interest for
4037
+ * @param {int} [limit] the maximum number of structures to retrieve
4038
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4039
+ * @param {string} [params.marginMode] 'cross' or 'isolated' default is 'cross'
4040
+ * @returns {object[]} a list of [borrow interest structures]{@link https://docs.ccxt.com/#/?id=borrow-interest-structure}
4041
+ */
4042
+ await this.loadMarkets();
4043
+ let marginMode = undefined;
4044
+ [marginMode, params] = this.handleMarginModeAndParams('fetchBorrowInterest', params);
4045
+ if (marginMode === undefined) {
4046
+ marginMode = 'cross'; // cross as default marginMode
4047
+ }
4048
+ const request = {};
4049
+ let response = undefined;
4050
+ if (code !== undefined) {
4051
+ const currency = this.currency(code);
4052
+ request['quoteCurrency'] = currency['id'];
4053
+ }
4054
+ if (marginMode === 'isolated') {
4055
+ response = await this.privateGetIsolatedAccounts(this.extend(request, params));
4056
+ }
4057
+ else {
4058
+ response = await this.privateGetMarginAccounts(this.extend(request, params));
4059
+ }
4060
+ //
4061
+ // Cross
4062
+ //
4063
+ // {
4064
+ // "code": "200000",
4065
+ // "data": {
4066
+ // "totalAssetOfQuoteCurrency": "0",
4067
+ // "totalLiabilityOfQuoteCurrency": "0",
4068
+ // "debtRatio": "0",
4069
+ // "status": "EFFECTIVE",
4070
+ // "accounts": [
4071
+ // {
4072
+ // "currency": "1INCH",
4073
+ // "total": "0",
4074
+ // "available": "0",
4075
+ // "hold": "0",
4076
+ // "liability": "0",
4077
+ // "maxBorrowSize": "0",
4078
+ // "borrowEnabled": true,
4079
+ // "transferInEnabled": true
4080
+ // }
4081
+ // ]
4082
+ // }
4083
+ // }
4084
+ //
4085
+ // Isolated
4086
+ //
4087
+ // {
4088
+ // "code": "200000",
4089
+ // "data": {
4090
+ // "totalConversionBalance": "0.02138647",
4091
+ // "liabilityConversionBalance": "0.01480001",
4092
+ // "assets": [
4093
+ // {
4094
+ // "symbol": "MANA-USDT",
4095
+ // "debtRatio": "0",
4096
+ // "status": "BORROW",
4097
+ // "baseAsset": {
4098
+ // "currency": "MANA",
4099
+ // "borrowEnabled": true,
4100
+ // "repayEnabled": true,
4101
+ // "transferEnabled": true,
4102
+ // "borrowed": "0",
4103
+ // "totalAsset": "0",
4104
+ // "available": "0",
4105
+ // "hold": "0",
4106
+ // "maxBorrowSize": "1000"
4107
+ // },
4108
+ // "quoteAsset": {
4109
+ // "currency": "USDT",
4110
+ // "borrowEnabled": true,
4111
+ // "repayEnabled": true,
4112
+ // "transferEnabled": true,
4113
+ // "borrowed": "0",
4114
+ // "totalAsset": "0",
4115
+ // "available": "0",
4116
+ // "hold": "0",
4117
+ // "maxBorrowSize": "50000"
4118
+ // }
4119
+ // }
4120
+ // ]
4121
+ // }
4122
+ // }
4123
+ //
4124
+ const data = this.safeValue(response, 'data', {});
4125
+ const assets = (marginMode === 'isolated') ? this.safeValue(data, 'assets', []) : this.safeValue(data, 'accounts', []);
4126
+ return this.parseBorrowInterests(assets, undefined);
4127
+ }
4128
+ parseBorrowInterest(info, market = undefined) {
4129
+ //
4130
+ // Cross
4131
+ //
4132
+ // {
4133
+ // "currency": "1INCH",
4134
+ // "total": "0",
4135
+ // "available": "0",
4136
+ // "hold": "0",
4137
+ // "liability": "0",
4138
+ // "maxBorrowSize": "0",
4139
+ // "borrowEnabled": true,
4140
+ // "transferInEnabled": true
4141
+ // }
4142
+ //
4143
+ // Isolated
4144
+ //
4145
+ // {
4146
+ // "symbol": "MANA-USDT",
4147
+ // "debtRatio": "0",
4148
+ // "status": "BORROW",
4149
+ // "baseAsset": {
4150
+ // "currency": "MANA",
4151
+ // "borrowEnabled": true,
4152
+ // "repayEnabled": true,
4153
+ // "transferEnabled": true,
4154
+ // "borrowed": "0",
4155
+ // "totalAsset": "0",
4156
+ // "available": "0",
4157
+ // "hold": "0",
4158
+ // "maxBorrowSize": "1000"
4159
+ // },
4160
+ // "quoteAsset": {
4161
+ // "currency": "USDT",
4162
+ // "borrowEnabled": true,
4163
+ // "repayEnabled": true,
4164
+ // "transferEnabled": true,
4165
+ // "borrowed": "0",
4166
+ // "totalAsset": "0",
4167
+ // "available": "0",
4168
+ // "hold": "0",
4169
+ // "maxBorrowSize": "50000"
4170
+ // }
4171
+ // }
4172
+ //
4173
+ const marketId = this.safeString(info, 'symbol');
4174
+ const marginMode = (marketId === undefined) ? 'cross' : 'isolated';
4175
+ market = this.safeMarket(marketId, market);
4176
+ const symbol = this.safeString(market, 'symbol');
4177
+ const timestamp = this.safeInteger(info, 'createdAt');
4178
+ const isolatedBase = this.safeValue(info, 'baseAsset', {});
4179
+ let amountBorrowed = undefined;
4180
+ let interest = undefined;
4181
+ let currencyId = undefined;
4182
+ if (marginMode === 'isolated') {
4183
+ amountBorrowed = this.safeNumber(isolatedBase, 'liability');
4184
+ interest = this.safeNumber(isolatedBase, 'interest');
4185
+ currencyId = this.safeString(isolatedBase, 'currency');
4186
+ }
4187
+ else {
4188
+ amountBorrowed = this.safeNumber(info, 'liability');
4189
+ interest = this.safeNumber(info, 'accruedInterest');
4190
+ currencyId = this.safeString(info, 'currency');
4191
+ }
4192
+ return {
4193
+ 'symbol': symbol,
4194
+ 'marginMode': marginMode,
4195
+ 'currency': this.safeCurrencyCode(currencyId),
4196
+ 'interest': interest,
4197
+ 'interestRate': this.safeNumber(info, 'dailyIntRate'),
4198
+ 'amountBorrowed': amountBorrowed,
4199
+ 'timestamp': timestamp,
4200
+ 'datetime': this.iso8601(timestamp),
4201
+ 'info': info,
4202
+ };
4203
+ }
4204
+ async borrowCrossMargin(code, amount, params = {}) {
4205
+ /**
4206
+ * @method
4207
+ * @name kucoin#borrowCrossMargin
4208
+ * @description create a loan to borrow margin
4209
+ * @see https://docs.kucoin.com/#1-margin-borrowing
4210
+ * @param {string} code unified currency code of the currency to borrow
4211
+ * @param {float} amount the amount to borrow
4212
+ * @param {object} [params] extra parameters specific to the exchange API endpoints
4213
+ * @param {string} [params.timeInForce] either IOC or FOK
4214
+ * @returns {object} a [margin loan structure]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
4215
+ */
4216
+ await this.loadMarkets();
4217
+ const currency = this.currency(code);
4218
+ const request = {
4219
+ 'currency': currency['id'],
4220
+ 'size': this.currencyToPrecision(code, amount),
4221
+ 'timeInForce': 'FOK',
4222
+ };
4223
+ const response = await this.privatePostMarginBorrow(this.extend(request, params));
4224
+ //
4225
+ // {
4226
+ // "success": true,
4227
+ // "code": "200",
4228
+ // "msg": "success",
4229
+ // "retry": false,
4230
+ // "data": {
4231
+ // "orderNo": "5da6dba0f943c0c81f5d5db5",
4232
+ // "actualSize": 10
4233
+ // }
4234
+ // }
4235
+ //
4236
+ const data = this.safeValue(response, 'data', {});
4237
+ return this.parseMarginLoan(data, currency);
4238
+ }
4239
+ async borrowIsolatedMargin(symbol, code, amount, params = {}) {
4240
+ /**
4241
+ * @method
4242
+ * @name kucoin#borrowIsolatedMargin
4243
+ * @description create a loan to borrow margin
4244
+ * @see https://docs.kucoin.com/#1-margin-borrowing
4245
+ * @param {string} symbol unified market symbol, required for isolated margin
4246
+ * @param {string} code unified currency code of the currency to borrow
4247
+ * @param {float} amount the amount to borrow
4248
+ * @param {object} [params] extra parameters specific to the exchange API endpoints
4249
+ * @param {string} [params.timeInForce] either IOC or FOK
4250
+ * @returns {object} a [margin loan structure]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
4251
+ */
4252
+ await this.loadMarkets();
4253
+ const market = this.market(symbol);
4254
+ const currency = this.currency(code);
4255
+ const request = {
4256
+ 'currency': currency['id'],
4257
+ 'size': this.currencyToPrecision(code, amount),
4258
+ 'symbol': market['id'],
4259
+ 'timeInForce': 'FOK',
4260
+ 'isIsolated': true,
4261
+ };
4262
+ const response = await this.privatePostMarginBorrow(this.extend(request, params));
4263
+ //
4264
+ // {
4265
+ // "success": true,
4266
+ // "code": "200",
4267
+ // "msg": "success",
4268
+ // "retry": false,
4269
+ // "data": {
4270
+ // "orderNo": "5da6dba0f943c0c81f5d5db5",
4271
+ // "actualSize": 10
4272
+ // }
4273
+ // }
4274
+ //
4275
+ const data = this.safeValue(response, 'data', {});
4276
+ return this.parseMarginLoan(data, currency);
4277
+ }
4278
+ async repayCrossMargin(code, amount, params = {}) {
4279
+ /**
4280
+ * @method
4281
+ * @name kucoin#repayCrossMargin
4282
+ * @description repay borrowed margin and interest
4283
+ * @see https://docs.kucoin.com/#2-repayment
4284
+ * @param {string} code unified currency code of the currency to repay
4285
+ * @param {float} amount the amount to repay
4286
+ * @param {object} [params] extra parameters specific to the exchange API endpoints
4287
+ * @returns {object} a [margin loan structure]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
4288
+ */
4289
+ await this.loadMarkets();
4290
+ const currency = this.currency(code);
4291
+ const request = {
4292
+ 'currency': currency['id'],
4293
+ 'size': this.currencyToPrecision(code, amount),
4294
+ };
4295
+ const response = await this.privatePostMarginRepay(this.extend(request, params));
4296
+ //
4297
+ // {
4298
+ // "success": true,
4299
+ // "code": "200",
4300
+ // "msg": "success",
4301
+ // "retry": false,
4302
+ // "data": {
4303
+ // "orderNo": "5da6dba0f943c0c81f5d5db5",
4304
+ // "actualSize": 10
4305
+ // }
4306
+ // }
4307
+ //
4308
+ const data = this.safeValue(response, 'data', {});
4309
+ return this.parseMarginLoan(data, currency);
4310
+ }
4311
+ async repayIsolatedMargin(symbol, code, amount, params = {}) {
4312
+ /**
4313
+ * @method
4314
+ * @name kucoin#repayIsolatedMargin
4315
+ * @description repay borrowed margin and interest
4316
+ * @see https://docs.kucoin.com/#2-repayment
4317
+ * @param {string} symbol unified market symbol
4318
+ * @param {string} code unified currency code of the currency to repay
4319
+ * @param {float} amount the amount to repay
4320
+ * @param {object} [params] extra parameters specific to the exchange API endpoints
4321
+ * @returns {object} a [margin loan structure]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
4322
+ */
4323
+ await this.loadMarkets();
4324
+ const market = this.market(symbol);
4325
+ const currency = this.currency(code);
4326
+ const request = {
4327
+ 'currency': currency['id'],
4328
+ 'size': this.currencyToPrecision(code, amount),
4329
+ 'symbol': market['id'],
4330
+ 'isIsolated': true,
4331
+ };
4332
+ const response = await this.privatePostMarginRepay(this.extend(request, params));
4333
+ //
4334
+ // {
4335
+ // "success": true,
4336
+ // "code": "200",
4337
+ // "msg": "success",
4338
+ // "retry": false,
4339
+ // "data": {
4340
+ // "orderNo": "5da6dba0f943c0c81f5d5db5",
4341
+ // "actualSize": 10
4342
+ // }
4343
+ // }
4344
+ //
4345
+ const data = this.safeValue(response, 'data', {});
4346
+ return this.parseMarginLoan(data, currency);
4347
+ }
4348
+ parseMarginLoan(info, currency = undefined) {
4349
+ //
4350
+ // {
4351
+ // "orderNo": "5da6dba0f943c0c81f5d5db5",
4352
+ // "actualSize": 10
4353
+ // }
4354
+ //
4355
+ const timestamp = this.milliseconds();
4356
+ const currencyId = this.safeString(info, 'currency');
4357
+ return {
4358
+ 'id': this.safeString(info, 'orderNo'),
4359
+ 'currency': this.safeCurrencyCode(currencyId, currency),
4360
+ 'amount': this.safeNumber(info, 'actualSize'),
4361
+ 'symbol': undefined,
4362
+ 'timestamp': timestamp,
4363
+ 'datetime': this.iso8601(timestamp),
4364
+ 'info': info,
4365
+ };
4366
+ }
4367
+ async fetchDepositWithdrawFees(codes = undefined, params = {}) {
4368
+ /**
4369
+ * @method
4370
+ * @name kucoin#fetchDepositWithdrawFees
4371
+ * @description fetch deposit and withdraw fees - *IMPORTANT* use fetchDepositWithdrawFee to get more in-depth info
4372
+ * @see https://docs.kucoin.com/#get-currencies
4373
+ * @param {string[]|undefined} codes list of unified currency codes
4374
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4375
+ * @returns {object} a list of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure}
4376
+ */
4377
+ await this.loadMarkets();
4378
+ const response = await this.publicGetCurrencies(params);
4379
+ //
4380
+ // [
4381
+ // {
4382
+ // "currency": "CSP",
4383
+ // "name": "CSP",
4384
+ // "fullName": "Caspian",
4385
+ // "precision": 8,
4386
+ // "confirms": 12,
4387
+ // "contractAddress": "0xa6446d655a0c34bc4f05042ee88170d056cbaf45",
4388
+ // "withdrawalMinSize": "2000",
4389
+ // "withdrawalMinFee": "1000",
4390
+ // "isWithdrawEnabled": true,
4391
+ // "isDepositEnabled": true,
4392
+ // "isMarginEnabled": false,
4393
+ // "isDebitEnabled": false
4394
+ // },
4395
+ // ]
4396
+ //
4397
+ const data = this.safeValue(response, 'data', []);
4398
+ return this.parseDepositWithdrawFees(data, codes, 'currency');
4399
+ }
4400
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
4401
+ //
4402
+ // the v2 URL is https://openapi-v2.kucoin.com/api/v1/endpoint
4403
+ // ↑ ↑
4404
+ // ↑ ↑
4405
+ //
4406
+ const versions = this.safeValue(this.options, 'versions', {});
4407
+ const apiVersions = this.safeValue(versions, api, {});
4408
+ const methodVersions = this.safeValue(apiVersions, method, {});
4409
+ const defaultVersion = this.safeString(methodVersions, path, this.options['version']);
4410
+ const version = this.safeString(params, 'version', defaultVersion);
4411
+ params = this.omit(params, 'version');
4412
+ let endpoint = '/api/' + version + '/' + this.implodeParams(path, params);
4413
+ if (api === 'webExchange') {
4414
+ endpoint = '/' + this.implodeParams(path, params);
4415
+ }
4416
+ const query = this.omit(params, this.extractParams(path));
4417
+ let endpart = '';
4418
+ headers = (headers !== undefined) ? headers : {};
4419
+ let url = this.urls['api'][api];
4420
+ if (Object.keys(query).length) {
4421
+ if ((method === 'GET') || (method === 'DELETE')) {
4422
+ endpoint += '?' + this.rawencode(query);
4423
+ }
4424
+ else {
4425
+ body = this.json(query);
4426
+ endpart = body;
4427
+ headers['Content-Type'] = 'application/json';
4428
+ }
4429
+ }
4430
+ url = url + endpoint;
4431
+ const isFuturePrivate = (api === 'futuresPrivate');
4432
+ const isPrivate = (api === 'private');
4433
+ if (isPrivate || isFuturePrivate) {
4434
+ this.checkRequiredCredentials();
4435
+ const timestamp = this.nonce().toString();
4436
+ headers = this.extend({
4437
+ 'KC-API-KEY-VERSION': '2',
4438
+ 'KC-API-KEY': this.apiKey,
4439
+ 'KC-API-TIMESTAMP': timestamp,
4440
+ }, headers);
4441
+ const apiKeyVersion = this.safeString(headers, 'KC-API-KEY-VERSION');
4442
+ if (apiKeyVersion === '2') {
4443
+ const passphrase = this.hmac(this.encode(this.password), this.encode(this.secret), sha256.sha256, 'base64');
4444
+ headers['KC-API-PASSPHRASE'] = passphrase;
4445
+ }
4446
+ else {
4447
+ headers['KC-API-PASSPHRASE'] = this.password;
4448
+ }
4449
+ const payload = timestamp + method + endpoint + endpart;
4450
+ const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256.sha256, 'base64');
4451
+ headers['KC-API-SIGN'] = signature;
4452
+ let partner = this.safeValue(this.options, 'partner', {});
4453
+ partner = isFuturePrivate ? this.safeValue(partner, 'future', partner) : this.safeValue(partner, 'spot', partner);
4454
+ const partnerId = this.safeString(partner, 'id');
4455
+ const partnerSecret = this.safeString2(partner, 'secret', 'key');
4456
+ if ((partnerId !== undefined) && (partnerSecret !== undefined)) {
4457
+ const partnerPayload = timestamp + partnerId + this.apiKey;
4458
+ const partnerSignature = this.hmac(this.encode(partnerPayload), this.encode(partnerSecret), sha256.sha256, 'base64');
4459
+ headers['KC-API-PARTNER-SIGN'] = partnerSignature;
4460
+ headers['KC-API-PARTNER'] = partnerId;
4461
+ }
4462
+ }
4463
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
4464
+ }
4465
+ handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
4466
+ if (!response) {
4467
+ this.throwBroadlyMatchedException(this.exceptions['broad'], body, body);
4468
+ return undefined;
4469
+ }
4470
+ //
4471
+ // bad
4472
+ // { "code": "400100", "msg": "validation.createOrder.clientOidIsRequired" }
4473
+ // good
4474
+ // { code: '200000', data: { ... }}
4475
+ //
4476
+ const errorCode = this.safeString(response, 'code');
4477
+ const message = this.safeString2(response, 'msg', 'data', '');
4478
+ const feedback = this.id + ' ' + message;
4479
+ this.throwExactlyMatchedException(this.exceptions['exact'], message, feedback);
4480
+ this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
4481
+ this.throwBroadlyMatchedException(this.exceptions['broad'], body, feedback);
4482
+ if (errorCode !== '200000' && errorCode !== '200') {
4483
+ throw new errors.ExchangeError(feedback);
4484
+ }
4485
+ return undefined;
4486
+ }
4487
+ }
4488
+
4489
+ module.exports = kucoin;