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/vcc.js ADDED
@@ -0,0 +1,1353 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, OrderNotFound, InvalidOrder, BadRequest, AuthenticationError, RateLimitExceeded, RequestTimeout, BadSymbol, AddressPending, PermissionDenied, InsufficientFunds } = require ('./base/errors');
7
+ const { ROUND } = require ('./base/functions/number');
8
+ const Precise = require ('./base/Precise');
9
+
10
+ // ---------------------------------------------------------------------------
11
+
12
+ module.exports = class vcc extends Exchange {
13
+ describe () {
14
+ return this.deepExtend (super.describe (), {
15
+ 'id': 'vcc',
16
+ 'name': 'VCC Exchange',
17
+ 'countries': [ 'VN' ], // Vietnam
18
+ 'rateLimit': 1000,
19
+ 'version': 'v3',
20
+ 'has': {
21
+ 'CORS': undefined,
22
+ 'spot': true,
23
+ 'margin': false,
24
+ 'swap': false,
25
+ 'future': false,
26
+ 'option': false,
27
+ 'addMargin': false,
28
+ 'cancelAllOrders': true,
29
+ 'cancelOrder': true,
30
+ 'createOrder': true,
31
+ 'createReduceOnlyOrder': false,
32
+ 'createStopLimitOrder': true,
33
+ 'createStopMarketOrder': true,
34
+ 'createStopOrder': true,
35
+ 'editOrder': undefined,
36
+ 'fetchBalance': true,
37
+ 'fetchBorrowRate': false,
38
+ 'fetchBorrowRateHistories': false,
39
+ 'fetchBorrowRateHistory': false,
40
+ 'fetchBorrowRates': false,
41
+ 'fetchBorrowRatesPerSymbol': false,
42
+ 'fetchClosedOrders': true,
43
+ 'fetchCurrencies': true,
44
+ 'fetchDepositAddress': true,
45
+ 'fetchDeposits': true,
46
+ 'fetchFundingHistory': false,
47
+ 'fetchFundingRate': false,
48
+ 'fetchFundingRateHistory': false,
49
+ 'fetchFundingRates': false,
50
+ 'fetchIndexOHLCV': false,
51
+ 'fetchLeverage': false,
52
+ 'fetchLeverageTiers': false,
53
+ 'fetchMarkets': true,
54
+ 'fetchMarkOHLCV': false,
55
+ 'fetchMyTrades': true,
56
+ 'fetchOHLCV': true,
57
+ 'fetchOpenOrders': true,
58
+ 'fetchOrder': true,
59
+ 'fetchOrderBook': true,
60
+ 'fetchOrders': undefined,
61
+ 'fetchPosition': false,
62
+ 'fetchPositions': false,
63
+ 'fetchPositionsRisk': false,
64
+ 'fetchPremiumIndexOHLCV': false,
65
+ 'fetchTicker': 'emulated',
66
+ 'fetchTickers': true,
67
+ 'fetchTrades': true,
68
+ 'fetchTradingFee': true,
69
+ 'fetchTradingFees': undefined,
70
+ 'fetchTransactions': true,
71
+ 'fetchTransfer': false,
72
+ 'fetchTransfers': false,
73
+ 'fetchWithdrawals': true,
74
+ 'reduceMargin': false,
75
+ 'setLeverage': false,
76
+ 'setMarginMode': false,
77
+ 'setPositionMode': false,
78
+ 'transfer': false,
79
+ 'withdraw': false,
80
+ },
81
+ 'timeframes': {
82
+ '1m': '60000',
83
+ '5m': '300000',
84
+ '15m': '900000',
85
+ '30m': '1800000',
86
+ '1h': '3600000',
87
+ '2h': '7200000',
88
+ '4h': '14400000',
89
+ '6h': '21600000',
90
+ '12h': '43200000',
91
+ '1d': '86400000',
92
+ '1w': '604800000',
93
+ },
94
+ 'urls': {
95
+ 'logo': 'https://user-images.githubusercontent.com/1294454/100545356-8427f500-326c-11eb-9539-7d338242d61b.jpg',
96
+ 'api': {
97
+ 'public': 'https://api.vcc.exchange',
98
+ 'private': 'https://api.vcc.exchange',
99
+ },
100
+ 'www': 'https://vcc.exchange',
101
+ 'doc': [
102
+ 'https://vcc.exchange/api',
103
+ ],
104
+ 'fees': 'https://support.vcc.exchange/hc/en-us/articles/360016401754',
105
+ 'referral': 'https://vcc.exchange?ref=l4xhrH',
106
+ },
107
+ 'api': {
108
+ 'public': {
109
+ 'get': [
110
+ 'summary',
111
+ 'exchange_info',
112
+ 'assets', // Available Currencies
113
+ 'ticker', // Ticker list for all symbols
114
+ 'trades/{market_pair}', // Recent trades
115
+ 'orderbook/{market_pair}', // Orderbook
116
+ 'chart/bars', // Candles
117
+ 'tick_sizes',
118
+ ],
119
+ },
120
+ 'private': {
121
+ 'get': [
122
+ 'user',
123
+ 'balance', // Get trading balance
124
+ 'orders/{order_id}', // Get a single order by order_id
125
+ 'orders/open', // Get open orders
126
+ 'orders', // Get closed orders
127
+ 'orders/trades', // Get trades history
128
+ 'deposit-address', // Generate or get deposit address
129
+ 'transactions', // Get deposit/withdrawal history
130
+ ],
131
+ 'post': [
132
+ 'orders', // Create new order
133
+ ],
134
+ 'put': [
135
+ 'orders/{order_id}/cancel', // Cancel order
136
+ 'orders/cancel-by-type',
137
+ 'orders/cancel-all',
138
+ ],
139
+ },
140
+ },
141
+ 'fees': {
142
+ 'trading': {
143
+ 'tierBased': false,
144
+ 'percentage': true,
145
+ 'maker': this.parseNumber ('0.002'),
146
+ 'taker': this.parseNumber ('0.002'),
147
+ },
148
+ },
149
+ 'exceptions': {
150
+ 'exact': {},
151
+ 'broad': {
152
+ 'limit may not be greater than': BadRequest, // {"message":"The given data was invalid.","errors":{"limit":["The limit may not be greater than 1000."]}}
153
+ 'Insufficient balance': InsufficientFunds, // {"message":"Insufficient balance."}
154
+ 'Unauthenticated': AuthenticationError, // {"message":"Unauthenticated."} // wrong api key
155
+ 'signature is invalid': AuthenticationError, // {"message":"The given data was invalid.","errors":{"signature":["HMAC signature is invalid"]}}
156
+ 'Timeout': RequestTimeout, // {"code":504,"message":"Gateway Timeout","description":""}
157
+ 'Too many requests': RateLimitExceeded, // {"code":429,"message":"Too many requests","description":"Too many requests"}
158
+ 'quantity field is required': InvalidOrder, // {"message":"The given data was invalid.","errors":{"quantity":["The quantity field is required when type is market."]}}
159
+ 'price field is required': InvalidOrder, // {"message":"The given data was invalid.","errors":{"price":["The price field is required when type is limit."]}}
160
+ 'error_security_level': PermissionDenied, // {"message":"error_security_level"}
161
+ 'pair is invalid': BadSymbol, // {"message":"The given data was invalid.","errors":{"coin":["Trading pair is invalid","Trading pair is offline"]}}
162
+ // {"message":"The given data was invalid.","errors":{"type":["The selected type is invalid."]}}
163
+ // {"message":"The given data was invalid.","errors":{"trade_type":["The selected trade type is invalid."]}}
164
+ 'type is invalid': InvalidOrder,
165
+ 'Data not found': OrderNotFound, // {"message":"Data not found"}
166
+ },
167
+ },
168
+ });
169
+ }
170
+
171
+ async fetchMarkets (params = {}) {
172
+ const response = await this.publicGetExchangeInfo (params);
173
+ //
174
+ // {
175
+ // "message":null,
176
+ // "dataVersion":"4677e56a42f0c29872f3a6e75f5d39d2f07c748c",
177
+ // "data":{
178
+ // "timezone":"UTC",
179
+ // "serverTime":1605821914333,
180
+ // "symbols":[
181
+ // {
182
+ // "id":"btcvnd",
183
+ // "symbol":"BTC\/VND",
184
+ // "coin":"btc",
185
+ // "currency":"vnd",
186
+ // "baseId":1,
187
+ // "quoteId":0,
188
+ // "active":true,
189
+ // "base_precision":"0.0000010000",
190
+ // "quote_precision":"1.0000000000",
191
+ // "minimum_quantity":"0.0000010000",
192
+ // "minimum_amount":"250000.0000000000",
193
+ // "precision":{"price":0,"amount":6,"cost":6},
194
+ // "limits":{
195
+ // "amount":{"min":"0.0000010000"},
196
+ // "price":{"min":"1.0000000000"},
197
+ // "cost":{"min":"250000.0000000000"},
198
+ // },
199
+ // },
200
+ // ],
201
+ // },
202
+ // }
203
+ //
204
+ const data = this.safeValue (response, 'data');
205
+ const markets = this.safeValue (data, 'symbols');
206
+ const result = [];
207
+ for (let i = 0; i < markets.length; i++) {
208
+ const market = this.safeValue (markets, i);
209
+ const symbol = this.safeString (market, 'symbol');
210
+ const id = symbol.replace ('/', '_');
211
+ const baseId = this.safeString (market, 'coin');
212
+ const quoteId = this.safeString (market, 'currency');
213
+ const base = this.safeCurrencyCode (baseId);
214
+ const quote = this.safeCurrencyCode (quoteId);
215
+ const precision = this.safeValue (market, 'precision', {});
216
+ const limits = this.safeValue (market, 'limits', {});
217
+ const amountLimits = this.safeValue (limits, 'amount', {});
218
+ const priceLimits = this.safeValue (limits, 'price', {});
219
+ const costLimits = this.safeValue (limits, 'cost', {});
220
+ const entry = {
221
+ 'id': id,
222
+ 'symbol': symbol,
223
+ 'base': base,
224
+ 'quote': quote,
225
+ 'settle': undefined,
226
+ 'baseId': baseId,
227
+ 'quoteId': quoteId,
228
+ 'settledId': undefined,
229
+ 'type': 'spot',
230
+ 'spot': true,
231
+ 'margin': false,
232
+ 'swap': false,
233
+ 'future': false,
234
+ 'option': false,
235
+ 'active': this.safeValue (market, 'active'),
236
+ 'contract': false,
237
+ 'linear': undefined,
238
+ 'inverse': undefined,
239
+ 'contractSize': undefined,
240
+ 'expiry': undefined,
241
+ 'expiryDatetime': undefined,
242
+ 'strike': undefined,
243
+ 'optionType': undefined,
244
+ 'precision': {
245
+ 'amount': this.safeInteger (precision, 'amount'),
246
+ 'price': this.safeInteger (precision, 'price'),
247
+ 'cost': this.safeInteger (precision, 'cost'),
248
+ },
249
+ 'limits': {
250
+ 'leverage': {
251
+ 'min': undefined,
252
+ 'max': undefined,
253
+ },
254
+ 'amount': {
255
+ 'min': this.safeNumber (amountLimits, 'min'),
256
+ 'max': undefined,
257
+ },
258
+ 'price': {
259
+ 'min': this.safeNumber (priceLimits, 'min'),
260
+ 'max': undefined,
261
+ },
262
+ 'cost': {
263
+ 'min': this.safeNumber (costLimits, 'min'),
264
+ 'max': undefined,
265
+ },
266
+ },
267
+ 'info': market,
268
+ };
269
+ result.push (entry);
270
+ }
271
+ return result;
272
+ }
273
+
274
+ async fetchCurrencies (params = {}) {
275
+ const response = await this.publicGetAssets (params);
276
+ //
277
+ // {
278
+ // "message":null,
279
+ // "dataVersion":"2514c8012d94ea375018fc13e0b5d4d896e435df",
280
+ // "data":{
281
+ // "BTC":{
282
+ // "name":"Bitcoin",
283
+ // "unified_cryptoasset_id":1,
284
+ // "can_withdraw":1,
285
+ // "can_deposit":1,
286
+ // "min_withdraw":"0.0011250000",
287
+ // "max_withdraw":"100.0000000000",
288
+ // "maker_fee":"0.002",
289
+ // "taker_fee":"0.002",
290
+ // "decimal":8,
291
+ // "withdrawal_fee":"0.0006250000",
292
+ // },
293
+ // },
294
+ // }
295
+ //
296
+ const result = {};
297
+ const data = this.safeValue (response, 'data');
298
+ const ids = Object.keys (data);
299
+ for (let i = 0; i < ids.length; i++) {
300
+ const id = this.safeStringLower (ids, i);
301
+ const currency = this.safeValue (data, ids[i]);
302
+ const code = this.safeCurrencyCode (id);
303
+ const canDeposit = this.safeInteger (currency, 'can_deposit');
304
+ const canWithdraw = this.safeInteger (currency, 'can_withdraw');
305
+ const active = (canDeposit && canWithdraw);
306
+ const depositEnabled = (canDeposit === 1);
307
+ const withdrawEnabled = (canWithdraw === 1);
308
+ result[code] = {
309
+ 'id': id,
310
+ 'code': code,
311
+ 'name': this.safeString (currency, 'name'),
312
+ 'active': active,
313
+ 'deposit': depositEnabled,
314
+ 'withdraw': withdrawEnabled,
315
+ 'fee': this.safeNumber (currency, 'withdrawal_fee'),
316
+ 'precision': this.safeInteger (currency, 'decimal'),
317
+ 'limits': {
318
+ 'withdraw': {
319
+ 'min': this.safeNumber (currency, 'min_withdraw'),
320
+ 'max': this.safeNumber (currency, 'max_withdraw'),
321
+ },
322
+ },
323
+ };
324
+ }
325
+ return result;
326
+ }
327
+
328
+ async fetchTradingFee (symbol, params = {}) {
329
+ await this.loadMarkets ();
330
+ const market = this.market (symbol);
331
+ const request = this.extend ({
332
+ 'symbol': market['id'],
333
+ }, this.omit (params, 'symbol'));
334
+ const response = await this.privateGetTradingFeeSymbol (request);
335
+ //
336
+ // {
337
+ // takeLiquidityRate: '0.001',
338
+ // provideLiquidityRate: '-0.0001'
339
+ // }
340
+ //
341
+ return {
342
+ 'info': response,
343
+ 'maker': this.safeNumber (response, 'provideLiquidityRate'),
344
+ 'taker': this.safeNumber (response, 'takeLiquidityRate'),
345
+ };
346
+ }
347
+
348
+ parseBalance (response) {
349
+ const data = this.safeValue (response, 'data');
350
+ const result = {
351
+ 'info': response,
352
+ 'timestamp': undefined,
353
+ 'datetime': undefined,
354
+ };
355
+ const currencyIds = Object.keys (data);
356
+ for (let i = 0; i < currencyIds.length; i++) {
357
+ const currencyId = currencyIds[i];
358
+ const code = this.safeCurrencyCode (currencyId);
359
+ const balance = this.safeValue (data, currencyId);
360
+ const account = this.account ();
361
+ account['free'] = this.safeString (balance, 'available_balance');
362
+ account['total'] = this.safeString (balance, 'balance');
363
+ result[code] = account;
364
+ }
365
+ return this.safeBalance (result);
366
+ }
367
+
368
+ async fetchBalance (params = {}) {
369
+ await this.loadMarkets ();
370
+ const response = await this.privateGetBalance (params);
371
+ //
372
+ // {
373
+ // "message":null,
374
+ // "dataVersion":"7168e6c99e90f60673070944d987988eef7d91fa",
375
+ // "data":{
376
+ // "vnd":{"balance":0,"available_balance":0},
377
+ // "btc":{"balance":0,"available_balance":0},
378
+ // "eth":{"balance":0,"available_balance":0},
379
+ // },
380
+ // }
381
+ //
382
+ return this.parseBalance (response);
383
+ }
384
+
385
+ parseOHLCV (ohlcv, market = undefined) {
386
+ //
387
+ // {
388
+ // "low":"415805323.0000000000",
389
+ // "high":"415805323.0000000000",
390
+ // "open":"415805323.0000000000",
391
+ // "close":"415805323.0000000000",
392
+ // "time":"1605845940000",
393
+ // "volume":"0.0065930000",
394
+ // "opening_time":1605845963263,
395
+ // "closing_time":1605845963263
396
+ // }
397
+ //
398
+ return [
399
+ this.safeInteger (ohlcv, 'time'),
400
+ this.safeNumber (ohlcv, 'open'),
401
+ this.safeNumber (ohlcv, 'high'),
402
+ this.safeNumber (ohlcv, 'low'),
403
+ this.safeNumber (ohlcv, 'close'),
404
+ this.safeNumber (ohlcv, 'volume'),
405
+ ];
406
+ }
407
+
408
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
409
+ await this.loadMarkets ();
410
+ const market = this.market (symbol);
411
+ const request = {
412
+ 'coin': market['baseId'],
413
+ 'currency': market['quoteId'],
414
+ 'resolution': this.timeframes[timeframe],
415
+ };
416
+ limit = (limit === undefined) ? 100 : limit;
417
+ limit = Math.min (100, limit);
418
+ const duration = this.parseTimeframe (timeframe);
419
+ if (since === undefined) {
420
+ const end = this.seconds ();
421
+ request['to'] = end;
422
+ request['from'] = end - limit * duration;
423
+ } else {
424
+ const start = parseInt (since / 1000);
425
+ request['from'] = start;
426
+ request['to'] = this.sum (start, limit * duration);
427
+ }
428
+ const response = await this.publicGetChartBars (this.extend (request, params));
429
+ //
430
+ // [
431
+ // {"low":"415805323.0000000000","high":"415805323.0000000000","open":"415805323.0000000000","close":"415805323.0000000000","time":"1605845940000","volume":"0.0065930000","opening_time":1605845963263,"closing_time":1605845963263},
432
+ // {"low":"416344148.0000000000","high":"416344148.0000000000","open":"415805323.0000000000","close":"416344148.0000000000","time":"1605846000000","volume":"0.0052810000","opening_time":1605846011490,"closing_time":1605846011490},
433
+ // {"low":"416299269.0000000000","high":"417278376.0000000000","open":"416344148.0000000000","close":"417278376.0000000000","time":"1605846060000","volume":"0.0136750000","opening_time":1605846070727,"closing_time":1605846102282},
434
+ // ]
435
+ //
436
+ return this.parseOHLCVs (response, market, timeframe, since, limit);
437
+ }
438
+
439
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
440
+ await this.loadMarkets ();
441
+ const market = this.market (symbol);
442
+ const request = {
443
+ 'market_pair': market['id'],
444
+ // 'depth': 0, // 0 = full orderbook, 5, 10, 20, 50, 100, 500
445
+ 'level': 2, // 1 = best bidask, 2 = aggregated by price, 3 = no aggregation
446
+ };
447
+ if (limit !== undefined) {
448
+ if ((limit !== 0) && (limit !== 5) && (limit !== 10) && (limit !== 20) && (limit !== 50) && (limit !== 100) && (limit !== 500)) {
449
+ throw new BadRequest (this.id + ' fetchOrderBook() limit must be 0, 5, 10, 20, 50, 100, 500 if specified');
450
+ }
451
+ request['depth'] = limit;
452
+ }
453
+ const response = await this.publicGetOrderbookMarketPair (this.extend (request, params));
454
+ //
455
+ // {
456
+ // "message":null,
457
+ // "dataVersion":"376cee43af26deabcd3762ab11a876b6e7a71e82",
458
+ // "data":{
459
+ // "bids":[
460
+ // ["413342637.0000000000","0.165089"],
461
+ // ["413274576.0000000000","0.03"],
462
+ // ["413274574.0000000000","0.03"],
463
+ // ],
464
+ // "asks":[
465
+ // ["416979125.0000000000","0.122835"],
466
+ // ["417248934.0000000000","0.030006"],
467
+ // ["417458879.0000000000","0.1517"],
468
+ // ],
469
+ // "timestamp":"1605841619147"
470
+ // }
471
+ // }
472
+ //
473
+ const data = this.safeValue (response, 'data');
474
+ const timestamp = this.safeValue (data, 'timestamp');
475
+ return this.parseOrderBook (data, symbol, timestamp, 'bids', 'asks', 0, 1);
476
+ }
477
+
478
+ parseTicker (ticker, market = undefined) {
479
+ //
480
+ // {
481
+ // "base_id":1,
482
+ // "quote_id":0,
483
+ // "last_price":"411119457",
484
+ // "max_price":"419893173.0000000000",
485
+ // "min_price":"401292577.0000000000",
486
+ // "open_price":null,
487
+ // "base_volume":"10.5915050000",
488
+ // "quote_volume":"4367495977.4484430060",
489
+ // "isFrozen":0
490
+ // }
491
+ //
492
+ const timestamp = this.milliseconds ();
493
+ const baseVolume = this.safeString (ticker, 'base_volume');
494
+ const quoteVolume = this.safeString (ticker, 'quote_volume');
495
+ const open = this.safeString (ticker, 'open_price');
496
+ const last = this.safeString (ticker, 'last_price');
497
+ const symbol = this.safeSymbol (undefined, market);
498
+ return this.safeTicker ({
499
+ 'symbol': symbol,
500
+ 'timestamp': timestamp,
501
+ 'datetime': this.iso8601 (timestamp),
502
+ 'high': this.safeString (ticker, 'max_price'),
503
+ 'low': this.safeString (ticker, 'min_price'),
504
+ 'bid': this.safeString (ticker, 'bid'),
505
+ 'bidVolume': undefined,
506
+ 'ask': this.safeString (ticker, 'ask'),
507
+ 'askVolume': undefined,
508
+ 'vwap': undefined,
509
+ 'open': open,
510
+ 'close': last,
511
+ 'last': last,
512
+ 'previousClose': undefined,
513
+ 'change': undefined,
514
+ 'percentage': undefined,
515
+ 'average': undefined,
516
+ 'baseVolume': baseVolume,
517
+ 'quoteVolume': quoteVolume,
518
+ 'info': ticker,
519
+ }, market, false);
520
+ }
521
+
522
+ async fetchTickers (symbols = undefined, params = {}) {
523
+ await this.loadMarkets ();
524
+ const response = await this.publicGetTicker (params);
525
+ //
526
+ // {
527
+ // "message":null,
528
+ // "dataVersion":"fc521161aebe506178b8588cd2adb598eaf1018e",
529
+ // "data":{
530
+ // "BTC_VND":{
531
+ // "base_id":1,
532
+ // "quote_id":0,
533
+ // "last_price":"411119457",
534
+ // "max_price":"419893173.0000000000",
535
+ // "min_price":"401292577.0000000000",
536
+ // "open_price":null,
537
+ // "base_volume":"10.5915050000",
538
+ // "quote_volume":"4367495977.4484430060",
539
+ // "isFrozen":0
540
+ // },
541
+ // }
542
+ // }
543
+ //
544
+ const result = {};
545
+ const data = this.safeValue (response, 'data');
546
+ const marketIds = Object.keys (data);
547
+ for (let i = 0; i < marketIds.length; i++) {
548
+ const marketId = marketIds[i];
549
+ const market = this.safeMarket (marketId, undefined, '_');
550
+ const symbol = market['symbol'];
551
+ result[symbol] = this.parseTicker (data[marketId], market);
552
+ }
553
+ return this.filterByArray (result, 'symbol', symbols);
554
+ }
555
+
556
+ parseTrade (trade, market = undefined) {
557
+ //
558
+ // public fetchTrades
559
+ //
560
+ // {
561
+ // "trade_id":181509285,
562
+ // "price":"415933022.0000000000",
563
+ // "base_volume":"0.0022080000",
564
+ // "quote_volume":"918380.1125760000",
565
+ // "trade_timestamp":1605842150357,
566
+ // "type":"buy",
567
+ // }
568
+ //
569
+ // private fetchMyTrades
570
+ //
571
+ // {
572
+ // "trade_type":"sell",
573
+ // "fee":"0.0610578086",
574
+ // "id":1483372,
575
+ // "created_at":1606581578368,
576
+ // "currency":"usdt",
577
+ // "coin":"btc",
578
+ // "price":"17667.1900000000",
579
+ // "quantity":"0.0017280000",
580
+ // "amount":"30.5289043200",
581
+ // }
582
+ //
583
+ const timestamp = this.safeInteger2 (trade, 'trade_timestamp', 'created_at');
584
+ const baseId = this.safeStringUpper (trade, 'coin');
585
+ const quoteId = this.safeStringUpper (trade, 'currency');
586
+ let marketId = undefined;
587
+ if ((baseId !== undefined) && (quoteId !== undefined)) {
588
+ marketId = baseId + '_' + quoteId;
589
+ }
590
+ market = this.safeMarket (marketId, market, '_');
591
+ const symbol = market['symbol'];
592
+ const priceString = this.safeString (trade, 'price');
593
+ const amountString = this.safeString2 (trade, 'base_volume', 'quantity');
594
+ const price = this.parseNumber (priceString);
595
+ const amount = this.parseNumber (amountString);
596
+ let cost = this.safeNumber2 (trade, 'quote_volume', 'amount');
597
+ if (cost === undefined) {
598
+ cost = this.parseNumber (Precise.stringMul (priceString, amountString));
599
+ }
600
+ const side = this.safeString2 (trade, 'type', 'trade_type');
601
+ const id = this.safeString2 (trade, 'trade_id', 'id');
602
+ const feeCost = this.safeNumber (trade, 'fee');
603
+ let fee = undefined;
604
+ if (feeCost !== undefined) {
605
+ fee = {
606
+ 'cost': feeCost,
607
+ 'currency': market['quote'],
608
+ };
609
+ }
610
+ return {
611
+ 'info': trade,
612
+ 'id': id,
613
+ 'order': undefined,
614
+ 'timestamp': timestamp,
615
+ 'datetime': this.iso8601 (timestamp),
616
+ 'symbol': symbol,
617
+ 'type': undefined,
618
+ 'side': side,
619
+ 'takerOrMaker': undefined,
620
+ 'price': price,
621
+ 'amount': amount,
622
+ 'cost': cost,
623
+ 'fee': fee,
624
+ };
625
+ }
626
+
627
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
628
+ await this.loadMarkets ();
629
+ const market = this.market (symbol);
630
+ const request = {
631
+ 'market_pair': market['id'],
632
+ // 'type': 'buy', // 'sell'
633
+ // 'count': limit, // default 500, max 1000
634
+ };
635
+ if (limit !== undefined) {
636
+ request['count'] = Math.min (1000, limit);
637
+ }
638
+ const response = await this.publicGetTradesMarketPair (this.extend (request, params));
639
+ //
640
+ // {
641
+ // "message":null,
642
+ // "dataVersion":"1f811b533143f739008a3e4ecaaab2ec82ea50d4",
643
+ // "data":[
644
+ // {
645
+ // "trade_id":181509285,
646
+ // "price":"415933022.0000000000",
647
+ // "base_volume":"0.0022080000",
648
+ // "quote_volume":"918380.1125760000",
649
+ // "trade_timestamp":1605842150357,
650
+ // "type":"buy",
651
+ // },
652
+ // ],
653
+ // }
654
+ //
655
+ const data = this.safeValue (response, 'data');
656
+ return this.parseTrades (data, market, since, limit);
657
+ }
658
+
659
+ async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
660
+ await this.loadMarkets ();
661
+ const request = {
662
+ // 'type': type, // 'deposit', 'withdraw'
663
+ // 'start': parseInt (since / 1000),
664
+ // 'end': this.seconds (),
665
+ };
666
+ let currency = undefined;
667
+ if (code !== undefined) {
668
+ currency = this.currency (code);
669
+ request['currency'] = currency['id'];
670
+ }
671
+ if (limit !== undefined) {
672
+ request['limit'] = Math.min (1000, limit);
673
+ }
674
+ if (since !== undefined) {
675
+ request['start'] = since;
676
+ }
677
+ const response = await this.privateGetTransactions (this.extend (request, params));
678
+ //
679
+ // {
680
+ // "message":null,
681
+ // "dataVersion":"1fdfb0ec85b666871d62fe59d098d01839b05e97",
682
+ // "data":{
683
+ // "current_page":1,
684
+ // "data":[
685
+ // {
686
+ // "id":85391,
687
+ // "user_id":253063,
688
+ // "transaction_id":"0x885719cee5910ca509a223d208797510e80eb27a2f1d51a71bb4ccb82d538131",
689
+ // "internal_transaction_id":null,
690
+ // "temp_transaction_id":"2367",
691
+ // "currency":"usdt",
692
+ // "amount":"30.0000000000",
693
+ // "btc_amount":"0.0000000000",
694
+ // "usdt_amount":"0.0000000000",
695
+ // "fee":"0.0000000000",
696
+ // "tx_cost":"0.0000000000",
697
+ // "confirmation":0,
698
+ // "deposit_code":null,
699
+ // "status":"success",
700
+ // "bank_name":null,
701
+ // "foreign_bank_account":null,
702
+ // "foreign_bank_account_holder":null,
703
+ // "blockchain_address":"0xd54b84AD27E4c4a8C9E0b2b53701DeFc728f6E44",
704
+ // "destination_tag":null,
705
+ // "error_detail":null,
706
+ // "refunded":"0.0000000000",
707
+ // "transaction_date":"2020-11-28",
708
+ // "transaction_timestamp":"1606563143.959",
709
+ // "created_at":1606563143959,
710
+ // "updated_at":1606563143959,
711
+ // "transaction_email_timestamp":0,
712
+ // "network":null,
713
+ // "collect_tx_id":null,
714
+ // "collect_id":null
715
+ // }
716
+ // ],
717
+ // "first_page_url":"http:\/\/api.vcc.exchange\/v3\/transactions?page=1",
718
+ // "from":1,
719
+ // "last_page":1,
720
+ // "last_page_url":"http:\/\/api.vcc.exchange\/v3\/transactions?page=1",
721
+ // "next_page_url":null,
722
+ // "path":"http:\/\/api.vcc.exchange\/v3\/transactions",
723
+ // "per_page":10,
724
+ // "prev_page_url":null,
725
+ // "to":1,
726
+ // "total":1
727
+ // }
728
+ // }
729
+ //
730
+ let data = this.safeValue (response, 'data', {});
731
+ data = this.safeValue (data, 'data', []);
732
+ return this.parseTransactions (data, currency, since, limit);
733
+ }
734
+
735
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
736
+ const request = { 'type': 'deposit' };
737
+ return await this.fetchTransactions (code, since, limit, this.extend (request, params));
738
+ }
739
+
740
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
741
+ const request = { 'type': 'withdraw' };
742
+ return await this.fetchTransactions (code, since, limit, this.extend (request, params));
743
+ }
744
+
745
+ parseTransaction (transaction, currency = undefined) {
746
+ //
747
+ // fetchTransactions, fetchDeposits, fetchWithdrawals
748
+ //
749
+ // {
750
+ // "id":85391,
751
+ // "user_id":253063,
752
+ // "transaction_id":"0x885719cee5910ca509a223d208797510e80eb27a2f1d51a71bb4ccb82d538131",
753
+ // "internal_transaction_id":null,
754
+ // "temp_transaction_id":"2367",
755
+ // "currency":"usdt",
756
+ // "amount":"30.0000000000",
757
+ // "btc_amount":"0.0000000000",
758
+ // "usdt_amount":"0.0000000000",
759
+ // "fee":"0.0000000000",
760
+ // "tx_cost":"0.0000000000",
761
+ // "confirmation":0,
762
+ // "deposit_code":null,
763
+ // "status":"success",
764
+ // "bank_name":null,
765
+ // "foreign_bank_account":null,
766
+ // "foreign_bank_account_holder":null,
767
+ // "blockchain_address":"0xd54b84AD27E4c4a8C9E0b2b53701DeFc728f6E44",
768
+ // "destination_tag":null,
769
+ // "error_detail":null,
770
+ // "refunded":"0.0000000000",
771
+ // "transaction_date":"2020-11-28",
772
+ // "transaction_timestamp":"1606563143.959",
773
+ // "created_at":1606563143959,
774
+ // "updated_at":1606563143959,
775
+ // "transaction_email_timestamp":0,
776
+ // "network":null,
777
+ // "collect_tx_id":null,
778
+ // "collect_id":null
779
+ // }
780
+ //
781
+ const id = this.safeString (transaction, 'id');
782
+ const timestamp = this.safeInteger (transaction, 'created_at');
783
+ const updated = this.safeInteger (transaction, 'updated_at');
784
+ const currencyId = this.safeString (transaction, 'currency');
785
+ const code = this.safeCurrencyCode (currencyId, currency);
786
+ const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
787
+ let amount = this.safeNumber (transaction, 'amount');
788
+ if (amount !== undefined) {
789
+ amount = Math.abs (amount);
790
+ }
791
+ const address = this.safeString (transaction, 'blockchain_address');
792
+ const txid = this.safeString (transaction, 'transaction_id');
793
+ const tag = this.safeString (transaction, 'destination_tag');
794
+ let fee = undefined;
795
+ const feeCost = this.safeNumber (transaction, 'fee');
796
+ if (feeCost !== undefined) {
797
+ fee = {
798
+ 'cost': feeCost,
799
+ 'currency': code,
800
+ };
801
+ }
802
+ const type = (amount > 0) ? 'deposit' : 'withdrawal';
803
+ const network = this.safeString (transaction, 'network');
804
+ return {
805
+ 'info': transaction,
806
+ 'id': id,
807
+ 'txid': txid,
808
+ 'timestamp': timestamp,
809
+ 'datetime': this.iso8601 (timestamp),
810
+ 'network': network,
811
+ 'address': address,
812
+ 'addressTo': address,
813
+ 'addressFrom': undefined,
814
+ 'tag': tag,
815
+ 'tagTo': tag,
816
+ 'tagFrom': undefined,
817
+ 'type': type,
818
+ 'amount': amount,
819
+ 'currency': code,
820
+ 'status': status,
821
+ 'updated': updated,
822
+ 'fee': fee,
823
+ };
824
+ }
825
+
826
+ parseTransactionStatus (status) {
827
+ const statuses = {
828
+ 'pending': 'pending',
829
+ 'error': 'failed',
830
+ 'success': 'ok',
831
+ 'cancel': 'canceled',
832
+ };
833
+ return this.safeString (statuses, status, status);
834
+ }
835
+
836
+ parseTransactionType (type) {
837
+ const types = {
838
+ 'deposit': 'deposit',
839
+ 'withdraw': 'withdrawal',
840
+ };
841
+ return this.safeString (types, type, type);
842
+ }
843
+
844
+ costToPrecision (symbol, cost) {
845
+ return this.decimalToPrecision (cost, ROUND, this.markets[symbol]['precision']['cost'], this.precisionMode, this.paddingMode);
846
+ }
847
+
848
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
849
+ await this.loadMarkets ();
850
+ const market = this.market (symbol);
851
+ const request = {
852
+ 'coin': market['baseId'],
853
+ 'currency': market['quoteId'],
854
+ 'trade_type': side,
855
+ 'type': type,
856
+ };
857
+ if (type === 'ceiling_market') {
858
+ const ceiling = this.safeValue (params, 'ceiling');
859
+ if (ceiling !== undefined) {
860
+ request['ceiling'] = this.costToPrecision (symbol, ceiling);
861
+ } else if (price !== undefined) {
862
+ request['ceiling'] = this.costToPrecision (symbol, amount * price);
863
+ } else {
864
+ throw new InvalidOrder (this.id + ' createOrder() requires a price argument or a ceiling parameter for ' + type + ' orders');
865
+ }
866
+ } else {
867
+ request['quantity'] = this.amountToPrecision (symbol, amount);
868
+ }
869
+ if (type === 'limit') {
870
+ request['price'] = this.priceToPrecision (symbol, price);
871
+ }
872
+ const stopPrice = this.safeValue2 (params, 'stop_price', 'stopPrice');
873
+ if (stopPrice !== undefined) {
874
+ request['is_stop'] = 1;
875
+ request['stop_condition'] = (side === 'buy') ? 'le' : 'ge'; // ge = greater than or equal, le = less than or equal
876
+ request['stop_price'] = this.priceToPrecision (symbol, stopPrice);
877
+ }
878
+ params = this.omit (params, [ 'stop_price', 'stopPrice' ]);
879
+ const response = await this.privatePostOrders (this.extend (request, params));
880
+ //
881
+ // ceiling_market order
882
+ //
883
+ // {
884
+ // "message":null,
885
+ // "dataVersion":"213fc0d433f38307f736cae1cbda4cc310469b7a",
886
+ // "data":{
887
+ // "coin":"btc",
888
+ // "currency":"usdt",
889
+ // "trade_type":"buy",
890
+ // "type":"ceiling_market",
891
+ // "ceiling":"30",
892
+ // "user_id":253063,
893
+ // "email":"igor.kroitor@gmail.com",
894
+ // "side":"buy",
895
+ // "quantity":"0.00172800",
896
+ // "status":"pending",
897
+ // "fee":0,
898
+ // "created_at":1606571333035,
899
+ // "updated_at":1606571333035,
900
+ // "instrument_symbol":"BTCUSDT",
901
+ // "remaining":"0.00172800",
902
+ // "fee_rate":"0.002",
903
+ // "id":88214435
904
+ // }
905
+ // }
906
+ //
907
+ // limit order
908
+ //
909
+ // {
910
+ // "message":null,
911
+ // "dataVersion":"d9b1159d2bcefa2388be156e32ddc7cc324400ee",
912
+ // "data":{
913
+ // "id":41230,
914
+ // "trade_type":"sell",
915
+ // "type":"limit",
916
+ // "quantity":"1",
917
+ // "price":"14.99",
918
+ // "currency":"usdt",
919
+ // "coin":"neo",
920
+ // "status":"pending",
921
+ // "is_stop": "1",
922
+ // "stop_price": "13",
923
+ // "stop_condition": "ge",
924
+ // "fee":0,
925
+ // "created_at":1560244052168,
926
+ // "updated_at":1560244052168
927
+ // }
928
+ // }
929
+ //
930
+ const data = this.safeValue (response, 'data');
931
+ return this.parseOrder (data, market);
932
+ }
933
+
934
+ async cancelOrder (id, symbol = undefined, params = {}) {
935
+ await this.loadMarkets ();
936
+ const request = {
937
+ 'order_id': id,
938
+ };
939
+ const response = await this.privatePutOrdersOrderIdCancel (this.extend (request, params));
940
+ return this.parseOrder (response);
941
+ }
942
+
943
+ async cancelAllOrders (symbol = undefined, params = {}) {
944
+ const type = this.safeString (params, 'type');
945
+ const method = (type === undefined) ? 'privatePutOrdersCancelAll' : 'privatePutOrdersCancelByType';
946
+ const request = {};
947
+ if (type !== undefined) {
948
+ request['type'] = type;
949
+ }
950
+ await this.loadMarkets ();
951
+ const response = await this[method] (this.extend (request, params));
952
+ //
953
+ // {
954
+ // "dataVersion":"6d72fb82a9c613c8166581a887e1723ce5a937ff",
955
+ // "data":{
956
+ // "data":[
957
+ // {
958
+ // "id":410,
959
+ // "trade_type":"sell",
960
+ // "currency":"usdt",
961
+ // "coin":"neo",
962
+ // "type":"limit",
963
+ // "quantity":"1.0000000000",
964
+ // "price":"14.9900000000",
965
+ // "executed_quantity":"0.0000000000",
966
+ // "executed_price":"0.0000000000",
967
+ // "fee":"0.0000000000",
968
+ // "status":"canceled",
969
+ // "created_at":1560244052168,
970
+ // "updated_at":1560244052168,
971
+ // },
972
+ // ],
973
+ // },
974
+ // }
975
+ //
976
+ let data = this.safeValue (response, 'data', {});
977
+ data = this.safeValue (response, 'data', []);
978
+ return this.parseOrders (data);
979
+ }
980
+
981
+ parseOrderStatus (status) {
982
+ const statuses = {
983
+ 'pending': 'open',
984
+ 'stopping': 'open',
985
+ 'executing': 'open',
986
+ 'executed': 'closed',
987
+ 'canceled': 'canceled',
988
+ };
989
+ return this.safeString (statuses, status, status);
990
+ }
991
+
992
+ parseOrder (order, market = undefined) {
993
+ //
994
+ // ceiling_market
995
+ //
996
+ // {
997
+ // "coin":"btc",
998
+ // "currency":"usdt",
999
+ // "trade_type":"buy",
1000
+ // "type":"ceiling_market",
1001
+ // "ceiling":"30",
1002
+ // "user_id":253063,
1003
+ // "email":"igor.kroitor@gmail.com",
1004
+ // "side":"buy",
1005
+ // "quantity":"0.00172800",
1006
+ // "status":"pending",
1007
+ // "fee":0,
1008
+ // "created_at":1606571333035,
1009
+ // "updated_at":1606571333035,
1010
+ // "instrument_symbol":"BTCUSDT",
1011
+ // "remaining":"0.00172800",
1012
+ // "fee_rate":"0.002",
1013
+ // "id":88214435
1014
+ // }
1015
+ //
1016
+ // limit order
1017
+ //
1018
+ // {
1019
+ // "id":41230,
1020
+ // "trade_type":"sell",
1021
+ // "type":"limit",
1022
+ // "quantity":"1",
1023
+ // "price":"14.99",
1024
+ // "currency":"usdt",
1025
+ // "coin":"neo",
1026
+ // "status":"pending",
1027
+ // "is_stop": "1",
1028
+ // "stop_price": "13",
1029
+ // "stop_condition": "ge",
1030
+ // "fee":0,
1031
+ // "created_at":1560244052168,
1032
+ // "updated_at":1560244052168
1033
+ // }
1034
+ //
1035
+ const created = this.safeValue (order, 'created_at');
1036
+ const updated = this.safeValue (order, 'updated_at');
1037
+ const baseId = this.safeStringUpper (order, 'coin');
1038
+ const quoteId = this.safeStringUpper (order, 'currency');
1039
+ const marketId = baseId + '_' + quoteId;
1040
+ market = this.safeMarket (marketId, market, '_');
1041
+ const symbol = market['symbol'];
1042
+ const amount = this.safeString (order, 'quantity');
1043
+ const filled = this.safeString (order, 'executed_quantity');
1044
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
1045
+ const cost = this.safeString (order, 'ceiling');
1046
+ const id = this.safeString (order, 'id');
1047
+ const price = this.safeString (order, 'price');
1048
+ const average = this.safeString (order, 'executed_price');
1049
+ const remaining = this.safeString (order, 'remaining');
1050
+ const type = this.safeString (order, 'type');
1051
+ const side = this.safeString (order, 'trade_type');
1052
+ const fee = {
1053
+ 'currency': market['quote'],
1054
+ 'cost': this.safeNumber (order, 'fee'),
1055
+ 'rate': this.safeNumber (order, 'fee_rate'),
1056
+ };
1057
+ let lastTradeTimestamp = undefined;
1058
+ if (updated !== created) {
1059
+ lastTradeTimestamp = updated;
1060
+ }
1061
+ const stopPrice = this.safeNumber (order, 'stopPrice');
1062
+ return this.safeOrder ({
1063
+ 'id': id,
1064
+ 'clientOrderId': id,
1065
+ 'timestamp': created,
1066
+ 'datetime': this.iso8601 (created),
1067
+ 'lastTradeTimestamp': lastTradeTimestamp,
1068
+ 'status': status,
1069
+ 'symbol': symbol,
1070
+ 'type': type,
1071
+ 'timeInForce': undefined,
1072
+ 'postOnly': undefined,
1073
+ 'side': side,
1074
+ 'price': price,
1075
+ 'stopPrice': stopPrice,
1076
+ 'average': average,
1077
+ 'amount': amount,
1078
+ 'cost': cost,
1079
+ 'filled': filled,
1080
+ 'remaining': remaining,
1081
+ 'fee': fee,
1082
+ 'trades': undefined,
1083
+ 'info': order,
1084
+ }, market);
1085
+ }
1086
+
1087
+ async fetchOrder (id, symbol = undefined, params = {}) {
1088
+ await this.loadMarkets ();
1089
+ const request = {
1090
+ 'order_id': id,
1091
+ };
1092
+ const response = await this.privateGetOrdersOrderId (this.extend (request, params));
1093
+ //
1094
+ // {
1095
+ // "message":null,
1096
+ // "dataVersion":"57448aa1fb8f227254e8e2e925b3ade8e1e5bbef",
1097
+ // "data":{
1098
+ // "id":88265741,
1099
+ // "user_id":253063,
1100
+ // "email":"igor.kroitor@gmail.com",
1101
+ // "updated_at":1606581578141,
1102
+ // "created_at":1606581578141,
1103
+ // "coin":"btc",
1104
+ // "currency":"usdt",
1105
+ // "type":"market",
1106
+ // "trade_type":"sell",
1107
+ // "executed_price":"17667.1900000000",
1108
+ // "price":null,
1109
+ // "executed_quantity":"0.0017280000",
1110
+ // "quantity":"0.0017280000",
1111
+ // "fee":"0.0610578086",
1112
+ // "status":"executed",
1113
+ // "is_stop":0,
1114
+ // "stop_condition":null,
1115
+ // "stop_price":null,
1116
+ // "ceiling":null
1117
+ // }
1118
+ // }
1119
+ //
1120
+ const data = this.safeValue (response, 'data');
1121
+ return this.parseOrder (data);
1122
+ }
1123
+
1124
+ async fetchOrdersWithMethod (method, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1125
+ await this.loadMarkets ();
1126
+ const request = {
1127
+ // 'page': 1,
1128
+ // 'limit': limit, // max 1000
1129
+ // 'start_date': since,
1130
+ // 'end_date': this.milliseconds (),
1131
+ // 'currency': market['quoteId'],
1132
+ // 'coin': market['baseId'],
1133
+ // 'trade_type': 'buy', // or 'sell'
1134
+ // 'hide_canceled': 0, // 1 to exclude canceled orders
1135
+ };
1136
+ let market = undefined;
1137
+ if (symbol !== undefined) {
1138
+ market = this.market (symbol);
1139
+ request['coin'] = market['baseId'];
1140
+ request['currency'] = market['quoteId'];
1141
+ }
1142
+ if (since !== undefined) {
1143
+ request['start_date'] = since;
1144
+ }
1145
+ if (limit !== undefined) {
1146
+ request['limit'] = Math.min (1000, limit); // max 1000
1147
+ }
1148
+ const response = await this[method] (this.extend (request, params));
1149
+ //
1150
+ // {
1151
+ // "message":null,
1152
+ // "dataVersion":"89aa11497f23fdd34cf9de9c55acfad863c78780",
1153
+ // "data":{
1154
+ // "current_page":1,
1155
+ // "data":[
1156
+ // {
1157
+ // "id":88489678,
1158
+ // "email":"igor.kroitor@gmail.com",
1159
+ // "updated_at":1606628593567,
1160
+ // "created_at":1606628593567,
1161
+ // "coin":"btc",
1162
+ // "currency":"usdt",
1163
+ // "type":"limit",
1164
+ // "trade_type":"buy",
1165
+ // "executed_price":"0.0000000000",
1166
+ // "price":"10000.0000000000",
1167
+ // "executed_quantity":"0.0000000000",
1168
+ // "quantity":"0.0010000000",
1169
+ // "fee":"0.0000000000",
1170
+ // "status":"pending",
1171
+ // "is_stop":0,
1172
+ // "stop_condition":null,
1173
+ // "stop_price":null,
1174
+ // "ceiling":null,
1175
+ // },
1176
+ // ],
1177
+ // "first_page_url":"http:\/\/api.vcc.exchange\/v3\/orders\/open?page=1",
1178
+ // "from":1,
1179
+ // "last_page":1,
1180
+ // "last_page_url":"http:\/\/api.vcc.exchange\/v3\/orders\/open?page=1",
1181
+ // "next_page_url":null,
1182
+ // "path":"http:\/\/api.vcc.exchange\/v3\/orders\/open",
1183
+ // "per_page":10,
1184
+ // "prev_page_url":null,
1185
+ // "to":1,
1186
+ // "total":1,
1187
+ // },
1188
+ // }
1189
+ //
1190
+ let data = this.safeValue (response, 'data', {});
1191
+ data = this.safeValue (data, 'data', []);
1192
+ return this.parseOrders (data, market, since, limit);
1193
+ }
1194
+
1195
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1196
+ return await this.fetchOrdersWithMethod ('privateGetOrdersOpen', symbol, since, limit, params);
1197
+ }
1198
+
1199
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1200
+ return await this.fetchOrdersWithMethod ('privateGetOrders', symbol, since, limit, params);
1201
+ }
1202
+
1203
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1204
+ await this.loadMarkets ();
1205
+ const request = {
1206
+ // 'page': 1,
1207
+ // 'limit': limit, // max 1000
1208
+ // 'start_date': since,
1209
+ // 'end_date': this.milliseconds (),
1210
+ // 'currency': market['quoteId'],
1211
+ // 'coin': market['baseId'],
1212
+ // 'trade_type': 'buy', // or 'sell'
1213
+ };
1214
+ let market = undefined;
1215
+ if (symbol !== undefined) {
1216
+ market = this.market (symbol);
1217
+ request['coin'] = market['baseId'];
1218
+ request['currency'] = market['quoteId'];
1219
+ }
1220
+ if (since !== undefined) {
1221
+ request['start_date'] = since;
1222
+ }
1223
+ if (limit !== undefined) {
1224
+ request['limit'] = Math.min (1000, limit); // max 1000
1225
+ }
1226
+ const response = await this.privateGetOrdersTrades (this.extend (request, params));
1227
+ //
1228
+ // {
1229
+ // "message":null,
1230
+ // "dataVersion":"eb890af684cf84e20044e9a9771b96302e7b8dec",
1231
+ // "data":{
1232
+ // "current_page":1,
1233
+ // "data":[
1234
+ // {
1235
+ // "trade_type":"sell",
1236
+ // "fee":"0.0610578086",
1237
+ // "id":1483372,
1238
+ // "created_at":1606581578368,
1239
+ // "currency":"usdt",
1240
+ // "coin":"btc",
1241
+ // "price":"17667.1900000000",
1242
+ // "quantity":"0.0017280000",
1243
+ // "amount":"30.5289043200",
1244
+ // },
1245
+ // ],
1246
+ // "first_page_url":"http:\/\/api.vcc.exchange\/v3\/orders\/trades?page=1",
1247
+ // "from":1,
1248
+ // "last_page":1,
1249
+ // "last_page_url":"http:\/\/api.vcc.exchange\/v3\/orders\/trades?page=1",
1250
+ // "next_page_url":null,
1251
+ // "path":"http:\/\/api.vcc.exchange\/v3\/orders\/trades",
1252
+ // "per_page":10,
1253
+ // "prev_page_url":null,
1254
+ // "to":2,
1255
+ // "total":2,
1256
+ // },
1257
+ // }
1258
+ //
1259
+ let data = this.safeValue (response, 'data', {});
1260
+ data = this.safeValue (data, 'data', []);
1261
+ return this.parseTrades (data, market, since, limit);
1262
+ }
1263
+
1264
+ async fetchDepositAddress (code, params = {}) {
1265
+ await this.loadMarkets ();
1266
+ const currency = this.currency (code);
1267
+ const request = {
1268
+ 'currency': currency['id'],
1269
+ };
1270
+ const response = await this.privateGetDepositAddress (this.extend (request, params));
1271
+ //
1272
+ // {
1273
+ // "dataVersion":"6d72fb82a9c613c8166581a887e1723ce5a937ff",
1274
+ // "data":{
1275
+ // "status": "REQUESTED",
1276
+ // "blockchain_address": "",
1277
+ // "currency": "btc"
1278
+ // }
1279
+ // }
1280
+ //
1281
+ // {
1282
+ // "dataVersion":"6d72fb82a9c613c8166581a887e1723ce5a937ff",
1283
+ // "data":{
1284
+ // "status": "PROVISIONED",
1285
+ // "blockchain_address": "rPVMhWBsfF9iMXYj3aAzJVkPDTFNSyWdKy",
1286
+ // "blockchain_tag": "920396135",
1287
+ // "currency": "xrp"
1288
+ // }
1289
+ // }
1290
+ //
1291
+ const data = this.safeValue (response, 'data');
1292
+ const status = this.safeString (data, 'status');
1293
+ if (status === 'REQUESTED') {
1294
+ throw new AddressPending (this.id + ' is generating ' + code + ' deposit address, call fetchDepositAddress one more time later to retrieve the generated address');
1295
+ }
1296
+ const address = this.safeString (data, 'blockchain_address');
1297
+ this.checkAddress (address);
1298
+ const tag = this.safeString (data, 'blockchain_tag');
1299
+ const currencyId = this.safeString (data, 'currency');
1300
+ return {
1301
+ 'currency': this.safeCurrencyCode (currencyId),
1302
+ 'address': address,
1303
+ 'tag': tag,
1304
+ 'network': undefined,
1305
+ 'info': data,
1306
+ };
1307
+ }
1308
+
1309
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1310
+ let url = this.version + '/' + this.implodeParams (path, params);
1311
+ const query = this.omit (params, this.extractParams (path));
1312
+ if (Object.keys (query).length) {
1313
+ url += '?' + this.urlencode (query);
1314
+ }
1315
+ if (api === 'private') {
1316
+ this.checkRequiredCredentials ();
1317
+ const timestamp = this.milliseconds ().toString ();
1318
+ if (method !== 'GET') {
1319
+ body = this.json (query);
1320
+ }
1321
+ const auth = method + ' ' + url;
1322
+ const signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha256');
1323
+ headers = {
1324
+ 'Authorization': 'Bearer ' + this.apiKey,
1325
+ 'Content-Type': 'application/json',
1326
+ 'timestamp': timestamp,
1327
+ 'signature': signature,
1328
+ };
1329
+ }
1330
+ url = this.urls['api'][api] + '/' + url;
1331
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1332
+ }
1333
+
1334
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1335
+ if (response === undefined) {
1336
+ return;
1337
+ }
1338
+ //
1339
+ // {"message":"Insufficient balance."}
1340
+ // {"message":"Unauthenticated."} // wrong api key
1341
+ // {"message":"The given data was invalid.","errors":{"signature":["HMAC signature is invalid"]}}
1342
+ // {"code":504,"message":"Gateway Timeout","description":""}
1343
+ // {"code":429,"message":"Too many requests","description":"Too many requests"}
1344
+ //
1345
+ const message = this.safeString (response, 'message');
1346
+ if (message !== undefined) {
1347
+ const feedback = this.id + ' ' + body;
1348
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
1349
+ this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
1350
+ throw new ExchangeError (feedback);
1351
+ }
1352
+ }
1353
+ };