ccxt-look 1.81.50

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 (264) hide show
  1. package/.cache/eslintcache +1 -0
  2. package/.dockerignore +6 -0
  3. package/.eslintignore +1 -0
  4. package/.gitattributes +5 -0
  5. package/.readthedocs.yaml +16 -0
  6. package/CONTRIBUTING.md +1049 -0
  7. package/LICENSE.txt +21 -0
  8. package/README.md +537 -0
  9. package/SECURITY.md +5 -0
  10. package/build/cleanup-old-tags.js +94 -0
  11. package/build/countries.js +256 -0
  12. package/build/export-exchanges.js +520 -0
  13. package/build/fs.js +51 -0
  14. package/build/transpile.js +1772 -0
  15. package/build/vss.js +78 -0
  16. package/ccxt.browser.js +7 -0
  17. package/ccxt.d.ts +692 -0
  18. package/ccxt.js +171 -0
  19. package/cleanup.sh +2 -0
  20. package/composer-install.sh +20 -0
  21. package/dist/ccxt.browser.js +208383 -0
  22. package/gource.sh +3 -0
  23. package/index.html +7 -0
  24. package/js/.eslintrc +87 -0
  25. package/js/aax.js +2686 -0
  26. package/js/ascendex.js +2584 -0
  27. package/js/base/.eslintrc.js +43 -0
  28. package/js/base/Exchange.js +2371 -0
  29. package/js/base/Precise.js +283 -0
  30. package/js/base/errorHierarchy.js +47 -0
  31. package/js/base/errors.js +55 -0
  32. package/js/base/functions/crypto.js +158 -0
  33. package/js/base/functions/encode.js +118 -0
  34. package/js/base/functions/generic.js +270 -0
  35. package/js/base/functions/misc.js +138 -0
  36. package/js/base/functions/number.js +329 -0
  37. package/js/base/functions/platform.js +38 -0
  38. package/js/base/functions/string.js +21 -0
  39. package/js/base/functions/throttle.js +79 -0
  40. package/js/base/functions/time.js +210 -0
  41. package/js/base/functions/type.js +66 -0
  42. package/js/base/functions.js +28 -0
  43. package/js/bequant.js +32 -0
  44. package/js/bibox.js +1407 -0
  45. package/js/bigone.js +1366 -0
  46. package/js/binance.js +5652 -0
  47. package/js/binancecoinm.js +46 -0
  48. package/js/binanceus.js +46 -0
  49. package/js/binanceusdm.js +49 -0
  50. package/js/bit2c.js +535 -0
  51. package/js/bitbank.js +842 -0
  52. package/js/bitbay.js +16 -0
  53. package/js/bitbns.js +1073 -0
  54. package/js/bitcoincom.js +15 -0
  55. package/js/bitfinex.js +1433 -0
  56. package/js/bitfinex2.js +2025 -0
  57. package/js/bitflyer.js +840 -0
  58. package/js/bitforex.js +614 -0
  59. package/js/bitget.js +2397 -0
  60. package/js/bithumb.js +980 -0
  61. package/js/bitmart.js +2516 -0
  62. package/js/bitmex.js +1809 -0
  63. package/js/bitopro.js +1443 -0
  64. package/js/bitpanda.js +1782 -0
  65. package/js/bitrue.js +1747 -0
  66. package/js/bitso.js +1062 -0
  67. package/js/bitstamp.js +1757 -0
  68. package/js/bitstamp1.js +343 -0
  69. package/js/bittrex.js +1876 -0
  70. package/js/bitvavo.js +1579 -0
  71. package/js/bkex.js +1233 -0
  72. package/js/bl3p.js +346 -0
  73. package/js/blockchaincom.js +969 -0
  74. package/js/btcalpha.js +680 -0
  75. package/js/btcbox.js +477 -0
  76. package/js/btcmarkets.js +1022 -0
  77. package/js/btctradeua.js +466 -0
  78. package/js/btcturk.js +734 -0
  79. package/js/buda.js +946 -0
  80. package/js/bw.js +1265 -0
  81. package/js/bybit.js +3372 -0
  82. package/js/bytetrade.js +1336 -0
  83. package/js/cdax.js +1646 -0
  84. package/js/cex.js +1410 -0
  85. package/js/coinbase.js +1342 -0
  86. package/js/coinbaseprime.js +31 -0
  87. package/js/coinbasepro.js +1466 -0
  88. package/js/coincheck.js +755 -0
  89. package/js/coinex.js +3400 -0
  90. package/js/coinfalcon.js +880 -0
  91. package/js/coinmate.js +794 -0
  92. package/js/coinone.js +816 -0
  93. package/js/coinspot.js +345 -0
  94. package/js/crex24.js +1636 -0
  95. package/js/cryptocom.js +1832 -0
  96. package/js/currencycom.js +1748 -0
  97. package/js/delta.js +1547 -0
  98. package/js/deribit.js +2148 -0
  99. package/js/digifinex.js +1585 -0
  100. package/js/eqonex.js +1660 -0
  101. package/js/exmo.js +1670 -0
  102. package/js/fairdesk.js +1231 -0
  103. package/js/flowbtc.js +35 -0
  104. package/js/fmfwio.js +34 -0
  105. package/js/ftx.js +2751 -0
  106. package/js/ftxus.js +38 -0
  107. package/js/gateio.js +4174 -0
  108. package/js/gemini.js +1397 -0
  109. package/js/hitbtc.js +1343 -0
  110. package/js/hitbtc3.js +2329 -0
  111. package/js/hollaex.js +1486 -0
  112. package/js/huobi.js +5706 -0
  113. package/js/huobijp.js +1710 -0
  114. package/js/huobipro.js +18 -0
  115. package/js/idex.js +1439 -0
  116. package/js/independentreserve.js +649 -0
  117. package/js/indodax.js +742 -0
  118. package/js/itbit.js +722 -0
  119. package/js/kraken.js +2179 -0
  120. package/js/kucoin.js +2571 -0
  121. package/js/kucoinfutures.js +1771 -0
  122. package/js/kuna.js +809 -0
  123. package/js/latoken.js +1445 -0
  124. package/js/lbank.js +760 -0
  125. package/js/liquid.js +1432 -0
  126. package/js/luno.js +873 -0
  127. package/js/lykke.js +1147 -0
  128. package/js/mercado.js +771 -0
  129. package/js/mexc.js +3151 -0
  130. package/js/ndax.js +2233 -0
  131. package/js/novadax.js +1318 -0
  132. package/js/oceanex.js +816 -0
  133. package/js/okcoin.js +3841 -0
  134. package/js/okex.js +16 -0
  135. package/js/okex5.js +16 -0
  136. package/js/okx.js +4795 -0
  137. package/js/paymium.js +498 -0
  138. package/js/phemex.js +2957 -0
  139. package/js/poloniex.js +1674 -0
  140. package/js/probit.js +1346 -0
  141. package/js/qtrade.js +1588 -0
  142. package/js/ripio.js +1061 -0
  143. package/js/static_dependencies/BN/bn.js +3526 -0
  144. package/js/static_dependencies/README.md +1 -0
  145. package/js/static_dependencies/crypto-js/crypto-js.js +5988 -0
  146. package/js/static_dependencies/elliptic/lib/elliptic/curve/base.js +375 -0
  147. package/js/static_dependencies/elliptic/lib/elliptic/curve/edwards.js +433 -0
  148. package/js/static_dependencies/elliptic/lib/elliptic/curve/index.js +8 -0
  149. package/js/static_dependencies/elliptic/lib/elliptic/curve/mont.js +180 -0
  150. package/js/static_dependencies/elliptic/lib/elliptic/curve/short.js +938 -0
  151. package/js/static_dependencies/elliptic/lib/elliptic/curves.js +204 -0
  152. package/js/static_dependencies/elliptic/lib/elliptic/ec/index.js +240 -0
  153. package/js/static_dependencies/elliptic/lib/elliptic/ec/key.js +119 -0
  154. package/js/static_dependencies/elliptic/lib/elliptic/ec/signature.js +24 -0
  155. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/index.js +145 -0
  156. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/key.js +100 -0
  157. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/signature.js +65 -0
  158. package/js/static_dependencies/elliptic/lib/elliptic/precomputed/secp256k1.js +780 -0
  159. package/js/static_dependencies/elliptic/lib/elliptic/utils.js +214 -0
  160. package/js/static_dependencies/elliptic/lib/elliptic.js +22 -0
  161. package/js/static_dependencies/elliptic/lib/hmac-drbg/hmac-drbg.js +114 -0
  162. package/js/static_dependencies/fetch-ponyfill/fetch-node.js +39 -0
  163. package/js/static_dependencies/node-fetch/index.js +1564 -0
  164. package/js/static_dependencies/node-rsa/NodeRSA.js +223 -0
  165. package/js/static_dependencies/node-rsa/asn1/ber/errors.js +13 -0
  166. package/js/static_dependencies/node-rsa/asn1/ber/index.js +21 -0
  167. package/js/static_dependencies/node-rsa/asn1/ber/reader.js +262 -0
  168. package/js/static_dependencies/node-rsa/asn1/ber/types.js +36 -0
  169. package/js/static_dependencies/node-rsa/asn1/index.js +17 -0
  170. package/js/static_dependencies/node-rsa/encryptEngines/js.js +34 -0
  171. package/js/static_dependencies/node-rsa/formats/components.js +71 -0
  172. package/js/static_dependencies/node-rsa/formats/formats.js +31 -0
  173. package/js/static_dependencies/node-rsa/formats/pkcs1.js +148 -0
  174. package/js/static_dependencies/node-rsa/formats/pkcs8.js +187 -0
  175. package/js/static_dependencies/node-rsa/libs/jsbn.js +1252 -0
  176. package/js/static_dependencies/node-rsa/libs/rsa.js +147 -0
  177. package/js/static_dependencies/node-rsa/schemes/pkcs1.js +176 -0
  178. package/js/static_dependencies/node-rsa/schemes/schemes.js +21 -0
  179. package/js/static_dependencies/node-rsa/utils.js +98 -0
  180. package/js/static_dependencies/qs/formats.js +18 -0
  181. package/js/static_dependencies/qs/index.js +11 -0
  182. package/js/static_dependencies/qs/parse.js +242 -0
  183. package/js/static_dependencies/qs/stringify.js +269 -0
  184. package/js/static_dependencies/qs/utils.js +230 -0
  185. package/js/stex.js +1925 -0
  186. package/js/test/.eslintrc.js +42 -0
  187. package/js/test/Exchange/test.balance.js +61 -0
  188. package/js/test/Exchange/test.borrowRate.js +32 -0
  189. package/js/test/Exchange/test.currency.js +52 -0
  190. package/js/test/Exchange/test.fetchBalance.js +23 -0
  191. package/js/test/Exchange/test.fetchBorrowInterest.js +59 -0
  192. package/js/test/Exchange/test.fetchBorrowRate.js +32 -0
  193. package/js/test/Exchange/test.fetchBorrowRates.js +28 -0
  194. package/js/test/Exchange/test.fetchClosedOrders.js +32 -0
  195. package/js/test/Exchange/test.fetchCurrencies.js +35 -0
  196. package/js/test/Exchange/test.fetchDeposits.js +31 -0
  197. package/js/test/Exchange/test.fetchFundingFees.js +19 -0
  198. package/js/test/Exchange/test.fetchFundingRateHistory.js +40 -0
  199. package/js/test/Exchange/test.fetchL2OrderBook.js +23 -0
  200. package/js/test/Exchange/test.fetchLedger.js +42 -0
  201. package/js/test/Exchange/test.fetchLeverageTiers.js +33 -0
  202. package/js/test/Exchange/test.fetchMarketLeverageTiers.js +22 -0
  203. package/js/test/Exchange/test.fetchMarkets.js +33 -0
  204. package/js/test/Exchange/test.fetchMyTrades.js +42 -0
  205. package/js/test/Exchange/test.fetchOHLCV.js +46 -0
  206. package/js/test/Exchange/test.fetchOpenOrders.js +36 -0
  207. package/js/test/Exchange/test.fetchOrderBook.js +25 -0
  208. package/js/test/Exchange/test.fetchOrderBooks.js +35 -0
  209. package/js/test/Exchange/test.fetchOrders.js +41 -0
  210. package/js/test/Exchange/test.fetchPositions.js +47 -0
  211. package/js/test/Exchange/test.fetchStatus.js +35 -0
  212. package/js/test/Exchange/test.fetchTicker.js +38 -0
  213. package/js/test/Exchange/test.fetchTickers.js +49 -0
  214. package/js/test/Exchange/test.fetchTrades.js +39 -0
  215. package/js/test/Exchange/test.fetchTradingFee.js +18 -0
  216. package/js/test/Exchange/test.fetchTradingFees.js +22 -0
  217. package/js/test/Exchange/test.fetchTransactions.js +31 -0
  218. package/js/test/Exchange/test.fetchWithdrawals.js +31 -0
  219. package/js/test/Exchange/test.ledgerItem.js +46 -0
  220. package/js/test/Exchange/test.leverageTier.js +33 -0
  221. package/js/test/Exchange/test.loadMarkets.js +35 -0
  222. package/js/test/Exchange/test.market.js +129 -0
  223. package/js/test/Exchange/test.ohlcv.js +33 -0
  224. package/js/test/Exchange/test.order.js +62 -0
  225. package/js/test/Exchange/test.orderbook.js +61 -0
  226. package/js/test/Exchange/test.position.js +21 -0
  227. package/js/test/Exchange/test.throttle.js +94 -0
  228. package/js/test/Exchange/test.ticker.js +95 -0
  229. package/js/test/Exchange/test.trade.js +68 -0
  230. package/js/test/Exchange/test.tradingFee.js +34 -0
  231. package/js/test/Exchange/test.transaction.js +35 -0
  232. package/js/test/base/.eslintrc +38 -0
  233. package/js/test/base/functions/test.crypto.js +110 -0
  234. package/js/test/base/functions/test.datetime.js +62 -0
  235. package/js/test/base/functions/test.generic.js +152 -0
  236. package/js/test/base/functions/test.number.js +362 -0
  237. package/js/test/base/functions/test.time.js +56 -0
  238. package/js/test/base/functions/test.type.js +53 -0
  239. package/js/test/base/test.base.js +193 -0
  240. package/js/test/errors/test.InsufficientFunds.js +86 -0
  241. package/js/test/errors/test.InvalidNonce.js +64 -0
  242. package/js/test/errors/test.InvalidOrder.js +35 -0
  243. package/js/test/errors/test.OrderNotFound.js +39 -0
  244. package/js/test/test.js +426 -0
  245. package/js/test/test.timeout_hang.js +12 -0
  246. package/js/therock.js +1431 -0
  247. package/js/tidebit.js +632 -0
  248. package/js/tidex.js +939 -0
  249. package/js/timex.js +1283 -0
  250. package/js/upbit.js +1622 -0
  251. package/js/vcc.js +1353 -0
  252. package/js/wavesexchange.js +2185 -0
  253. package/js/wazirx.js +732 -0
  254. package/js/whitebit.js +1352 -0
  255. package/js/woo.js +1577 -0
  256. package/js/xena.js +1948 -0
  257. package/js/yobit.js +1129 -0
  258. package/js/zaif.js +647 -0
  259. package/js/zb.js +4088 -0
  260. package/js/zipmex.js +40 -0
  261. package/js/zonda.js +1497 -0
  262. package/multilang.sh +159 -0
  263. package/package.json +591 -0
  264. package/postinstall.js +103 -0
