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,2645 @@
1
+ 'use strict';
2
+
3
+ var exmo$1 = require('./abstract/exmo.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 sha512 = require('./static_dependencies/noble-hashes/sha512.js');
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * @class exmo
13
+ * @augments Exchange
14
+ */
15
+ class exmo extends exmo$1 {
16
+ describe() {
17
+ return this.deepExtend(super.describe(), {
18
+ 'id': 'exmo',
19
+ 'name': 'EXMO',
20
+ 'countries': ['LT'],
21
+ 'rateLimit': 350,
22
+ 'version': 'v1.1',
23
+ 'has': {
24
+ 'CORS': undefined,
25
+ 'spot': true,
26
+ 'margin': true,
27
+ 'swap': false,
28
+ 'future': false,
29
+ 'option': false,
30
+ 'addMargin': true,
31
+ 'cancelOrder': true,
32
+ 'cancelOrders': false,
33
+ 'createDepositAddress': false,
34
+ 'createOrder': true,
35
+ 'createStopLimitOrder': true,
36
+ 'createStopMarketOrder': true,
37
+ 'createStopOrder': true,
38
+ 'editOrder': true,
39
+ 'fetchAccounts': false,
40
+ 'fetchBalance': true,
41
+ 'fetchCanceledOrders': true,
42
+ 'fetchCurrencies': true,
43
+ 'fetchDeposit': true,
44
+ 'fetchDepositAddress': true,
45
+ 'fetchDeposits': true,
46
+ 'fetchDepositsWithdrawals': true,
47
+ 'fetchDepositWithdrawFee': 'emulated',
48
+ 'fetchDepositWithdrawFees': true,
49
+ 'fetchFundingHistory': false,
50
+ 'fetchFundingRate': false,
51
+ 'fetchFundingRateHistory': false,
52
+ 'fetchFundingRates': false,
53
+ 'fetchIndexOHLCV': false,
54
+ 'fetchMarginMode': false,
55
+ 'fetchMarkets': true,
56
+ 'fetchMarkOHLCV': false,
57
+ 'fetchMyTrades': true,
58
+ 'fetchOHLCV': true,
59
+ 'fetchOpenInterestHistory': false,
60
+ 'fetchOpenOrders': true,
61
+ 'fetchOrder': 'emulated',
62
+ 'fetchOrderBook': true,
63
+ 'fetchOrderBooks': true,
64
+ 'fetchOrderTrades': true,
65
+ 'fetchPositionMode': false,
66
+ 'fetchPremiumIndexOHLCV': false,
67
+ 'fetchTicker': true,
68
+ 'fetchTickers': true,
69
+ 'fetchTrades': true,
70
+ 'fetchTradingFee': false,
71
+ 'fetchTradingFees': true,
72
+ 'fetchTransactionFees': true,
73
+ 'fetchTransactions': 'emulated',
74
+ 'fetchTransfer': false,
75
+ 'fetchTransfers': false,
76
+ 'fetchWithdrawal': true,
77
+ 'fetchWithdrawals': true,
78
+ 'reduceMargin': true,
79
+ 'setMargin': false,
80
+ 'transfer': false,
81
+ 'withdraw': true,
82
+ },
83
+ 'timeframes': {
84
+ '1m': '1',
85
+ '5m': '5',
86
+ '15m': '15',
87
+ '30m': '30',
88
+ '45m': '45',
89
+ '1h': '60',
90
+ '2h': '120',
91
+ '3h': '180',
92
+ '4h': '240',
93
+ '1d': 'D',
94
+ '1w': 'W',
95
+ '1M': 'M',
96
+ },
97
+ 'urls': {
98
+ 'logo': 'https://user-images.githubusercontent.com/1294454/27766491-1b0ea956-5eda-11e7-9225-40d67b481b8d.jpg',
99
+ 'api': {
100
+ 'public': 'https://api.exmo.com',
101
+ 'private': 'https://api.exmo.com',
102
+ 'web': 'https://exmo.me',
103
+ },
104
+ 'www': 'https://exmo.me',
105
+ 'referral': 'https://exmo.me/?ref=131685',
106
+ 'doc': [
107
+ 'https://exmo.me/en/api_doc?ref=131685',
108
+ ],
109
+ 'fees': 'https://exmo.com/en/docs/fees',
110
+ },
111
+ 'api': {
112
+ 'web': {
113
+ 'get': [
114
+ 'ctrl/feesAndLimits',
115
+ 'en/docs/fees',
116
+ ],
117
+ },
118
+ 'public': {
119
+ 'get': [
120
+ 'currency',
121
+ 'currency/list/extended',
122
+ 'order_book',
123
+ 'pair_settings',
124
+ 'ticker',
125
+ 'trades',
126
+ 'candles_history',
127
+ 'required_amount',
128
+ 'payments/providers/crypto/list',
129
+ ],
130
+ },
131
+ 'private': {
132
+ 'post': [
133
+ 'user_info',
134
+ 'order_create',
135
+ 'order_cancel',
136
+ 'stop_market_order_create',
137
+ 'stop_market_order_cancel',
138
+ 'user_open_orders',
139
+ 'user_trades',
140
+ 'user_cancelled_orders',
141
+ 'order_trades',
142
+ 'deposit_address',
143
+ 'withdraw_crypt',
144
+ 'withdraw_get_txid',
145
+ 'excode_create',
146
+ 'excode_load',
147
+ 'code_check',
148
+ 'wallet_history',
149
+ 'wallet_operations',
150
+ 'margin/user/order/create',
151
+ 'margin/user/order/update',
152
+ 'margin/user/order/cancel',
153
+ 'margin/user/position/close',
154
+ 'margin/user/position/margin_add',
155
+ 'margin/user/position/margin_remove',
156
+ 'margin/currency/list',
157
+ 'margin/pair/list',
158
+ 'margin/settings',
159
+ 'margin/funding/list',
160
+ 'margin/user/info',
161
+ 'margin/user/order/list',
162
+ 'margin/user/order/history',
163
+ 'margin/user/order/trades',
164
+ 'margin/user/order/max_quantity',
165
+ 'margin/user/position/list',
166
+ 'margin/user/position/margin_remove_info',
167
+ 'margin/user/position/margin_add_info',
168
+ 'margin/user/wallet/list',
169
+ 'margin/user/wallet/history',
170
+ 'margin/user/trade/list',
171
+ 'margin/trades',
172
+ 'margin/liquidation/feed',
173
+ ],
174
+ },
175
+ },
176
+ 'fees': {
177
+ 'trading': {
178
+ 'feeSide': 'get',
179
+ 'tierBased': true,
180
+ 'percentage': true,
181
+ 'maker': this.parseNumber('0.004'),
182
+ 'taker': this.parseNumber('0.004'),
183
+ },
184
+ 'transaction': {
185
+ 'tierBased': false,
186
+ 'percentage': false, // fixed transaction fees for crypto, see fetchDepositWithdrawFees below
187
+ },
188
+ },
189
+ 'options': {
190
+ 'networks': {
191
+ 'ETH': 'ERC20',
192
+ 'TRX': 'TRC20',
193
+ },
194
+ 'fetchTradingFees': {
195
+ 'method': 'fetchPrivateTradingFees', // or 'fetchPublicTradingFees'
196
+ },
197
+ 'margin': {
198
+ 'fillResponseFromRequest': true,
199
+ },
200
+ },
201
+ 'commonCurrencies': {
202
+ 'GMT': 'GMT Token',
203
+ },
204
+ 'precisionMode': number.TICK_SIZE,
205
+ 'exceptions': {
206
+ 'exact': {
207
+ '140434': errors.BadRequest,
208
+ '40005': errors.AuthenticationError,
209
+ '40009': errors.InvalidNonce,
210
+ '40015': errors.ExchangeError,
211
+ '40016': errors.OnMaintenance,
212
+ '40017': errors.AuthenticationError,
213
+ '40032': errors.PermissionDenied,
214
+ '40033': errors.PermissionDenied,
215
+ '40034': errors.RateLimitExceeded,
216
+ '50052': errors.InsufficientFunds,
217
+ '50054': errors.InsufficientFunds,
218
+ '50304': errors.OrderNotFound,
219
+ '50173': errors.OrderNotFound,
220
+ '50277': errors.InvalidOrder,
221
+ '50319': errors.InvalidOrder,
222
+ '50321': errors.InvalidOrder,
223
+ '50381': errors.InvalidOrder, // {"result":false,"error":"Error 50381: More than 2 decimal places are not permitted for pair BTC_USD"}
224
+ },
225
+ 'broad': {
226
+ 'range period is too long': errors.BadRequest,
227
+ 'invalid syntax': errors.BadRequest,
228
+ 'API rate limit exceeded': errors.RateLimitExceeded, // {"result":false,"error":"API rate limit exceeded for x.x.x.x. Retry after 60 sec.","history":[],"begin":1579392000,"end":1579478400}
229
+ },
230
+ },
231
+ });
232
+ }
233
+ async modifyMarginHelper(symbol, amount, type, params = {}) {
234
+ await this.loadMarkets();
235
+ const market = this.market(symbol);
236
+ const request = {
237
+ 'position_id': market['id'],
238
+ 'quantity': amount,
239
+ };
240
+ let response = undefined;
241
+ if (type === 'add') {
242
+ response = await this.privatePostMarginUserPositionMarginAdd(this.extend(request, params));
243
+ }
244
+ else if (type === 'reduce') {
245
+ response = await this.privatePostMarginUserPositionMarginRemove(this.extend(request, params));
246
+ }
247
+ //
248
+ // {}
249
+ //
250
+ const margin = this.parseMarginModification(response, market);
251
+ const options = this.safeValue(this.options, 'margin', {});
252
+ const fillResponseFromRequest = this.safeValue(options, 'fillResponseFromRequest', true);
253
+ if (fillResponseFromRequest) {
254
+ margin['type'] = type;
255
+ margin['amount'] = amount;
256
+ }
257
+ return margin;
258
+ }
259
+ parseMarginModification(data, market = undefined) {
260
+ //
261
+ // {}
262
+ //
263
+ return {
264
+ 'info': data,
265
+ 'type': undefined,
266
+ 'amount': undefined,
267
+ 'code': this.safeValue(market, 'quote'),
268
+ 'symbol': this.safeSymbol(undefined, market),
269
+ 'total': undefined,
270
+ 'status': 'ok',
271
+ };
272
+ }
273
+ async reduceMargin(symbol, amount, params = {}) {
274
+ /**
275
+ * @method
276
+ * @name exmo#reduceMargin
277
+ * @description remove margin from a position
278
+ * @param {string} symbol unified market symbol
279
+ * @param {float} amount the amount of margin to remove
280
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
281
+ * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=reduce-margin-structure}
282
+ */
283
+ return await this.modifyMarginHelper(symbol, amount, 'reduce', params);
284
+ }
285
+ async addMargin(symbol, amount, params = {}) {
286
+ /**
287
+ * @method
288
+ * @name exmo#addMargin
289
+ * @description add margin
290
+ * @param {string} symbol unified market symbol
291
+ * @param {float} amount amount of margin to add
292
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
293
+ * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=add-margin-structure}
294
+ */
295
+ return await this.modifyMarginHelper(symbol, amount, 'add', params);
296
+ }
297
+ async fetchTradingFees(params = {}) {
298
+ /**
299
+ * @method
300
+ * @name exmo#fetchTradingFees
301
+ * @description fetch the trading fees for multiple markets
302
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
303
+ * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
304
+ */
305
+ const options = this.safeValue(this.options, 'fetchTradingFees', {});
306
+ const defaultMethod = this.safeString(options, 'method', 'fetchPrivateTradingFees');
307
+ const method = this.safeString(params, 'method', defaultMethod);
308
+ params = this.omit(params, 'method');
309
+ if (method === 'fetchPrivateTradingFees') {
310
+ return await this.fetchPrivateTradingFees(params);
311
+ }
312
+ else {
313
+ return await this.fetchPublicTradingFees(params);
314
+ }
315
+ }
316
+ async fetchPrivateTradingFees(params = {}) {
317
+ await this.loadMarkets();
318
+ const response = await this.privatePostMarginPairList(params);
319
+ //
320
+ // {
321
+ // "pairs": [{
322
+ // "name": "EXM_USD",
323
+ // "buy_price": "0.02728391",
324
+ // "sell_price": "0.0276",
325
+ // "last_trade_price": "0.0276",
326
+ // "ticker_updated": "1646956050056696046",
327
+ // "is_fair_price": true,
328
+ // "max_price_precision": "8",
329
+ // "min_order_quantity": "1",
330
+ // "max_order_quantity": "50000",
331
+ // "min_order_price": "0.00000001",
332
+ // "max_order_price": "1000",
333
+ // "max_position_quantity": "50000",
334
+ // "trade_taker_fee": "0.05",
335
+ // "trade_maker_fee": "0",
336
+ // "liquidation_fee": "0.5",
337
+ // "max_leverage": "3",
338
+ // "default_leverage": "3",
339
+ // "liquidation_level": "5",
340
+ // "margin_call_level": "7.5",
341
+ // "position": "1",
342
+ // "updated": "1638976144797807397"
343
+ // }
344
+ // ...
345
+ // ]
346
+ // }
347
+ //
348
+ const pairs = this.safeValue(response, 'pairs', []);
349
+ const result = {};
350
+ for (let i = 0; i < pairs.length; i++) {
351
+ const pair = pairs[i];
352
+ const marketId = this.safeString(pair, 'name');
353
+ const symbol = this.safeSymbol(marketId, undefined, '_');
354
+ const makerString = this.safeString(pair, 'trade_maker_fee');
355
+ const takerString = this.safeString(pair, 'trade_taker_fee');
356
+ const maker = this.parseNumber(Precise["default"].stringDiv(makerString, '100'));
357
+ const taker = this.parseNumber(Precise["default"].stringDiv(takerString, '100'));
358
+ result[symbol] = {
359
+ 'info': pair,
360
+ 'symbol': symbol,
361
+ 'maker': maker,
362
+ 'taker': taker,
363
+ 'percentage': true,
364
+ 'tierBased': true,
365
+ };
366
+ }
367
+ return result;
368
+ }
369
+ async fetchPublicTradingFees(params = {}) {
370
+ await this.loadMarkets();
371
+ const response = await this.publicGetPairSettings(params);
372
+ //
373
+ // {
374
+ // "BTC_USD": {
375
+ // "min_quantity": "0.00002",
376
+ // "max_quantity": "1000",
377
+ // "min_price": "1",
378
+ // "max_price": "150000",
379
+ // "max_amount": "500000",
380
+ // "min_amount": "1",
381
+ // "price_precision": "2",
382
+ // "commission_taker_percent": "0.3",
383
+ // "commission_maker_percent": "0.3"
384
+ // },
385
+ // }
386
+ //
387
+ const result = {};
388
+ for (let i = 0; i < this.symbols.length; i++) {
389
+ const symbol = this.symbols[i];
390
+ const market = this.market(symbol);
391
+ const fee = this.safeValue(response, market['id'], {});
392
+ const makerString = this.safeString(fee, 'commission_maker_percent');
393
+ const takerString = this.safeString(fee, 'commission_taker_percent');
394
+ const maker = this.parseNumber(Precise["default"].stringDiv(makerString, '100'));
395
+ const taker = this.parseNumber(Precise["default"].stringDiv(takerString, '100'));
396
+ result[symbol] = {
397
+ 'info': fee,
398
+ 'symbol': symbol,
399
+ 'maker': maker,
400
+ 'taker': taker,
401
+ 'percentage': true,
402
+ 'tierBased': true,
403
+ };
404
+ }
405
+ return result;
406
+ }
407
+ parseFixedFloatValue(input) {
408
+ if ((input === undefined) || (input === '-')) {
409
+ return undefined;
410
+ }
411
+ if (input === '') {
412
+ return 0;
413
+ }
414
+ const isPercentage = (input.indexOf('%') >= 0);
415
+ const parts = input.split(' ');
416
+ const value = parts[0].replace('%', '');
417
+ const result = parseFloat(value);
418
+ if ((result > 0) && isPercentage) {
419
+ throw new errors.ExchangeError(this.id + ' parseFixedFloatValue() detected an unsupported non-zero percentage-based fee ' + input);
420
+ }
421
+ return result;
422
+ }
423
+ async fetchTransactionFees(codes = undefined, params = {}) {
424
+ /**
425
+ * @method
426
+ * @name exmo#fetchTransactionFees
427
+ * @deprecated
428
+ * @description please use fetchDepositWithdrawFees instead
429
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2
430
+ * @param {string[]|undefined} codes list of unified currency codes
431
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
432
+ * @returns {object} a list of [transaction fees structures]{@link https://docs.ccxt.com/#/?id=fees-structure}
433
+ */
434
+ await this.loadMarkets();
435
+ const cryptoList = await this.publicGetPaymentsProvidersCryptoList(params);
436
+ //
437
+ // {
438
+ // "BTC":[
439
+ // { "type":"deposit", "name":"BTC", "currency_name":"BTC", "min":"0.001", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 0.001 BTC. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 },
440
+ // { "type":"withdraw", "name":"BTC", "currency_name":"BTC", "min":"0.001", "max":"350", "enabled":true,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"0.0005 BTC", "currency_confirmations":6 }
441
+ // ],
442
+ // "ETH":[
443
+ // { "type":"withdraw", "name":"ETH", "currency_name":"ETH", "min":"0.01", "max":"500", "enabled":true,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"0.004 ETH", "currency_confirmations":4 },
444
+ // { "type":"deposit", "name":"ETH", "currency_name":"ETH", "min":"0.01", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 0.01 ETH. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 }
445
+ // ],
446
+ // "USDT":[
447
+ // { "type":"deposit", "name":"USDT (OMNI)", "currency_name":"USDT", "min":"10", "max":"0", "enabled":false,"comment":"Minimum deposit amount is 10 USDT", "commission_desc":"0%", "currency_confirmations":2 },
448
+ // { "type":"withdraw", "name":"USDT (OMNI)", "currency_name":"USDT", "min":"10", "max":"100000", "enabled":false,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"5 USDT", "currency_confirmations":6 },
449
+ // { "type":"deposit", "name":"USDT (ERC20)", "currency_name":"USDT", "min":"10", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 10 USDT", "commission_desc":"0%", "currency_confirmations":2 },
450
+ // {
451
+ // "type":"withdraw",
452
+ // "name":"USDT (ERC20)",
453
+ // "currency_name":"USDT",
454
+ // "min":"55",
455
+ // "max":"200000",
456
+ // "enabled":true,
457
+ // "comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales. Recommendation: Due to the high load of ERC20 network, using TRC20 address for withdrawal is recommended.",
458
+ // "commission_desc":"10 USDT",
459
+ // "currency_confirmations":6
460
+ // },
461
+ // { "type":"deposit", "name":"USDT (TRC20)", "currency_name":"USDT", "min":"10", "max":"100000", "enabled":true,"comment":"Minimum deposit amount is 10 USDT. Only TRON main network supported", "commission_desc":"0%", "currency_confirmations":2 },
462
+ // { "type":"withdraw", "name":"USDT (TRC20)", "currency_name":"USDT", "min":"10", "max":"150000", "enabled":true,"comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales. Only TRON main network supported.", "commission_desc":"1 USDT", "currency_confirmations":6 }
463
+ // ],
464
+ // "XLM":[
465
+ // { "type":"deposit", "name":"XLM", "currency_name":"XLM", "min":"1", "max":"1000000", "enabled":true,"comment":"Attention! A deposit without memo(invoice) will not be credited. Minimum deposit amount is 1 XLM. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 },
466
+ // { "type":"withdraw", "name":"XLM", "currency_name":"XLM", "min":"21", "max":"1000000", "enabled":true,"comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales.", "commission_desc":"0.01 XLM", "currency_confirmations":1 }
467
+ // ],
468
+ // }
469
+ //
470
+ const result = {};
471
+ const cryptoListKeys = Object.keys(cryptoList);
472
+ for (let i = 0; i < cryptoListKeys.length; i++) {
473
+ const code = cryptoListKeys[i];
474
+ if (codes !== undefined && !this.inArray(code, codes)) {
475
+ continue;
476
+ }
477
+ result[code] = {
478
+ 'deposit': undefined,
479
+ 'withdraw': undefined,
480
+ };
481
+ const currency = this.currency(code);
482
+ const currencyId = this.safeString(currency, 'id');
483
+ const providers = this.safeValue(cryptoList, currencyId, []);
484
+ for (let j = 0; j < providers.length; j++) {
485
+ const provider = providers[j];
486
+ const typeInner = this.safeString(provider, 'type');
487
+ const commissionDesc = this.safeString(provider, 'commission_desc');
488
+ const fee = this.parseFixedFloatValue(commissionDesc);
489
+ result[code][typeInner] = fee;
490
+ }
491
+ result[code]['info'] = providers;
492
+ }
493
+ // cache them for later use
494
+ this.options['transactionFees'] = result;
495
+ return result;
496
+ }
497
+ async fetchDepositWithdrawFees(codes = undefined, params = {}) {
498
+ /**
499
+ * @method
500
+ * @name exmo#fetchDepositWithdrawFees
501
+ * @description fetch deposit and withdraw fees
502
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2
503
+ * @param {string[]|undefined} codes list of unified currency codes
504
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
505
+ * @returns {object} a list of [transaction fees structures]{@link https://docs.ccxt.com/#/?id=fees-structure}
506
+ */
507
+ await this.loadMarkets();
508
+ const response = await this.publicGetPaymentsProvidersCryptoList(params);
509
+ //
510
+ // {
511
+ // "USDT": [
512
+ // {
513
+ // "type": "deposit", // or "withdraw"
514
+ // "name": "USDT (ERC20)",
515
+ // "currency_name": "USDT",
516
+ // "min": "10",
517
+ // "max": "0",
518
+ // "enabled": true,
519
+ // "comment": "Minimum deposit amount is 10 USDT",
520
+ // "commission_desc": "0%",
521
+ // "currency_confirmations": 2
522
+ // },
523
+ // ...
524
+ // ],
525
+ // ...
526
+ // }
527
+ //
528
+ const result = this.parseDepositWithdrawFees(response, codes);
529
+ // cache them for later use
530
+ this.options['transactionFees'] = result;
531
+ return result;
532
+ }
533
+ parseDepositWithdrawFee(fee, currency = undefined) {
534
+ //
535
+ // [
536
+ // {
537
+ // "type": "deposit", // or "withdraw"
538
+ // "name": "BTC",
539
+ // "currency_name": "BTC",
540
+ // "min": "0.001",
541
+ // "max": "0",
542
+ // "enabled": true,
543
+ // "comment": "Minimum deposit amount is 0.001 BTC. We do not support BSC and BEP20 network, please consider this when sending funds",
544
+ // "commission_desc": "0%",
545
+ // "currency_confirmations": 1
546
+ // },
547
+ // ...
548
+ // ]
549
+ //
550
+ const result = this.depositWithdrawFee(fee);
551
+ for (let i = 0; i < fee.length; i++) {
552
+ const provider = fee[i];
553
+ const type = this.safeString(provider, 'type');
554
+ const networkId = this.safeString(provider, 'name');
555
+ const networkCode = this.networkIdToCode(networkId, this.safeString(currency, 'code'));
556
+ const commissionDesc = this.safeString(provider, 'commission_desc');
557
+ let splitCommissionDesc = [];
558
+ let percentage = undefined;
559
+ if (commissionDesc !== undefined) {
560
+ splitCommissionDesc = commissionDesc.split('%');
561
+ const splitCommissionDescLength = splitCommissionDesc.length;
562
+ percentage = splitCommissionDescLength >= 2;
563
+ }
564
+ const network = this.safeValue(result['networks'], networkCode);
565
+ if (network === undefined) {
566
+ result['networks'][networkCode] = {
567
+ 'withdraw': {
568
+ 'fee': undefined,
569
+ 'percentage': undefined,
570
+ },
571
+ 'deposit': {
572
+ 'fee': undefined,
573
+ 'percentage': undefined,
574
+ },
575
+ };
576
+ }
577
+ result['networks'][networkCode][type] = {
578
+ 'fee': this.parseFixedFloatValue(this.safeString(splitCommissionDesc, 0)),
579
+ 'percentage': percentage,
580
+ };
581
+ }
582
+ return this.assignDefaultDepositWithdrawFees(result);
583
+ }
584
+ async fetchCurrencies(params = {}) {
585
+ /**
586
+ * @method
587
+ * @name exmo#fetchCurrencies
588
+ * @description fetches all available currencies on an exchange
589
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
590
+ * @returns {object} an associative dictionary of currencies
591
+ */
592
+ //
593
+ const currencyList = await this.publicGetCurrencyListExtended(params);
594
+ //
595
+ // [
596
+ // {"name":"VLX","description":"Velas"},
597
+ // {"name":"RUB","description":"Russian Ruble"},
598
+ // {"name":"BTC","description":"Bitcoin"},
599
+ // {"name":"USD","description":"US Dollar"}
600
+ // ]
601
+ //
602
+ const cryptoList = await this.publicGetPaymentsProvidersCryptoList(params);
603
+ //
604
+ // {
605
+ // "BTC":[
606
+ // { "type":"deposit", "name":"BTC", "currency_name":"BTC", "min":"0.001", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 0.001 BTC. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 },
607
+ // { "type":"withdraw", "name":"BTC", "currency_name":"BTC", "min":"0.001", "max":"350", "enabled":true,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"0.0005 BTC", "currency_confirmations":6 }
608
+ // ],
609
+ // "ETH":[
610
+ // { "type":"withdraw", "name":"ETH", "currency_name":"ETH", "min":"0.01", "max":"500", "enabled":true,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"0.004 ETH", "currency_confirmations":4 },
611
+ // { "type":"deposit", "name":"ETH", "currency_name":"ETH", "min":"0.01", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 0.01 ETH. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 }
612
+ // ],
613
+ // "USDT":[
614
+ // { "type":"deposit", "name":"USDT (OMNI)", "currency_name":"USDT", "min":"10", "max":"0", "enabled":false,"comment":"Minimum deposit amount is 10 USDT", "commission_desc":"0%", "currency_confirmations":2 },
615
+ // { "type":"withdraw", "name":"USDT (OMNI)", "currency_name":"USDT", "min":"10", "max":"100000", "enabled":false,"comment":"Do not withdraw directly to the Crowdfunding or ICO address as your account will not be credited with tokens from such sales.", "commission_desc":"5 USDT", "currency_confirmations":6 },
616
+ // { "type":"deposit", "name":"USDT (ERC20)", "currency_name":"USDT", "min":"10", "max":"0", "enabled":true,"comment":"Minimum deposit amount is 10 USDT", "commission_desc":"0%", "currency_confirmations":2 },
617
+ // { "type":"withdraw", "name":"USDT (ERC20)", "currency_name":"USDT", "min":"55", "max":"200000", "enabled":true, "comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales. Recommendation: Due to the high load of ERC20 network, using TRC20 address for withdrawal is recommended.", "commission_desc":"10 USDT", "currency_confirmations":6 },
618
+ // { "type":"deposit", "name":"USDT (TRC20)", "currency_name":"USDT", "min":"10", "max":"100000", "enabled":true,"comment":"Minimum deposit amount is 10 USDT. Only TRON main network supported", "commission_desc":"0%", "currency_confirmations":2 },
619
+ // { "type":"withdraw", "name":"USDT (TRC20)", "currency_name":"USDT", "min":"10", "max":"150000", "enabled":true,"comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales. Only TRON main network supported.", "commission_desc":"1 USDT", "currency_confirmations":6 }
620
+ // ],
621
+ // "XLM":[
622
+ // { "type":"deposit", "name":"XLM", "currency_name":"XLM", "min":"1", "max":"1000000", "enabled":true,"comment":"Attention! A deposit without memo(invoice) will not be credited. Minimum deposit amount is 1 XLM. We do not support BSC and BEP20 network, please consider this when sending funds", "commission_desc":"0%", "currency_confirmations":1 },
623
+ // { "type":"withdraw", "name":"XLM", "currency_name":"XLM", "min":"21", "max":"1000000", "enabled":true,"comment":"Caution! Do not withdraw directly to a crowdfund or ICO address, as your account will not be credited with tokens from such sales.", "commission_desc":"0.01 XLM", "currency_confirmations":1 }
624
+ // ],
625
+ // }
626
+ //
627
+ const result = {};
628
+ for (let i = 0; i < currencyList.length; i++) {
629
+ const currency = currencyList[i];
630
+ const currencyId = this.safeString(currency, 'name');
631
+ const name = this.safeString(currency, 'description');
632
+ const providers = this.safeValue(cryptoList, currencyId);
633
+ let active = false;
634
+ let type = 'crypto';
635
+ const limits = {
636
+ 'deposit': {
637
+ 'min': undefined,
638
+ 'max': undefined,
639
+ },
640
+ 'withdraw': {
641
+ 'min': undefined,
642
+ 'max': undefined,
643
+ },
644
+ };
645
+ let fee = undefined;
646
+ let depositEnabled = undefined;
647
+ let withdrawEnabled = undefined;
648
+ if (providers === undefined) {
649
+ active = true;
650
+ type = 'fiat';
651
+ }
652
+ else {
653
+ for (let j = 0; j < providers.length; j++) {
654
+ const provider = providers[j];
655
+ const typeInner = this.safeString(provider, 'type');
656
+ const minValue = this.safeString(provider, 'min');
657
+ let maxValue = this.safeString(provider, 'max');
658
+ if (Precise["default"].stringEq(maxValue, '0.0')) {
659
+ maxValue = undefined;
660
+ }
661
+ const activeProvider = this.safeValue(provider, 'enabled');
662
+ if (typeInner === 'deposit') {
663
+ if (activeProvider && !depositEnabled) {
664
+ depositEnabled = true;
665
+ }
666
+ else if (!activeProvider) {
667
+ depositEnabled = false;
668
+ }
669
+ }
670
+ else if (typeInner === 'withdraw') {
671
+ if (activeProvider && !withdrawEnabled) {
672
+ withdrawEnabled = true;
673
+ }
674
+ else if (!activeProvider) {
675
+ withdrawEnabled = false;
676
+ }
677
+ }
678
+ if (activeProvider) {
679
+ active = true;
680
+ const limitMin = this.numberToString(limits[typeInner]['min']);
681
+ if ((limits[typeInner]['min'] === undefined) || (Precise["default"].stringLt(minValue, limitMin))) {
682
+ limits[typeInner]['min'] = minValue;
683
+ limits[typeInner]['max'] = maxValue;
684
+ if (typeInner === 'withdraw') {
685
+ const commissionDesc = this.safeString(provider, 'commission_desc');
686
+ fee = this.parseFixedFloatValue(commissionDesc);
687
+ }
688
+ }
689
+ }
690
+ }
691
+ }
692
+ const code = this.safeCurrencyCode(currencyId);
693
+ result[code] = {
694
+ 'id': currencyId,
695
+ 'code': code,
696
+ 'name': name,
697
+ 'type': type,
698
+ 'active': active,
699
+ 'deposit': depositEnabled,
700
+ 'withdraw': withdrawEnabled,
701
+ 'fee': fee,
702
+ 'precision': this.parseNumber('1e-8'),
703
+ 'limits': limits,
704
+ 'info': providers,
705
+ 'networks': {},
706
+ };
707
+ }
708
+ return result;
709
+ }
710
+ async fetchMarkets(params = {}) {
711
+ /**
712
+ * @method
713
+ * @name exmo#fetchMarkets
714
+ * @description retrieves data on all markets for exmo
715
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
716
+ * @returns {object[]} an array of objects representing market data
717
+ */
718
+ const response = await this.publicGetPairSettings(params);
719
+ //
720
+ // {
721
+ // "BTC_USD":{
722
+ // "min_quantity":"0.0001",
723
+ // "max_quantity":"1000",
724
+ // "min_price":"1",
725
+ // "max_price":"30000",
726
+ // "max_amount":"500000",
727
+ // "min_amount":"1",
728
+ // "price_precision":8,
729
+ // "commission_taker_percent":"0.4",
730
+ // "commission_maker_percent":"0.4"
731
+ // },
732
+ // }
733
+ //
734
+ let marginPairsDict = {};
735
+ if (this.checkRequiredCredentials(false)) {
736
+ const marginPairs = await this.privatePostMarginPairList(params);
737
+ //
738
+ // {
739
+ // "pairs": [
740
+ // {
741
+ // "buy_price": "55978.85",
742
+ // "default_leverage": "3",
743
+ // "is_fair_price": true,
744
+ // "last_trade_price": "55999.23",
745
+ // "liquidation_fee": "2",
746
+ // "liquidation_level": "10",
747
+ // "margin_call_level": "15",
748
+ // "max_leverage": "3",
749
+ // "max_order_price": "150000",
750
+ // "max_order_quantity": "1",
751
+ // "max_position_quantity": "1",
752
+ // "max_price_precision": 2,
753
+ // "min_order_price": "1",
754
+ // "min_order_quantity": "0.00002",
755
+ // "name": "BTC_USD",
756
+ // "position": 1,
757
+ // "sell_price": "55985.51",
758
+ // "ticker_updated": "1619019818936107989",
759
+ // "trade_maker_fee": "0",
760
+ // "trade_taker_fee": "0.05",
761
+ // "updated": "1619008608955599013"
762
+ // }
763
+ // ]
764
+ // }
765
+ //
766
+ const pairs = this.safeValue(marginPairs, 'pairs');
767
+ marginPairsDict = this.indexBy(pairs, 'name');
768
+ }
769
+ const keys = Object.keys(response);
770
+ const result = [];
771
+ for (let i = 0; i < keys.length; i++) {
772
+ const id = keys[i];
773
+ const market = response[id];
774
+ const marginMarket = this.safeValue(marginPairsDict, id);
775
+ const symbol = id.replace('_', '/');
776
+ const [baseId, quoteId] = symbol.split('/');
777
+ const base = this.safeCurrencyCode(baseId);
778
+ const quote = this.safeCurrencyCode(quoteId);
779
+ const takerString = this.safeString(market, 'commission_taker_percent');
780
+ const makerString = this.safeString(market, 'commission_maker_percent');
781
+ const maxQuantity = this.safeString(market, 'max_quantity');
782
+ const marginMaxQuantity = this.safeString(marginMarket, 'max_order_quantity');
783
+ result.push({
784
+ 'id': id,
785
+ 'symbol': symbol,
786
+ 'base': base,
787
+ 'quote': quote,
788
+ 'settle': undefined,
789
+ 'baseId': baseId,
790
+ 'quoteId': quoteId,
791
+ 'settleId': undefined,
792
+ 'type': 'spot',
793
+ 'spot': true,
794
+ 'margin': marginMarket !== undefined,
795
+ 'swap': false,
796
+ 'future': false,
797
+ 'option': false,
798
+ 'active': undefined,
799
+ 'contract': false,
800
+ 'linear': undefined,
801
+ 'inverse': undefined,
802
+ 'taker': this.parseNumber(Precise["default"].stringDiv(takerString, '100')),
803
+ 'maker': this.parseNumber(Precise["default"].stringDiv(makerString, '100')),
804
+ 'contractSize': undefined,
805
+ 'expiry': undefined,
806
+ 'expiryDatetime': undefined,
807
+ 'strike': undefined,
808
+ 'optionType': undefined,
809
+ 'precision': {
810
+ 'amount': this.parseNumber('1e-8'),
811
+ 'price': this.parseNumber(this.parsePrecision(this.safeString(market, 'price_precision'))),
812
+ },
813
+ 'limits': {
814
+ 'leverage': {
815
+ 'min': undefined,
816
+ 'max': this.safeNumber(market, 'leverage'),
817
+ },
818
+ 'amount': {
819
+ 'min': this.safeNumber(market, 'min_quantity'),
820
+ 'max': this.parseNumber(Precise["default"].stringMax(maxQuantity, marginMaxQuantity)),
821
+ },
822
+ 'price': {
823
+ 'min': this.safeNumber(market, 'min_price'),
824
+ 'max': this.safeNumber(market, 'max_price'),
825
+ },
826
+ 'cost': {
827
+ 'min': this.safeNumber(market, 'min_amount'),
828
+ 'max': this.safeNumber(market, 'max_amount'),
829
+ },
830
+ },
831
+ 'created': undefined,
832
+ 'info': market,
833
+ });
834
+ }
835
+ return result;
836
+ }
837
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
838
+ /**
839
+ * @method
840
+ * @name exmo#fetchOHLCV
841
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
842
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
843
+ * @param {string} timeframe the length of time each candle represents
844
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
845
+ * @param {int} [limit] the maximum amount of candles to fetch
846
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
847
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
848
+ */
849
+ await this.loadMarkets();
850
+ const market = this.market(symbol);
851
+ const request = {
852
+ 'symbol': market['id'],
853
+ 'resolution': this.safeString(this.timeframes, timeframe, timeframe),
854
+ };
855
+ const options = this.safeValue(this.options, 'fetchOHLCV');
856
+ const maxLimit = this.safeInteger(options, 'maxLimit', 3000);
857
+ const duration = this.parseTimeframe(timeframe);
858
+ const now = this.milliseconds();
859
+ if (since === undefined) {
860
+ if (limit === undefined) {
861
+ limit = 1000; // cap default at generous amount
862
+ }
863
+ if (limit > maxLimit) {
864
+ limit = maxLimit; // avoid exception
865
+ }
866
+ request['from'] = this.parseToInt(now / 1000) - limit * duration - 1;
867
+ request['to'] = this.parseToInt(now / 1000);
868
+ }
869
+ else {
870
+ request['from'] = this.parseToInt(since / 1000) - 1;
871
+ if (limit === undefined) {
872
+ request['to'] = this.parseToInt(now / 1000);
873
+ }
874
+ else {
875
+ if (limit > maxLimit) {
876
+ throw new errors.BadRequest(this.id + ' fetchOHLCV() will serve ' + maxLimit.toString() + ' candles at most');
877
+ }
878
+ const to = this.sum(since, limit * duration * 1000);
879
+ request['to'] = this.parseToInt(to / 1000);
880
+ }
881
+ }
882
+ const response = await this.publicGetCandlesHistory(this.extend(request, params));
883
+ //
884
+ // {
885
+ // "candles":[
886
+ // {"t":1584057600000,"o":0.02235144,"c":0.02400233,"h":0.025171,"l":0.02221,"v":5988.34031761},
887
+ // {"t":1584144000000,"o":0.0240373,"c":0.02367413,"h":0.024399,"l":0.0235,"v":2027.82522329},
888
+ // {"t":1584230400000,"o":0.02363458,"c":0.02319242,"h":0.0237948,"l":0.02223196,"v":1707.96944997},
889
+ // ]
890
+ // }
891
+ //
892
+ const candles = this.safeValue(response, 'candles', []);
893
+ return this.parseOHLCVs(candles, market, timeframe, since, limit);
894
+ }
895
+ parseOHLCV(ohlcv, market = undefined) {
896
+ //
897
+ // {
898
+ // "t":1584057600000,
899
+ // "o":0.02235144,
900
+ // "c":0.02400233,
901
+ // "h":0.025171,
902
+ // "l":0.02221,
903
+ // "v":5988.34031761
904
+ // }
905
+ //
906
+ return [
907
+ this.safeInteger(ohlcv, 't'),
908
+ this.safeNumber(ohlcv, 'o'),
909
+ this.safeNumber(ohlcv, 'h'),
910
+ this.safeNumber(ohlcv, 'l'),
911
+ this.safeNumber(ohlcv, 'c'),
912
+ this.safeNumber(ohlcv, 'v'),
913
+ ];
914
+ }
915
+ parseBalance(response) {
916
+ const result = { 'info': response };
917
+ const wallets = this.safeValue(response, 'wallets');
918
+ if (wallets !== undefined) {
919
+ const currencyIds = Object.keys(wallets);
920
+ for (let i = 0; i < currencyIds.length; i++) {
921
+ const currencyId = currencyIds[i];
922
+ const item = wallets[currencyId];
923
+ const currency = this.safeCurrencyCode(currencyId);
924
+ const account = this.account();
925
+ account['used'] = this.safeString(item, 'used');
926
+ account['free'] = this.safeString(item, 'free');
927
+ account['total'] = this.safeString(item, 'balance');
928
+ result[currency] = account;
929
+ }
930
+ }
931
+ else {
932
+ const free = this.safeValue(response, 'balances', {});
933
+ const used = this.safeValue(response, 'reserved', {});
934
+ const currencyIds = Object.keys(free);
935
+ for (let i = 0; i < currencyIds.length; i++) {
936
+ const currencyId = currencyIds[i];
937
+ const code = this.safeCurrencyCode(currencyId);
938
+ const account = this.account();
939
+ if (currencyId in free) {
940
+ account['free'] = this.safeString(free, currencyId);
941
+ }
942
+ if (currencyId in used) {
943
+ account['used'] = this.safeString(used, currencyId);
944
+ }
945
+ result[code] = account;
946
+ }
947
+ }
948
+ return this.safeBalance(result);
949
+ }
950
+ async fetchBalance(params = {}) {
951
+ /**
952
+ * @method
953
+ * @name exmo#fetchBalance
954
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
955
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
956
+ * @param {string} [params.marginMode] *isolated* fetches the isolated margin balance
957
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
958
+ */
959
+ await this.loadMarkets();
960
+ let marginMode = undefined;
961
+ [marginMode, params] = this.handleMarginModeAndParams('fetchBalance', params);
962
+ if (marginMode === 'cross') {
963
+ throw new errors.BadRequest(this.id + ' does not support cross margin');
964
+ }
965
+ let response = undefined;
966
+ if (marginMode === 'isolated') {
967
+ response = await this.privatePostMarginUserWalletList(params);
968
+ //
969
+ // {
970
+ // "wallets": {
971
+ // "USD": {
972
+ // "balance": "1000",
973
+ // "free": "600",
974
+ // "used": "400"
975
+ // }
976
+ // }
977
+ // }
978
+ //
979
+ }
980
+ else {
981
+ response = await this.privatePostUserInfo(params);
982
+ //
983
+ // {
984
+ // "uid":131685,
985
+ // "server_date":1628999600,
986
+ // "balances":{
987
+ // "EXM":"0",
988
+ // "USD":"0",
989
+ // "EUR":"0",
990
+ // "GBP":"0",
991
+ // },
992
+ // }
993
+ //
994
+ }
995
+ return this.parseBalance(response);
996
+ }
997
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
998
+ /**
999
+ * @method
1000
+ * @name exmo#fetchOrderBook
1001
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1002
+ * @param {string} symbol unified symbol of the market to fetch the order book for
1003
+ * @param {int} [limit] the maximum amount of order book entries to return
1004
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1005
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
1006
+ */
1007
+ await this.loadMarkets();
1008
+ const market = this.market(symbol);
1009
+ const request = {
1010
+ 'pair': market['id'],
1011
+ };
1012
+ if (limit !== undefined) {
1013
+ request['limit'] = limit;
1014
+ }
1015
+ const response = await this.publicGetOrderBook(this.extend(request, params));
1016
+ const result = this.safeValue(response, market['id']);
1017
+ return this.parseOrderBook(result, market['symbol'], undefined, 'bid', 'ask');
1018
+ }
1019
+ async fetchOrderBooks(symbols = undefined, limit = undefined, params = {}) {
1020
+ /**
1021
+ * @method
1022
+ * @name exmo#fetchOrderBooks
1023
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data for multiple markets
1024
+ * @param {string[]|undefined} symbols list of unified market symbols, all symbols fetched if undefined, default is undefined
1025
+ * @param {int} [limit] max number of entries per orderbook to return, default is undefined
1026
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1027
+ * @returns {object} a dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbol
1028
+ */
1029
+ await this.loadMarkets();
1030
+ let ids = undefined;
1031
+ if (symbols === undefined) {
1032
+ ids = this.ids.join(',');
1033
+ // max URL length is 2083 symbols, including http schema, hostname, tld, etc...
1034
+ if (ids.length > 2048) {
1035
+ const numIds = this.ids.length;
1036
+ throw new errors.ExchangeError(this.id + ' fetchOrderBooks() has ' + numIds.toString() + ' symbols exceeding max URL length, you are required to specify a list of symbols in the first argument to fetchOrderBooks');
1037
+ }
1038
+ }
1039
+ else {
1040
+ ids = this.marketIds(symbols);
1041
+ ids = ids.join(',');
1042
+ }
1043
+ const request = {
1044
+ 'pair': ids,
1045
+ };
1046
+ if (limit !== undefined) {
1047
+ request['limit'] = limit;
1048
+ }
1049
+ const response = await this.publicGetOrderBook(this.extend(request, params));
1050
+ const result = {};
1051
+ const marketIds = Object.keys(response);
1052
+ for (let i = 0; i < marketIds.length; i++) {
1053
+ const marketId = marketIds[i];
1054
+ const symbol = this.safeSymbol(marketId);
1055
+ result[symbol] = this.parseOrderBook(response[marketId], symbol, undefined, 'bid', 'ask');
1056
+ }
1057
+ return result;
1058
+ }
1059
+ parseTicker(ticker, market = undefined) {
1060
+ //
1061
+ // {
1062
+ // "buy_price":"0.00002996",
1063
+ // "sell_price":"0.00003002",
1064
+ // "last_trade":"0.00002992",
1065
+ // "high":"0.00003028",
1066
+ // "low":"0.00002935",
1067
+ // "avg":"0.00002963",
1068
+ // "vol":"1196546.3163222",
1069
+ // "vol_curr":"35.80066578",
1070
+ // "updated":1642291733
1071
+ // }
1072
+ //
1073
+ const timestamp = this.safeTimestamp(ticker, 'updated');
1074
+ market = this.safeMarket(undefined, market);
1075
+ const last = this.safeString(ticker, 'last_trade');
1076
+ return this.safeTicker({
1077
+ 'symbol': market['symbol'],
1078
+ 'timestamp': timestamp,
1079
+ 'datetime': this.iso8601(timestamp),
1080
+ 'high': this.safeString(ticker, 'high'),
1081
+ 'low': this.safeString(ticker, 'low'),
1082
+ 'bid': this.safeString(ticker, 'buy_price'),
1083
+ 'bidVolume': undefined,
1084
+ 'ask': this.safeString(ticker, 'sell_price'),
1085
+ 'askVolume': undefined,
1086
+ 'vwap': undefined,
1087
+ 'open': undefined,
1088
+ 'close': last,
1089
+ 'last': last,
1090
+ 'previousClose': undefined,
1091
+ 'change': undefined,
1092
+ 'percentage': undefined,
1093
+ 'average': this.safeString(ticker, 'avg'),
1094
+ 'baseVolume': this.safeString(ticker, 'vol'),
1095
+ 'quoteVolume': this.safeString(ticker, 'vol_curr'),
1096
+ 'info': ticker,
1097
+ }, market);
1098
+ }
1099
+ async fetchTickers(symbols = undefined, params = {}) {
1100
+ /**
1101
+ * @method
1102
+ * @name exmo#fetchTickers
1103
+ * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1104
+ * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1105
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1106
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1107
+ */
1108
+ await this.loadMarkets();
1109
+ symbols = this.marketSymbols(symbols);
1110
+ const response = await this.publicGetTicker(params);
1111
+ //
1112
+ // {
1113
+ // "ADA_BTC":{
1114
+ // "buy_price":"0.00002996",
1115
+ // "sell_price":"0.00003002",
1116
+ // "last_trade":"0.00002992",
1117
+ // "high":"0.00003028",
1118
+ // "low":"0.00002935",
1119
+ // "avg":"0.00002963",
1120
+ // "vol":"1196546.3163222",
1121
+ // "vol_curr":"35.80066578",
1122
+ // "updated":1642291733
1123
+ // }
1124
+ // }
1125
+ //
1126
+ const result = {};
1127
+ const marketIds = Object.keys(response);
1128
+ for (let i = 0; i < marketIds.length; i++) {
1129
+ const marketId = marketIds[i];
1130
+ const market = this.safeMarket(marketId, undefined, '_');
1131
+ const symbol = market['symbol'];
1132
+ const ticker = this.safeValue(response, marketId);
1133
+ result[symbol] = this.parseTicker(ticker, market);
1134
+ }
1135
+ return this.filterByArrayTickers(result, 'symbol', symbols);
1136
+ }
1137
+ async fetchTicker(symbol, params = {}) {
1138
+ /**
1139
+ * @method
1140
+ * @name exmo#fetchTicker
1141
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1142
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
1143
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1144
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1145
+ */
1146
+ await this.loadMarkets();
1147
+ const response = await this.publicGetTicker(params);
1148
+ const market = this.market(symbol);
1149
+ return this.parseTicker(response[market['id']], market);
1150
+ }
1151
+ parseTrade(trade, market = undefined) {
1152
+ //
1153
+ // fetchTrades (public)
1154
+ //
1155
+ // {
1156
+ // "trade_id":165087520,
1157
+ // "date":1587470005,
1158
+ // "type":"buy",
1159
+ // "quantity":"1.004",
1160
+ // "price":"0.02491461",
1161
+ // "amount":"0.02501426"
1162
+ // },
1163
+ //
1164
+ // fetchMyTrades, fetchOrderTrades
1165
+ //
1166
+ // {
1167
+ // "trade_id": 3,
1168
+ // "date": 1435488248,
1169
+ // "type": "buy",
1170
+ // "pair": "BTC_USD",
1171
+ // "order_id": 12345,
1172
+ // "quantity": 1,
1173
+ // "price": 100,
1174
+ // "amount": 100,
1175
+ // "exec_type": "taker",
1176
+ // "commission_amount": "0.02",
1177
+ // "commission_currency": "BTC",
1178
+ // "commission_percent": "0.2"
1179
+ // }
1180
+ //
1181
+ // fetchMyTrades (margin)
1182
+ //
1183
+ // {
1184
+ // "trade_id": "692861757015952517",
1185
+ // "trade_dt": "1693951853197811824",
1186
+ // "trade_type": "buy",
1187
+ // "pair": "ADA_USDT",
1188
+ // "quantity": "1.96607879",
1189
+ // "price": "0.2568",
1190
+ // "amount": "0.50488903"
1191
+ // }
1192
+ //
1193
+ const timestamp = this.safeTimestamp(trade, 'date');
1194
+ const id = this.safeString(trade, 'trade_id');
1195
+ const orderId = this.safeString(trade, 'order_id');
1196
+ const priceString = this.safeString(trade, 'price');
1197
+ const amountString = this.safeString(trade, 'quantity');
1198
+ const costString = this.safeString(trade, 'amount');
1199
+ const side = this.safeString2(trade, 'type', 'trade_type');
1200
+ const type = undefined;
1201
+ const marketId = this.safeString(trade, 'pair');
1202
+ market = this.safeMarket(marketId, market, '_');
1203
+ const symbol = market['symbol'];
1204
+ const isMaker = this.safeValue(trade, 'is_maker');
1205
+ let takerOrMakerDefault = undefined;
1206
+ if (isMaker !== undefined) {
1207
+ takerOrMakerDefault = isMaker ? 'maker' : 'taker';
1208
+ }
1209
+ const takerOrMaker = this.safeString(trade, 'exec_type', takerOrMakerDefault);
1210
+ let fee = undefined;
1211
+ const feeCostString = this.safeString(trade, 'commission_amount');
1212
+ if (feeCostString !== undefined) {
1213
+ const feeCurrencyId = this.safeString(trade, 'commission_currency');
1214
+ const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
1215
+ let feeRateString = this.safeString(trade, 'commission_percent');
1216
+ if (feeRateString !== undefined) {
1217
+ feeRateString = Precise["default"].stringDiv(feeRateString, '1000', 18);
1218
+ }
1219
+ fee = {
1220
+ 'cost': feeCostString,
1221
+ 'currency': feeCurrencyCode,
1222
+ 'rate': feeRateString,
1223
+ };
1224
+ }
1225
+ return this.safeTrade({
1226
+ 'id': id,
1227
+ 'info': trade,
1228
+ 'timestamp': timestamp,
1229
+ 'datetime': this.iso8601(timestamp),
1230
+ 'symbol': symbol,
1231
+ 'order': orderId,
1232
+ 'type': type,
1233
+ 'side': side,
1234
+ 'takerOrMaker': takerOrMaker,
1235
+ 'price': priceString,
1236
+ 'amount': amountString,
1237
+ 'cost': costString,
1238
+ 'fee': fee,
1239
+ }, market);
1240
+ }
1241
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
1242
+ /**
1243
+ * @method
1244
+ * @name exmo#fetchTrades
1245
+ * @description get the list of most recent trades for a particular symbol
1246
+ * @param {string} symbol unified symbol of the market to fetch trades for
1247
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
1248
+ * @param {int} [limit] the maximum amount of trades to fetch
1249
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1250
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
1251
+ */
1252
+ await this.loadMarkets();
1253
+ const market = this.market(symbol);
1254
+ const request = {
1255
+ 'pair': market['id'],
1256
+ };
1257
+ const response = await this.publicGetTrades(this.extend(request, params));
1258
+ //
1259
+ // {
1260
+ // "ETH_BTC":[
1261
+ // {
1262
+ // "trade_id":165087520,
1263
+ // "date":1587470005,
1264
+ // "type":"buy",
1265
+ // "quantity":"1.004",
1266
+ // "price":"0.02491461",
1267
+ // "amount":"0.02501426"
1268
+ // },
1269
+ // {
1270
+ // "trade_id":165087369,
1271
+ // "date":1587469938,
1272
+ // "type":"buy",
1273
+ // "quantity":"0.94",
1274
+ // "price":"0.02492348",
1275
+ // "amount":"0.02342807"
1276
+ // }
1277
+ // ]
1278
+ // }
1279
+ //
1280
+ const data = this.safeValue(response, market['id'], []);
1281
+ return this.parseTrades(data, market, since, limit);
1282
+ }
1283
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1284
+ /**
1285
+ * @method
1286
+ * @name exmo#fetchMyTrades
1287
+ * @description fetch all trades made by the user
1288
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#b8d8d9af-4f46-46a1-939b-ad261d79f452 // spot
1289
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#f4b1aaf8-399f-403b-ab5e-4926d967a106 // margin
1290
+ * @param {string} symbol a symbol is required but it can be a single string, or a non-empty array
1291
+ * @param {int} [since] the earliest time in ms to fetch trades for
1292
+ * @param {int} [limit] *required for margin orders* the maximum number of trades structures to retrieve
1293
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1294
+ *
1295
+ * EXCHANGE SPECIFIC PARAMETERS
1296
+ * @param {int} [params.offset] last deal offset, default = 0
1297
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1298
+ */
1299
+ if (symbol === undefined) {
1300
+ throw new errors.ArgumentsRequired(this.id + ' fetchMyTrades() requires a symbol argument');
1301
+ }
1302
+ let marginMode = undefined;
1303
+ [marginMode, params] = this.handleMarginModeAndParams('fetchMyTrades', params);
1304
+ if (marginMode === 'cross') {
1305
+ throw new errors.BadRequest(this.id + 'only isolated margin is supported');
1306
+ }
1307
+ await this.loadMarkets();
1308
+ const market = this.market(symbol);
1309
+ const pair = market['id'];
1310
+ const isSpot = marginMode !== 'isolated';
1311
+ if (limit === undefined) {
1312
+ limit = 100;
1313
+ }
1314
+ const request = {};
1315
+ if (isSpot) {
1316
+ request['pair'] = pair;
1317
+ }
1318
+ else {
1319
+ request['pair_name'] = pair;
1320
+ }
1321
+ if (limit !== undefined) {
1322
+ request['limit'] = limit;
1323
+ }
1324
+ const offset = this.safeInteger(params, 'offset', 0);
1325
+ request['offset'] = offset;
1326
+ let response = undefined;
1327
+ if (isSpot) {
1328
+ response = await this.privatePostUserTrades(this.extend(request, params));
1329
+ //
1330
+ // {
1331
+ // "BTC_USD": [
1332
+ // {
1333
+ // "trade_id": 20056872,
1334
+ // "client_id": 100500,
1335
+ // "date": 1435488248,
1336
+ // "type": "buy",
1337
+ // "pair": "BTC_USD",
1338
+ // "quantity": "1",
1339
+ // "price": "100",
1340
+ // "amount": "100",
1341
+ // "order_id": 7,
1342
+ // "parent_order_id": 117684023830293,
1343
+ // "exec_type": "taker",
1344
+ // "commission_amount": "0.02",
1345
+ // "commission_currency": "BTC",
1346
+ // "commission_percent": "0.2"
1347
+ // }
1348
+ // ],
1349
+ // ...
1350
+ // }
1351
+ //
1352
+ }
1353
+ else {
1354
+ const responseFromExchange = await this.privatePostMarginTrades(this.extend(request, params));
1355
+ //
1356
+ // {
1357
+ // "trades": {
1358
+ // "ADA_USDT": [
1359
+ // {
1360
+ // "trade_id": "692861757015952517",
1361
+ // "trade_dt": "1693951853197811824",
1362
+ // "trade_type": "buy",
1363
+ // "pair": "ADA_USDT",
1364
+ // "quantity": "1.96607879",
1365
+ // "price": "0.2568",
1366
+ // "amount": "0.50488903"
1367
+ // },
1368
+ // ]
1369
+ // ...
1370
+ // }
1371
+ // }
1372
+ //
1373
+ response = this.safeValue(responseFromExchange, 'trades');
1374
+ }
1375
+ let result = [];
1376
+ const marketIdsInner = Object.keys(response);
1377
+ for (let i = 0; i < marketIdsInner.length; i++) {
1378
+ const marketId = marketIdsInner[i];
1379
+ const resultMarket = this.safeMarket(marketId, undefined, '_');
1380
+ const items = response[marketId];
1381
+ const trades = this.parseTrades(items, resultMarket, since, limit);
1382
+ result = this.arrayConcat(result, trades);
1383
+ }
1384
+ return this.filterBySinceLimit(result, since, limit);
1385
+ }
1386
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1387
+ /**
1388
+ * @method
1389
+ * @name exmo#createOrder
1390
+ * @description create a trade order
1391
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd
1392
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#de6f4321-eeac-468c-87f7-c4ad7062e265 // stop market
1393
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#3561b86c-9ff1-436e-8e68-ac926b7eb523 // margin
1394
+ * @param {string} symbol unified symbol of the market to create an order in
1395
+ * @param {string} type 'market' or 'limit'
1396
+ * @param {string} side 'buy' or 'sell'
1397
+ * @param {float} amount how much of currency you want to trade in units of base currency
1398
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1399
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1400
+ * @param {float} [params.stopPrice] the price at which a trigger order is triggered at
1401
+ * @param {string} [params.timeInForce] *spot only* 'fok', 'ioc' or 'post_only'
1402
+ * @param {boolean} [params.postOnly] *spot only* true for post only orders
1403
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1404
+ */
1405
+ await this.loadMarkets();
1406
+ const market = this.market(symbol);
1407
+ const isMarket = (type === 'market') && (price === undefined);
1408
+ let marginMode = undefined;
1409
+ [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
1410
+ if (marginMode === 'cross') {
1411
+ throw new errors.BadRequest(this.id + ' only supports isolated margin');
1412
+ }
1413
+ const isSpot = (marginMode !== 'isolated');
1414
+ const triggerPrice = this.safeNumberN(params, ['triggerPrice', 'stopPrice', 'stop_price']);
1415
+ const request = {
1416
+ 'pair': market['id'],
1417
+ // 'leverage': 2,
1418
+ 'quantity': this.amountToPrecision(market['symbol'], amount),
1419
+ // spot - buy, sell, market_buy, market_sell, market_buy_total, market_sell_total
1420
+ // margin - limit_buy, limit_sell, market_buy, market_sell, stop_buy, stop_sell, stop_limit_buy, stop_limit_sell, trailing_stop_buy, trailing_stop_sell
1421
+ // 'stop_price': this.priceToPrecision (symbol, stopPrice),
1422
+ // 'distance': 0, // distance for trailing stop orders
1423
+ // 'expire': 0, // expiration timestamp in UTC timezone for the order, unless expire is 0
1424
+ // 'client_id': 123, // optional, must be a positive integer
1425
+ // 'comment': '', // up to 50 latin symbols, whitespaces, underscores
1426
+ };
1427
+ let clientOrderId = this.safeValue2(params, 'client_id', 'clientOrderId');
1428
+ if (clientOrderId !== undefined) {
1429
+ clientOrderId = this.safeInteger2(params, 'client_id', 'clientOrderId');
1430
+ if (clientOrderId === undefined) {
1431
+ throw new errors.BadRequest(this.id + ' createOrder() client order id must be an integer / numeric literal');
1432
+ }
1433
+ else {
1434
+ request['client_id'] = clientOrderId;
1435
+ }
1436
+ }
1437
+ const leverage = this.safeNumber(params, 'leverage');
1438
+ if (!isSpot && (leverage === undefined)) {
1439
+ throw new errors.ArgumentsRequired(this.id + ' createOrder requires an extra param params["leverage"] for margin orders');
1440
+ }
1441
+ params = this.omit(params, ['stopPrice', 'stop_price', 'triggerPrice', 'timeInForce', 'client_id', 'clientOrderId']);
1442
+ if (price !== undefined) {
1443
+ request['price'] = this.priceToPrecision(market['symbol'], price);
1444
+ }
1445
+ let response = undefined;
1446
+ if (isSpot) {
1447
+ if (triggerPrice !== undefined) {
1448
+ if (type === 'limit') {
1449
+ throw new errors.BadRequest(this.id + ' createOrder () cannot create stop limit orders for spot, only stop market');
1450
+ }
1451
+ else {
1452
+ request['type'] = side;
1453
+ request['trigger_price'] = this.priceToPrecision(symbol, triggerPrice);
1454
+ }
1455
+ response = await this.privatePostStopMarketOrderCreate(this.extend(request, params));
1456
+ }
1457
+ else {
1458
+ const execType = this.safeString(params, 'exec_type');
1459
+ let isPostOnly = undefined;
1460
+ [isPostOnly, params] = this.handlePostOnly(type === 'market', execType === 'post_only', params);
1461
+ const timeInForce = this.safeString(params, 'timeInForce');
1462
+ request['price'] = isMarket ? 0 : this.priceToPrecision(market['symbol'], price);
1463
+ if (type === 'limit') {
1464
+ request['type'] = side;
1465
+ }
1466
+ else if (type === 'market') {
1467
+ request['type'] = 'market_' + side;
1468
+ }
1469
+ if (isPostOnly) {
1470
+ request['exec_type'] = 'post_only';
1471
+ }
1472
+ else if (timeInForce !== undefined) {
1473
+ request['exec_type'] = timeInForce;
1474
+ }
1475
+ response = await this.privatePostOrderCreate(this.extend(request, params));
1476
+ }
1477
+ }
1478
+ else {
1479
+ if (triggerPrice !== undefined) {
1480
+ request['stop_price'] = this.priceToPrecision(symbol, triggerPrice);
1481
+ if (type === 'limit') {
1482
+ request['type'] = 'stop_limit_' + side;
1483
+ }
1484
+ else if (type === 'market') {
1485
+ request['type'] = 'stop_' + side;
1486
+ }
1487
+ else {
1488
+ request['type'] = type;
1489
+ }
1490
+ }
1491
+ else {
1492
+ if (type === 'limit' || type === 'market') {
1493
+ request['type'] = type + '_' + side;
1494
+ }
1495
+ else {
1496
+ request['type'] = type;
1497
+ }
1498
+ }
1499
+ response = await this.privatePostMarginUserOrderCreate(this.extend(request, params));
1500
+ }
1501
+ return this.parseOrder(response, market);
1502
+ }
1503
+ async cancelOrder(id, symbol = undefined, params = {}) {
1504
+ /**
1505
+ * @method
1506
+ * @name exmo#cancelOrder
1507
+ * @description cancels an open order
1508
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#1f710d4b-75bc-4b65-ad68-006f863a3f26
1509
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#a4d0aae8-28f7-41ac-94fd-c4030130453d // stop market
1510
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#705dfec5-2b35-4667-862b-faf54eca6209 // margin
1511
+ * @param {string} id order id
1512
+ * @param {string} symbol not used by exmo cancelOrder ()
1513
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1514
+ * @param {boolean} [params.trigger] true to cancel a trigger order
1515
+ * @param {string} [params.marginMode] set to 'cross' or 'isolated' to cancel a margin order
1516
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1517
+ */
1518
+ await this.loadMarkets();
1519
+ const request = {};
1520
+ const stop = this.safeValue2(params, 'trigger', 'stop');
1521
+ params = this.omit(params, ['trigger', 'stop']);
1522
+ let marginMode = undefined;
1523
+ [marginMode, params] = this.handleMarginModeAndParams('cancelOrder', params);
1524
+ if (marginMode === 'cross') {
1525
+ throw new errors.BadRequest(this.id + ' only supports isolated margin');
1526
+ }
1527
+ let response = undefined;
1528
+ if ((marginMode === 'isolated')) {
1529
+ request['order_id'] = id;
1530
+ response = await this.privatePostMarginUserOrderCancel(this.extend(request, params));
1531
+ //
1532
+ // {}
1533
+ //
1534
+ }
1535
+ else {
1536
+ if (stop) {
1537
+ request['parent_order_id'] = id;
1538
+ response = await this.privatePostStopMarketOrderCancel(this.extend(request, params));
1539
+ //
1540
+ // {}
1541
+ //
1542
+ }
1543
+ else {
1544
+ request['order_id'] = id;
1545
+ response = await this.privatePostOrderCancel(this.extend(request, params));
1546
+ //
1547
+ // {
1548
+ // "error": '',
1549
+ // "result": True
1550
+ // }
1551
+ //
1552
+ }
1553
+ }
1554
+ return this.parseOrder(response);
1555
+ }
1556
+ async fetchOrder(id, symbol = undefined, params = {}) {
1557
+ /**
1558
+ * @method
1559
+ * @name exmo#fetchOrder
1560
+ * @description *spot only* fetches information on an order made by the user
1561
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#cf27781e-28e5-4b39-a52d-3110f5d22459 // spot
1562
+ * @param {string} symbol not used by exmo fetchOrder
1563
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1564
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1565
+ */
1566
+ await this.loadMarkets();
1567
+ const request = {
1568
+ 'order_id': id.toString(),
1569
+ };
1570
+ const response = await this.privatePostOrderTrades(this.extend(request, params));
1571
+ //
1572
+ // {
1573
+ // "type": "buy",
1574
+ // "in_currency": "BTC",
1575
+ // "in_amount": "1",
1576
+ // "out_currency": "USD",
1577
+ // "out_amount": "100",
1578
+ // "trades": [
1579
+ // {
1580
+ // "trade_id": 3,
1581
+ // "date": 1435488248,
1582
+ // "type": "buy",
1583
+ // "pair": "BTC_USD",
1584
+ // "order_id": 12345,
1585
+ // "quantity": 1,
1586
+ // "price": 100,
1587
+ // "amount": 100
1588
+ // }
1589
+ // ]
1590
+ // }
1591
+ //
1592
+ const order = this.parseOrder(response);
1593
+ order['id'] = id.toString();
1594
+ return order;
1595
+ }
1596
+ async fetchOrderTrades(id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1597
+ /**
1598
+ * @method
1599
+ * @name exmo#fetchOrderTrades
1600
+ * @description fetch all the trades made from a single order
1601
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#cf27781e-28e5-4b39-a52d-3110f5d22459 // spot
1602
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#00810661-9119-46c5-aec5-55abe9cb42c7 // margin
1603
+ * @param {string} id order id
1604
+ * @param {string} symbol unified market symbol
1605
+ * @param {int} [since] the earliest time in ms to fetch trades for
1606
+ * @param {int} [limit] the maximum number of trades to retrieve
1607
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1608
+ * @param {string} [params.marginMode] set to "isolated" to fetch trades for a margin order
1609
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1610
+ */
1611
+ let marginMode = undefined;
1612
+ [marginMode, params] = this.handleMarginModeAndParams('fetchOrderTrades', params);
1613
+ if (marginMode === 'cross') {
1614
+ throw new errors.BadRequest(this.id + ' only supports isolated margin');
1615
+ }
1616
+ let market = undefined;
1617
+ if (symbol !== undefined) {
1618
+ market = this.market(symbol);
1619
+ }
1620
+ const request = {
1621
+ 'order_id': id.toString(),
1622
+ };
1623
+ let response = undefined;
1624
+ if (marginMode === 'isolated') {
1625
+ response = await this.privatePostMarginUserOrderTrades(this.extend(request, params));
1626
+ //
1627
+ // {
1628
+ // "trades": [
1629
+ // {
1630
+ // "is_maker": false,
1631
+ // "order_id": "123",
1632
+ // "pair": "BTC_USD",
1633
+ // "price": "54122.25",
1634
+ // "quantity": "0.00069994",
1635
+ // "trade_dt": "1619069561718824428",
1636
+ // "trade_id": "692842802860135010",
1637
+ // "type": "sell"
1638
+ // }
1639
+ // ]
1640
+ // }
1641
+ //
1642
+ }
1643
+ else {
1644
+ response = await this.privatePostOrderTrades(this.extend(request, params));
1645
+ //
1646
+ // {
1647
+ // "type": "buy",
1648
+ // "in_currency": "BTC",
1649
+ // "in_amount": "1",
1650
+ // "out_currency": "USD",
1651
+ // "out_amount": "100",
1652
+ // "trades": [
1653
+ // {
1654
+ // "trade_id": 3,
1655
+ // "date": 1435488248,
1656
+ // "type": "buy",
1657
+ // "pair": "BTC_USD",
1658
+ // "order_id": 12345,
1659
+ // "quantity": 1,
1660
+ // "price": 100,
1661
+ // "amount": 100,
1662
+ // "exec_type": "taker",
1663
+ // "commission_amount": "0.02",
1664
+ // "commission_currency": "BTC",
1665
+ // "commission_percent": "0.2"
1666
+ // }
1667
+ // ]
1668
+ // }
1669
+ //
1670
+ }
1671
+ const trades = this.safeValue(response, 'trades');
1672
+ return this.parseTrades(trades, market, since, limit);
1673
+ }
1674
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1675
+ /**
1676
+ * @method
1677
+ * @name exmo#fetchOpenOrders
1678
+ * @description fetch all unfilled currently open orders
1679
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#0e135370-daa4-4689-8acd-b6876dee9ba1 // spot open orders
1680
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#a7cfd4f0-476e-4675-b33f-22a46902f245 // margin
1681
+ * @param {string} symbol unified market symbol
1682
+ * @param {int} [since] the earliest time in ms to fetch open orders for
1683
+ * @param {int} [limit] the maximum number of open orders structures to retrieve
1684
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1685
+ * @param {string} [params.marginMode] set to "isolated" for margin orders
1686
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1687
+ */
1688
+ await this.loadMarkets();
1689
+ let market = undefined;
1690
+ if (symbol !== undefined) {
1691
+ market = this.market(symbol);
1692
+ symbol = market['symbol'];
1693
+ }
1694
+ let marginMode = undefined;
1695
+ [marginMode, params] = this.handleMarginModeAndParams('fetchOpenOrders', params);
1696
+ const isMargin = ((marginMode === 'cross') || (marginMode === 'isolated'));
1697
+ let response = undefined;
1698
+ let orders = [];
1699
+ if (isMargin) {
1700
+ response = await this.privatePostMarginUserOrderList(params);
1701
+ //
1702
+ // {
1703
+ // "orders": [
1704
+ // {
1705
+ // "client_id": "0",
1706
+ // "comment": "",
1707
+ // "created": "1619068707985325495",
1708
+ // "distance": "0",
1709
+ // "expire": 0,
1710
+ // "funding_currency": "BTC",
1711
+ // "funding_quantity": "0.01",
1712
+ // "funding_rate": "0.02",
1713
+ // "leverage": "2",
1714
+ // "order_id": "123",
1715
+ // "pair": "BTC_USD",
1716
+ // "previous_type": "limit_sell",
1717
+ // "price": "58000",
1718
+ // "quantity": "0.01",
1719
+ // "src": 0,
1720
+ // "stop_price": "0",
1721
+ // "trigger_price": "58000",
1722
+ // "type": "limit_sell",
1723
+ // "updated": 1619068707989411800
1724
+ // }
1725
+ // ]
1726
+ // }
1727
+ //
1728
+ params = this.extend(params, {
1729
+ 'status': 'open',
1730
+ });
1731
+ const responseOrders = this.safeValue(response, 'orders');
1732
+ orders = this.parseOrders(responseOrders, market, since, limit, params);
1733
+ }
1734
+ else {
1735
+ response = await this.privatePostUserOpenOrders(params);
1736
+ //
1737
+ // {
1738
+ // "USDT_USD": [
1739
+ // {
1740
+ // "parent_order_id": "507061384740151010",
1741
+ // "client_id": "100500",
1742
+ // "created": "1589547391",
1743
+ // "type": "stop_market_buy",
1744
+ // "pair": "USDT_USD",
1745
+ // "quantity": "1",
1746
+ // "trigger_price": "5",
1747
+ // "amount": "5"
1748
+ // }
1749
+ // ],
1750
+ // ...
1751
+ // }
1752
+ //
1753
+ const marketIds = Object.keys(response);
1754
+ for (let i = 0; i < marketIds.length; i++) {
1755
+ const marketId = marketIds[i];
1756
+ const marketInner = this.safeMarket(marketId);
1757
+ params = this.extend(params, {
1758
+ 'status': 'open',
1759
+ });
1760
+ const parsedOrders = this.parseOrders(response[marketId], marketInner, since, limit, params);
1761
+ orders = this.arrayConcat(orders, parsedOrders);
1762
+ }
1763
+ }
1764
+ return orders;
1765
+ }
1766
+ parseStatus(status) {
1767
+ if (status === undefined) {
1768
+ return undefined;
1769
+ }
1770
+ const statuses = {
1771
+ 'cancel_started': 'canceled',
1772
+ };
1773
+ if (status.indexOf('cancel') >= 0) {
1774
+ status = 'canceled';
1775
+ }
1776
+ return this.safeString(statuses, status, status);
1777
+ }
1778
+ parseSide(orderType) {
1779
+ const side = {
1780
+ 'limit_buy': 'buy',
1781
+ 'limit_sell': 'sell',
1782
+ 'market_buy': 'buy',
1783
+ 'market_sell': 'sell',
1784
+ 'stop_buy': 'buy',
1785
+ 'stop_sell': 'sell',
1786
+ 'stop_limit_buy': 'buy',
1787
+ 'stop_limit_sell': 'sell',
1788
+ 'trailing_stop_buy': 'buy',
1789
+ 'trailing_stop_sell': 'sell',
1790
+ 'stop_market_sell': 'sell',
1791
+ 'stop_market_buy': 'buy',
1792
+ 'buy': 'buy',
1793
+ 'sell': 'sell',
1794
+ };
1795
+ return this.safeString(side, orderType, orderType);
1796
+ }
1797
+ parseOrder(order, market = undefined) {
1798
+ //
1799
+ // fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders
1800
+ //
1801
+ // {
1802
+ // "order_id": "14",
1803
+ // "created": "1435517311",
1804
+ // "type": "buy",
1805
+ // "pair": "BTC_USD",
1806
+ // "price": "100",
1807
+ // "quantity": "1",
1808
+ // "amount": "100"
1809
+ // }
1810
+ //
1811
+ // fetchOrder
1812
+ //
1813
+ // {
1814
+ // "type": "buy",
1815
+ // "in_currency": "BTC",
1816
+ // "in_amount": "1",
1817
+ // "out_currency": "USD",
1818
+ // "out_amount": "100",
1819
+ // "trades": [
1820
+ // {
1821
+ // "trade_id": 3,
1822
+ // "date": 1435488248,
1823
+ // "type": "buy",
1824
+ // "pair": "BTC_USD",
1825
+ // "order_id": 12345,
1826
+ // "quantity": 1,
1827
+ // "price": 100,
1828
+ // "amount": 100
1829
+ // }
1830
+ // ]
1831
+ // }
1832
+ //
1833
+ // Margin fetchOpenOrders
1834
+ //
1835
+ // {
1836
+ // "client_id": "0",
1837
+ // "comment": "",
1838
+ // "created": "1619068707985325495",
1839
+ // "distance": "0",
1840
+ // "expire": 0,
1841
+ // "funding_currency": "BTC",
1842
+ // "funding_quantity": "0.01",
1843
+ // "funding_rate": "0.02",
1844
+ // "leverage": "2",
1845
+ // "order_id": "123",
1846
+ // "pair": "BTC_USD",
1847
+ // "previous_type": "limit_sell",
1848
+ // "price": "58000",
1849
+ // "quantity": "0.01",
1850
+ // "src": 0,
1851
+ // "stop_price": "0",
1852
+ // "trigger_price": "58000",
1853
+ // "type": "limit_sell",
1854
+ // "updated": 1619068707989411800
1855
+ // }
1856
+ //
1857
+ // Margin fetchClosedOrders
1858
+ //
1859
+ // {
1860
+ // "distance": "0",
1861
+ // "event_id": "692842802860022508",
1862
+ // "event_time": "1619069531190173720",
1863
+ // "event_type": "OrderCancelStarted",
1864
+ // "order_id": "123",
1865
+ // "order_status": "cancel_started",
1866
+ // "order_type": "limit_sell",
1867
+ // "pair": "BTC_USD",
1868
+ // "price": "54115",
1869
+ // "quantity": "0.001",
1870
+ // "stop_price": "0",
1871
+ // "trade_id": "0",
1872
+ // "trade_price": "0",
1873
+ // "trade_quantity": "0",
1874
+ // "trade_type": ""
1875
+ // },
1876
+ //
1877
+ const id = this.safeString2(order, 'order_id', 'parent_order_id');
1878
+ const eventTime = this.safeIntegerProduct2(order, 'event_time', 'created', 0.000001);
1879
+ const timestamp = this.safeTimestamp(order, 'created', eventTime);
1880
+ const orderType = this.safeString2(order, 'type', 'order_type');
1881
+ const side = this.parseSide(orderType);
1882
+ let marketId = undefined;
1883
+ if ('pair' in order) {
1884
+ marketId = order['pair'];
1885
+ }
1886
+ else if (('in_currency' in order) && ('out_currency' in order)) {
1887
+ if (side === 'buy') {
1888
+ marketId = order['in_currency'] + '_' + order['out_currency'];
1889
+ }
1890
+ else {
1891
+ marketId = order['out_currency'] + '_' + order['in_currency'];
1892
+ }
1893
+ }
1894
+ market = this.safeMarket(marketId, market);
1895
+ const symbol = market['symbol'];
1896
+ let amount = this.safeString(order, 'quantity');
1897
+ if (amount === undefined) {
1898
+ const amountField = (side === 'buy') ? 'in_amount' : 'out_amount';
1899
+ amount = this.safeString(order, amountField);
1900
+ }
1901
+ const price = this.safeString(order, 'price');
1902
+ const cost = this.safeString(order, 'amount');
1903
+ const transactions = this.safeValue(order, 'trades', []);
1904
+ const clientOrderId = this.safeInteger(order, 'client_id');
1905
+ let triggerPrice = this.safeString(order, 'stop_price');
1906
+ if (triggerPrice === '0') {
1907
+ triggerPrice = undefined;
1908
+ }
1909
+ let type = undefined;
1910
+ if ((orderType !== 'buy') && (orderType !== 'sell')) {
1911
+ type = orderType;
1912
+ }
1913
+ return this.safeOrder({
1914
+ 'id': id,
1915
+ 'clientOrderId': clientOrderId,
1916
+ 'datetime': this.iso8601(timestamp),
1917
+ 'timestamp': timestamp,
1918
+ 'lastTradeTimestamp': this.safeIntegerProduct(order, 'updated', 0.000001),
1919
+ 'status': this.parseStatus(this.safeString(order, 'order_status')),
1920
+ 'symbol': symbol,
1921
+ 'type': type,
1922
+ 'timeInForce': undefined,
1923
+ 'postOnly': undefined,
1924
+ 'side': side,
1925
+ 'price': price,
1926
+ 'stopPrice': triggerPrice,
1927
+ 'triggerPrice': triggerPrice,
1928
+ 'cost': cost,
1929
+ 'amount': amount,
1930
+ 'filled': undefined,
1931
+ 'remaining': undefined,
1932
+ 'average': undefined,
1933
+ 'trades': transactions,
1934
+ 'fee': undefined,
1935
+ 'info': order,
1936
+ }, market);
1937
+ }
1938
+ async fetchCanceledOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1939
+ /**
1940
+ * @method
1941
+ * @name exmo#fetchCanceledOrders
1942
+ * @description fetches information on multiple canceled orders made by the user
1943
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#1d2524dd-ae6d-403a-a067-77b50d13fbe5 // margin
1944
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#a51be1d0-af5f-44e4-99d7-f7b04c6067d0 // spot canceled orders
1945
+ * @param {string} symbol unified market symbol of the market orders were made in
1946
+ * @param {int} [since] timestamp in ms of the earliest order, default is undefined
1947
+ * @param {int} [limit] max number of orders to return, default is undefined
1948
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1949
+ * @param {string} [params.marginMode] set to "isolated" for margin orders
1950
+ * @returns {object} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1951
+ */
1952
+ await this.loadMarkets();
1953
+ let marginMode = undefined;
1954
+ [marginMode, params] = this.handleMarginModeAndParams('fetchOrders', params);
1955
+ if (marginMode === 'cross') {
1956
+ throw new errors.BadRequest(this.id + ' only supports isolated margin');
1957
+ }
1958
+ if (limit === undefined) {
1959
+ limit = 100;
1960
+ }
1961
+ const isSpot = (marginMode !== 'isolated');
1962
+ if (symbol !== undefined) {
1963
+ const marketInner = this.market(symbol);
1964
+ symbol = marketInner['symbol'];
1965
+ }
1966
+ const request = {
1967
+ 'limit': limit,
1968
+ };
1969
+ request['offset'] = (since !== undefined) ? limit : 0;
1970
+ request['limit'] = limit;
1971
+ let market = undefined;
1972
+ if (symbol !== undefined) {
1973
+ market = this.market(symbol);
1974
+ }
1975
+ let response = undefined;
1976
+ if (isSpot) {
1977
+ response = await this.privatePostUserCancelledOrders(this.extend(request, params));
1978
+ //
1979
+ // [
1980
+ // {
1981
+ // "order_id": "27056153840",
1982
+ // "client_id": "0",
1983
+ // "created": "1653428646",
1984
+ // "type": "buy",
1985
+ // "pair": "BTC_USDT",
1986
+ // "quantity": "0.1",
1987
+ // "price": "10",
1988
+ // "amount": "1"
1989
+ // }
1990
+ // ]
1991
+ //
1992
+ params = this.extend(params, {
1993
+ 'status': 'canceled',
1994
+ });
1995
+ return this.parseOrders(response, market, since, limit, params);
1996
+ }
1997
+ else {
1998
+ const responseSwap = await this.privatePostMarginUserOrderHistory(this.extend(request, params));
1999
+ //
2000
+ // {
2001
+ // "items": [
2002
+ // {
2003
+ // "event_id": "692862104574106858",
2004
+ // "event_time": "1694116400173489405",
2005
+ // "event_type": "OrderCancelStarted",
2006
+ // "order_id": "692862104561289319",
2007
+ // "order_type": "stop_limit_sell",
2008
+ // "order_status": "cancel_started",
2009
+ // "trade_id": "0",
2010
+ // "trade_type":"",
2011
+ // "trade_quantity": "0",
2012
+ // "trade_price": "0",
2013
+ // "pair": "ADA_USDT",
2014
+ // "quantity": "12",
2015
+ // "price": "0.23",
2016
+ // "stop_price": "0.22",
2017
+ // "distance": "0"
2018
+ // }
2019
+ // ...
2020
+ // ]
2021
+ // }
2022
+ //
2023
+ const items = this.safeValue(responseSwap, 'items');
2024
+ const orders = this.parseOrders(items, market, since, limit, params);
2025
+ const result = [];
2026
+ for (let i = 0; i < orders.length; i++) {
2027
+ const order = orders[i];
2028
+ if (order['status'] === 'canceled') {
2029
+ result.push(order);
2030
+ }
2031
+ }
2032
+ return result;
2033
+ }
2034
+ }
2035
+ async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
2036
+ /**
2037
+ * @method
2038
+ * @name exmo#editOrder
2039
+ * @description *margin only* edit a trade order
2040
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#f27ee040-c75f-4b59-b608-d05bd45b7899 // margin
2041
+ * @param {string} id order id
2042
+ * @param {string} symbol unified CCXT market symbol
2043
+ * @param {string} type not used by exmo editOrder
2044
+ * @param {string} side not used by exmo editOrder
2045
+ * @param {float} [amount] how much of the currency you want to trade in units of the base currency
2046
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2047
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2048
+ * @param {float} [params.triggerPrice] stop price for stop-market and stop-limit orders
2049
+ * @param {string} params.marginMode must be set to isolated
2050
+ *
2051
+ * EXCHANGE SPECIFIC PARAMETERS
2052
+ * @param {int} [params.distance] distance for trailing stop orders
2053
+ * @param {int} [params.expire] expiration timestamp in UTC timezone for the order. order will not be expired if expire is 0
2054
+ * @param {string} [params.comment] optional comment for order. up to 50 latin symbols, whitespaces, underscores
2055
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2056
+ */
2057
+ await this.loadMarkets();
2058
+ const market = this.market(symbol);
2059
+ let marginMode = undefined;
2060
+ [marginMode, params] = this.handleMarginModeAndParams('editOrder', params);
2061
+ if (marginMode !== 'isolated') {
2062
+ throw new errors.BadRequest(this.id + ' editOrder() can only be used for isolated margin orders');
2063
+ }
2064
+ const triggerPrice = this.safeNumberN(params, ['triggerPrice', 'stopPrice', 'stop_price']);
2065
+ params = this.omit(params, ['triggerPrice', 'stopPrice']);
2066
+ const request = {
2067
+ 'order_id': id, // id of the open order
2068
+ };
2069
+ if (amount !== undefined) {
2070
+ request['quantity'] = amount;
2071
+ }
2072
+ if (price !== undefined) {
2073
+ request['price'] = this.priceToPrecision(market['symbol'], price);
2074
+ }
2075
+ if (triggerPrice !== undefined) {
2076
+ request['stop_price'] = this.priceToPrecision(market['symbol'], triggerPrice);
2077
+ }
2078
+ const response = await this.privatePostMarginUserOrderUpdate(this.extend(request, params));
2079
+ return this.parseOrder(response);
2080
+ }
2081
+ async fetchDepositAddress(code, params = {}) {
2082
+ /**
2083
+ * @method
2084
+ * @name exmo#fetchDepositAddress
2085
+ * @description fetch the deposit address for a currency associated with this account
2086
+ * @param {string} code unified currency code
2087
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2088
+ * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
2089
+ */
2090
+ await this.loadMarkets();
2091
+ const response = await this.privatePostDepositAddress(params);
2092
+ //
2093
+ // {
2094
+ // "TRX":"TBnwrf4ZdoYXE3C8L2KMs7YPSL3fg6q6V9",
2095
+ // "USDTTRC20":"TBnwrf4ZdoYXE3C8L2KMs7YPSL3fg6q6V9"
2096
+ // }
2097
+ //
2098
+ const depositAddress = this.safeString(response, code);
2099
+ let address = undefined;
2100
+ let tag = undefined;
2101
+ if (depositAddress) {
2102
+ const addressAndTag = depositAddress.split(',');
2103
+ address = addressAndTag[0];
2104
+ const numParts = addressAndTag.length;
2105
+ if (numParts > 1) {
2106
+ tag = addressAndTag[1];
2107
+ }
2108
+ }
2109
+ this.checkAddress(address);
2110
+ return {
2111
+ 'currency': code,
2112
+ 'address': address,
2113
+ 'tag': tag,
2114
+ 'network': undefined,
2115
+ 'info': response,
2116
+ };
2117
+ }
2118
+ getMarketFromTrades(trades) {
2119
+ const tradesBySymbol = this.indexBy(trades, 'pair');
2120
+ const symbols = Object.keys(tradesBySymbol);
2121
+ const numSymbols = symbols.length;
2122
+ if (numSymbols === 1) {
2123
+ return this.markets[symbols[0]];
2124
+ }
2125
+ return undefined;
2126
+ }
2127
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
2128
+ /**
2129
+ * @method
2130
+ * @name exmo#withdraw
2131
+ * @description make a withdrawal
2132
+ * @param {string} code unified currency code
2133
+ * @param {float} amount the amount to withdraw
2134
+ * @param {string} address the address to withdraw to
2135
+ * @param {string} tag
2136
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2137
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2138
+ */
2139
+ [tag, params] = this.handleWithdrawTagAndParams(tag, params);
2140
+ await this.loadMarkets();
2141
+ const currency = this.currency(code);
2142
+ const request = {
2143
+ 'amount': amount,
2144
+ 'currency': currency['id'],
2145
+ 'address': address,
2146
+ };
2147
+ if (tag !== undefined) {
2148
+ request['invoice'] = tag;
2149
+ }
2150
+ const networks = this.safeValue(this.options, 'networks', {});
2151
+ let network = this.safeStringUpper(params, 'network'); // this line allows the user to specify either ERC20 or ETH
2152
+ network = this.safeString(networks, network, network); // handle ERC20>ETH alias
2153
+ if (network !== undefined) {
2154
+ request['transport'] = network;
2155
+ params = this.omit(params, 'network');
2156
+ }
2157
+ const response = await this.privatePostWithdrawCrypt(this.extend(request, params));
2158
+ return this.parseTransaction(response, currency);
2159
+ }
2160
+ parseTransactionStatus(status) {
2161
+ const statuses = {
2162
+ 'transferred': 'ok',
2163
+ 'paid': 'ok',
2164
+ 'pending': 'pending',
2165
+ 'processing': 'pending',
2166
+ 'verifying': 'pending',
2167
+ };
2168
+ return this.safeString(statuses, status, status);
2169
+ }
2170
+ parseTransaction(transaction, currency = undefined) {
2171
+ //
2172
+ // fetchDepositsWithdrawals
2173
+ //
2174
+ // {
2175
+ // "dt": 1461841192,
2176
+ // "type": "deposit",
2177
+ // "curr": "RUB",
2178
+ // "status": "processing",
2179
+ // "provider": "Qiwi (LA) [12345]",
2180
+ // "amount": "1",
2181
+ // "account": "",
2182
+ // "txid": "ec46f784ad976fd7f7539089d1a129fe46...",
2183
+ // }
2184
+ //
2185
+ // fetchWithdrawals
2186
+ //
2187
+ // {
2188
+ // "operation_id": 47412538520634344,
2189
+ // "created": 1573760013,
2190
+ // "updated": 1573760013,
2191
+ // "type": "withdraw",
2192
+ // "currency": "DOGE",
2193
+ // "status": "Paid",
2194
+ // "amount": "300",
2195
+ // "provider": "DOGE",
2196
+ // "commission": "0",
2197
+ // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS",
2198
+ // "order_id": 69670170,
2199
+ // "provider_type": "crypto",
2200
+ // "crypto_address": "DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS",
2201
+ // "card_number": "",
2202
+ // "wallet_address": "",
2203
+ // "email": "",
2204
+ // "phone": "",
2205
+ // "extra": {
2206
+ // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792",
2207
+ // "confirmations": null,
2208
+ // "excode": "",
2209
+ // "invoice": ""
2210
+ // },
2211
+ // "error": ""
2212
+ // }
2213
+ //
2214
+ // withdraw
2215
+ //
2216
+ // {
2217
+ // "result": true,
2218
+ // "error": "",
2219
+ // "task_id": 11775077
2220
+ // }
2221
+ //
2222
+ const timestamp = this.safeTimestamp2(transaction, 'dt', 'created');
2223
+ let amountString = this.safeString(transaction, 'amount');
2224
+ if (amountString !== undefined) {
2225
+ amountString = Precise["default"].stringAbs(amountString);
2226
+ }
2227
+ let txid = this.safeString(transaction, 'txid');
2228
+ if (txid === undefined) {
2229
+ const extra = this.safeValue(transaction, 'extra', {});
2230
+ const extraTxid = this.safeString(extra, 'txid');
2231
+ if (extraTxid !== '') {
2232
+ txid = extraTxid;
2233
+ }
2234
+ }
2235
+ const type = this.safeString(transaction, 'type');
2236
+ const currencyId = this.safeString2(transaction, 'curr', 'currency');
2237
+ const code = this.safeCurrencyCode(currencyId, currency);
2238
+ let address = undefined;
2239
+ let comment = undefined;
2240
+ const account = this.safeString(transaction, 'account');
2241
+ if (type === 'deposit') {
2242
+ comment = account;
2243
+ }
2244
+ else if (type === 'withdrawal') {
2245
+ address = account;
2246
+ if (address !== undefined) {
2247
+ const parts = address.split(':');
2248
+ const numParts = parts.length;
2249
+ if (numParts === 2) {
2250
+ address = this.safeString(parts, 1);
2251
+ address = address.replace(' ', '');
2252
+ }
2253
+ }
2254
+ }
2255
+ const fee = {
2256
+ 'currency': undefined,
2257
+ 'cost': undefined,
2258
+ 'rate': undefined,
2259
+ };
2260
+ // fixed funding fees only (for now)
2261
+ if (!this.fees['transaction']['percentage']) {
2262
+ const key = (type === 'withdrawal') ? 'withdraw' : 'deposit';
2263
+ let feeCost = this.safeString(transaction, 'commission');
2264
+ if (feeCost === undefined) {
2265
+ const transactionFees = this.safeValue(this.options, 'transactionFees', {});
2266
+ const codeFees = this.safeValue(transactionFees, code, {});
2267
+ feeCost = this.safeString(codeFees, key);
2268
+ }
2269
+ // users don't pay for cashbacks, no fees for that
2270
+ const provider = this.safeString(transaction, 'provider');
2271
+ if (provider === 'cashback') {
2272
+ feeCost = '0';
2273
+ }
2274
+ if (feeCost !== undefined) {
2275
+ // withdrawal amount includes the fee
2276
+ if (type === 'withdrawal') {
2277
+ amountString = Precise["default"].stringSub(amountString, feeCost);
2278
+ }
2279
+ fee['cost'] = this.parseNumber(feeCost);
2280
+ fee['currency'] = code;
2281
+ }
2282
+ }
2283
+ return {
2284
+ 'info': transaction,
2285
+ 'id': this.safeString2(transaction, 'order_id', 'task_id'),
2286
+ 'txid': txid,
2287
+ 'type': type,
2288
+ 'currency': code,
2289
+ 'network': this.safeString(transaction, 'provider'),
2290
+ 'amount': this.parseNumber(amountString),
2291
+ 'status': this.parseTransactionStatus(this.safeStringLower(transaction, 'status')),
2292
+ 'timestamp': timestamp,
2293
+ 'datetime': this.iso8601(timestamp),
2294
+ 'address': address,
2295
+ 'addressFrom': undefined,
2296
+ 'addressTo': address,
2297
+ 'tag': undefined,
2298
+ 'tagFrom': undefined,
2299
+ 'tagTo': undefined,
2300
+ 'updated': this.safeTimestamp(transaction, 'updated'),
2301
+ 'comment': comment,
2302
+ 'internal': undefined,
2303
+ 'fee': fee,
2304
+ };
2305
+ }
2306
+ async fetchDepositsWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2307
+ /**
2308
+ * @method
2309
+ * @name exmo#fetchDepositsWithdrawals
2310
+ * @description fetch history of deposits and withdrawals
2311
+ * @param {string} [code] unified currency code for the currency of the deposit/withdrawals, default is undefined
2312
+ * @param {int} [since] timestamp in ms of the earliest deposit/withdrawal, default is undefined
2313
+ * @param {int} [limit] max number of deposit/withdrawals to return, default is undefined
2314
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2315
+ * @returns {object} a list of [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2316
+ */
2317
+ await this.loadMarkets();
2318
+ const request = {};
2319
+ if (since !== undefined) {
2320
+ request['date'] = this.parseToInt(since / 1000);
2321
+ }
2322
+ let currency = undefined;
2323
+ if (code !== undefined) {
2324
+ currency = this.currency(code);
2325
+ }
2326
+ const response = await this.privatePostWalletHistory(this.extend(request, params));
2327
+ //
2328
+ // {
2329
+ // "result": true,
2330
+ // "error": "",
2331
+ // "begin": "1493942400",
2332
+ // "end": "1494028800",
2333
+ // "history": [
2334
+ // {
2335
+ // "dt": 1461841192,
2336
+ // "type": "deposit",
2337
+ // "curr": "RUB",
2338
+ // "status": "processing",
2339
+ // "provider": "Qiwi (LA) [12345]",
2340
+ // "amount": "1",
2341
+ // "account": "",
2342
+ // "txid": "ec46f784ad976fd7f7539089d1a129fe46...",
2343
+ // },
2344
+ // {
2345
+ // "dt": 1463414785,
2346
+ // "type": "withdrawal",
2347
+ // "curr": "USD",
2348
+ // "status": "paid",
2349
+ // "provider": "EXCODE",
2350
+ // "amount": "-1",
2351
+ // "account": "EX-CODE_19371_USDda...",
2352
+ // "txid": "",
2353
+ // },
2354
+ // ],
2355
+ // }
2356
+ //
2357
+ return this.parseTransactions(response['history'], currency, since, limit);
2358
+ }
2359
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2360
+ /**
2361
+ * @method
2362
+ * @name exmo#fetchWithdrawals
2363
+ * @description fetch all withdrawals made from an account
2364
+ * @param {string} code unified currency code
2365
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
2366
+ * @param {int} [limit] the maximum number of withdrawals structures to retrieve
2367
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2368
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2369
+ */
2370
+ await this.loadMarkets();
2371
+ let currency = undefined;
2372
+ const request = {
2373
+ 'type': 'withdraw',
2374
+ };
2375
+ if (limit !== undefined) {
2376
+ request['limit'] = limit; // default: 100, maximum: 100
2377
+ }
2378
+ if (code !== undefined) {
2379
+ currency = this.currency(code);
2380
+ request['currency'] = currency['id'];
2381
+ }
2382
+ const response = await this.privatePostWalletOperations(this.extend(request, params));
2383
+ //
2384
+ // {
2385
+ // "items": [
2386
+ // {
2387
+ // "operation_id": 47412538520634344,
2388
+ // "created": 1573760013,
2389
+ // "updated": 1573760013,
2390
+ // "type": "withdraw",
2391
+ // "currency": "DOGE",
2392
+ // "status": "Paid",
2393
+ // "amount": "300",
2394
+ // "provider": "DOGE",
2395
+ // "commission": "0",
2396
+ // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS",
2397
+ // "order_id": 69670170,
2398
+ // "extra": {
2399
+ // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792",
2400
+ // "excode": "",
2401
+ // "invoice": ""
2402
+ // },
2403
+ // "error": ""
2404
+ // },
2405
+ // ],
2406
+ // "count": 23
2407
+ // }
2408
+ //
2409
+ const items = this.safeValue(response, 'items', []);
2410
+ return this.parseTransactions(items, currency, since, limit);
2411
+ }
2412
+ async fetchWithdrawal(id, code = undefined, params = {}) {
2413
+ /**
2414
+ * @method
2415
+ * @name exmo#fetchWithdrawal
2416
+ * @description fetch data on a currency withdrawal via the withdrawal id
2417
+ * @param {string} id withdrawal id
2418
+ * @param {string} code unified currency code of the currency withdrawn, default is undefined
2419
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2420
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2421
+ */
2422
+ await this.loadMarkets();
2423
+ let currency = undefined;
2424
+ const request = {
2425
+ 'order_id': id,
2426
+ 'type': 'withdraw',
2427
+ };
2428
+ if (code !== undefined) {
2429
+ currency = this.currency(code);
2430
+ request['currency'] = currency['id'];
2431
+ }
2432
+ const response = await this.privatePostWalletOperations(this.extend(request, params));
2433
+ //
2434
+ // {
2435
+ // "items": [
2436
+ // {
2437
+ // "operation_id": 47412538520634344,
2438
+ // "created": 1573760013,
2439
+ // "updated": 1573760013,
2440
+ // "type": "deposit",
2441
+ // "currency": "DOGE",
2442
+ // "status": "Paid",
2443
+ // "amount": "300",
2444
+ // "provider": "DOGE",
2445
+ // "commission": "0",
2446
+ // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS",
2447
+ // "order_id": 69670170,
2448
+ // "extra": {
2449
+ // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792",
2450
+ // "excode": "",
2451
+ // "invoice": ""
2452
+ // },
2453
+ // "error": ""
2454
+ // },
2455
+ // ],
2456
+ // "count": 23
2457
+ // }
2458
+ //
2459
+ const items = this.safeValue(response, 'items', []);
2460
+ const first = this.safeValue(items, 0, {});
2461
+ return this.parseTransaction(first, currency);
2462
+ }
2463
+ async fetchDeposit(id = undefined, code = undefined, params = {}) {
2464
+ /**
2465
+ * @method
2466
+ * @name exmo#fetchDeposit
2467
+ * @description fetch information on a deposit
2468
+ * @param {string} id deposit id
2469
+ * @param {string} code unified currency code, default is undefined
2470
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2471
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2472
+ */
2473
+ await this.loadMarkets();
2474
+ let currency = undefined;
2475
+ const request = {
2476
+ 'order_id': id,
2477
+ 'type': 'deposit',
2478
+ };
2479
+ if (code !== undefined) {
2480
+ currency = this.currency(code);
2481
+ request['currency'] = currency['id'];
2482
+ }
2483
+ const response = await this.privatePostWalletOperations(this.extend(request, params));
2484
+ //
2485
+ // {
2486
+ // "items": [
2487
+ // {
2488
+ // "operation_id": 47412538520634344,
2489
+ // "created": 1573760013,
2490
+ // "updated": 1573760013,
2491
+ // "type": "deposit",
2492
+ // "currency": "DOGE",
2493
+ // "status": "Paid",
2494
+ // "amount": "300",
2495
+ // "provider": "DOGE",
2496
+ // "commission": "0",
2497
+ // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS",
2498
+ // "order_id": 69670170,
2499
+ // "extra": {
2500
+ // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792",
2501
+ // "excode": "",
2502
+ // "invoice": ""
2503
+ // },
2504
+ // "error": ""
2505
+ // },
2506
+ // ],
2507
+ // "count": 23
2508
+ // }
2509
+ //
2510
+ const items = this.safeValue(response, 'items', []);
2511
+ const first = this.safeValue(items, 0, {});
2512
+ return this.parseTransaction(first, currency);
2513
+ }
2514
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
2515
+ /**
2516
+ * @method
2517
+ * @name exmo#fetchDeposits
2518
+ * @description fetch all deposits made to an account
2519
+ * @param {string} code unified currency code
2520
+ * @param {int} [since] the earliest time in ms to fetch deposits for
2521
+ * @param {int} [limit] the maximum number of deposits structures to retrieve
2522
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2523
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2524
+ */
2525
+ await this.loadMarkets();
2526
+ let currency = undefined;
2527
+ const request = {
2528
+ 'type': 'deposit',
2529
+ };
2530
+ if (limit !== undefined) {
2531
+ request['limit'] = limit; // default: 100, maximum: 100
2532
+ }
2533
+ if (code !== undefined) {
2534
+ currency = this.currency(code);
2535
+ request['currency'] = currency['id'];
2536
+ }
2537
+ const response = await this.privatePostWalletOperations(this.extend(request, params));
2538
+ //
2539
+ // {
2540
+ // "items": [
2541
+ // {
2542
+ // "operation_id": 47412538520634344,
2543
+ // "created": 1573760013,
2544
+ // "updated": 1573760013,
2545
+ // "type": "deposit",
2546
+ // "currency": "DOGE",
2547
+ // "status": "Paid",
2548
+ // "amount": "300",
2549
+ // "provider": "DOGE",
2550
+ // "commission": "0",
2551
+ // "account": "DOGE: DBVy8pF1f8yxaCVEHqHeR7kkcHecLQ8nRS",
2552
+ // "order_id": 69670170,
2553
+ // "extra": {
2554
+ // "txid": "f2b66259ae1580f371d38dd27e31a23fff8c04122b65ee3ab5a3f612d579c792",
2555
+ // "excode": "",
2556
+ // "invoice": ""
2557
+ // },
2558
+ // "error": ""
2559
+ // },
2560
+ // ],
2561
+ // "count": 23
2562
+ // }
2563
+ //
2564
+ const items = this.safeValue(response, 'items', []);
2565
+ return this.parseTransactions(items, currency, since, limit);
2566
+ }
2567
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2568
+ let url = this.urls['api'][api] + '/';
2569
+ if (api !== 'web') {
2570
+ url += this.version + '/';
2571
+ }
2572
+ url += path;
2573
+ if ((api === 'public') || (api === 'web')) {
2574
+ if (Object.keys(params).length) {
2575
+ url += '?' + this.urlencode(params);
2576
+ }
2577
+ }
2578
+ else if (api === 'private') {
2579
+ this.checkRequiredCredentials();
2580
+ const nonce = this.nonce();
2581
+ body = this.urlencode(this.extend({ 'nonce': nonce }, params));
2582
+ headers = {
2583
+ 'Content-Type': 'application/x-www-form-urlencoded',
2584
+ 'Key': this.apiKey,
2585
+ 'Sign': this.hmac(this.encode(body), this.encode(this.secret), sha512.sha512),
2586
+ };
2587
+ }
2588
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2589
+ }
2590
+ nonce() {
2591
+ return this.milliseconds();
2592
+ }
2593
+ handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2594
+ if (response === undefined) {
2595
+ return undefined; // fallback to default error handler
2596
+ }
2597
+ if (('error' in response) && !('result' in response)) {
2598
+ // error: {
2599
+ // "code": "140434",
2600
+ // "msg": "Your margin balance is not sufficient to place the order for '5 TON'. Please top up your margin wallet by "2.5 USDT"."
2601
+ // }
2602
+ //
2603
+ const errorCode = this.safeValue(response, 'error', {});
2604
+ const messageError = this.safeString(errorCode, 'msg');
2605
+ const code = this.safeString(errorCode, 'code');
2606
+ const feedback = this.id + ' ' + body;
2607
+ this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
2608
+ this.throwBroadlyMatchedException(this.exceptions['broad'], messageError, feedback);
2609
+ throw new errors.ExchangeError(feedback);
2610
+ }
2611
+ if (('result' in response) || ('errmsg' in response)) {
2612
+ //
2613
+ // {"result":false,"error":"Error 50052: Insufficient funds"}
2614
+ // {"s":"error","errmsg":"strconv.ParseInt: parsing \"\": invalid syntax"}
2615
+ //
2616
+ let success = this.safeValue(response, 'result', false);
2617
+ if (typeof success === 'string') {
2618
+ if ((success === 'true') || (success === '1')) {
2619
+ success = true;
2620
+ }
2621
+ else {
2622
+ success = false;
2623
+ }
2624
+ }
2625
+ if (!success) {
2626
+ let code = undefined;
2627
+ const message = this.safeString2(response, 'error', 'errmsg');
2628
+ const errorParts = message.split(':');
2629
+ const numParts = errorParts.length;
2630
+ if (numParts > 1) {
2631
+ const errorSubParts = errorParts[0].split(' ');
2632
+ const numSubParts = errorSubParts.length;
2633
+ code = (numSubParts > 1) ? errorSubParts[1] : errorSubParts[0];
2634
+ }
2635
+ const feedback = this.id + ' ' + body;
2636
+ this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
2637
+ this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
2638
+ throw new errors.ExchangeError(feedback);
2639
+ }
2640
+ }
2641
+ return undefined;
2642
+ }
2643
+ }
2644
+
2645
+ module.exports = exmo;