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/upbit.js ADDED
@@ -0,0 +1,1622 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, BadRequest, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, PermissionDenied, AddressPending } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class upbit extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'upbit',
15
+ 'name': 'Upbit',
16
+ 'countries': [ 'KR' ],
17
+ 'version': 'v1',
18
+ 'rateLimit': 1000,
19
+ 'pro': true,
20
+ // new metainfo interface
21
+ 'has': {
22
+ 'CORS': true,
23
+ 'spot': true,
24
+ 'margin': undefined,
25
+ 'swap': false,
26
+ 'future': false,
27
+ 'option': false,
28
+ 'cancelOrder': true,
29
+ 'createDepositAddress': true,
30
+ 'createMarketOrder': true,
31
+ 'createOrder': true,
32
+ 'fetchBalance': true,
33
+ 'fetchCanceledOrders': true,
34
+ 'fetchClosedOrders': true,
35
+ 'fetchDepositAddress': true,
36
+ 'fetchDepositAddresses': true,
37
+ 'fetchDeposits': true,
38
+ 'fetchFundingHistory': false,
39
+ 'fetchFundingRate': false,
40
+ 'fetchFundingRateHistories': false,
41
+ 'fetchFundingRateHistory': false,
42
+ 'fetchFundingRates': false,
43
+ 'fetchIndexOHLCV': false,
44
+ 'fetchMarkets': true,
45
+ 'fetchMarkOHLCV': false,
46
+ 'fetchMyTrades': undefined,
47
+ 'fetchOHLCV': true,
48
+ 'fetchOpenOrders': true,
49
+ 'fetchOrder': true,
50
+ 'fetchOrderBook': true,
51
+ 'fetchOrderBooks': true,
52
+ 'fetchOrders': undefined,
53
+ 'fetchPremiumIndexOHLCV': false,
54
+ 'fetchTicker': true,
55
+ 'fetchTickers': true,
56
+ 'fetchTrades': true,
57
+ 'fetchTradingFee': true,
58
+ 'fetchTradingFees': false,
59
+ 'fetchTransactions': undefined,
60
+ 'fetchWithdrawals': true,
61
+ 'transfer': false,
62
+ 'withdraw': true,
63
+ },
64
+ 'timeframes': {
65
+ '1m': 'minutes',
66
+ '3m': 'minutes',
67
+ '5m': 'minutes',
68
+ '15m': 'minutes',
69
+ '30m': 'minutes',
70
+ '1h': 'minutes',
71
+ '4h': 'minutes',
72
+ '1d': 'days',
73
+ '1w': 'weeks',
74
+ '1M': 'months',
75
+ },
76
+ 'hostname': 'api.upbit.com',
77
+ 'urls': {
78
+ 'logo': 'https://user-images.githubusercontent.com/1294454/49245610-eeaabe00-f423-11e8-9cba-4b0aed794799.jpg',
79
+ 'api': {
80
+ 'public': 'https://{hostname}',
81
+ 'private': 'https://{hostname}',
82
+ },
83
+ 'www': 'https://upbit.com',
84
+ 'doc': 'https://docs.upbit.com/docs/%EC%9A%94%EC%B2%AD-%EC%88%98-%EC%A0%9C%ED%95%9C',
85
+ 'fees': 'https://upbit.com/service_center/guide',
86
+ },
87
+ 'api': {
88
+ 'public': {
89
+ 'get': [
90
+ 'market/all',
91
+ 'candles/{timeframe}',
92
+ 'candles/{timeframe}/{unit}',
93
+ 'candles/minutes/{unit}',
94
+ 'candles/minutes/1',
95
+ 'candles/minutes/3',
96
+ 'candles/minutes/5',
97
+ 'candles/minutes/15',
98
+ 'candles/minutes/30',
99
+ 'candles/minutes/60',
100
+ 'candles/minutes/240',
101
+ 'candles/days',
102
+ 'candles/weeks',
103
+ 'candles/months',
104
+ 'trades/ticks',
105
+ 'ticker',
106
+ 'orderbook',
107
+ ],
108
+ },
109
+ 'private': {
110
+ 'get': [
111
+ 'accounts',
112
+ 'orders/chance',
113
+ 'order',
114
+ 'orders',
115
+ 'withdraws',
116
+ 'withdraw',
117
+ 'withdraws/chance',
118
+ 'deposits',
119
+ 'deposit',
120
+ 'deposits/coin_addresses',
121
+ 'deposits/coin_address',
122
+ ],
123
+ 'post': [
124
+ 'orders',
125
+ 'withdraws/coin',
126
+ 'withdraws/krw',
127
+ 'deposits/generate_coin_address',
128
+ ],
129
+ 'delete': [
130
+ 'order',
131
+ ],
132
+ },
133
+ },
134
+ 'fees': {
135
+ 'trading': {
136
+ 'tierBased': false,
137
+ 'percentage': true,
138
+ 'maker': this.parseNumber ('0.0025'),
139
+ 'taker': this.parseNumber ('0.0025'),
140
+ },
141
+ 'funding': {
142
+ 'tierBased': false,
143
+ 'percentage': false,
144
+ 'withdraw': {},
145
+ 'deposit': {},
146
+ },
147
+ },
148
+ 'exceptions': {
149
+ 'exact': {
150
+ 'This key has expired.': AuthenticationError,
151
+ 'Missing request parameter error. Check the required parameters!': BadRequest,
152
+ 'side is missing, side does not have a valid value': InvalidOrder,
153
+ },
154
+ 'broad': {
155
+ 'thirdparty_agreement_required': PermissionDenied,
156
+ 'out_of_scope': PermissionDenied,
157
+ 'order_not_found': OrderNotFound,
158
+ 'insufficient_funds': InsufficientFunds,
159
+ 'invalid_access_key': AuthenticationError,
160
+ 'jwt_verification': AuthenticationError,
161
+ 'create_ask_error': ExchangeError,
162
+ 'create_bid_error': ExchangeError,
163
+ 'volume_too_large': InvalidOrder,
164
+ 'invalid_funds': InvalidOrder,
165
+ },
166
+ },
167
+ 'options': {
168
+ 'createMarketBuyOrderRequiresPrice': true,
169
+ 'fetchTickersMaxLength': 4096, // 2048,
170
+ 'fetchOrderBooksMaxLength': 4096, // 2048,
171
+ 'tradingFeesByQuoteCurrency': {
172
+ 'KRW': 0.0005,
173
+ },
174
+ },
175
+ 'commonCurrencies': {
176
+ 'TON': 'Tokamak Network',
177
+ },
178
+ });
179
+ }
180
+
181
+ async fetchCurrency (code, params = {}) {
182
+ // this method is for retrieving funding fees and limits per currency
183
+ // it requires private access and API keys properly set up
184
+ await this.loadMarkets ();
185
+ const currency = this.currency (code);
186
+ return await this.fetchCurrencyById (currency['id'], params);
187
+ }
188
+
189
+ async fetchCurrencyById (id, params = {}) {
190
+ // this method is for retrieving funding fees and limits per currency
191
+ // it requires private access and API keys properly set up
192
+ const request = {
193
+ 'currency': id,
194
+ };
195
+ const response = await this.privateGetWithdrawsChance (this.extend (request, params));
196
+ //
197
+ // {
198
+ // "member_level": {
199
+ // "security_level": 3,
200
+ // "fee_level": 0,
201
+ // "email_verified": true,
202
+ // "identity_auth_verified": true,
203
+ // "bank_account_verified": true,
204
+ // "kakao_pay_auth_verified": false,
205
+ // "locked": false,
206
+ // "wallet_locked": false
207
+ // },
208
+ // "currency": {
209
+ // "code": "BTC",
210
+ // "withdraw_fee": "0.0005",
211
+ // "is_coin": true,
212
+ // "wallet_state": "working",
213
+ // "wallet_support": [ "deposit", "withdraw" ]
214
+ // },
215
+ // "account": {
216
+ // "currency": "BTC",
217
+ // "balance": "10.0",
218
+ // "locked": "0.0",
219
+ // "avg_krw_buy_price": "8042000",
220
+ // "modified": false
221
+ // },
222
+ // "withdraw_limit": {
223
+ // "currency": "BTC",
224
+ // "minimum": null,
225
+ // "onetime": null,
226
+ // "daily": "10.0",
227
+ // "remaining_daily": "10.0",
228
+ // "remaining_daily_krw": "0.0",
229
+ // "fixed": null,
230
+ // "can_withdraw": true
231
+ // }
232
+ // }
233
+ //
234
+ const memberInfo = this.safeValue (response, 'member_level', {});
235
+ const currencyInfo = this.safeValue (response, 'currency', {});
236
+ const withdrawLimits = this.safeValue (response, 'withdraw_limit', {});
237
+ const canWithdraw = this.safeValue (withdrawLimits, 'can_withdraw');
238
+ const walletState = this.safeString (currencyInfo, 'wallet_state');
239
+ const walletLocked = this.safeValue (memberInfo, 'wallet_locked');
240
+ const locked = this.safeValue (memberInfo, 'locked');
241
+ let active = true;
242
+ if ((canWithdraw !== undefined) && !canWithdraw) {
243
+ active = false;
244
+ } else if (walletState !== 'working') {
245
+ active = false;
246
+ } else if ((walletLocked !== undefined) && walletLocked) {
247
+ active = false;
248
+ } else if ((locked !== undefined) && locked) {
249
+ active = false;
250
+ }
251
+ const maxOnetimeWithdrawal = this.safeNumber (withdrawLimits, 'onetime');
252
+ const maxDailyWithdrawal = this.safeNumber (withdrawLimits, 'daily', maxOnetimeWithdrawal);
253
+ const remainingDailyWithdrawal = this.safeNumber (withdrawLimits, 'remaining_daily', maxDailyWithdrawal);
254
+ let maxWithdrawLimit = undefined;
255
+ if (remainingDailyWithdrawal > 0) {
256
+ maxWithdrawLimit = remainingDailyWithdrawal;
257
+ } else {
258
+ maxWithdrawLimit = maxDailyWithdrawal;
259
+ }
260
+ const precision = undefined;
261
+ const currencyId = this.safeString (currencyInfo, 'code');
262
+ const code = this.safeCurrencyCode (currencyId);
263
+ return {
264
+ 'info': response,
265
+ 'id': currencyId,
266
+ 'code': code,
267
+ 'name': code,
268
+ 'active': active,
269
+ 'fee': this.safeNumber (currencyInfo, 'withdraw_fee'),
270
+ 'precision': precision,
271
+ 'limits': {
272
+ 'withdraw': {
273
+ 'min': this.safeNumber (withdrawLimits, 'minimum'),
274
+ 'max': maxWithdrawLimit,
275
+ },
276
+ },
277
+ };
278
+ }
279
+
280
+ async fetchMarket (symbol, params = {}) {
281
+ // this method is for retrieving trading fees and limits per market
282
+ // it requires private access and API keys properly set up
283
+ await this.loadMarkets ();
284
+ const market = this.market (symbol);
285
+ return await this.fetchMarketById (market['id'], params);
286
+ }
287
+
288
+ async fetchMarketById (id, params = {}) {
289
+ // this method is for retrieving trading fees and limits per market
290
+ // it requires private access and API keys properly set up
291
+ const request = {
292
+ 'market': id,
293
+ };
294
+ const response = await this.privateGetOrdersChance (this.extend (request, params));
295
+ //
296
+ // {
297
+ // "bid_fee": "0.0015",
298
+ // "ask_fee": "0.0015",
299
+ // "market": {
300
+ // "id": "KRW-BTC",
301
+ // "name": "BTC/KRW",
302
+ // "order_types": [ "limit" ],
303
+ // "order_sides": [ "ask", "bid" ],
304
+ // "bid": { "currency": "KRW", "price_unit": null, "min_total": 1000 },
305
+ // "ask": { "currency": "BTC", "price_unit": null, "min_total": 1000 },
306
+ // "max_total": "100000000.0",
307
+ // "state": "active",
308
+ // },
309
+ // "bid_account": {
310
+ // "currency": "KRW",
311
+ // "balance": "0.0",
312
+ // "locked": "0.0",
313
+ // "avg_buy_price": "0",
314
+ // "avg_buy_price_modified": false,
315
+ // "unit_currency": "KRW",
316
+ // },
317
+ // "ask_account": {
318
+ // "currency": "BTC",
319
+ // "balance": "10.0",
320
+ // "locked": "0.0",
321
+ // "avg_buy_price": "8042000",
322
+ // "avg_buy_price_modified": false,
323
+ // "unit_currency": "KRW",
324
+ // }
325
+ // }
326
+ //
327
+ const marketInfo = this.safeValue (response, 'market');
328
+ const bid = this.safeValue (marketInfo, 'bid');
329
+ const ask = this.safeValue (marketInfo, 'ask');
330
+ const marketId = this.safeString (marketInfo, 'id');
331
+ const baseId = this.safeString (ask, 'currency');
332
+ const quoteId = this.safeString (bid, 'currency');
333
+ const base = this.safeCurrencyCode (baseId);
334
+ const quote = this.safeCurrencyCode (quoteId);
335
+ const state = this.safeString (marketInfo, 'state');
336
+ const bidFee = this.safeNumber (response, 'bid_fee');
337
+ const askFee = this.safeNumber (response, 'ask_fee');
338
+ const fee = Math.max (bidFee, askFee);
339
+ return {
340
+ 'id': marketId,
341
+ 'symbol': base + '/' + quote,
342
+ 'base': base,
343
+ 'quote': quote,
344
+ 'settle': undefined,
345
+ 'baseId': baseId,
346
+ 'quoteId': quoteId,
347
+ 'settleId': undefined,
348
+ 'type': 'spot',
349
+ 'spot': true,
350
+ 'margin': false,
351
+ 'swap': false,
352
+ 'future': false,
353
+ 'option': false,
354
+ 'active': (state === 'active'),
355
+ 'contract': false,
356
+ 'linear': undefined,
357
+ 'inverse': undefined,
358
+ 'taker': fee,
359
+ 'maker': fee,
360
+ 'contractSize': undefined,
361
+ 'expiry': undefined,
362
+ 'expiryDatetime': undefined,
363
+ 'strike': undefined,
364
+ 'optionType': undefined,
365
+ 'precision': {
366
+ 'amount': parseInt ('8'),
367
+ 'price': parseInt ('8'),
368
+ },
369
+ 'limits': {
370
+ 'leverage': {
371
+ 'min': undefined,
372
+ 'max': undefined,
373
+ },
374
+ 'amount': {
375
+ 'min': this.safeNumber (ask, 'min_total'),
376
+ 'max': undefined,
377
+ },
378
+ 'price': {
379
+ 'min': undefined,
380
+ 'max': undefined,
381
+ },
382
+ 'cost': {
383
+ 'min': this.safeNumber (bid, 'min_total'),
384
+ 'max': this.safeNumber (marketInfo, 'max_total'),
385
+ },
386
+ 'info': response,
387
+ },
388
+ };
389
+ }
390
+
391
+ async fetchMarkets (params = {}) {
392
+ const response = await this.publicGetMarketAll (params);
393
+ //
394
+ // [
395
+ // {
396
+ // market: "KRW-BTC",
397
+ // korean_name: "비트코인",
398
+ // english_name: "Bitcoin"
399
+ // },
400
+ // ...,
401
+ // ]
402
+ //
403
+ const result = [];
404
+ for (let i = 0; i < response.length; i++) {
405
+ const market = response[i];
406
+ const id = this.safeString (market, 'market');
407
+ const [ quoteId, baseId ] = id.split ('-');
408
+ const base = this.safeCurrencyCode (baseId);
409
+ const quote = this.safeCurrencyCode (quoteId);
410
+ result.push ({
411
+ 'id': id,
412
+ 'symbol': base + '/' + quote,
413
+ 'base': base,
414
+ 'quote': quote,
415
+ 'settle': undefined,
416
+ 'baseId': baseId,
417
+ 'quoteId': quoteId,
418
+ 'settleId': undefined,
419
+ 'type': 'spot',
420
+ 'spot': true,
421
+ 'margin': false,
422
+ 'swap': false,
423
+ 'future': false,
424
+ 'option': false,
425
+ 'active': true,
426
+ 'contract': false,
427
+ 'linear': undefined,
428
+ 'inverse': undefined,
429
+ 'taker': this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['taker']),
430
+ 'maker': this.safeNumber (this.options['tradingFeesByQuoteCurrency'], quote, this.fees['trading']['maker']),
431
+ 'contractSize': undefined,
432
+ 'expiry': undefined,
433
+ 'expiryDatetime': undefined,
434
+ 'strike': undefined,
435
+ 'optionType': undefined,
436
+ 'precision': {
437
+ 'price': 8,
438
+ 'amount': 8,
439
+ },
440
+ 'limits': {
441
+ 'leverage': {
442
+ 'min': undefined,
443
+ 'max': undefined,
444
+ },
445
+ 'amount': {
446
+ 'min': undefined,
447
+ 'max': undefined,
448
+ },
449
+ 'price': {
450
+ 'min': undefined,
451
+ 'max': undefined,
452
+ },
453
+ 'cost': {
454
+ 'min': undefined,
455
+ 'max': undefined,
456
+ },
457
+ },
458
+ 'info': market,
459
+ });
460
+ }
461
+ return result;
462
+ }
463
+
464
+ parseBalance (response) {
465
+ const result = {
466
+ 'info': response,
467
+ 'timestamp': undefined,
468
+ 'datetime': undefined,
469
+ };
470
+ for (let i = 0; i < response.length; i++) {
471
+ const balance = response[i];
472
+ const currencyId = this.safeString (balance, 'currency');
473
+ const code = this.safeCurrencyCode (currencyId);
474
+ const account = this.account ();
475
+ account['free'] = this.safeString (balance, 'balance');
476
+ account['used'] = this.safeString (balance, 'locked');
477
+ result[code] = account;
478
+ }
479
+ return this.safeBalance (result);
480
+ }
481
+
482
+ async fetchBalance (params = {}) {
483
+ await this.loadMarkets ();
484
+ const response = await this.privateGetAccounts (params);
485
+ //
486
+ // [ { currency: "BTC",
487
+ // balance: "0.005",
488
+ // locked: "0.0",
489
+ // avg_krw_buy_price: "7446000",
490
+ // modified: false },
491
+ // { currency: "ETH",
492
+ // balance: "0.1",
493
+ // locked: "0.0",
494
+ // avg_krw_buy_price: "250000",
495
+ // modified: false } ]
496
+ //
497
+ return this.parseBalance (response);
498
+ }
499
+
500
+ async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
501
+ await this.loadMarkets ();
502
+ let ids = undefined;
503
+ if (symbols === undefined) {
504
+ ids = this.ids.join (',');
505
+ // max URL length is 2083 symbols, including http schema, hostname, tld, etc...
506
+ if (ids.length > this.options['fetchOrderBooksMaxLength']) {
507
+ const numIds = this.ids.length;
508
+ throw new ExchangeError (this.id + ' fetchOrderBooks() has ' + numIds.toString () + ' symbols (' + ids.length.toString () + ' characters) exceeding max URL length (' + this.options['fetchOrderBooksMaxLength'].toString () + ' characters), you are required to specify a list of symbols in the first argument to fetchOrderBooks');
509
+ }
510
+ } else {
511
+ ids = this.marketIds (symbols);
512
+ ids = ids.join (',');
513
+ }
514
+ const request = {
515
+ 'markets': ids,
516
+ };
517
+ const response = await this.publicGetOrderbook (this.extend (request, params));
518
+ //
519
+ // [ { market: "BTC-ETH",
520
+ // timestamp: 1542899030043,
521
+ // total_ask_size: 109.57065201,
522
+ // total_bid_size: 125.74430631,
523
+ // orderbook_units: [ { ask_price: 0.02926679,
524
+ // bid_price: 0.02919904,
525
+ // ask_size: 4.20293961,
526
+ // bid_size: 11.65043576 },
527
+ // ...,
528
+ // { ask_price: 0.02938209,
529
+ // bid_price: 0.0291231,
530
+ // ask_size: 0.05135782,
531
+ // bid_size: 13.5595 } ] },
532
+ // { market: "KRW-BTC",
533
+ // timestamp: 1542899034662,
534
+ // total_ask_size: 12.89790974,
535
+ // total_bid_size: 4.88395783,
536
+ // orderbook_units: [ { ask_price: 5164000,
537
+ // bid_price: 5162000,
538
+ // ask_size: 2.57606495,
539
+ // bid_size: 0.214 },
540
+ // ...,
541
+ // { ask_price: 5176000,
542
+ // bid_price: 5152000,
543
+ // ask_size: 2.752,
544
+ // bid_size: 0.4650305 } ] } ]
545
+ //
546
+ const result = {};
547
+ for (let i = 0; i < response.length; i++) {
548
+ const orderbook = response[i];
549
+ const marketId = this.safeString (orderbook, 'market');
550
+ const symbol = this.safeSymbol (marketId, undefined, '-');
551
+ const timestamp = this.safeInteger (orderbook, 'timestamp');
552
+ result[symbol] = {
553
+ 'symbol': symbol,
554
+ 'bids': this.sortBy (this.parseBidsAsks (orderbook['orderbook_units'], 'bid_price', 'bid_size'), 0, true),
555
+ 'asks': this.sortBy (this.parseBidsAsks (orderbook['orderbook_units'], 'ask_price', 'ask_size'), 0),
556
+ 'timestamp': timestamp,
557
+ 'datetime': this.iso8601 (timestamp),
558
+ 'nonce': undefined,
559
+ };
560
+ }
561
+ return result;
562
+ }
563
+
564
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
565
+ const orderbooks = await this.fetchOrderBooks ([ symbol ], limit, params);
566
+ return this.safeValue (orderbooks, symbol);
567
+ }
568
+
569
+ parseTicker (ticker, market = undefined) {
570
+ //
571
+ // { market: "BTC-ETH",
572
+ // trade_date: "20181122",
573
+ // trade_time: "104543",
574
+ // trade_date_kst: "20181122",
575
+ // trade_time_kst: "194543",
576
+ // trade_timestamp: 1542883543097,
577
+ // opening_price: 0.02976455,
578
+ // high_price: 0.02992577,
579
+ // low_price: 0.02934283,
580
+ // trade_price: 0.02947773,
581
+ // prev_closing_price: 0.02966,
582
+ // change: "FALL",
583
+ // change_price: 0.00018227,
584
+ // change_rate: 0.0061453136,
585
+ // signed_change_price: -0.00018227,
586
+ // signed_change_rate: -0.0061453136,
587
+ // trade_volume: 1.00000005,
588
+ // acc_trade_price: 100.95825586,
589
+ // acc_trade_price_24h: 289.58650166,
590
+ // acc_trade_volume: 3409.85311036,
591
+ // acc_trade_volume_24h: 9754.40510513,
592
+ // highest_52_week_price: 0.12345678,
593
+ // highest_52_week_date: "2018-02-01",
594
+ // lowest_52_week_price: 0.023936,
595
+ // lowest_52_week_date: "2017-12-08",
596
+ // timestamp: 1542883543813 }
597
+ //
598
+ const timestamp = this.safeInteger (ticker, 'trade_timestamp');
599
+ const marketId = this.safeString2 (ticker, 'market', 'code');
600
+ market = this.safeMarket (marketId, market, '-');
601
+ const last = this.safeString (ticker, 'trade_price');
602
+ return this.safeTicker ({
603
+ 'symbol': market['symbol'],
604
+ 'timestamp': timestamp,
605
+ 'datetime': this.iso8601 (timestamp),
606
+ 'high': this.safeString (ticker, 'high_price'),
607
+ 'low': this.safeString (ticker, 'low_price'),
608
+ 'bid': undefined,
609
+ 'bidVolume': undefined,
610
+ 'ask': undefined,
611
+ 'askVolume': undefined,
612
+ 'vwap': undefined,
613
+ 'open': this.safeString (ticker, 'opening_price'),
614
+ 'close': last,
615
+ 'last': last,
616
+ 'previousClose': this.safeString (ticker, 'prev_closing_price'),
617
+ 'change': this.safeString (ticker, 'signed_change_price'),
618
+ 'percentage': this.safeString (ticker, 'signed_change_rate'),
619
+ 'average': undefined,
620
+ 'baseVolume': this.safeString (ticker, 'acc_trade_volume_24h'),
621
+ 'quoteVolume': this.safeString (ticker, 'acc_trade_price_24h'),
622
+ 'info': ticker,
623
+ }, market, false);
624
+ }
625
+
626
+ async fetchTickers (symbols = undefined, params = {}) {
627
+ await this.loadMarkets ();
628
+ let ids = undefined;
629
+ if (symbols === undefined) {
630
+ ids = this.ids.join (',');
631
+ // max URL length is 2083 symbols, including http schema, hostname, tld, etc...
632
+ if (ids.length > this.options['fetchTickersMaxLength']) {
633
+ const numIds = this.ids.length;
634
+ throw new ExchangeError (this.id + ' fetchTickers() has ' + numIds.toString () + ' symbols exceeding max URL length, you are required to specify a list of symbols in the first argument to fetchTickers');
635
+ }
636
+ } else {
637
+ ids = this.marketIds (symbols);
638
+ ids = ids.join (',');
639
+ }
640
+ const request = {
641
+ 'markets': ids,
642
+ };
643
+ const response = await this.publicGetTicker (this.extend (request, params));
644
+ //
645
+ // [ { market: "BTC-ETH",
646
+ // trade_date: "20181122",
647
+ // trade_time: "104543",
648
+ // trade_date_kst: "20181122",
649
+ // trade_time_kst: "194543",
650
+ // trade_timestamp: 1542883543097,
651
+ // opening_price: 0.02976455,
652
+ // high_price: 0.02992577,
653
+ // low_price: 0.02934283,
654
+ // trade_price: 0.02947773,
655
+ // prev_closing_price: 0.02966,
656
+ // change: "FALL",
657
+ // change_price: 0.00018227,
658
+ // change_rate: 0.0061453136,
659
+ // signed_change_price: -0.00018227,
660
+ // signed_change_rate: -0.0061453136,
661
+ // trade_volume: 1.00000005,
662
+ // acc_trade_price: 100.95825586,
663
+ // acc_trade_price_24h: 289.58650166,
664
+ // acc_trade_volume: 3409.85311036,
665
+ // acc_trade_volume_24h: 9754.40510513,
666
+ // highest_52_week_price: 0.12345678,
667
+ // highest_52_week_date: "2018-02-01",
668
+ // lowest_52_week_price: 0.023936,
669
+ // lowest_52_week_date: "2017-12-08",
670
+ // timestamp: 1542883543813 } ]
671
+ //
672
+ const result = {};
673
+ for (let t = 0; t < response.length; t++) {
674
+ const ticker = this.parseTicker (response[t]);
675
+ const symbol = ticker['symbol'];
676
+ result[symbol] = ticker;
677
+ }
678
+ return this.filterByArray (result, 'symbol', symbols);
679
+ }
680
+
681
+ async fetchTicker (symbol, params = {}) {
682
+ const tickers = await this.fetchTickers ([ symbol ], params);
683
+ return this.safeValue (tickers, symbol);
684
+ }
685
+
686
+ parseTrade (trade, market = undefined) {
687
+ //
688
+ // fetchTrades
689
+ //
690
+ // { market: "BTC-ETH",
691
+ // trade_date_utc: "2018-11-22",
692
+ // trade_time_utc: "13:55:24",
693
+ // timestamp: 1542894924397,
694
+ // trade_price: 0.02914289,
695
+ // trade_volume: 0.20074397,
696
+ // prev_closing_price: 0.02966,
697
+ // change_price: -0.00051711,
698
+ // ask_bid: "ASK",
699
+ // sequential_id: 15428949259430000 }
700
+ //
701
+ // fetchOrder trades
702
+ //
703
+ // {
704
+ // "market": "KRW-BTC",
705
+ // "uuid": "78162304-1a4d-4524-b9e6-c9a9e14d76c3",
706
+ // "price": "101000.0",
707
+ // "volume": "0.77368323",
708
+ // "funds": "78142.00623",
709
+ // "ask_fee": "117.213009345",
710
+ // "bid_fee": "117.213009345",
711
+ // "created_at": "2018-04-05T14:09:15+09:00",
712
+ // "side": "bid",
713
+ // }
714
+ //
715
+ const id = this.safeString2 (trade, 'sequential_id', 'uuid');
716
+ const orderId = undefined;
717
+ let timestamp = this.safeInteger (trade, 'timestamp');
718
+ if (timestamp === undefined) {
719
+ timestamp = this.parse8601 (this.safeString (trade, 'created_at'));
720
+ }
721
+ let side = undefined;
722
+ const askOrBid = this.safeStringLower2 (trade, 'ask_bid', 'side');
723
+ if (askOrBid === 'ask') {
724
+ side = 'sell';
725
+ } else if (askOrBid === 'bid') {
726
+ side = 'buy';
727
+ }
728
+ const cost = this.safeString (trade, 'funds');
729
+ const price = this.safeString2 (trade, 'trade_price', 'price');
730
+ const amount = this.safeString2 (trade, 'trade_volume', 'volume');
731
+ const marketId = this.safeString2 (trade, 'market', 'code');
732
+ market = this.safeMarket (marketId, market, '-');
733
+ let fee = undefined;
734
+ const feeCost = this.safeString (trade, askOrBid + '_fee');
735
+ if (feeCost !== undefined) {
736
+ fee = {
737
+ 'currency': market['quote'],
738
+ 'cost': feeCost,
739
+ };
740
+ }
741
+ return this.safeTrade ({
742
+ 'id': id,
743
+ 'info': trade,
744
+ 'order': orderId,
745
+ 'timestamp': timestamp,
746
+ 'datetime': this.iso8601 (timestamp),
747
+ 'symbol': market['symbol'],
748
+ 'type': undefined,
749
+ 'side': side,
750
+ 'takerOrMaker': undefined,
751
+ 'price': price,
752
+ 'amount': amount,
753
+ 'cost': cost,
754
+ 'fee': fee,
755
+ }, market);
756
+ }
757
+
758
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
759
+ await this.loadMarkets ();
760
+ const market = this.market (symbol);
761
+ if (limit === undefined) {
762
+ limit = 200;
763
+ }
764
+ const request = {
765
+ 'market': market['id'],
766
+ 'count': limit,
767
+ };
768
+ const response = await this.publicGetTradesTicks (this.extend (request, params));
769
+ //
770
+ // [ { market: "BTC-ETH",
771
+ // trade_date_utc: "2018-11-22",
772
+ // trade_time_utc: "13:55:24",
773
+ // timestamp: 1542894924397,
774
+ // trade_price: 0.02914289,
775
+ // trade_volume: 0.20074397,
776
+ // prev_closing_price: 0.02966,
777
+ // change_price: -0.00051711,
778
+ // ask_bid: "ASK",
779
+ // sequential_id: 15428949259430000 },
780
+ // { market: "BTC-ETH",
781
+ // trade_date_utc: "2018-11-22",
782
+ // trade_time_utc: "13:03:10",
783
+ // timestamp: 1542891790123,
784
+ // trade_price: 0.02917,
785
+ // trade_volume: 7.392,
786
+ // prev_closing_price: 0.02966,
787
+ // change_price: -0.00049,
788
+ // ask_bid: "ASK",
789
+ // sequential_id: 15428917910540000 } ]
790
+ //
791
+ return this.parseTrades (response, market, since, limit);
792
+ }
793
+
794
+ async fetchTradingFee (symbol, params = {}) {
795
+ await this.loadMarkets ();
796
+ const market = this.market (symbol);
797
+ const request = {
798
+ 'market': market['id'],
799
+ };
800
+ const response = await this.privateGetOrdersChance (this.extend (request, params));
801
+ //
802
+ // {
803
+ // "bid_fee": "0.0005",
804
+ // "ask_fee": "0.0005",
805
+ // "maker_bid_fee": "0.0005",
806
+ // "maker_ask_fee": "0.0005",
807
+ // "market": {
808
+ // "id": "KRW-BTC",
809
+ // "name": "BTC/KRW",
810
+ // "order_types": [ "limit" ],
811
+ // "order_sides": [ "ask", "bid" ],
812
+ // "bid": { "currency": "KRW", "price_unit": null, "min_total": 5000 },
813
+ // "ask": { "currency": "BTC", "price_unit": null, "min_total": 5000 },
814
+ // "max_total": "1000000000.0",
815
+ // "state": "active"
816
+ // },
817
+ // "bid_account": {
818
+ // "currency": "KRW",
819
+ // "balance": "0.34202414",
820
+ // "locked": "4999.99999922",
821
+ // "avg_buy_price": "0",
822
+ // "avg_buy_price_modified": true,
823
+ // "unit_currency": "KRW"
824
+ // },
825
+ // "ask_account": {
826
+ // "currency": "BTC",
827
+ // "balance": "0.00048",
828
+ // "locked": "0.0",
829
+ // "avg_buy_price": "20870000",
830
+ // "avg_buy_price_modified": false,
831
+ // "unit_currency": "KRW"
832
+ // }
833
+ // }
834
+ //
835
+ const askFee = this.safeString (response, 'ask_fee');
836
+ const bidFee = this.safeString (response, 'bid_fee');
837
+ const taker = Precise.stringMax (askFee, bidFee);
838
+ const makerAskFee = this.safeString (response, 'maker_ask_fee');
839
+ const makerBidFee = this.safeString (response, 'maker_bid_fee');
840
+ const maker = Precise.stringMax (makerAskFee, makerBidFee);
841
+ return {
842
+ 'info': response,
843
+ 'symbol': symbol,
844
+ 'maker': this.parseNumber (maker),
845
+ 'taker': this.parseNumber (taker),
846
+ 'percentage': true,
847
+ 'tierBased': false,
848
+ };
849
+ }
850
+
851
+ parseOHLCV (ohlcv, market = undefined) {
852
+ //
853
+ // {
854
+ // market: "BTC-ETH",
855
+ // candle_date_time_utc: "2018-11-22T13:47:00",
856
+ // candle_date_time_kst: "2018-11-22T22:47:00",
857
+ // opening_price: 0.02915963,
858
+ // high_price: 0.02915963,
859
+ // low_price: 0.02915448,
860
+ // trade_price: 0.02915448,
861
+ // timestamp: 1542894473674,
862
+ // candle_acc_trade_price: 0.0981629437535248,
863
+ // candle_acc_trade_volume: 3.36693173,
864
+ // unit: 1
865
+ // }
866
+ //
867
+ return [
868
+ this.parse8601 (this.safeString (ohlcv, 'candle_date_time_utc')),
869
+ this.safeNumber (ohlcv, 'opening_price'),
870
+ this.safeNumber (ohlcv, 'high_price'),
871
+ this.safeNumber (ohlcv, 'low_price'),
872
+ this.safeNumber (ohlcv, 'trade_price'),
873
+ this.safeNumber (ohlcv, 'candle_acc_trade_volume'), // base volume
874
+ ];
875
+ }
876
+
877
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
878
+ await this.loadMarkets ();
879
+ const market = this.market (symbol);
880
+ const timeframePeriod = this.parseTimeframe (timeframe);
881
+ const timeframeValue = this.timeframes[timeframe];
882
+ if (limit === undefined) {
883
+ limit = 200;
884
+ }
885
+ const request = {
886
+ 'market': market['id'],
887
+ 'timeframe': timeframeValue,
888
+ 'count': limit,
889
+ };
890
+ let method = 'publicGetCandlesTimeframe';
891
+ if (timeframeValue === 'minutes') {
892
+ const numMinutes = Math.round (timeframePeriod / 60);
893
+ request['unit'] = numMinutes;
894
+ method += 'Unit';
895
+ }
896
+ if (since !== undefined) {
897
+ // convert `since` to `to` value
898
+ request['to'] = this.iso8601 (this.sum (since, timeframePeriod * limit * 1000));
899
+ }
900
+ const response = await this[method] (this.extend (request, params));
901
+ //
902
+ // [
903
+ // {
904
+ // market: "BTC-ETH",
905
+ // candle_date_time_utc: "2018-11-22T13:47:00",
906
+ // candle_date_time_kst: "2018-11-22T22:47:00",
907
+ // opening_price: 0.02915963,
908
+ // high_price: 0.02915963,
909
+ // low_price: 0.02915448,
910
+ // trade_price: 0.02915448,
911
+ // timestamp: 1542894473674,
912
+ // candle_acc_trade_price: 0.0981629437535248,
913
+ // candle_acc_trade_volume: 3.36693173,
914
+ // unit: 1
915
+ // },
916
+ // {
917
+ // market: "BTC-ETH",
918
+ // candle_date_time_utc: "2018-11-22T10:06:00",
919
+ // candle_date_time_kst: "2018-11-22T19:06:00",
920
+ // opening_price: 0.0294,
921
+ // high_price: 0.02940882,
922
+ // low_price: 0.02934283,
923
+ // trade_price: 0.02937354,
924
+ // timestamp: 1542881219276,
925
+ // candle_acc_trade_price: 0.0762597110943884,
926
+ // candle_acc_trade_volume: 2.5949617,
927
+ // unit: 1
928
+ // }
929
+ // ]
930
+ //
931
+ return this.parseOHLCVs (response, market, timeframe, since, limit);
932
+ }
933
+
934
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
935
+ if (type === 'market') {
936
+ // for market buy it requires the amount of quote currency to spend
937
+ if (side === 'buy') {
938
+ if (this.options['createMarketBuyOrderRequiresPrice']) {
939
+ if (price === undefined) {
940
+ throw new InvalidOrder (this.id + " createOrder() requires the price argument with 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 to supply the cost in the amount argument (the exchange-specific behaviour)");
941
+ } else {
942
+ amount = amount * price;
943
+ }
944
+ }
945
+ }
946
+ }
947
+ let orderSide = undefined;
948
+ if (side === 'buy') {
949
+ orderSide = 'bid';
950
+ } else if (side === 'sell') {
951
+ orderSide = 'ask';
952
+ } else {
953
+ throw new InvalidOrder (this.id + ' createOrder() allows buy or sell side only!');
954
+ }
955
+ await this.loadMarkets ();
956
+ const market = this.market (symbol);
957
+ const request = {
958
+ 'market': market['id'],
959
+ 'side': orderSide,
960
+ };
961
+ if (type === 'limit') {
962
+ request['volume'] = this.amountToPrecision (symbol, amount);
963
+ request['price'] = this.priceToPrecision (symbol, price);
964
+ request['ord_type'] = type;
965
+ } else if (type === 'market') {
966
+ if (side === 'buy') {
967
+ request['ord_type'] = 'price';
968
+ request['price'] = this.priceToPrecision (symbol, amount);
969
+ } else if (side === 'sell') {
970
+ request['ord_type'] = type;
971
+ request['volume'] = this.amountToPrecision (symbol, amount);
972
+ }
973
+ }
974
+ const clientOrderId = this.safeString2 (params, 'clientOrderId', 'identifier');
975
+ if (clientOrderId !== undefined) {
976
+ request['identifier'] = clientOrderId;
977
+ }
978
+ params = this.omit (params, [ 'clientOrderId', 'identifier' ]);
979
+ const response = await this.privatePostOrders (this.extend (request, params));
980
+ //
981
+ // {
982
+ // 'uuid': 'cdd92199-2897-4e14-9448-f923320408ad',
983
+ // 'side': 'bid',
984
+ // 'ord_type': 'limit',
985
+ // 'price': '100.0',
986
+ // 'avg_price': '0.0',
987
+ // 'state': 'wait',
988
+ // 'market': 'KRW-BTC',
989
+ // 'created_at': '2018-04-10T15:42:23+09:00',
990
+ // 'volume': '0.01',
991
+ // 'remaining_volume': '0.01',
992
+ // 'reserved_fee': '0.0015',
993
+ // 'remaining_fee': '0.0015',
994
+ // 'paid_fee': '0.0',
995
+ // 'locked': '1.0015',
996
+ // 'executed_volume': '0.0',
997
+ // 'trades_count': 0
998
+ // }
999
+ //
1000
+ return this.parseOrder (response);
1001
+ }
1002
+
1003
+ async cancelOrder (id, symbol = undefined, params = {}) {
1004
+ await this.loadMarkets ();
1005
+ const request = {
1006
+ 'uuid': id,
1007
+ };
1008
+ const response = await this.privateDeleteOrder (this.extend (request, params));
1009
+ //
1010
+ // {
1011
+ // "uuid": "cdd92199-2897-4e14-9448-f923320408ad",
1012
+ // "side": "bid",
1013
+ // "ord_type": "limit",
1014
+ // "price": "100.0",
1015
+ // "state": "wait",
1016
+ // "market": "KRW-BTC",
1017
+ // "created_at": "2018-04-10T15:42:23+09:00",
1018
+ // "volume": "0.01",
1019
+ // "remaining_volume": "0.01",
1020
+ // "reserved_fee": "0.0015",
1021
+ // "remaining_fee": "0.0015",
1022
+ // "paid_fee": "0.0",
1023
+ // "locked": "1.0015",
1024
+ // "executed_volume": "0.0",
1025
+ // "trades_count": 0
1026
+ // }
1027
+ //
1028
+ return this.parseOrder (response);
1029
+ }
1030
+
1031
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
1032
+ await this.loadMarkets ();
1033
+ const request = {
1034
+ // 'page': 1,
1035
+ // 'order_by': 'asc', // 'desc'
1036
+ };
1037
+ let currency = undefined;
1038
+ if (code !== undefined) {
1039
+ currency = this.currency (code);
1040
+ request['currency'] = currency['id'];
1041
+ }
1042
+ if (limit !== undefined) {
1043
+ request['limit'] = limit; // default is 100
1044
+ }
1045
+ const response = await this.privateGetDeposits (this.extend (request, params));
1046
+ //
1047
+ // [
1048
+ // {
1049
+ // "type": "deposit",
1050
+ // "uuid": "94332e99-3a87-4a35-ad98-28b0c969f830",
1051
+ // "currency": "KRW",
1052
+ // "txid": "9e37c537-6849-4c8b-a134-57313f5dfc5a",
1053
+ // "state": "ACCEPTED",
1054
+ // "created_at": "2017-12-08T15:38:02+09:00",
1055
+ // "done_at": "2017-12-08T15:38:02+09:00",
1056
+ // "amount": "100000.0",
1057
+ // "fee": "0.0"
1058
+ // },
1059
+ // ...,
1060
+ // ]
1061
+ //
1062
+ return this.parseTransactions (response, currency, since, limit);
1063
+ }
1064
+
1065
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
1066
+ await this.loadMarkets ();
1067
+ const request = {
1068
+ // 'state': 'submitting', // 'submitted', 'almost_accepted', 'rejected', 'accepted', 'processing', 'done', 'canceled'
1069
+ };
1070
+ let currency = undefined;
1071
+ if (code !== undefined) {
1072
+ currency = this.currency (code);
1073
+ request['currency'] = currency['id'];
1074
+ }
1075
+ if (limit !== undefined) {
1076
+ request['limit'] = limit; // default is 100
1077
+ }
1078
+ const response = await this.privateGetWithdraws (this.extend (request, params));
1079
+ //
1080
+ // [
1081
+ // {
1082
+ // "type": "withdraw",
1083
+ // "uuid": "9f432943-54e0-40b7-825f-b6fec8b42b79",
1084
+ // "currency": "BTC",
1085
+ // "txid": null,
1086
+ // "state": "processing",
1087
+ // "created_at": "2018-04-13T11:24:01+09:00",
1088
+ // "done_at": null,
1089
+ // "amount": "0.01",
1090
+ // "fee": "0.0",
1091
+ // "krw_amount": "80420.0"
1092
+ // },
1093
+ // ...,
1094
+ // ]
1095
+ //
1096
+ return this.parseTransactions (response, currency, since, limit);
1097
+ }
1098
+
1099
+ parseTransactionStatus (status) {
1100
+ const statuses = {
1101
+ 'submitting': 'pending', // 처리 중
1102
+ 'submitted': 'pending', // 처리 완료
1103
+ 'almost_accepted': 'pending', // 출금대기중
1104
+ 'rejected': 'failed', // 거부
1105
+ 'accepted': 'pending', // 승인됨
1106
+ 'processing': 'pending', // 처리 중
1107
+ 'done': 'ok', // 완료
1108
+ 'canceled': 'canceled', // 취소됨
1109
+ };
1110
+ return this.safeString (statuses, status, status);
1111
+ }
1112
+
1113
+ parseTransaction (transaction, currency = undefined) {
1114
+ //
1115
+ // fetchDeposits
1116
+ //
1117
+ // {
1118
+ // "type": "deposit",
1119
+ // "uuid": "94332e99-3a87-4a35-ad98-28b0c969f830",
1120
+ // "currency": "KRW",
1121
+ // "txid": "9e37c537-6849-4c8b-a134-57313f5dfc5a",
1122
+ // "state": "ACCEPTED",
1123
+ // "created_at": "2017-12-08T15:38:02+09:00",
1124
+ // "done_at": "2017-12-08T15:38:02+09:00",
1125
+ // "amount": "100000.0",
1126
+ // "fee": "0.0"
1127
+ // }
1128
+ //
1129
+ // fetchWithdrawals
1130
+ //
1131
+ // {
1132
+ // "type": "withdraw",
1133
+ // "uuid": "9f432943-54e0-40b7-825f-b6fec8b42b79",
1134
+ // "currency": "BTC",
1135
+ // "txid": "cd81e9b45df8da29f936836e58c907a106057e454a45767a7b06fcb19b966bba",
1136
+ // "state": "processing",
1137
+ // "created_at": "2018-04-13T11:24:01+09:00",
1138
+ // "done_at": null,
1139
+ // "amount": "0.01",
1140
+ // "fee": "0.0",
1141
+ // "krw_amount": "80420.0"
1142
+ // }
1143
+ //
1144
+ const id = this.safeString (transaction, 'uuid');
1145
+ const amount = this.safeNumber (transaction, 'amount');
1146
+ const address = undefined; // not present in the data structure received from the exchange
1147
+ const tag = undefined; // not present in the data structure received from the exchange
1148
+ const txid = this.safeString (transaction, 'txid');
1149
+ const updated = this.parse8601 (this.safeString (transaction, 'done_at'));
1150
+ const timestamp = this.parse8601 (this.safeString (transaction, 'created_at', updated));
1151
+ let type = this.safeString (transaction, 'type');
1152
+ if (type === 'withdraw') {
1153
+ type = 'withdrawal';
1154
+ }
1155
+ const currencyId = this.safeString (transaction, 'currency');
1156
+ const code = this.safeCurrencyCode (currencyId);
1157
+ const status = this.parseTransactionStatus (this.safeStringLower (transaction, 'state'));
1158
+ const feeCost = this.safeNumber (transaction, 'fee');
1159
+ return {
1160
+ 'info': transaction,
1161
+ 'id': id,
1162
+ 'currency': code,
1163
+ 'amount': amount,
1164
+ 'network': undefined,
1165
+ 'address': address,
1166
+ 'addressTo': undefined,
1167
+ 'addressFrom': undefined,
1168
+ 'tag': tag,
1169
+ 'tagTo': undefined,
1170
+ 'tagFrom': undefined,
1171
+ 'status': status,
1172
+ 'type': type,
1173
+ 'updated': updated,
1174
+ 'txid': txid,
1175
+ 'timestamp': timestamp,
1176
+ 'datetime': this.iso8601 (timestamp),
1177
+ 'fee': {
1178
+ 'currency': code,
1179
+ 'cost': feeCost,
1180
+ },
1181
+ };
1182
+ }
1183
+
1184
+ parseOrderStatus (status) {
1185
+ const statuses = {
1186
+ 'wait': 'open',
1187
+ 'done': 'closed',
1188
+ 'cancel': 'canceled',
1189
+ };
1190
+ return this.safeString (statuses, status, status);
1191
+ }
1192
+
1193
+ parseOrder (order, market = undefined) {
1194
+ //
1195
+ // {
1196
+ // "uuid": "a08f09b1-1718-42e2-9358-f0e5e083d3ee",
1197
+ // "side": "bid",
1198
+ // "ord_type": "limit",
1199
+ // "price": "17417000.0",
1200
+ // "state": "done",
1201
+ // "market": "KRW-BTC",
1202
+ // "created_at": "2018-04-05T14:09:14+09:00",
1203
+ // "volume": "1.0",
1204
+ // "remaining_volume": "0.0",
1205
+ // "reserved_fee": "26125.5",
1206
+ // "remaining_fee": "25974.0",
1207
+ // "paid_fee": "151.5",
1208
+ // "locked": "17341974.0",
1209
+ // "executed_volume": "1.0",
1210
+ // "trades_count": 2,
1211
+ // "trades": [
1212
+ // {
1213
+ // "market": "KRW-BTC",
1214
+ // "uuid": "78162304-1a4d-4524-b9e6-c9a9e14d76c3",
1215
+ // "price": "101000.0",
1216
+ // "volume": "0.77368323",
1217
+ // "funds": "78142.00623",
1218
+ // "ask_fee": "117.213009345",
1219
+ // "bid_fee": "117.213009345",
1220
+ // "created_at": "2018-04-05T14:09:15+09:00",
1221
+ // "side": "bid",
1222
+ // },
1223
+ // {
1224
+ // "market": "KRW-BTC",
1225
+ // "uuid": "f73da467-c42f-407d-92fa-e10d86450a20",
1226
+ // "price": "101000.0",
1227
+ // "volume": "0.22631677",
1228
+ // "funds": "22857.99377",
1229
+ // "ask_fee": "34.286990655", // missing in market orders
1230
+ // "bid_fee": "34.286990655", // missing in market orders
1231
+ // "created_at": "2018-04-05T14:09:15+09:00", // missing in market orders
1232
+ // "side": "bid",
1233
+ // },
1234
+ // ],
1235
+ // }
1236
+ //
1237
+ const id = this.safeString (order, 'uuid');
1238
+ let side = this.safeString (order, 'side');
1239
+ if (side === 'bid') {
1240
+ side = 'buy';
1241
+ } else {
1242
+ side = 'sell';
1243
+ }
1244
+ let type = this.safeString (order, 'ord_type');
1245
+ const timestamp = this.parse8601 (this.safeString (order, 'created_at'));
1246
+ const status = this.parseOrderStatus (this.safeString (order, 'state'));
1247
+ let lastTradeTimestamp = undefined;
1248
+ let price = this.safeNumber (order, 'price');
1249
+ const amount = this.safeNumber (order, 'volume');
1250
+ const remaining = this.safeNumber (order, 'remaining_volume');
1251
+ const filled = this.safeNumber (order, 'executed_volume');
1252
+ let cost = undefined;
1253
+ if (type === 'price') {
1254
+ type = 'market';
1255
+ cost = price;
1256
+ price = undefined;
1257
+ }
1258
+ let average = undefined;
1259
+ let fee = undefined;
1260
+ let feeCost = this.safeNumber (order, 'paid_fee');
1261
+ const marketId = this.safeString (order, 'market');
1262
+ market = this.safeMarket (marketId, market);
1263
+ let trades = this.safeValue (order, 'trades', []);
1264
+ trades = this.parseTrades (trades, market, undefined, undefined, {
1265
+ 'order': id,
1266
+ 'type': type,
1267
+ });
1268
+ const numTrades = trades.length;
1269
+ if (numTrades > 0) {
1270
+ // the timestamp in fetchOrder trades is missing
1271
+ lastTradeTimestamp = trades[numTrades - 1]['timestamp'];
1272
+ let getFeesFromTrades = false;
1273
+ if (feeCost === undefined) {
1274
+ getFeesFromTrades = true;
1275
+ feeCost = 0;
1276
+ }
1277
+ cost = 0;
1278
+ for (let i = 0; i < numTrades; i++) {
1279
+ const trade = trades[i];
1280
+ cost = this.sum (cost, trade['cost']);
1281
+ if (getFeesFromTrades) {
1282
+ const tradeFee = this.safeValue (trades[i], 'fee', {});
1283
+ const tradeFeeCost = this.safeNumber (tradeFee, 'cost');
1284
+ if (tradeFeeCost !== undefined) {
1285
+ feeCost = this.sum (feeCost, tradeFeeCost);
1286
+ }
1287
+ }
1288
+ }
1289
+ average = cost / filled;
1290
+ }
1291
+ if (feeCost !== undefined) {
1292
+ fee = {
1293
+ 'currency': market['quote'],
1294
+ 'cost': feeCost,
1295
+ };
1296
+ }
1297
+ const result = {
1298
+ 'info': order,
1299
+ 'id': id,
1300
+ 'clientOrderId': undefined,
1301
+ 'timestamp': timestamp,
1302
+ 'datetime': this.iso8601 (timestamp),
1303
+ 'lastTradeTimestamp': lastTradeTimestamp,
1304
+ 'symbol': market['symbol'],
1305
+ 'type': type,
1306
+ 'timeInForce': undefined,
1307
+ 'postOnly': undefined,
1308
+ 'side': side,
1309
+ 'price': price,
1310
+ 'stopPrice': undefined,
1311
+ 'cost': cost,
1312
+ 'average': average,
1313
+ 'amount': amount,
1314
+ 'filled': filled,
1315
+ 'remaining': remaining,
1316
+ 'status': status,
1317
+ 'fee': fee,
1318
+ 'trades': trades,
1319
+ };
1320
+ return result;
1321
+ }
1322
+
1323
+ async fetchOrdersByState (state, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1324
+ await this.loadMarkets ();
1325
+ const request = {
1326
+ // 'market': this.marketId (symbol),
1327
+ 'state': state,
1328
+ // 'page': 1,
1329
+ // 'order_by': 'asc',
1330
+ };
1331
+ let market = undefined;
1332
+ if (symbol !== undefined) {
1333
+ market = this.market (symbol);
1334
+ request['market'] = market['id'];
1335
+ }
1336
+ const response = await this.privateGetOrders (this.extend (request, params));
1337
+ //
1338
+ // [
1339
+ // {
1340
+ // "uuid": "a08f09b1-1718-42e2-9358-f0e5e083d3ee",
1341
+ // "side": "bid",
1342
+ // "ord_type": "limit",
1343
+ // "price": "17417000.0",
1344
+ // "state": "done",
1345
+ // "market": "KRW-BTC",
1346
+ // "created_at": "2018-04-05T14:09:14+09:00",
1347
+ // "volume": "1.0",
1348
+ // "remaining_volume": "0.0",
1349
+ // "reserved_fee": "26125.5",
1350
+ // "remaining_fee": "25974.0",
1351
+ // "paid_fee": "151.5",
1352
+ // "locked": "17341974.0",
1353
+ // "executed_volume": "1.0",
1354
+ // "trades_count":2
1355
+ // },
1356
+ // ]
1357
+ //
1358
+ return this.parseOrders (response, market, since, limit);
1359
+ }
1360
+
1361
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1362
+ return await this.fetchOrdersByState ('wait', symbol, since, limit, params);
1363
+ }
1364
+
1365
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1366
+ return await this.fetchOrdersByState ('done', symbol, since, limit, params);
1367
+ }
1368
+
1369
+ async fetchCanceledOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1370
+ return await this.fetchOrdersByState ('cancel', symbol, since, limit, params);
1371
+ }
1372
+
1373
+ async fetchOrder (id, symbol = undefined, params = {}) {
1374
+ await this.loadMarkets ();
1375
+ const request = {
1376
+ 'uuid': id,
1377
+ };
1378
+ const response = await this.privateGetOrder (this.extend (request, params));
1379
+ //
1380
+ // {
1381
+ // "uuid": "a08f09b1-1718-42e2-9358-f0e5e083d3ee",
1382
+ // "side": "bid",
1383
+ // "ord_type": "limit",
1384
+ // "price": "17417000.0",
1385
+ // "state": "done",
1386
+ // "market": "KRW-BTC",
1387
+ // "created_at": "2018-04-05T14:09:14+09:00",
1388
+ // "volume": "1.0",
1389
+ // "remaining_volume": "0.0",
1390
+ // "reserved_fee": "26125.5",
1391
+ // "remaining_fee": "25974.0",
1392
+ // "paid_fee": "151.5",
1393
+ // "locked": "17341974.0",
1394
+ // "executed_volume": "1.0",
1395
+ // "trades_count": 2,
1396
+ // "trades": [
1397
+ // {
1398
+ // "market": "KRW-BTC",
1399
+ // "uuid": "78162304-1a4d-4524-b9e6-c9a9e14d76c3",
1400
+ // "price": "101000.0",
1401
+ // "volume": "0.77368323",
1402
+ // "funds": "78142.00623",
1403
+ // "ask_fee": "117.213009345",
1404
+ // "bid_fee": "117.213009345",
1405
+ // "created_at": "2018-04-05T14:09:15+09:00",
1406
+ // "side": "bid"
1407
+ // },
1408
+ // {
1409
+ // "market": "KRW-BTC",
1410
+ // "uuid": "f73da467-c42f-407d-92fa-e10d86450a20",
1411
+ // "price": "101000.0",
1412
+ // "volume": "0.22631677",
1413
+ // "funds": "22857.99377",
1414
+ // "ask_fee": "34.286990655",
1415
+ // "bid_fee": "34.286990655",
1416
+ // "created_at": "2018-04-05T14:09:15+09:00",
1417
+ // "side": "bid"
1418
+ // }
1419
+ // ]
1420
+ // }
1421
+ //
1422
+ return this.parseOrder (response);
1423
+ }
1424
+
1425
+ async fetchDepositAddresses (codes = undefined, params = {}) {
1426
+ await this.loadMarkets ();
1427
+ const response = await this.privateGetDepositsCoinAddresses (params);
1428
+ //
1429
+ // [
1430
+ // {
1431
+ // "currency": "BTC",
1432
+ // "deposit_address": "3EusRwybuZUhVDeHL7gh3HSLmbhLcy7NqD",
1433
+ // "secondary_address": null
1434
+ // },
1435
+ // {
1436
+ // "currency": "ETH",
1437
+ // "deposit_address": "0x0d73e0a482b8cf568976d2e8688f4a899d29301c",
1438
+ // "secondary_address": null
1439
+ // },
1440
+ // {
1441
+ // "currency": "XRP",
1442
+ // "deposit_address": "rN9qNpgnBaZwqCg8CvUZRPqCcPPY7wfWep",
1443
+ // "secondary_address": "3057887915"
1444
+ // }
1445
+ // ]
1446
+ //
1447
+ return this.parseDepositAddresses (response);
1448
+ }
1449
+
1450
+ parseDepositAddress (depositAddress, currency = undefined) {
1451
+ //
1452
+ // {
1453
+ // "currency": "BTC",
1454
+ // "deposit_address": "3EusRwybuZUhVDeHL7gh3HSLmbhLcy7NqD",
1455
+ // "secondary_address": null
1456
+ // }
1457
+ //
1458
+ const address = this.safeString (depositAddress, 'deposit_address');
1459
+ const tag = this.safeString (depositAddress, 'secondary_address');
1460
+ const currencyId = this.safeString (depositAddress, 'currency');
1461
+ const code = this.safeCurrencyCode (currencyId);
1462
+ this.checkAddress (address);
1463
+ return {
1464
+ 'currency': code,
1465
+ 'address': address,
1466
+ 'tag': tag,
1467
+ 'network': undefined,
1468
+ 'info': depositAddress,
1469
+ };
1470
+ }
1471
+
1472
+ async fetchDepositAddress (code, params = {}) {
1473
+ await this.loadMarkets ();
1474
+ const currency = this.currency (code);
1475
+ const response = await this.privateGetDepositsCoinAddress (this.extend ({
1476
+ 'currency': currency['id'],
1477
+ }, params));
1478
+ //
1479
+ // {
1480
+ // "currency": "BTC",
1481
+ // "deposit_address": "3EusRwybuZUhVDeHL7gh3HSLmbhLcy7NqD",
1482
+ // "secondary_address": null
1483
+ // }
1484
+ //
1485
+ return this.parseDepositAddress (response);
1486
+ }
1487
+
1488
+ async createDepositAddress (code, params = {}) {
1489
+ await this.loadMarkets ();
1490
+ const currency = this.currency (code);
1491
+ const request = {
1492
+ 'currency': currency['id'],
1493
+ };
1494
+ // https://github.com/ccxt/ccxt/issues/6452
1495
+ const response = await this.privatePostDepositsGenerateCoinAddress (this.extend (request, params));
1496
+ //
1497
+ // https://docs.upbit.com/v1.0/reference#%EC%9E%85%EA%B8%88-%EC%A3%BC%EC%86%8C-%EC%83%9D%EC%84%B1-%EC%9A%94%EC%B2%AD
1498
+ // can be any of the two responses:
1499
+ //
1500
+ // {
1501
+ // "success" : true,
1502
+ // "message" : "Creating BTC deposit address."
1503
+ // }
1504
+ //
1505
+ // {
1506
+ // "currency": "BTC",
1507
+ // "deposit_address": "3EusRwybuZUhVDeHL7gh3HSLmbhLcy7NqD",
1508
+ // "secondary_address": null
1509
+ // }
1510
+ //
1511
+ const message = this.safeString (response, 'message');
1512
+ if (message !== undefined) {
1513
+ throw new AddressPending (this.id + ' is generating ' + code + ' deposit address, call fetchDepositAddress or createDepositAddress one more time later to retrieve the generated address');
1514
+ }
1515
+ return this.parseDepositAddress (response);
1516
+ }
1517
+
1518
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1519
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1520
+ this.checkAddress (address);
1521
+ await this.loadMarkets ();
1522
+ const currency = this.currency (code);
1523
+ const request = {
1524
+ 'amount': amount,
1525
+ };
1526
+ let method = 'privatePostWithdraws';
1527
+ if (code !== 'KRW') {
1528
+ method += 'Coin';
1529
+ request['currency'] = currency['id'];
1530
+ request['address'] = address;
1531
+ if (tag !== undefined) {
1532
+ request['secondary_address'] = tag;
1533
+ }
1534
+ } else {
1535
+ method += 'Krw';
1536
+ }
1537
+ const response = await this[method] (this.extend (request, params));
1538
+ //
1539
+ // {
1540
+ // "type": "withdraw",
1541
+ // "uuid": "9f432943-54e0-40b7-825f-b6fec8b42b79",
1542
+ // "currency": "BTC",
1543
+ // "txid": "ebe6937b-130e-4066-8ac6-4b0e67f28adc",
1544
+ // "state": "processing",
1545
+ // "created_at": "2018-04-13T11:24:01+09:00",
1546
+ // "done_at": null,
1547
+ // "amount": "0.01",
1548
+ // "fee": "0.0",
1549
+ // "krw_amount": "80420.0"
1550
+ // }
1551
+ //
1552
+ return this.parseTransaction (response);
1553
+ }
1554
+
1555
+ nonce () {
1556
+ return this.milliseconds ();
1557
+ }
1558
+
1559
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1560
+ let url = this.implodeParams (this.urls['api'][api], {
1561
+ 'hostname': this.hostname,
1562
+ });
1563
+ url += '/' + this.version + '/' + this.implodeParams (path, params);
1564
+ const query = this.omit (params, this.extractParams (path));
1565
+ if (method !== 'POST') {
1566
+ if (Object.keys (query).length) {
1567
+ url += '?' + this.urlencode (query);
1568
+ }
1569
+ }
1570
+ if (api === 'private') {
1571
+ this.checkRequiredCredentials ();
1572
+ const nonce = this.nonce ();
1573
+ const request = {
1574
+ 'access_key': this.apiKey,
1575
+ 'nonce': nonce,
1576
+ };
1577
+ if (Object.keys (query).length) {
1578
+ const auth = this.urlencode (query);
1579
+ const hash = this.hash (this.encode (auth), 'sha512');
1580
+ request['query_hash'] = hash;
1581
+ request['query_hash_alg'] = 'SHA512';
1582
+ }
1583
+ const jwt = this.jwt (request, this.encode (this.secret));
1584
+ headers = {
1585
+ 'Authorization': 'Bearer ' + jwt,
1586
+ };
1587
+ if ((method !== 'GET') && (method !== 'DELETE')) {
1588
+ body = this.json (params);
1589
+ headers['Content-Type'] = 'application/json';
1590
+ }
1591
+ }
1592
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1593
+ }
1594
+
1595
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1596
+ if (response === undefined) {
1597
+ return; // fallback to default error handler
1598
+ }
1599
+ //
1600
+ // { 'error': { 'message': "Missing request parameter error. Check the required parameters!", 'name': 400 } },
1601
+ // { 'error': { 'message': "side is missing, side does not have a valid value", 'name': "validation_error" } },
1602
+ // { 'error': { 'message': "개인정보 제 3자 제공 동의가 필요합니다.", 'name': "thirdparty_agreement_required" } },
1603
+ // { 'error': { 'message': "권한이 부족합니다.", 'name': "out_of_scope" } },
1604
+ // { 'error': { 'message': "주문을 찾지 못했습니다.", 'name': "order_not_found" } },
1605
+ // { 'error': { 'message': "주문가능한 금액(ETH)이 부족합니다.", 'name': "insufficient_funds_ask" } },
1606
+ // { 'error': { 'message': "주문가능한 금액(BTC)이 부족합니다.", 'name': "insufficient_funds_bid" } },
1607
+ // { 'error': { 'message': "잘못된 엑세스 키입니다.", 'name': "invalid_access_key" } },
1608
+ // { 'error': { 'message': "Jwt 토큰 검증에 실패했습니다.", 'name': "jwt_verification" } }
1609
+ //
1610
+ const error = this.safeValue (response, 'error');
1611
+ if (error !== undefined) {
1612
+ const message = this.safeString (error, 'message');
1613
+ const name = this.safeString (error, 'name');
1614
+ const feedback = this.id + ' ' + body;
1615
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
1616
+ this.throwExactlyMatchedException (this.exceptions['exact'], name, feedback);
1617
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
1618
+ this.throwBroadlyMatchedException (this.exceptions['broad'], name, feedback);
1619
+ throw new ExchangeError (feedback); // unknown message
1620
+ }
1621
+ }
1622
+ };