package/js/whitebit.js ADDED
@@ -0,0 +1,1352 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeNotAvailable, ExchangeError, DDoSProtection, BadSymbol, InvalidOrder, ArgumentsRequired, AuthenticationError, OrderNotFound, PermissionDenied, InsufficientFunds, BadRequest } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class whitebit extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'whitebit',
15
+ 'name': 'WhiteBit',
16
+ 'version': 'v2',
17
+ 'countries': [ 'EE' ],
18
+ 'rateLimit': 500,
19
+ 'has': {
20
+ 'CORS': undefined,
21
+ 'spot': true,
22
+ 'margin': undefined, // has but unimplemented
23
+ 'swap': false,
24
+ 'future': false,
25
+ 'option': false,
26
+ 'cancelOrder': true,
27
+ 'createDepositAddress': undefined,
28
+ 'createLimitOrder': undefined,
29
+ 'createMarketOrder': undefined,
30
+ 'createOrder': true,
31
+ 'createStopLimitOrder': true,
32
+ 'createStopMarketOrder': true,
33
+ 'createStopOrder': true,
34
+ 'editOrder': undefined,
35
+ 'fetchBalance': true,
36
+ 'fetchBidsAsks': undefined,
37
+ 'fetchClosedOrders': true,
38
+ 'fetchCurrencies': true,
39
+ 'fetchDepositAddress': true,
40
+ 'fetchFundingFees': true,
41
+ 'fetchFundingHistory': false,
42
+ 'fetchFundingRate': false,
43
+ 'fetchFundingRateHistory': false,
44
+ 'fetchFundingRates': false,
45
+ 'fetchIndexOHLCV': false,
46
+ 'fetchMarkets': true,
47
+ 'fetchMarkOHLCV': false,
48
+ 'fetchOHLCV': true,
49
+ 'fetchOpenOrders': true,
50
+ 'fetchOrderBook': true,
51
+ 'fetchOrderTrades': true,
52
+ 'fetchPremiumIndexOHLCV': false,
53
+ 'fetchTicker': true,
54
+ 'fetchTickers': true,
55
+ 'fetchTime': true,
56
+ 'fetchTrades': true,
57
+ 'fetchTradingFee': false,
58
+ 'fetchTradingFees': true,
59
+ 'transfer': true,
60
+ 'withdraw': true,
61
+ },
62
+ 'timeframes': {
63
+ '1m': '1m',
64
+ '3m': '3m',
65
+ '5m': '5m',
66
+ '15m': '15m',
67
+ '30m': '30m',
68
+ '1h': '1h',
69
+ '2h': '2h',
70
+ '4h': '4h',
71
+ '6h': '6h',
72
+ '8h': '8h',
73
+ '12h': '12h',
74
+ '1d': '1d',
75
+ '3d': '3d',
76
+ '1w': '1w',
77
+ '1M': '1M',
78
+ },
79
+ 'urls': {
80
+ 'logo': 'https://user-images.githubusercontent.com/1294454/66732963-8eb7dd00-ee66-11e9-849b-10d9282bb9e0.jpg',
81
+ 'api': {
82
+ 'v1': {
83
+ 'public': 'https://whitebit.com/api/v1/public',
84
+ 'private': 'https://whitebit.com/api/v1',
85
+ },
86
+ 'v2': {
87
+ 'public': 'https://whitebit.com/api/v2/public',
88
+ },
89
+ 'v4': {
90
+ 'public': 'https://whitebit.com/api/v4/public',
91
+ 'private': 'https://whitebit.com/api/v4',
92
+ },
93
+ },
94
+ 'www': 'https://www.whitebit.com',
95
+ 'doc': 'https://github.com/whitebit-exchange/api-docs',
96
+ 'fees': 'https://whitebit.com/fee-schedule',
97
+ 'referral': 'https://whitebit.com/referral/d9bdf40e-28f2-4b52-b2f9-cd1415d82963',
98
+ },
99
+ 'api': {
100
+ 'web': {
101
+ 'get': [
102
+ 'v1/healthcheck',
103
+ ],
104
+ },
105
+ 'v1': {
106
+ 'public': {
107
+ 'get': [
108
+ 'markets',
109
+ 'tickers',
110
+ 'ticker',
111
+ 'symbols',
112
+ 'depth/result',
113
+ 'history',
114
+ 'kline',
115
+ ],
116
+ },
117
+ 'private': {
118
+ 'post': [
119
+ 'account/balance',
120
+ 'order/new',
121
+ 'order/cancel',
122
+ 'orders',
123
+ 'account/order_history',
124
+ 'account/executed_history',
125
+ 'account/executed_history/all',
126
+ 'account/order',
127
+ ],
128
+ },
129
+ },
130
+ 'v2': {
131
+ 'public': {
132
+ 'get': [
133
+ 'markets',
134
+ 'ticker',
135
+ 'assets',
136
+ 'fee',
137
+ 'depth/{market}',
138
+ 'trades/{market}',
139
+ ],
140
+ },
141
+ },
142
+ 'v4': {
143
+ 'public': {
144
+ 'get': [
145
+ 'assets',
146
+ 'fee',
147
+ 'orderbook/{market}',
148
+ 'ticker',
149
+ 'trades/{market}',
150
+ 'time',
151
+ 'ping',
152
+ ],
153
+ },
154
+ 'private': {
155
+ 'post': [
156
+ 'main-account/address',
157
+ 'main-account/balance',
158
+ 'main-account/create-new-address',
159
+ 'main-account/codes',
160
+ 'main-account/codes/apply',
161
+ 'main-account/codes/my',
162
+ 'main-account/codes/history',
163
+ 'main-account/fiat-deposit-url',
164
+ 'main-account/history',
165
+ 'main-account/withdraw',
166
+ 'main-account/withdraw-pay',
167
+ 'main-account/transfer',
168
+ 'trade-account/balance',
169
+ 'trade-account/executed-history',
170
+ 'trade-account/order',
171
+ 'trade-account/order/history',
172
+ 'order/new',
173
+ 'order/market',
174
+ 'order/stock_market',
175
+ 'order/stop_limit',
176
+ 'order/stop_market',
177
+ 'order/cancel',
178
+ 'orders',
179
+ ],
180
+ },
181
+ },
182
+ },
183
+ 'fees': {
184
+ 'trading': {
185
+ 'tierBased': false,
186
+ 'percentage': true,
187
+ 'taker': this.parseNumber ('0.001'),
188
+ 'maker': this.parseNumber ('0.001'),
189
+ },
190
+ },
191
+ 'options': {
192
+ 'createMarketBuyOrderRequiresPrice': true,
193
+ 'fiatCurrencies': [ 'EUR', 'USD', 'RUB', 'UAH' ],
194
+ 'accountsByType': {
195
+ 'main': 'main',
196
+ 'spot': 'trade',
197
+ 'margin': 'margin', // api does not suppot transfers to margin
198
+ },
199
+ 'transfer': {
200
+ 'fillTransferResponseFromRequest': true,
201
+ },
202
+ },
203
+ 'exceptions': {
204
+ 'exact': {
205
+ 'Unauthorized request.': AuthenticationError, // {"code":10,"message":"Unauthorized request."}
206
+ 'The market format is invalid.': BadSymbol, // {"code":0,"message":"Validation failed","errors":{"market":["The market format is invalid."]}}
207
+ 'Market is not available': BadSymbol, // {"success":false,"message":{"market":["Market is not available"]},"result":[]}
208
+ 'Invalid payload.': BadRequest, // {"code":9,"message":"Invalid payload."}
209
+ 'Amount must be greater than 0': InvalidOrder, // {"code":0,"message":"Validation failed","errors":{"amount":["Amount must be greater than 0"]}}
210
+ 'The order id field is required.': InvalidOrder, // {"code":0,"message":"Validation failed","errors":{"orderId":["The order id field is required."]}}
211
+ 'Not enough balance': InsufficientFunds, // {"code":0,"message":"Validation failed","errors":{"amount":["Not enough balance"]}}
212
+ 'This action is unauthorized.': PermissionDenied, // {"code":0,"message":"This action is unauthorized."}
213
+ 'This API Key is not authorized to perform this action.': PermissionDenied, // {"code":4,"message":"This API Key is not authorized to perform this action."}
214
+ 'Unexecuted order was not found.': OrderNotFound, // {"code":2,"message":"Inner validation failed","errors":{"order_id":["Unexecuted order was not found."]}}
215
+ '503': ExchangeNotAvailable, // {"response":null,"status":503,"errors":{"message":[""]},"notification":null,"warning":null,"_token":null},
216
+ '422': OrderNotFound, // {"response":null,"status":422,"errors":{"orderId":["Finished order id 1295772653 not found on your account"]},"notification":null,"warning":"Finished order id 1295772653 not found on your account","_token":null}
217
+ },
218
+ 'broad': {
219
+ 'Given amount is less than min amount': InvalidOrder, // {"code":0,"message":"Validation failed","errors":{"amount":["Given amount is less than min amount 200000"],"total":["Total is less than 5.05"]}}
220
+ 'Total is less than': InvalidOrder, // {"code":0,"message":"Validation failed","errors":{"amount":["Given amount is less than min amount 200000"],"total":["Total is less than 5.05"]}}
221
+ 'fee must be no less than': InvalidOrder, // {"code":0,"message":"Validation failed","errors":{"amount":["Total amount + fee must be no less than 5.05505"]}}
222
+ 'Enable your key in API settings': PermissionDenied, // {"code":2,"message":"This action is unauthorized. Enable your key in API settings"}
223
+ },
224
+ },
225
+ });
226
+ }
227
+
228
+ async fetchMarkets (params = {}) {
229
+ const response = await this.v2PublicGetMarkets (params);
230
+ //
231
+ // {
232
+ // "success": true,
233
+ // "message": "",
234
+ // "result": [
235
+ // {
236
+ // "name":
237
+ // "C98_USDT",
238
+ // "stock":"C98",
239
+ // "money":"USDT",
240
+ // "stockPrec":"3",
241
+ // "moneyPrec":"5",
242
+ // "feePrec":"6",
243
+ // "makerFee":"0.001",
244
+ // "takerFee":"0.001",
245
+ // "minAmount":"2.5",
246
+ // "minTotal":"5.05",
247
+ // "tradesEnabled":true
248
+ // },
249
+ // ...
250
+ // ]
251
+ // }
252
+ //
253
+ const markets = this.safeValue (response, 'result');
254
+ const result = [];
255
+ for (let i = 0; i < markets.length; i++) {
256
+ const market = markets[i];
257
+ const id = this.safeString (market, 'name');
258
+ const baseId = this.safeString (market, 'stock');
259
+ const quoteId = this.safeString (market, 'money');
260
+ const base = this.safeCurrencyCode (baseId);
261
+ const quote = this.safeCurrencyCode (quoteId);
262
+ const symbol = base + '/' + quote;
263
+ const active = this.safeValue (market, 'tradesEnabled');
264
+ const entry = {
265
+ 'id': id,
266
+ 'symbol': symbol,
267
+ 'base': base,
268
+ 'quote': quote,
269
+ 'settle': undefined,
270
+ 'baseId': baseId,
271
+ 'quoteId': quoteId,
272
+ 'settleId': undefined,
273
+ 'type': 'spot',
274
+ 'spot': true,
275
+ 'margin': undefined,
276
+ 'swap': false,
277
+ 'future': false,
278
+ 'option': false,
279
+ 'active': active,
280
+ 'contract': false,
281
+ 'linear': undefined,
282
+ 'inverse': undefined,
283
+ 'taker': this.safeNumber (market, 'makerFee'),
284
+ 'maker': this.safeNumber (market, 'takerFee'),
285
+ 'contractSize': undefined,
286
+ 'expiry': undefined,
287
+ 'expiryDatetime': undefined,
288
+ 'strike': undefined,
289
+ 'optionType': undefined,
290
+ 'precision': {
291
+ 'amount': this.safeInteger (market, 'stockPrec'),
292
+ 'price': this.safeInteger (market, 'moneyPrec'),
293
+ },
294
+ 'limits': {
295
+ 'leverage': {
296
+ 'min': undefined,
297
+ 'max': undefined,
298
+ },
299
+ 'amount': {
300
+ 'min': this.safeNumber (market, 'minAmount'),
301
+ 'max': undefined,
302
+ },
303
+ 'price': {
304
+ 'min': undefined,
305
+ 'max': undefined,
306
+ },
307
+ 'cost': {
308
+ 'min': this.safeNumber (market, 'minTotal'),
309
+ 'max': undefined,
310
+ },
311
+ },
312
+ 'info': market,
313
+ };
314
+ result.push (entry);
315
+ }
316
+ return result;
317
+ }
318
+
319
+ async fetchCurrencies (params = {}) {
320
+ const response = await this.v4PublicGetAssets (params);
321
+ //
322
+ // "BTC": {
323
+ // "name": "Bitcoin",
324
+ // "unified_cryptoasset_id": 1,
325
+ // "can_withdraw": true,
326
+ // "can_deposit": true,
327
+ // "min_withdraw": "0.001",
328
+ // "max_withdraw": "2",
329
+ // "maker_fee": "0.1",
330
+ // "taker_fee": "0.1",
331
+ // "min_deposit": "0.0001",
332
+ // "max_deposit": "0",
333
+ // },
334
+ //
335
+ const ids = Object.keys (response);
336
+ const result = {};
337
+ for (let i = 0; i < ids.length; i++) {
338
+ const id = ids[i];
339
+ const currency = response[id];
340
+ // breaks down in Python due to utf8 encoding issues on the exchange side
341
+ // const name = this.safeString (currency, 'name');
342
+ const canDeposit = this.safeValue (currency, 'can_deposit', true);
343
+ const canWithdraw = this.safeValue (currency, 'can_withdraw', true);
344
+ const active = canDeposit && canWithdraw;
345
+ const code = this.safeCurrencyCode (id);
346
+ result[code] = {
347
+ 'id': id,
348
+ 'code': code,
349
+ 'info': currency, // the original payload
350
+ 'name': undefined, // see the comment above
351
+ 'active': active,
352
+ 'deposit': canDeposit,
353
+ 'withdraw': canWithdraw,
354
+ 'fee': undefined,
355
+ 'precision': undefined,
356
+ 'limits': {
357
+ 'amount': {
358
+ 'min': undefined,
359
+ 'max': undefined,
360
+ },
361
+ 'withdraw': {
362
+ 'min': this.safeNumber (currency, 'min_withdraw'),
363
+ 'max': this.safeNumber (currency, 'max_withdraw'),
364
+ },
365
+ },
366
+ };
367
+ }
368
+ return result;
369
+ }
370
+
371
+ async fetchFundingFees (params = {}) {
372
+ await this.loadMarkets ();
373
+ const response = await this.v4PublicGetFee (params);
374
+ //
375
+ // {
376
+ // "1INCH":{
377
+ // "is_depositable":true,
378
+ // "is_withdrawal":true,
379
+ // "ticker":"1INCH",
380
+ // "name":"1inch",
381
+ // "providers":[
382
+ // ],
383
+ // "withdraw":{
384
+ // "max_amount":"0",
385
+ // "min_amount":"21.5",
386
+ // "fixed":"17.5",
387
+ // "flex":null
388
+ // },
389
+ // "deposit":{
390
+ // "max_amount":"0",
391
+ // "min_amount":"19.5",
392
+ // "fixed":null,
393
+ // "flex":null
394
+ // }
395
+ // },
396
+ // {...}
397
+ // }
398
+ //
399
+ const currenciesIds = Object.keys (response);
400
+ const withdrawFees = {};
401
+ const depositFees = {};
402
+ for (let i = 0; i < currenciesIds.length; i++) {
403
+ const currency = currenciesIds[i];
404
+ const data = response[currency];
405
+ const code = this.safeCurrencyCode (currency);
406
+ const withdraw = this.safeValue (data, 'withdraw', {});
407
+ withdrawFees[code] = this.safeString (withdraw, 'fixed');
408
+ const deposit = this.safeValue (data, 'deposit', {});
409
+ depositFees[code] = this.safeString (deposit, 'fixed');
410
+ }
411
+ return {
412
+ 'withdraw': withdrawFees,
413
+ 'deposit': depositFees,
414
+ 'info': response,
415
+ };
416
+ }
417
+
418
+ async fetchTradingFees (params = {}) {
419
+ const response = await this.v4PublicGetAssets (params);
420
+ //
421
+ // {
422
+ // '1INCH': {
423
+ // name: '1inch',
424
+ // unified_cryptoasset_id: '8104',
425
+ // can_withdraw: true,
426
+ // can_deposit: true,
427
+ // min_withdraw: '33',
428
+ // max_withdraw: '0',
429
+ // maker_fee: '0.1',
430
+ // taker_fee: '0.1',
431
+ // min_deposit: '30',
432
+ // max_deposit: '0'
433
+ // },
434
+ // ...
435
+ // }
436
+ //
437
+ const result = {};
438
+ for (let i = 0; i < this.symbols.length; i++) {
439
+ const symbol = this.symbols[i];
440
+ const market = this.market (symbol);
441
+ const fee = this.safeValue (response, market['baseId'], {});
442
+ let makerFee = this.safeString (fee, 'maker_fee');
443
+ let takerFee = this.safeString (fee, 'taker_fee');
444
+ makerFee = Precise.stringDiv (makerFee, '100');
445
+ takerFee = Precise.stringDiv (takerFee, '100');
446
+ result[symbol] = {
447
+ 'info': fee,
448
+ 'symbol': market['symbol'],
449
+ 'percentage': true,
450
+ 'tierBased': false,
451
+ 'maker': this.parseNumber (makerFee),
452
+ 'taker': this.parseNumber (takerFee),
453
+ };
454
+ }
455
+ return result;
456
+ }
457
+
458
+ async fetchTicker (symbol, params = {}) {
459
+ await this.loadMarkets ();
460
+ const market = this.market (symbol);
461
+ const request = {
462
+ 'market': market['id'],
463
+ };
464
+ const response = await this.v1PublicGetTicker (this.extend (request, params));
465
+ //
466
+ // {
467
+ // "success":true,
468
+ // "message":"",
469
+ // "result": {
470
+ // "bid":"0.021979",
471
+ // "ask":"0.021996",
472
+ // "open":"0.02182",
473
+ // "high":"0.022039",
474
+ // "low":"0.02161",
475
+ // "last":"0.021987",
476
+ // "volume":"2810.267",
477
+ // "deal":"61.383565474",
478
+ // "change":"0.76",
479
+ // },
480
+ // }
481
+ //
482
+ const ticker = this.safeValue (response, 'result', {});
483
+ return this.parseTicker (ticker, market);
484
+ }
485
+
486
+ parseTicker (ticker, market = undefined) {
487
+ //
488
+ // FetchTicker (v1)
489
+ //
490
+ // {
491
+ // "bid": "0.021979",
492
+ // "ask": "0.021996",
493
+ // "open": "0.02182",
494
+ // "high": "0.022039",
495
+ // "low": "0.02161",
496
+ // "last": "0.021987",
497
+ // "volume": "2810.267",
498
+ // "deal": "61.383565474",
499
+ // "change": "0.76",
500
+ // }
501
+ //
502
+ // FetchTickers (v4)
503
+ //
504
+ // "BCH_RUB": {
505
+ // "base_id": 1831,
506
+ // "quote_id": 0,
507
+ // "last_price": "32830.21",
508
+ // "quote_volume": "1494659.8024096",
509
+ // "base_volume": "46.1083",
510
+ // "isFrozen": false,
511
+ // "change": "2.12" // in percent
512
+ // }
513
+ //
514
+ market = this.safeMarket (undefined, market);
515
+ const last = this.safeString (ticker, 'last_price');
516
+ return this.safeTicker ({
517
+ 'symbol': market['symbol'],
518
+ 'timestamp': undefined,
519
+ 'datetime': undefined,
520
+ 'high': this.safeString (ticker, 'high'),
521
+ 'low': this.safeString (ticker, 'low'),
522
+ 'bid': this.safeString (ticker, 'bid'),
523
+ 'bidVolume': undefined,
524
+ 'ask': this.safeString (ticker, 'ask'),
525
+ 'askVolume': undefined,
526
+ 'vwap': undefined,
527
+ 'open': this.safeString (ticker, 'open'),
528
+ 'close': last,
529
+ 'last': last,
530
+ 'previousClose': undefined,
531
+ 'change': undefined,
532
+ 'percentage': this.safeString (ticker, 'change'),
533
+ 'average': undefined,
534
+ 'baseVolume': this.safeString2 (ticker, 'base_volume', 'volume'),
535
+ 'quoteVolume': this.safeString2 (ticker, 'quote_volume', 'deal'),
536
+ 'info': ticker,
537
+ }, market, false);
538
+ }
539
+
540
+ async fetchTickers (symbols = undefined, params = {}) {
541
+ await this.loadMarkets ();
542
+ const response = await this.v4PublicGetTicker (params);
543
+ //
544
+ // "BCH_RUB": {
545
+ // "base_id":1831,
546
+ // "quote_id":0,
547
+ // "last_price":"32830.21",
548
+ // "quote_volume":"1494659.8024096",
549
+ // "base_volume":"46.1083",
550
+ // "isFrozen":false,
551
+ // "change":"2.12"
552
+ // },
553
+ //
554
+ const marketIds = Object.keys (response);
555
+ const result = {};
556
+ for (let i = 0; i < marketIds.length; i++) {
557
+ const marketId = marketIds[i];
558
+ const market = this.safeMarket (marketId);
559
+ const ticker = this.parseTicker (response[marketId], market);
560
+ const symbol = ticker['symbol'];
561
+ result[symbol] = ticker;
562
+ }
563
+ return this.filterByArray (result, 'symbol', symbols);
564
+ }
565
+
566
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
567
+ await this.loadMarkets ();
568
+ const market = this.market (symbol);
569
+ const request = {
570
+ 'market': market['id'],
571
+ };
572
+ if (limit !== undefined) {
573
+ request['depth'] = limit; // default = 50, maximum = 100
574
+ }
575
+ const response = await this.v4PublicGetOrderbookMarket (this.extend (request, params));
576
+ //
577
+ // {
578
+ // "timestamp": 1594391413,
579
+ // "asks": [
580
+ // [
581
+ // "9184.41",
582
+ // "0.773162"
583
+ // ],
584
+ // [ ... ]
585
+ // ],
586
+ // "bids": [
587
+ // [
588
+ // "9181.19",
589
+ // "0.010873"
590
+ // ],
591
+ // [ ... ]
592
+ // ]
593
+ // }
594
+ //
595
+ const timestamp = this.safeString (response, 'timestamp');
596
+ return this.parseOrderBook (response, symbol, timestamp);
597
+ }
598
+
599
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
600
+ await this.loadMarkets ();
601
+ const market = this.market (symbol);
602
+ const request = {
603
+ 'market': market['id'],
604
+ };
605
+ const response = await this.v4PublicGetTradesMarket (this.extend (request, params));
606
+ //
607
+ // [
608
+ // {
609
+ // "tradeID": 158056419,
610
+ // "price": "9186.13",
611
+ // "quote_volume": "0.0021",
612
+ // "base_volume": "9186.13",
613
+ // "trade_timestamp": 1594391747,
614
+ // "type": "sell"
615
+ // },
616
+ // ],
617
+ //
618
+ return this.parseTrades (response, market, since, limit);
619
+ }
620
+
621
+ parseTrade (trade, market = undefined) {
622
+ // fetchTradesV4
623
+ // {
624
+ // "tradeID": 158056419,
625
+ // "price": "9186.13",
626
+ // "quote_volume": "0.0021",
627
+ // "base_volume": "9186.13",
628
+ // "trade_timestamp": 1594391747,
629
+ // "type": "sell"
630
+ // },
631
+ //
632
+ // orderTrades (v4Private)
633
+ //
634
+ // {
635
+ // "time": 1593342324.613711,
636
+ // "fee": "0.00000419198",
637
+ // "price": "0.00000701",
638
+ // "amount": "598",
639
+ // "id": 149156519, // trade id
640
+ // "dealOrderId": 3134995325, // orderId
641
+ // "clientOrderId": "customId11",
642
+ // "role": 2, // 1 = maker, 2 = taker
643
+ // "deal": "0.00419198" // amount in money
644
+ // }
645
+ //
646
+ const timestamp = this.safeTimestamp2 (trade, 'time', 'trade_timestamp');
647
+ const orderId = this.safeString (trade, 'dealOrderId');
648
+ const cost = this.safeString (trade, 'deal');
649
+ const price = this.safeString (trade, 'price');
650
+ const amount = this.safeString2 (trade, 'amount', 'base_volume');
651
+ const id = this.safeString2 (trade, 'id', 'tradeID');
652
+ const side = this.safeString (trade, 'type');
653
+ const symbol = this.safeSymbol (undefined, market);
654
+ const role = this.safeInteger (trade, 'role');
655
+ let takerOrMaker = undefined;
656
+ if (role !== undefined) {
657
+ takerOrMaker = (role === 1) ? 'maker' : 'taker';
658
+ }
659
+ let fee = undefined;
660
+ const feeCost = this.safeString (trade, 'fee');
661
+ if (feeCost !== undefined) {
662
+ const safeMarket = this.safeMarket (undefined, market);
663
+ const quote = safeMarket['quote'];
664
+ fee = {
665
+ 'cost': feeCost,
666
+ 'currency': quote,
667
+ };
668
+ }
669
+ return this.safeTrade ({
670
+ 'info': trade,
671
+ 'timestamp': timestamp,
672
+ 'datetime': this.iso8601 (timestamp),
673
+ 'symbol': symbol,
674
+ 'id': id,
675
+ 'order': orderId,
676
+ 'type': undefined,
677
+ 'takerOrMaker': takerOrMaker,
678
+ 'side': side,
679
+ 'price': price,
680
+ 'amount': amount,
681
+ 'cost': cost,
682
+ 'fee': fee,
683
+ }, market);
684
+ }
685
+
686
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
687
+ await this.loadMarkets ();
688
+ const market = this.market (symbol);
689
+ const request = {
690
+ 'market': market['id'],
691
+ 'interval': this.timeframes[timeframe],
692
+ };
693
+ if (since !== undefined) {
694
+ const maxLimit = 1440;
695
+ if (limit === undefined) {
696
+ limit = maxLimit;
697
+ }
698
+ limit = Math.min (limit, maxLimit);
699
+ const start = parseInt (since / 1000);
700
+ const duration = this.parseTimeframe (timeframe);
701
+ const end = this.sum (start, duration * limit);
702
+ request['start'] = start;
703
+ request['end'] = end;
704
+ }
705
+ if (limit !== undefined) {
706
+ request['limit'] = limit; // max 1440
707
+ }
708
+ const response = await this.v1PublicGetKline (this.extend (request, params));
709
+ //
710
+ // {
711
+ // "success":true,
712
+ // "message":"",
713
+ // "result":[
714
+ // [1591488000,"0.025025","0.025025","0.025029","0.025023","6.181","0.154686629"],
715
+ // [1591488060,"0.025028","0.025033","0.025035","0.025026","8.067","0.201921167"],
716
+ // [1591488120,"0.025034","0.02505","0.02505","0.025034","20.089","0.503114696"],
717
+ // ]
718
+ // }
719
+ //
720
+ const result = this.safeValue (response, 'result', []);
721
+ return this.parseOHLCVs (result, market, timeframe, since, limit);
722
+ }
723
+
724
+ parseOHLCV (ohlcv, market = undefined) {
725
+ //
726
+ // [
727
+ // 1591488000,
728
+ // "0.025025",
729
+ // "0.025025",
730
+ // "0.025029",
731
+ // "0.025023",
732
+ // "6.181",
733
+ // "0.154686629"
734
+ // ]
735
+ //
736
+ return [
737
+ this.safeTimestamp (ohlcv, 0), // timestamp
738
+ this.safeNumber (ohlcv, 1), // open
739
+ this.safeNumber (ohlcv, 3), // high
740
+ this.safeNumber (ohlcv, 4), // low
741
+ this.safeNumber (ohlcv, 2), // close
742
+ this.safeNumber (ohlcv, 5), // volume
743
+ ];
744
+ }
745
+
746
+ async fetchStatus (params = {}) {
747
+ const response = await this.v4PublicGetPing (params);
748
+ //
749
+ // [
750
+ // "pong"
751
+ // ]
752
+ //
753
+ const status = this.safeString (response, 0);
754
+ return {
755
+ 'status': (status === 'pong') ? 'ok' : status,
756
+ 'updated': this.milliseconds (),
757
+ 'eta': undefined,
758
+ 'url': undefined,
759
+ 'info': response,
760
+ };
761
+ }
762
+
763
+ async fetchTime (params = {}) {
764
+ const response = await this.v4PublicGetTime (params);
765
+ //
766
+ // {
767
+ // "time":1635467280514
768
+ // }
769
+ //
770
+ return this.safeInteger (response, 'time');
771
+ }
772
+
773
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
774
+ let method = undefined;
775
+ await this.loadMarkets ();
776
+ const market = this.market (symbol);
777
+ const request = {
778
+ 'market': market['id'],
779
+ 'side': side,
780
+ 'amount': this.amountToPrecision (symbol, amount),
781
+ };
782
+ const stopPrice = this.safeNumber2 (params, 'stopPrice', 'activationPrice');
783
+ if (stopPrice !== undefined) {
784
+ // it's a stop order
785
+ request['activation_price'] = this.priceToPrecision (symbol, stopPrice);
786
+ if (type === 'limit' || type === 'stopLimit') {
787
+ // it's a stop-limit-order
788
+ method = 'v4PrivateOPostOrderStopLimit';
789
+ } else if (type === 'market' || type === 'stopMarket') {
790
+ // it's a stop-market-order
791
+ method = 'v4PrivatePostOrderStopMarket';
792
+ }
793
+ } else {
794
+ if (type === 'market') {
795
+ // it's a regular market order
796
+ method = 'v4PrivatePostOrderMarket';
797
+ }
798
+ if (type === 'limit') {
799
+ // it's a regular limit order
800
+ method = 'v4PrivatePostOrderNew';
801
+ }
802
+ }
803
+ // aggregate common assignments regardless stop or not
804
+ if (type === 'limit' || type === 'stopLimit') {
805
+ if (price === undefined) {
806
+ throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument for a stopLimit order');
807
+ }
808
+ const convertedPrice = this.priceToPrecision (symbol, price);
809
+ request['price'] = convertedPrice;
810
+ }
811
+ if (type === 'market' || type === 'stopMarket') {
812
+ if (side === 'buy') {
813
+ let cost = this.safeNumber (params, 'cost');
814
+ const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true);
815
+ if (createMarketBuyOrderRequiresPrice) {
816
+ if (price !== undefined) {
817
+ if (cost === undefined) {
818
+ cost = amount * price;
819
+ }
820
+ } else if (cost === undefined) {
821
+ throw new InvalidOrder (this.id + " createOrder() requires the price argument for market buy orders to calculate total order cost (amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options['createMarketBuyOrderRequiresPrice'] = false and supply the total cost value in the 'amount' argument or in the 'cost' extra parameter (the exchange-specific behaviour)");
822
+ }
823
+ } else {
824
+ cost = (cost === undefined) ? amount : cost;
825
+ }
826
+ request['amount'] = this.costToPrecision (symbol, cost);
827
+ }
828
+ }
829
+ if (method === undefined) {
830
+ throw new ArgumentsRequired (this.id + ' createOrder() requires one of the following order types: market, limit, stopLimit or stopMarket');
831
+ }
832
+ const response = await this[method] (this.extend (request, params));
833
+ return this.parseOrder (response);
834
+ }
835
+
836
+ async cancelOrder (id, symbol = undefined, params = {}) {
837
+ if (symbol === undefined) {
838
+ throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
839
+ }
840
+ await this.loadMarkets ();
841
+ const market = this.market (symbol);
842
+ const request = {
843
+ 'market': market['id'],
844
+ 'orderId': parseInt (id),
845
+ };
846
+ return await this.v4PrivatePostOrderCancel (this.extend (request, params));
847
+ }
848
+
849
+ parseBalance (response) {
850
+ const balanceKeys = Object.keys (response);
851
+ const result = { };
852
+ for (let i = 0; i < balanceKeys.length; i++) {
853
+ const id = balanceKeys[i];
854
+ const balance = response[id];
855
+ const code = this.safeCurrencyCode (id);
856
+ const account = this.account ();
857
+ account['free'] = this.safeString (balance, 'available');
858
+ account['used'] = this.safeString (balance, 'freeze');
859
+ result[code] = account;
860
+ }
861
+ return this.safeBalance (result);
862
+ }
863
+
864
+ async fetchBalance (params = {}) {
865
+ await this.loadMarkets ();
866
+ const response = await this.v4PrivatePostTradeAccountBalance (params);
867
+ //
868
+ // {
869
+ // "BTC": { "available": "0.123", "freeze": "1" },
870
+ // "XMR": { "available": "3013", "freeze": "100" },
871
+ // }
872
+ //
873
+ return this.parseBalance (response);
874
+ }
875
+
876
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
877
+ if (symbol === undefined) {
878
+ throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument');
879
+ }
880
+ await this.loadMarkets ();
881
+ const market = this.market (symbol);
882
+ const request = {
883
+ 'market': market['id'],
884
+ };
885
+ if (limit !== undefined) {
886
+ request['limit'] = limit; // default 50 max 100
887
+ }
888
+ const response = await this.v4PrivatePostOrders (this.extend (request, params));
889
+ //
890
+ // [
891
+ // {
892
+ // "orderId": 3686033640,
893
+ // "clientOrderId": "customId11",
894
+ // "market": "BTC_USDT",
895
+ // "side": "buy",
896
+ // "type": "limit",
897
+ // "timestamp": 1594605801.49815, // current timestamp of unexecuted order
898
+ // "dealMoney": "0", // executed amount in money
899
+ // "dealStock": "0", // executed amount in stock
900
+ // "amount": "2.241379", // active order amount
901
+ // "takerFee": "0.001",
902
+ // "makerFee": "0.001",
903
+ // "left": "2.241379", // unexecuted amount in stock
904
+ // "dealFee": "0", // executed fee by deal
905
+ // "price": "40000"
906
+ // },
907
+ // ]
908
+ //
909
+ return this.parseOrders (response, market, since, limit, { 'status': 'open' });
910
+ }
911
+
912
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
913
+ await this.loadMarkets ();
914
+ const request = {};
915
+ let market = undefined;
916
+ if (symbol !== undefined) {
917
+ market = this.market (symbol);
918
+ symbol = market['symbol'];
919
+ request['market'] = market['id'];
920
+ }
921
+ if (limit !== undefined) {
922
+ request['limit'] = limit; // default 50 max 100
923
+ }
924
+ const response = await this.v4PrivatePostTradeAccountOrderHistory (this.extend (request, params));
925
+ //
926
+ // {
927
+ // "BTC_USDT": [
928
+ // {
929
+ // "id": 160305483,
930
+ // "clientOrderId": "customId11",
931
+ // "time": 1594667731.724403,
932
+ // "side": "sell",
933
+ // "role": 2, // 1 = maker, 2 = taker
934
+ // "amount": "0.000076",
935
+ // "price": "9264.21",
936
+ // "deal": "0.70407996",
937
+ // "fee": "0.00070407996"
938
+ // },
939
+ // ],
940
+ // }
941
+ //
942
+ const marketIds = Object.keys (response);
943
+ let results = [];
944
+ for (let i = 0; i < marketIds.length; i++) {
945
+ const marketId = marketIds[i];
946
+ const market = this.safeMarket (marketId, undefined, '_');
947
+ const orders = response[marketId];
948
+ for (let j = 0; j < orders.length; j++) {
949
+ const order = this.parseOrder (orders[j], market);
950
+ results.push (this.extend (order, { 'status': 'filled' }));
951
+ }
952
+ }
953
+ results = this.sortBy (results, 'timestamp');
954
+ results = this.filterBySymbolSinceLimit (results, symbol, since, limit, since === undefined);
955
+ return results;
956
+ }
957
+
958
+ parseOrder (order, market = undefined) {
959
+ //
960
+ // createOrder, fetchOpenOrders
961
+ //
962
+ // {
963
+ // "orderId": 4180284841,
964
+ // "clientOrderId": "order1987111",
965
+ // "market": "BTC_USDT",
966
+ // "side": "buy",
967
+ // "type": "stop limit",
968
+ // "timestamp": 1595792396.165973,
969
+ // "dealMoney": "0", // if order finished - amount in money currency that finished
970
+ // "dealStock": "0", // if order finished - amount in stock currency that finished
971
+ // "amount": "0.001",
972
+ // "takerFee": "0.001",
973
+ // "makerFee": "0.001",
974
+ // "left": "0.001", // remaining amount
975
+ // "dealFee": "0", // fee in money that you pay if order is finished
976
+ // "price": "40000",
977
+ // "activation_price": "40000" // activation price -> only for stopLimit, stopMarket
978
+ // }
979
+ //
980
+ // fetchClosedOrders
981
+ //
982
+ // {
983
+ // "market": "BTC_USDT"
984
+ // "amount": "0.0009",
985
+ // "price": "40000",
986
+ // "type": "limit",
987
+ // "id": 4986126152,
988
+ // "clientOrderId": "customId11",
989
+ // "side": "sell",
990
+ // "ctime": 1597486960.311311, // timestamp of order creation
991
+ // "takerFee": "0.001",
992
+ // "ftime": 1597486960.311332, // executed order timestamp
993
+ // "makerFee": "0.001",
994
+ // "dealFee": "0.041258268", // paid fee if order is finished
995
+ // "dealStock": "0.0009", // amount in stock currency that finished
996
+ // "dealMoney": "41.258268" // amount in money currency that finished
997
+ // }
998
+ //
999
+ const marketId = this.safeString (order, 'market');
1000
+ market = this.safeMarket (marketId, market, '_');
1001
+ const symbol = market['symbol'];
1002
+ const side = this.safeString (order, 'side');
1003
+ const filled = this.safeString (order, 'dealStock');
1004
+ const remaining = this.safeString (order, 'left');
1005
+ let clientOrderId = this.safeString (order, 'clientOrderId');
1006
+ if (clientOrderId === '') {
1007
+ clientOrderId = undefined;
1008
+ }
1009
+ let price = this.safeString (order, 'price');
1010
+ const stopPrice = this.safeString (order, 'activation_price');
1011
+ const orderId = this.safeString2 (order, 'orderId', 'id');
1012
+ const type = this.safeString (order, 'type');
1013
+ let amount = this.safeString (order, 'amount');
1014
+ let cost = undefined;
1015
+ if (price === '0') {
1016
+ // api error to be solved
1017
+ price = undefined;
1018
+ }
1019
+ if (side === 'buy' && type.indexOf ('market') >= 0) {
1020
+ // in these cases the amount is in the quote currency meaning it's the cost
1021
+ cost = amount;
1022
+ amount = undefined;
1023
+ if (price !== undefined) {
1024
+ // if the price is available we can do this conversion
1025
+ // from amount in quote currency to base currency
1026
+ amount = Precise.stringDiv (cost, price);
1027
+ }
1028
+ }
1029
+ const dealFee = this.safeString (order, 'dealFee');
1030
+ let fee = undefined;
1031
+ if (dealFee !== undefined) {
1032
+ fee = {
1033
+ 'cost': this.parseNumber (dealFee),
1034
+ 'currency': market['quote'],
1035
+ };
1036
+ }
1037
+ const timestamp = this.safeTimestamp2 (order, 'ctime', 'timestamp');
1038
+ const lastTradeTimestamp = this.safeTimestamp (order, 'ftime');
1039
+ return this.safeOrder ({
1040
+ 'info': order,
1041
+ 'id': orderId,
1042
+ 'symbol': symbol,
1043
+ 'clientOrderId': clientOrderId,
1044
+ 'timestamp': timestamp,
1045
+ 'datetime': this.iso8601 (timestamp),
1046
+ 'lastTradeTimestamp': lastTradeTimestamp,
1047
+ 'timeInForce': undefined,
1048
+ 'postOnly': undefined,
1049
+ 'status': undefined,
1050
+ 'side': side,
1051
+ 'price': price,
1052
+ 'type': type,
1053
+ 'stopPrice': stopPrice,
1054
+ 'amount': amount,
1055
+ 'filled': filled,
1056
+ 'remaining': remaining,
1057
+ 'average': undefined,
1058
+ 'cost': cost,
1059
+ 'fee': fee,
1060
+ 'trades': undefined,
1061
+ }, market);
1062
+ }
1063
+
1064
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1065
+ await this.loadMarkets ();
1066
+ const request = {
1067
+ 'orderId': parseInt (id),
1068
+ };
1069
+ let market = undefined;
1070
+ if (symbol !== undefined) {
1071
+ market = this.market (symbol);
1072
+ request['market'] = market['id'];
1073
+ }
1074
+ if (limit !== undefined) {
1075
+ request['limit'] = limit; // default 50, max 100
1076
+ }
1077
+ const response = await this.v4PrivatePostTradeAccountOrder (this.extend (request, params));
1078
+ //
1079
+ // {
1080
+ // "records": [
1081
+ // {
1082
+ // "time": 1593342324.613711,
1083
+ // "fee": "0.00000419198",
1084
+ // "price": "0.00000701",
1085
+ // "amount": "598",
1086
+ // "id": 149156519, // trade id
1087
+ // "dealOrderId": 3134995325, // orderId
1088
+ // "clientOrderId": "customId11", // empty string if not specified
1089
+ // "role": 2, // 1 = maker, 2 = taker
1090
+ // "deal": "0.00419198"
1091
+ // }
1092
+ // ],
1093
+ // "offset": 0,
1094
+ // "limit": 100
1095
+ // }
1096
+ //
1097
+ const data = this.safeValue (response, 'records', []);
1098
+ return this.parseTrades (data, market);
1099
+ }
1100
+
1101
+ async fetchDepositAddress (code, params = {}) {
1102
+ await this.loadMarkets ();
1103
+ const currency = this.currency (code);
1104
+ const request = {
1105
+ 'ticker': currency['id'],
1106
+ };
1107
+ let method = 'v4PrivatePostMainAccountAddress';
1108
+ if (this.isFiat (code)) {
1109
+ method = 'v4PrivatePostMainAccountFiatDepositUrl';
1110
+ const provider = this.safeNumber (params, 'provider');
1111
+ if (provider === undefined) {
1112
+ throw new ArgumentsRequired (this.id + ' fetchDepositAddress() requires a provider when the ticker is fiat');
1113
+ }
1114
+ request['provider'] = provider;
1115
+ const amount = this.safeNumber (params, 'amount');
1116
+ if (amount === undefined) {
1117
+ throw new ArgumentsRequired (this.id + ' fetchDepositAddress() requires an amount when the ticker is fiat');
1118
+ }
1119
+ request['amount'] = amount;
1120
+ const uniqueId = this.safeValue (params, 'uniqueId');
1121
+ if (uniqueId === undefined) {
1122
+ throw new ArgumentsRequired (this.id + ' fetchDepositAddress() requires an uniqueId when the ticker is fiat');
1123
+ }
1124
+ }
1125
+ const response = await this[method] (this.extend (request, params));
1126
+ //
1127
+ // fiat
1128
+ //
1129
+ // {
1130
+ // "url": "https://someaddress.com"
1131
+ // }
1132
+ //
1133
+ // crypto
1134
+ //
1135
+ // {
1136
+ // "account": {
1137
+ // "address": "GDTSOI56XNVAKJNJBLJGRNZIVOCIZJRBIDKTWSCYEYNFAZEMBLN75RMN",
1138
+ // "memo": "48565488244493"
1139
+ // },
1140
+ // "required": {
1141
+ // "fixedFee": "0",
1142
+ // "flexFee": {
1143
+ // "maxFee": "0",
1144
+ // "minFee": "0",
1145
+ // "percent": "0"
1146
+ // },
1147
+ // "maxAmount": "0",
1148
+ // "minAmount": "1"
1149
+ // }
1150
+ // }
1151
+ //
1152
+ const url = this.safeString (response, 'url');
1153
+ const account = this.safeValue (response, 'account', {});
1154
+ const address = this.safeString (account, 'address', url);
1155
+ const tag = this.safeString (account, 'memo');
1156
+ this.checkAddress (address);
1157
+ return {
1158
+ 'currency': code,
1159
+ 'address': address,
1160
+ 'tag': tag,
1161
+ 'network': undefined,
1162
+ 'info': response,
1163
+ };
1164
+ }
1165
+
1166
+ async transfer (code, amount, fromAccount, toAccount, params = {}) {
1167
+ await this.loadMarkets ();
1168
+ const currency = this.currency (code);
1169
+ const accountsByType = this.safeValue (this.options, 'accountsByType');
1170
+ const fromAccountId = this.safeString (accountsByType, fromAccount, fromAccount);
1171
+ const toAccountId = this.safeString (accountsByType, toAccount, toAccount);
1172
+ let type = undefined;
1173
+ if (fromAccountId === 'main' && toAccountId === 'trade') {
1174
+ type = 'deposit';
1175
+ } else if (fromAccountId === 'trade' && toAccountId === 'main') {
1176
+ type = 'withdraw';
1177
+ }
1178
+ if (type === undefined) {
1179
+ throw new ExchangeError (this.id + ' transfer() only allows transfers between main account and spot account');
1180
+ }
1181
+ const request = {
1182
+ 'ticker': currency['id'],
1183
+ 'method': type,
1184
+ 'amount': this.currencyToPrecision (code, amount),
1185
+ };
1186
+ const response = await this.v4PrivatePostMainAccountTransfer (this.extend (request, params));
1187
+ //
1188
+ // []
1189
+ //
1190
+ const transfer = this.parseTransfer (response, currency);
1191
+ const transferOptions = this.safeValue (this.options, 'transfer', {});
1192
+ const fillTransferResponseFromRequest = this.safeValue (transferOptions, 'fillTransferResponseFromRequest', true);
1193
+ if (fillTransferResponseFromRequest) {
1194
+ transfer['amount'] = amount;
1195
+ transfer['fromAccount'] = fromAccount;
1196
+ transfer['toAccount'] = toAccount;
1197
+ }
1198
+ return transfer;
1199
+ }
1200
+
1201
+ parseTransfer (transfer, currency) {
1202
+ //
1203
+ // []
1204
+ //
1205
+ return {
1206
+ 'info': transfer,
1207
+ 'id': undefined,
1208
+ 'timestamp': undefined,
1209
+ 'datetime': undefined,
1210
+ 'currency': this.safeCurrencyCode (undefined, currency),
1211
+ 'amount': undefined,
1212
+ 'fromAccount': undefined,
1213
+ 'toAccount': undefined,
1214
+ 'status': 'pending',
1215
+ };
1216
+ }
1217
+
1218
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1219
+ await this.loadMarkets ();
1220
+ const currency = this.currency (code); // check if it has canDeposit
1221
+ const request = {
1222
+ 'ticker': currency['id'],
1223
+ 'amount': this.currencyToPrecision (code, amount),
1224
+ 'address': address,
1225
+ };
1226
+ let uniqueId = this.safeValue (params, 'uniqueId');
1227
+ if (uniqueId === undefined) {
1228
+ uniqueId = this.uuid22 ();
1229
+ }
1230
+ request['uniqueId'] = uniqueId;
1231
+ if (tag !== undefined) {
1232
+ request['memo'] = tag;
1233
+ }
1234
+ if (this.isFiat (code)) {
1235
+ const provider = this.safeValue (params, 'provider');
1236
+ if (provider === undefined) {
1237
+ throw new ArgumentsRequired (this.id + ' fetchDepositAddress() requires a provider when the ticker is fiat');
1238
+ }
1239
+ request['provider'] = provider;
1240
+ }
1241
+ const response = await this.v4PrivatePostMainAccountWithdraw (this.extend (request, params));
1242
+ //
1243
+ // empty array with a success status
1244
+ // go to deposit/withdraw history and check you request status by uniqueId
1245
+ //
1246
+ // []
1247
+ //
1248
+ return this.extend ({ 'id': uniqueId }, this.parseTransaction (response, currency));
1249
+ }
1250
+
1251
+ parseTransaction (transaction, currency = undefined) {
1252
+ //
1253
+ // withdraw
1254
+ //
1255
+ // []
1256
+ //
1257
+ currency = this.safeCurrency (undefined, currency);
1258
+ return {
1259
+ 'id': undefined,
1260
+ 'txid': undefined,
1261
+ 'timestamp': undefined,
1262
+ 'datetime': undefined,
1263
+ 'network': undefined,
1264
+ 'addressFrom': undefined,
1265
+ 'address': undefined,
1266
+ 'addressTo': undefined,
1267
+ 'amount': undefined,
1268
+ 'type': undefined,
1269
+ 'currency': currency['code'],
1270
+ 'status': undefined,
1271
+ 'updated': undefined,
1272
+ 'tagFrom': undefined,
1273
+ 'tag': undefined,
1274
+ 'tagTo': undefined,
1275
+ 'comment': undefined,
1276
+ 'fee': undefined,
1277
+ 'info': transaction,
1278
+ };
1279
+ }
1280
+
1281
+ isFiat (currency) {
1282
+ const fiatCurrencies = this.safeValue (this.options, 'fiatCurrencies', []);
1283
+ return this.inArray (currency, fiatCurrencies);
1284
+ }
1285
+
1286
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1287
+ const query = this.omit (params, this.extractParams (path));
1288
+ const version = this.safeValue (api, 0);
1289
+ const accessibility = this.safeValue (api, 1);
1290
+ const pathWithParams = '/' + this.implodeParams (path, params);
1291
+ let url = this.urls['api'][version][accessibility] + pathWithParams;
1292
+ if (accessibility === 'public') {
1293
+ if (Object.keys (query).length) {
1294
+ url += '?' + this.urlencode (query);
1295
+ }
1296
+ }
1297
+ if (accessibility === 'private') {
1298
+ this.checkRequiredCredentials ();
1299
+ const nonce = this.nonce ().toString ();
1300
+ const secret = this.stringToBinary (this.encode (this.secret));
1301
+ const request = '/' + 'api' + '/' + version + pathWithParams;
1302
+ body = this.json (this.extend ({ 'request': request, 'nonce': nonce }, params));
1303
+ const payload = this.stringToBase64 (body);
1304
+ const signature = this.hmac (payload, secret, 'sha512');
1305
+ headers = {
1306
+ 'Content-Type': 'application/json',
1307
+ 'X-TXC-APIKEY': this.apiKey,
1308
+ 'X-TXC-PAYLOAD': payload,
1309
+ 'X-TXC-SIGNATURE': signature,
1310
+ };
1311
+ }
1312
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1313
+ }
1314
+
1315
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1316
+ if ((code === 418) || (code === 429)) {
1317
+ throw new DDoSProtection (this.id + ' ' + code.toString () + ' ' + reason + ' ' + body);
1318
+ }
1319
+ if (code === 404) {
1320
+ throw new ExchangeError (this.id + ' ' + code.toString () + ' endpoint not found');
1321
+ }
1322
+ if (response !== undefined) {
1323
+ // For cases where we have a meaningful status
1324
+ // {"response":null,"status":422,"errors":{"orderId":["Finished order id 435453454535 not found on your account"]},"notification":null,"warning":"Finished order id 435453454535 not found on your account","_token":null}
1325
+ const status = this.safeInteger (response, 'status');
1326
+ // {"code":10,"message":"Unauthorized request."}
1327
+ const message = this.safeString (response, 'message');
1328
+ // For these cases where we have a generic code variable error key
1329
+ // {"code":0,"message":"Validation failed","errors":{"amount":["Amount must be greater than 0"]}}
1330
+ const code = this.safeInteger (response, 'code');
1331
+ const hasErrorStatus = status !== undefined && status !== '200';
1332
+ if (hasErrorStatus || code !== undefined) {
1333
+ const feedback = this.id + ' ' + body;
1334
+ let errorInfo = message;
1335
+ if (hasErrorStatus) {
1336
+ errorInfo = status;
1337
+ } else {
1338
+ const errorObject = this.safeValue (response, 'errors');
1339
+ if (errorObject !== undefined) {
1340
+ const errorKey = Object.keys (errorObject)[0];
1341
+ const errorMessageArray = this.safeValue (errorObject, errorKey, []);
1342
+ const errorMessageLength = errorMessageArray.length;
1343
+ errorInfo = (errorMessageLength > 0) ? errorMessageArray[0] : body;
1344
+ }
1345
+ }
1346
+ this.throwExactlyMatchedException (this.exceptions['exact'], errorInfo, feedback);
1347
+ this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
1348
+ throw new ExchangeError (feedback);
1349
+ }
1350
+ }
1351
+ }
1352
+ };