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/bitpanda.js ADDED
@@ -0,0 +1,1782 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { AuthenticationError, ExchangeError, PermissionDenied, BadRequest, ArgumentsRequired, OrderNotFound, InsufficientFunds, ExchangeNotAvailable, DDoSProtection, InvalidAddress, InvalidOrder } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class bitpanda extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'bitpanda',
15
+ 'name': 'Bitpanda Pro',
16
+ 'countries': [ 'AT' ], // Austria
17
+ 'rateLimit': 300,
18
+ 'version': 'v1',
19
+ // new metainfo interface
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
+ 'cancelOrders': true,
31
+ 'createDepositAddress': true,
32
+ 'createOrder': true,
33
+ 'createReduceOnlyOrder': false,
34
+ 'fetchBalance': true,
35
+ 'fetchBorrowRate': false,
36
+ 'fetchBorrowRateHistories': false,
37
+ 'fetchBorrowRateHistory': false,
38
+ 'fetchBorrowRates': false,
39
+ 'fetchBorrowRatesPerSymbol': false,
40
+ 'fetchClosedOrders': true,
41
+ 'fetchCurrencies': true,
42
+ 'fetchDepositAddress': true,
43
+ 'fetchDeposits': true,
44
+ 'fetchFundingHistory': false,
45
+ 'fetchFundingRate': false,
46
+ 'fetchFundingRateHistory': false,
47
+ 'fetchFundingRates': false,
48
+ 'fetchIndexOHLCV': false,
49
+ 'fetchLeverage': false,
50
+ 'fetchMarkets': true,
51
+ 'fetchMarkOHLCV': false,
52
+ 'fetchMyTrades': true,
53
+ 'fetchOHLCV': true,
54
+ 'fetchOpenOrders': true,
55
+ 'fetchOrder': true,
56
+ 'fetchOrderBook': true,
57
+ 'fetchOrderTrades': true,
58
+ 'fetchPosition': false,
59
+ 'fetchPositions': false,
60
+ 'fetchPositionsRisk': false,
61
+ 'fetchPremiumIndexOHLCV': false,
62
+ 'fetchTicker': true,
63
+ 'fetchTickers': true,
64
+ 'fetchTime': true,
65
+ 'fetchTrades': true,
66
+ 'fetchTradingFee': false,
67
+ 'fetchTradingFees': true,
68
+ 'fetchTransfer': false,
69
+ 'fetchTransfers': false,
70
+ 'fetchWithdrawals': true,
71
+ 'privateAPI': true,
72
+ 'publicAPI': true,
73
+ 'reduceMargin': false,
74
+ 'setLeverage': false,
75
+ 'setMarginMode': false,
76
+ 'setPositionMode': false,
77
+ 'transfer': false,
78
+ 'withdraw': true,
79
+ },
80
+ 'timeframes': {
81
+ '1m': '1/MINUTES',
82
+ '5m': '5/MINUTES',
83
+ '15m': '15/MINUTES',
84
+ '30m': '30/MINUTES',
85
+ '1h': '1/HOURS',
86
+ '4h': '4/HOURS',
87
+ '1d': '1/DAYS',
88
+ '1w': '1/WEEKS',
89
+ '1M': '1/MONTHS',
90
+ },
91
+ 'urls': {
92
+ 'logo': 'https://user-images.githubusercontent.com/51840849/87591171-9a377d80-c6f0-11ea-94ac-97a126eac3bc.jpg',
93
+ 'api': {
94
+ 'public': 'https://api.exchange.bitpanda.com/public',
95
+ 'private': 'https://api.exchange.bitpanda.com/public',
96
+ },
97
+ 'www': 'https://www.bitpanda.com/en/pro',
98
+ 'doc': [
99
+ 'https://developers.bitpanda.com/exchange/',
100
+ ],
101
+ 'fees': 'https://www.bitpanda.com/en/pro/fees',
102
+ },
103
+ 'api': {
104
+ 'public': {
105
+ 'get': [
106
+ 'currencies',
107
+ 'candlesticks/{instrument_code}',
108
+ 'fees',
109
+ 'instruments',
110
+ 'order-book/{instrument_code}',
111
+ 'market-ticker',
112
+ 'market-ticker/{instrument_code}',
113
+ 'price-ticks/{instrument_code}',
114
+ 'time',
115
+ ],
116
+ },
117
+ 'private': {
118
+ 'get': [
119
+ 'account/balances',
120
+ 'account/deposit/crypto/{currency_code}',
121
+ 'account/deposit/fiat/EUR',
122
+ 'account/deposits',
123
+ 'account/deposits/bitpanda',
124
+ 'account/withdrawals',
125
+ 'account/withdrawals/bitpanda',
126
+ 'account/fees',
127
+ 'account/orders',
128
+ 'account/orders/{order_id}',
129
+ 'account/orders/{order_id}/trades',
130
+ 'account/trades',
131
+ 'account/trades/{trade_id}',
132
+ 'account/trading-volume',
133
+ ],
134
+ 'post': [
135
+ 'account/deposit/crypto',
136
+ 'account/withdraw/crypto',
137
+ 'account/withdraw/fiat',
138
+ 'account/fees',
139
+ 'account/orders',
140
+ ],
141
+ 'delete': [
142
+ 'account/orders',
143
+ 'account/orders/{order_id}',
144
+ 'account/orders/client/{client_id}',
145
+ ],
146
+ },
147
+ },
148
+ 'fees': {
149
+ 'trading': {
150
+ 'tierBased': true,
151
+ 'percentage': true,
152
+ 'taker': this.parseNumber ('0.0015'),
153
+ 'maker': this.parseNumber ('0.001'),
154
+ 'tiers': [
155
+ // volume in BTC
156
+ {
157
+ 'taker': [
158
+ [ this.parseNumber ('0'), this.parseNumber ('0.0015') ],
159
+ [ this.parseNumber ('100'), this.parseNumber ('0.0013') ],
160
+ [ this.parseNumber ('250'), this.parseNumber ('0.0013') ],
161
+ [ this.parseNumber ('1000'), this.parseNumber ('0.001') ],
162
+ [ this.parseNumber ('5000'), this.parseNumber ('0.0009') ],
163
+ [ this.parseNumber ('10000'), this.parseNumber ('0.00075') ],
164
+ [ this.parseNumber ('20000'), this.parseNumber ('0.00065') ],
165
+ ],
166
+ 'maker': [
167
+ [ this.parseNumber ('0'), this.parseNumber ('0.001') ],
168
+ [ this.parseNumber ('100'), this.parseNumber ('0.001') ],
169
+ [ this.parseNumber ('250'), this.parseNumber ('0.0009') ],
170
+ [ this.parseNumber ('1000'), this.parseNumber ('0.00075') ],
171
+ [ this.parseNumber ('5000'), this.parseNumber ('0.0006') ],
172
+ [ this.parseNumber ('10000'), this.parseNumber ('0.0005') ],
173
+ [ this.parseNumber ('20000'), this.parseNumber ('0.0005') ],
174
+ ],
175
+ },
176
+ ],
177
+ },
178
+ },
179
+ 'requiredCredentials': {
180
+ 'apiKey': true,
181
+ 'secret': false,
182
+ },
183
+ 'exceptions': {
184
+ 'exact': {
185
+ 'INVALID_CLIENT_UUID': InvalidOrder,
186
+ 'ORDER_NOT_FOUND': OrderNotFound,
187
+ 'ONLY_ONE_ERC20_ADDRESS_ALLOWED': InvalidAddress,
188
+ 'DEPOSIT_ADDRESS_NOT_USED': InvalidAddress,
189
+ 'INVALID_CREDENTIALS': AuthenticationError,
190
+ 'MISSING_CREDENTIALS': AuthenticationError,
191
+ 'INVALID_APIKEY': AuthenticationError,
192
+ 'INVALID_SCOPES': AuthenticationError,
193
+ 'INVALID_SUBJECT': AuthenticationError,
194
+ 'INVALID_ISSUER': AuthenticationError,
195
+ 'INVALID_AUDIENCE': AuthenticationError,
196
+ 'INVALID_DEVICE_ID': AuthenticationError,
197
+ 'INVALID_IP_RESTRICTION': AuthenticationError,
198
+ 'APIKEY_REVOKED': AuthenticationError,
199
+ 'APIKEY_EXPIRED': AuthenticationError,
200
+ 'SYNCHRONIZER_TOKEN_MISMATCH': AuthenticationError,
201
+ 'SESSION_EXPIRED': AuthenticationError,
202
+ 'INTERNAL_ERROR': AuthenticationError,
203
+ 'CLIENT_IP_BLOCKED': PermissionDenied,
204
+ 'MISSING_PERMISSION': PermissionDenied,
205
+ 'ILLEGAL_CHARS': BadRequest,
206
+ 'UNSUPPORTED_MEDIA_TYPE': BadRequest,
207
+ 'ACCOUNT_HISTORY_TIME_RANGE_TOO_BIG': BadRequest,
208
+ 'CANDLESTICKS_TIME_RANGE_TOO_BIG': BadRequest,
209
+ 'INVALID_INSTRUMENT_CODE': BadRequest,
210
+ 'INVALID_ORDER_TYPE': BadRequest,
211
+ 'INVALID_UNIT': BadRequest,
212
+ 'INVALID_PERIOD': BadRequest,
213
+ 'INVALID_TIME': BadRequest,
214
+ 'INVALID_DATE': BadRequest,
215
+ 'INVALID_CURRENCY': BadRequest,
216
+ 'INVALID_AMOUNT': BadRequest,
217
+ 'INVALID_PRICE': BadRequest,
218
+ 'INVALID_LIMIT': BadRequest,
219
+ 'INVALID_QUERY': BadRequest,
220
+ 'INVALID_CURSOR': BadRequest,
221
+ 'INVALID_ACCOUNT_ID': BadRequest,
222
+ 'INVALID_SIDE': InvalidOrder,
223
+ 'INVALID_ACCOUNT_HISTORY_FROM_TIME': BadRequest,
224
+ 'INVALID_ACCOUNT_HISTORY_MAX_PAGE_SIZE': BadRequest,
225
+ 'INVALID_ACCOUNT_HISTORY_TIME_PERIOD': BadRequest,
226
+ 'INVALID_ACCOUNT_HISTORY_TO_TIME': BadRequest,
227
+ 'INVALID_CANDLESTICKS_GRANULARITY': BadRequest,
228
+ 'INVALID_CANDLESTICKS_UNIT': BadRequest,
229
+ 'INVALID_ORDER_BOOK_DEPTH': BadRequest,
230
+ 'INVALID_ORDER_BOOK_LEVEL': BadRequest,
231
+ 'INVALID_PAGE_CURSOR': BadRequest,
232
+ 'INVALID_TIME_RANGE': BadRequest,
233
+ 'INVALID_TRADE_ID': BadRequest,
234
+ 'INVALID_UI_ACCOUNT_SETTINGS': BadRequest,
235
+ 'NEGATIVE_AMOUNT': InvalidOrder,
236
+ 'NEGATIVE_PRICE': InvalidOrder,
237
+ 'MIN_SIZE_NOT_SATISFIED': InvalidOrder,
238
+ 'BAD_AMOUNT_PRECISION': InvalidOrder,
239
+ 'BAD_PRICE_PRECISION': InvalidOrder,
240
+ 'BAD_TRIGGER_PRICE_PRECISION': InvalidOrder,
241
+ 'MAX_OPEN_ORDERS_EXCEEDED': BadRequest,
242
+ 'MISSING_PRICE': InvalidOrder,
243
+ 'MISSING_ORDER_TYPE': InvalidOrder,
244
+ 'MISSING_SIDE': InvalidOrder,
245
+ 'MISSING_CANDLESTICKS_PERIOD_PARAM': ArgumentsRequired,
246
+ 'MISSING_CANDLESTICKS_UNIT_PARAM': ArgumentsRequired,
247
+ 'MISSING_FROM_PARAM': ArgumentsRequired,
248
+ 'MISSING_INSTRUMENT_CODE': ArgumentsRequired,
249
+ 'MISSING_ORDER_ID': InvalidOrder,
250
+ 'MISSING_TO_PARAM': ArgumentsRequired,
251
+ 'MISSING_TRADE_ID': ArgumentsRequired,
252
+ 'INVALID_ORDER_ID': OrderNotFound,
253
+ 'NOT_FOUND': OrderNotFound,
254
+ 'INSUFFICIENT_LIQUIDITY': InsufficientFunds,
255
+ 'INSUFFICIENT_FUNDS': InsufficientFunds,
256
+ 'NO_TRADING': ExchangeNotAvailable,
257
+ 'SERVICE_UNAVAILABLE': ExchangeNotAvailable,
258
+ 'GATEWAY_TIMEOUT': ExchangeNotAvailable,
259
+ 'RATELIMIT': DDoSProtection,
260
+ 'CF_RATELIMIT': DDoSProtection,
261
+ 'INTERNAL_SERVER_ERROR': ExchangeError,
262
+ },
263
+ 'broad': {
264
+ },
265
+ },
266
+ 'commonCurrencies': {
267
+ 'MIOTA': 'IOTA', // https://github.com/ccxt/ccxt/issues/7487
268
+ },
269
+ // exchange-specific options
270
+ 'options': {
271
+ 'fetchTradingFees': {
272
+ 'method': 'fetchPrivateTradingFees', // or 'fetchPublicTradingFees'
273
+ },
274
+ 'fiat': [ 'EUR', 'CHF' ],
275
+ },
276
+ });
277
+ }
278
+
279
+ async fetchTime (params = {}) {
280
+ const response = await this.publicGetTime (params);
281
+ //
282
+ // {
283
+ // iso: '2020-07-10T05:17:26.716Z',
284
+ // epoch_millis: 1594358246716,
285
+ // }
286
+ //
287
+ return this.safeInteger (response, 'epoch_millis');
288
+ }
289
+
290
+ async fetchCurrencies (params = {}) {
291
+ const response = await this.publicGetCurrencies (params);
292
+ //
293
+ // [
294
+ // {
295
+ // "code":"BEST",
296
+ // "precision":8
297
+ // }
298
+ // ]
299
+ //
300
+ const result = {};
301
+ for (let i = 0; i < response.length; i++) {
302
+ const currency = response[i];
303
+ const id = this.safeString (currency, 'code');
304
+ const code = this.safeCurrencyCode (id);
305
+ result[code] = {
306
+ 'id': id,
307
+ 'code': code,
308
+ 'name': undefined,
309
+ 'info': currency, // the original payload
310
+ 'active': undefined,
311
+ 'fee': undefined,
312
+ 'precision': this.safeInteger (currency, 'precision'),
313
+ 'limits': {
314
+ 'amount': { 'min': undefined, 'max': undefined },
315
+ 'withdraw': { 'min': undefined, 'max': undefined },
316
+ },
317
+ };
318
+ }
319
+ return result;
320
+ }
321
+
322
+ async fetchMarkets (params = {}) {
323
+ const response = await this.publicGetInstruments (params);
324
+ //
325
+ // [
326
+ // {
327
+ // state: 'ACTIVE',
328
+ // base: { code: 'ETH', precision: 8 },
329
+ // quote: { code: 'CHF', precision: 2 },
330
+ // amount_precision: 4,
331
+ // market_precision: 2,
332
+ // min_size: '10.0'
333
+ // }
334
+ // ]
335
+ //
336
+ const result = [];
337
+ for (let i = 0; i < response.length; i++) {
338
+ const market = response[i];
339
+ const baseAsset = this.safeValue (market, 'base', {});
340
+ const quoteAsset = this.safeValue (market, 'quote', {});
341
+ const baseId = this.safeString (baseAsset, 'code');
342
+ const quoteId = this.safeString (quoteAsset, 'code');
343
+ const id = baseId + '_' + quoteId;
344
+ const base = this.safeCurrencyCode (baseId);
345
+ const quote = this.safeCurrencyCode (quoteId);
346
+ const state = this.safeString (market, 'state');
347
+ result.push ({
348
+ 'id': id,
349
+ 'symbol': base + '/' + quote,
350
+ 'base': base,
351
+ 'quote': quote,
352
+ 'settle': undefined,
353
+ 'baseId': baseId,
354
+ 'quoteId': quoteId,
355
+ 'settleId': undefined,
356
+ 'type': 'spot',
357
+ 'spot': true,
358
+ 'margin': false,
359
+ 'swap': false,
360
+ 'future': false,
361
+ 'option': false,
362
+ 'active': (state === 'ACTIVE'),
363
+ 'contract': false,
364
+ 'linear': undefined,
365
+ 'inverse': undefined,
366
+ 'contractSize': undefined,
367
+ 'expiry': undefined,
368
+ 'expiryDatetime': undefined,
369
+ 'strike': undefined,
370
+ 'optionType': undefined,
371
+ 'precision': {
372
+ 'amount': this.safeInteger (market, 'amount_precision'),
373
+ 'price': this.safeInteger (market, 'market_precision'),
374
+ },
375
+ 'limits': {
376
+ 'leverage': {
377
+ 'min': undefined,
378
+ 'max': undefined,
379
+ },
380
+ 'amount': {
381
+ 'min': undefined,
382
+ 'max': undefined,
383
+ },
384
+ 'price': {
385
+ 'min': undefined,
386
+ 'max': undefined,
387
+ },
388
+ 'cost': {
389
+ 'min': this.safeNumber (market, 'min_size'),
390
+ 'max': undefined,
391
+ },
392
+ },
393
+ 'info': market,
394
+ });
395
+ }
396
+ return result;
397
+ }
398
+
399
+ async fetchTradingFees (params = {}) {
400
+ let method = this.safeString (params, 'method');
401
+ params = this.omit (params, 'method');
402
+ if (method === undefined) {
403
+ const options = this.safeValue (this.options, 'fetchTradingFees', {});
404
+ method = this.safeString (options, 'method', 'fetchPrivateTradingFees');
405
+ }
406
+ return await this[method] (params);
407
+ }
408
+
409
+ async fetchPublicTradingFees (params = {}) {
410
+ await this.loadMarkets ();
411
+ const response = await this.publicGetFees (params);
412
+ //
413
+ // [
414
+ // {
415
+ // "fee_group_id":"default",
416
+ // "display_text":"The standard fee plan.",
417
+ // "fee_tiers":[
418
+ // {"volume":"0.0","fee_group_id":"default","maker_fee":"0.1","taker_fee":"0.15"},
419
+ // {"volume":"100.0","fee_group_id":"default","maker_fee":"0.1","taker_fee":"0.13"},
420
+ // {"volume":"250.0","fee_group_id":"default","maker_fee":"0.09","taker_fee":"0.13"},
421
+ // {"volume":"1000.0","fee_group_id":"default","maker_fee":"0.075","taker_fee":"0.1"},
422
+ // {"volume":"5000.0","fee_group_id":"default","maker_fee":"0.06","taker_fee":"0.09"},
423
+ // {"volume":"10000.0","fee_group_id":"default","maker_fee":"0.05","taker_fee":"0.075"},
424
+ // {"volume":"20000.0","fee_group_id":"default","maker_fee":"0.05","taker_fee":"0.065"}
425
+ // ],
426
+ // "fee_discount_rate":"25.0",
427
+ // "minimum_price_value":"0.12"
428
+ // }
429
+ // ]
430
+ //
431
+ const first = this.safeValue (response, 0, {});
432
+ const feeTiers = this.safeValue (first, 'fee_tiers');
433
+ const tiers = this.parseFeeTiers (feeTiers);
434
+ const firstTier = this.safeValue (feeTiers, 0, {});
435
+ const result = {};
436
+ for (let i = 0; i < this.symbols.length; i++) {
437
+ const symbol = this.symbols[i];
438
+ result[symbol] = {
439
+ 'info': first,
440
+ 'symbol': symbol,
441
+ 'maker': this.safeNumber (firstTier, 'maker_fee'),
442
+ 'taker': this.safeNumber (firstTier, 'taker_fee'),
443
+ 'percentage': true,
444
+ 'tierBased': true,
445
+ 'tiers': tiers,
446
+ };
447
+ }
448
+ return result;
449
+ }
450
+
451
+ async fetchPrivateTradingFees (params = {}) {
452
+ await this.loadMarkets ();
453
+ const response = await this.privateGetAccountFees (params);
454
+ //
455
+ // {
456
+ // "account_id": "ed524d00-820a-11e9-8f1e-69602df16d85",
457
+ // "running_trading_volume": "0.0",
458
+ // "fee_group_id": "default",
459
+ // "collect_fees_in_best": false,
460
+ // "fee_discount_rate": "25.0",
461
+ // "minimum_price_value": "0.12",
462
+ // "fee_tiers": [
463
+ // { "volume": "0.0", "fee_group_id": "default", "maker_fee": "0.1", "taker_fee": "0.1" },
464
+ // { "volume": "100.0", "fee_group_id": "default", "maker_fee": "0.09", "taker_fee": "0.1" },
465
+ // { "volume": "250.0", "fee_group_id": "default", "maker_fee": "0.08", "taker_fee": "0.1" },
466
+ // { "volume": "1000.0", "fee_group_id": "default", "maker_fee": "0.07", "taker_fee": "0.09" },
467
+ // { "volume": "5000.0", "fee_group_id": "default", "maker_fee": "0.06", "taker_fee": "0.08" },
468
+ // { "volume": "10000.0", "fee_group_id": "default", "maker_fee": "0.05", "taker_fee": "0.07" },
469
+ // { "volume": "20000.0", "fee_group_id": "default", "maker_fee": "0.05", "taker_fee": "0.06" },
470
+ // { "volume": "50000.0", "fee_group_id": "default", "maker_fee": "0.05", "taker_fee": "0.05" }
471
+ // ],
472
+ // "active_fee_tier": { "volume": "0.0", "fee_group_id": "default", "maker_fee": "0.1", "taker_fee": "0.1" }
473
+ // }
474
+ //
475
+ const activeFeeTier = this.safeValue (response, 'active_fee_tier', {});
476
+ let makerFee = this.safeString (activeFeeTier, 'maker_fee');
477
+ let takerFee = this.safeString (activeFeeTier, 'taker_fee');
478
+ makerFee = Precise.stringDiv (makerFee, '100');
479
+ takerFee = Precise.stringDiv (takerFee, '100');
480
+ const feeTiers = this.safeValue (response, 'fee_tiers');
481
+ const result = {};
482
+ const tiers = this.parseFeeTiers (feeTiers);
483
+ for (let i = 0; i < this.symbols.length; i++) {
484
+ const symbol = this.symbols[i];
485
+ result[symbol] = {
486
+ 'info': response,
487
+ 'symbol': symbol,
488
+ 'maker': this.parseNumber (makerFee),
489
+ 'taker': this.parseNumber (takerFee),
490
+ 'percentage': true,
491
+ 'tierBased': true,
492
+ 'tiers': tiers,
493
+ };
494
+ }
495
+ return result;
496
+ }
497
+
498
+ parseFeeTiers (feeTiers, market = undefined) {
499
+ const takerFees = [];
500
+ const makerFees = [];
501
+ for (let i = 0; i < feeTiers.length; i++) {
502
+ const tier = feeTiers[i];
503
+ const volume = this.safeNumber (tier, 'volume');
504
+ let taker = this.safeString (tier, 'taker_fee');
505
+ let maker = this.safeString (tier, 'maker_fee');
506
+ maker = Precise.stringDiv (maker, '100');
507
+ taker = Precise.stringDiv (taker, '100');
508
+ makerFees.push ([ volume, this.parseNumber (maker) ]);
509
+ takerFees.push ([ volume, this.parseNumber (taker) ]);
510
+ }
511
+ return {
512
+ 'maker': makerFees,
513
+ 'taker': takerFees,
514
+ };
515
+ }
516
+
517
+ parseTicker (ticker, market = undefined) {
518
+ //
519
+ // fetchTicker, fetchTickers
520
+ //
521
+ // {
522
+ // "instrument_code":"BTC_EUR",
523
+ // "sequence":602562,
524
+ // "time":"2020-07-10T06:27:34.951Z",
525
+ // "state":"ACTIVE",
526
+ // "is_frozen":0,
527
+ // "quote_volume":"1695555.1783768",
528
+ // "base_volume":"205.67436",
529
+ // "last_price":"8143.91",
530
+ // "best_bid":"8143.71",
531
+ // "best_ask":"8156.9",
532
+ // "price_change":"-147.47",
533
+ // "price_change_percentage":"-1.78",
534
+ // "high":"8337.45",
535
+ // "low":"8110.0"
536
+ // }
537
+ //
538
+ const timestamp = this.parse8601 (this.safeString (ticker, 'time'));
539
+ const marketId = this.safeString (ticker, 'instrument_code');
540
+ const symbol = this.safeSymbol (marketId, market, '_');
541
+ const last = this.safeString (ticker, 'last_price');
542
+ const percentage = this.safeString (ticker, 'price_change_percentage');
543
+ const change = this.safeString (ticker, 'price_change');
544
+ const baseVolume = this.safeString (ticker, 'base_volume');
545
+ const quoteVolume = this.safeString (ticker, 'quote_volume');
546
+ return this.safeTicker ({
547
+ 'symbol': symbol,
548
+ 'timestamp': timestamp,
549
+ 'datetime': this.iso8601 (timestamp),
550
+ 'high': this.safeString (ticker, 'high'),
551
+ 'low': this.safeString (ticker, 'low'),
552
+ 'bid': this.safeString (ticker, 'best_bid'),
553
+ 'bidVolume': undefined,
554
+ 'ask': this.safeString (ticker, 'best_ask'),
555
+ 'askVolume': undefined,
556
+ 'vwap': undefined,
557
+ 'open': undefined,
558
+ 'close': last,
559
+ 'last': last,
560
+ 'previousClose': undefined,
561
+ 'change': change,
562
+ 'percentage': percentage,
563
+ 'average': undefined,
564
+ 'baseVolume': baseVolume,
565
+ 'quoteVolume': quoteVolume,
566
+ 'info': ticker,
567
+ }, market, false);
568
+ }
569
+
570
+ async fetchTicker (symbol, params = {}) {
571
+ await this.loadMarkets ();
572
+ const market = this.market (symbol);
573
+ const request = {
574
+ 'instrument_code': market['id'],
575
+ };
576
+ const response = await this.publicGetMarketTickerInstrumentCode (this.extend (request, params));
577
+ //
578
+ // {
579
+ // "instrument_code":"BTC_EUR",
580
+ // "sequence":602562,
581
+ // "time":"2020-07-10T06:27:34.951Z",
582
+ // "state":"ACTIVE",
583
+ // "is_frozen":0,
584
+ // "quote_volume":"1695555.1783768",
585
+ // "base_volume":"205.67436",
586
+ // "last_price":"8143.91",
587
+ // "best_bid":"8143.71",
588
+ // "best_ask":"8156.9",
589
+ // "price_change":"-147.47",
590
+ // "price_change_percentage":"-1.78",
591
+ // "high":"8337.45",
592
+ // "low":"8110.0"
593
+ // }
594
+ //
595
+ return this.parseTicker (response, market);
596
+ }
597
+
598
+ async fetchTickers (symbols = undefined, params = {}) {
599
+ await this.loadMarkets ();
600
+ const response = await this.publicGetMarketTicker (params);
601
+ //
602
+ // [
603
+ // {
604
+ // "instrument_code":"BTC_EUR",
605
+ // "sequence":602562,
606
+ // "time":"2020-07-10T06:27:34.951Z",
607
+ // "state":"ACTIVE",
608
+ // "is_frozen":0,
609
+ // "quote_volume":"1695555.1783768",
610
+ // "base_volume":"205.67436",
611
+ // "last_price":"8143.91",
612
+ // "best_bid":"8143.71",
613
+ // "best_ask":"8156.9",
614
+ // "price_change":"-147.47",
615
+ // "price_change_percentage":"-1.78",
616
+ // "high":"8337.45",
617
+ // "low":"8110.0"
618
+ // }
619
+ // ]
620
+ //
621
+ const result = {};
622
+ for (let i = 0; i < response.length; i++) {
623
+ const ticker = this.parseTicker (response[i]);
624
+ const symbol = ticker['symbol'];
625
+ result[symbol] = ticker;
626
+ }
627
+ return this.filterByArray (result, 'symbol', symbols);
628
+ }
629
+
630
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
631
+ await this.loadMarkets ();
632
+ const request = {
633
+ 'instrument_code': this.marketId (symbol),
634
+ // level 1 means only the best bid and ask
635
+ // level 2 is a compiled order book up to market precision
636
+ // level 3 is a full orderbook
637
+ // if you wish to get regular updates about orderbooks please use the Websocket channel
638
+ // heavy usage of this endpoint may result in limited access according to rate limits rules
639
+ // 'level': 3, // default
640
+ };
641
+ if (limit !== undefined) {
642
+ request['depth'] = limit;
643
+ }
644
+ const response = await this.publicGetOrderBookInstrumentCode (this.extend (request, params));
645
+ //
646
+ // level 1
647
+ //
648
+ // {
649
+ // "instrument_code":"BTC_EUR",
650
+ // "time":"2020-07-10T07:39:06.343Z",
651
+ // "asks":{
652
+ // "value":{
653
+ // "price":"8145.29",
654
+ // "amount":"0.96538",
655
+ // "number_of_orders":1
656
+ // }
657
+ // },
658
+ // "bids":{
659
+ // "value":{
660
+ // "price":"8134.0",
661
+ // "amount":"1.5978",
662
+ // "number_of_orders":5
663
+ // }
664
+ // }
665
+ // }
666
+ //
667
+ // level 2
668
+ //
669
+ // {
670
+ // "instrument_code":"BTC_EUR","time":"2020-07-10T07:36:43.538Z",
671
+ // "asks":[
672
+ // {"price":"8146.59","amount":"0.89691","number_of_orders":1},
673
+ // {"price":"8146.89","amount":"1.92062","number_of_orders":1},
674
+ // {"price":"8169.5","amount":"0.0663","number_of_orders":1},
675
+ // ],
676
+ // "bids":[
677
+ // {"price":"8143.49","amount":"0.01329","number_of_orders":1},
678
+ // {"price":"8137.01","amount":"5.34748","number_of_orders":1},
679
+ // {"price":"8137.0","amount":"2.0","number_of_orders":1},
680
+ // ]
681
+ // }
682
+ //
683
+ // level 3
684
+ //
685
+ // {
686
+ // "instrument_code":"BTC_EUR",
687
+ // "time":"2020-07-10T07:32:31.525Z",
688
+ // "bids":[
689
+ // {"price":"8146.79","amount":"0.01537","order_id":"5d717da1-a8f4-422d-afcc-03cb6ab66825"},
690
+ // {"price":"8139.32","amount":"3.66009","order_id":"d0715c68-f28d-4cf1-a450-d56cf650e11c"},
691
+ // {"price":"8137.51","amount":"2.61049","order_id":"085fd6f4-e835-4ca5-9449-a8f165772e60"},
692
+ // ],
693
+ // "asks":[
694
+ // {"price":"8153.49","amount":"0.93384","order_id":"755d3aa3-42b5-46fa-903d-98f42e9ae6c4"},
695
+ // {"price":"8153.79","amount":"1.80456","order_id":"62034cf3-b70d-45ff-b285-ba6307941e7c"},
696
+ // {"price":"8167.9","amount":"0.0018","order_id":"036354e0-71cd-492f-94f2-01f7d4b66422"},
697
+ // ]
698
+ // }
699
+ //
700
+ const timestamp = this.parse8601 (this.safeString (response, 'time'));
701
+ return this.parseOrderBook (response, symbol, timestamp, 'bids', 'asks', 'price', 'amount');
702
+ }
703
+
704
+ parseOHLCV (ohlcv, market = undefined) {
705
+ //
706
+ // {
707
+ // "instrument_code":"BTC_EUR",
708
+ // "granularity":{"unit":"HOURS","period":1},
709
+ // "high":"9252.65",
710
+ // "low":"9115.27",
711
+ // "open":"9250.0",
712
+ // "close":"9132.35",
713
+ // "total_amount":"33.85924",
714
+ // "volume":"311958.9635744",
715
+ // "time":"2020-05-08T22:59:59.999Z",
716
+ // "last_sequence":461123
717
+ // }
718
+ //
719
+ const granularity = this.safeValue (ohlcv, 'granularity');
720
+ const unit = this.safeString (granularity, 'unit');
721
+ const period = this.safeString (granularity, 'period');
722
+ const units = {
723
+ 'MINUTES': 'm',
724
+ 'HOURS': 'h',
725
+ 'DAYS': 'd',
726
+ 'WEEKS': 'w',
727
+ 'MONTHS': 'M',
728
+ };
729
+ const lowercaseUnit = this.safeString (units, unit);
730
+ const timeframe = period + lowercaseUnit;
731
+ const durationInSeconds = this.parseTimeframe (timeframe);
732
+ const duration = durationInSeconds * 1000;
733
+ const timestamp = this.parse8601 (this.safeString (ohlcv, 'time'));
734
+ const alignedTimestamp = duration * parseInt (timestamp / duration);
735
+ const options = this.safeValue (this.options, 'fetchOHLCV', {});
736
+ const volumeField = this.safeString (options, 'volume', 'total_amount');
737
+ return [
738
+ alignedTimestamp,
739
+ this.safeNumber (ohlcv, 'open'),
740
+ this.safeNumber (ohlcv, 'high'),
741
+ this.safeNumber (ohlcv, 'low'),
742
+ this.safeNumber (ohlcv, 'close'),
743
+ this.safeNumber (ohlcv, volumeField),
744
+ ];
745
+ }
746
+
747
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
748
+ await this.loadMarkets ();
749
+ const market = this.market (symbol);
750
+ const periodUnit = this.safeString (this.timeframes, timeframe);
751
+ const [ period, unit ] = periodUnit.split ('/');
752
+ const durationInSeconds = this.parseTimeframe (timeframe);
753
+ const duration = durationInSeconds * 1000;
754
+ if (limit === undefined) {
755
+ limit = 1500;
756
+ }
757
+ const request = {
758
+ 'instrument_code': market['id'],
759
+ // 'from': this.iso8601 (since),
760
+ // 'to': this.iso8601 (this.milliseconds ()),
761
+ 'period': period,
762
+ 'unit': unit,
763
+ };
764
+ if (since === undefined) {
765
+ const now = this.milliseconds ();
766
+ request['to'] = this.iso8601 (now);
767
+ request['from'] = this.iso8601 (now - limit * duration);
768
+ } else {
769
+ request['from'] = this.iso8601 (since);
770
+ request['to'] = this.iso8601 (this.sum (since, limit * duration));
771
+ }
772
+ const response = await this.publicGetCandlesticksInstrumentCode (this.extend (request, params));
773
+ //
774
+ // [
775
+ // {"instrument_code":"BTC_EUR","granularity":{"unit":"HOURS","period":1},"high":"9252.65","low":"9115.27","open":"9250.0","close":"9132.35","total_amount":"33.85924","volume":"311958.9635744","time":"2020-05-08T22:59:59.999Z","last_sequence":461123},
776
+ // {"instrument_code":"BTC_EUR","granularity":{"unit":"HOURS","period":1},"high":"9162.49","low":"9040.0","open":"9132.53","close":"9083.69","total_amount":"26.19685","volume":"238553.7812365","time":"2020-05-08T23:59:59.999Z","last_sequence":461376},
777
+ // {"instrument_code":"BTC_EUR","granularity":{"unit":"HOURS","period":1},"high":"9135.7","low":"9002.59","open":"9055.45","close":"9133.98","total_amount":"26.21919","volume":"238278.8724959","time":"2020-05-09T00:59:59.999Z","last_sequence":461521},
778
+ // ]
779
+ //
780
+ return this.parseOHLCVs (response, market, timeframe, since, limit);
781
+ }
782
+
783
+ parseTrade (trade, market = undefined) {
784
+ //
785
+ // fetchTrades (public)
786
+ //
787
+ // {
788
+ // "instrument_code":"BTC_EUR",
789
+ // "price":"8137.28",
790
+ // "amount":"0.22269",
791
+ // "taker_side":"BUY",
792
+ // "volume":"1812.0908832",
793
+ // "time":"2020-07-10T14:44:32.299Z",
794
+ // "trade_timestamp":1594392272299,
795
+ // "sequence":603047
796
+ // }
797
+ //
798
+ // fetchMyTrades, fetchOrder, fetchOpenOrders, fetchClosedOrders trades (private)
799
+ //
800
+ // {
801
+ // "fee": {
802
+ // "fee_amount": "0.0014",
803
+ // "fee_currency": "BTC",
804
+ // "fee_percentage": "0.1",
805
+ // "fee_group_id": "default",
806
+ // "fee_type": "TAKER",
807
+ // "running_trading_volume": "0.0"
808
+ // },
809
+ // "trade": {
810
+ // "trade_id": "fdff2bcc-37d6-4a2d-92a5-46e09c868664",
811
+ // "order_id": "36bb2437-7402-4794-bf26-4bdf03526439",
812
+ // "account_id": "a4c699f6-338d-4a26-941f-8f9853bfc4b9",
813
+ // "amount": "1.4",
814
+ // "side": "BUY",
815
+ // "instrument_code": "BTC_EUR",
816
+ // "price": "7341.4",
817
+ // "time": "2019-09-27T15:05:32.564Z",
818
+ // "sequence": 48670
819
+ // }
820
+ // }
821
+ //
822
+ const feeInfo = this.safeValue (trade, 'fee', {});
823
+ trade = this.safeValue (trade, 'trade', trade);
824
+ let timestamp = this.safeInteger (trade, 'trade_timestamp');
825
+ if (timestamp === undefined) {
826
+ timestamp = this.parse8601 (this.safeString (trade, 'time'));
827
+ }
828
+ const side = this.safeStringLower2 (trade, 'side', 'taker_side');
829
+ const priceString = this.safeString (trade, 'price');
830
+ const amountString = this.safeString (trade, 'amount');
831
+ const costString = this.safeString (trade, 'volume');
832
+ const marketId = this.safeString (trade, 'instrument_code');
833
+ const symbol = this.safeSymbol (marketId, market, '_');
834
+ const feeCostString = this.safeString (feeInfo, 'fee_amount');
835
+ let takerOrMaker = undefined;
836
+ let fee = undefined;
837
+ if (feeCostString !== undefined) {
838
+ const feeCurrencyId = this.safeString (feeInfo, 'fee_currency');
839
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
840
+ const feeRateString = this.safeString (feeInfo, 'fee_percentage');
841
+ fee = {
842
+ 'cost': feeCostString,
843
+ 'currency': feeCurrencyCode,
844
+ 'rate': feeRateString,
845
+ };
846
+ takerOrMaker = this.safeStringLower (feeInfo, 'fee_type');
847
+ }
848
+ return this.safeTrade ({
849
+ 'id': this.safeString2 (trade, 'trade_id', 'sequence'),
850
+ 'order': this.safeString (trade, 'order_id'),
851
+ 'timestamp': timestamp,
852
+ 'datetime': this.iso8601 (timestamp),
853
+ 'symbol': symbol,
854
+ 'type': undefined,
855
+ 'side': side,
856
+ 'price': priceString,
857
+ 'amount': amountString,
858
+ 'cost': costString,
859
+ 'takerOrMaker': takerOrMaker,
860
+ 'fee': fee,
861
+ 'info': trade,
862
+ }, market);
863
+ }
864
+
865
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
866
+ await this.loadMarkets ();
867
+ const market = this.market (symbol);
868
+ const request = {
869
+ 'instrument_code': market['id'],
870
+ // 'from': this.iso8601 (since),
871
+ // 'to': this.iso8601 (this.milliseconds ()),
872
+ };
873
+ if (since !== undefined) {
874
+ // returns price ticks for a specific market with an interval of maximum of 4 hours
875
+ // sorted by latest first
876
+ request['from'] = this.iso8601 (since);
877
+ request['to'] = this.iso8601 (this.sum (since, 14400000));
878
+ }
879
+ const response = await this.publicGetPriceTicksInstrumentCode (this.extend (request, params));
880
+ //
881
+ // [
882
+ // {
883
+ // "instrument_code":"BTC_EUR",
884
+ // "price":"8137.28",
885
+ // "amount":"0.22269",
886
+ // "taker_side":"BUY",
887
+ // "volume":"1812.0908832",
888
+ // "time":"2020-07-10T14:44:32.299Z",
889
+ // "trade_timestamp":1594392272299,
890
+ // "sequence":603047
891
+ // }
892
+ // ]
893
+ //
894
+ return this.parseTrades (response, market, since, limit);
895
+ }
896
+
897
+ parseBalance (response) {
898
+ const balances = this.safeValue (response, 'balances', []);
899
+ const result = { 'info': response };
900
+ for (let i = 0; i < balances.length; i++) {
901
+ const balance = balances[i];
902
+ const currencyId = this.safeString (balance, 'currency_code');
903
+ const code = this.safeCurrencyCode (currencyId);
904
+ const account = this.account ();
905
+ account['free'] = this.safeString (balance, 'available');
906
+ account['used'] = this.safeString (balance, 'locked');
907
+ result[code] = account;
908
+ }
909
+ return this.safeBalance (result);
910
+ }
911
+
912
+ async fetchBalance (params = {}) {
913
+ await this.loadMarkets ();
914
+ const response = await this.privateGetAccountBalances (params);
915
+ //
916
+ // {
917
+ // "account_id":"4b95934f-55f1-460c-a525-bd5afc0cf071",
918
+ // "balances":[
919
+ // {
920
+ // "account_id":"4b95934f-55f1-460c-a525-bd5afc0cf071",
921
+ // "currency_code":"BTC",
922
+ // "change":"10.0",
923
+ // "available":"10.0",
924
+ // "locked":"0.0",
925
+ // "sequence":142135994,
926
+ // "time":"2020-07-01T10:57:32.959Z"
927
+ // }
928
+ // ]
929
+ // }
930
+ //
931
+ return this.parseBalance (response);
932
+ }
933
+
934
+ parseDepositAddress (depositAddress, currency = undefined) {
935
+ let code = undefined;
936
+ if (currency !== undefined) {
937
+ code = currency['code'];
938
+ }
939
+ const address = this.safeString (depositAddress, 'address');
940
+ const tag = this.safeString (depositAddress, 'destination_tag');
941
+ this.checkAddress (address);
942
+ return {
943
+ 'currency': code,
944
+ 'address': address,
945
+ 'tag': tag,
946
+ 'network': undefined,
947
+ 'info': depositAddress,
948
+ };
949
+ }
950
+
951
+ async createDepositAddress (code, params = {}) {
952
+ await this.loadMarkets ();
953
+ const currency = this.currency (code);
954
+ const request = {
955
+ 'currency': currency['id'],
956
+ };
957
+ const response = await this.privatePostAccountDepositCrypto (this.extend (request, params));
958
+ //
959
+ // {
960
+ // "address":"rBnNhk95FrdNisZtXcStzriFS8vEzz53DM",
961
+ // "destination_tag":"865690307",
962
+ // "enabled":true,
963
+ // "is_smart_contract":false
964
+ // }
965
+ //
966
+ return this.parseDepositAddress (response, currency);
967
+ }
968
+
969
+ async fetchDepositAddress (code, params = {}) {
970
+ await this.loadMarkets ();
971
+ const currency = this.currency (code);
972
+ const request = {
973
+ 'currency_code': currency['id'],
974
+ };
975
+ const response = await this.privateGetAccountDepositCryptoCurrencyCode (this.extend (request, params));
976
+ //
977
+ // {
978
+ // "address":"rBnNhk95FrdNisZtXcStzriFS8vEzz53DM",
979
+ // "destination_tag":"865690307",
980
+ // "enabled":true,
981
+ // "is_smart_contract":false,
982
+ // "can_create_more":false
983
+ // }
984
+ //
985
+ return this.parseDepositAddress (response, currency);
986
+ }
987
+
988
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
989
+ await this.loadMarkets ();
990
+ const request = {
991
+ // 'cursor': 'string', // pointer specifying the position from which the next pages should be returned
992
+ };
993
+ let currency = undefined;
994
+ if (code !== undefined) {
995
+ currency = this.currency (code);
996
+ request['currency_code'] = currency['id'];
997
+ }
998
+ if (limit !== undefined) {
999
+ request['max_page_size'] = limit;
1000
+ }
1001
+ if (since !== undefined) {
1002
+ const to = this.safeString (params, 'to');
1003
+ if (to === undefined) {
1004
+ throw new ArgumentsRequired (this.id + ' fetchDeposits() requires a "to" iso8601 string param with the since argument is specified');
1005
+ }
1006
+ request['from'] = this.iso8601 (since);
1007
+ }
1008
+ const response = await this.privateGetAccountDeposits (this.extend (request, params));
1009
+ //
1010
+ // {
1011
+ // "deposit_history": [
1012
+ // {
1013
+ // "transaction_id": "e5342efcd-d5b7-4a56-8e12-b69ffd68c5ef",
1014
+ // "account_id": "c2d0076a-c20d-41f8-9e9a-1a1d028b2b58",
1015
+ // "amount": "100",
1016
+ // "type": "CRYPTO",
1017
+ // "funds_source": "INTERNAL",
1018
+ // "time": "2020-04-22T09:57:47Z",
1019
+ // "currency": "BTC",
1020
+ // "fee_amount": "0.0",
1021
+ // "fee_currency": "BTC"
1022
+ // },
1023
+ // {
1024
+ // "transaction_id": "79793d00-2899-4a4d-95b7-73ae6b31384f",
1025
+ // "account_id": "c2d0076a-c20d-41f8-9e9a-1a1d028b2b58",
1026
+ // "time": "2020-05-05T11:22:07.925Z",
1027
+ // "currency": "EUR",
1028
+ // "funds_source": "EXTERNAL",
1029
+ // "type": "FIAT",
1030
+ // "amount": "50.0",
1031
+ // "fee_amount": "0.01",
1032
+ // "fee_currency": "EUR"
1033
+ // }
1034
+ // ],
1035
+ // "max_page_size": 2,
1036
+ // "cursor": "eyJhY2NvdW50X2lkIjp7InMiOiJlMzY5YWM4MC00NTc3LTExZTktYWUwOC05YmVkYzQ3OTBiODQiLCJzcyI6W10sIm5zIjpbXSwiYnMiOltdLCJtIjp7fSwibCI6W119LCJpdGVtX2tleSI6eyJzIjoiV0lUSERSQVdBTDo6MmFlMjYwY2ItOTk3MC00YmNiLTgxNmEtZGY4MDVmY2VhZTY1Iiwic3MiOltdLCJucyI6W10sImJzIjpbXSwibSI6e30sImwiOltdfSwiZ2xvYmFsX3dpdGhkcmF3YWxfaW5kZXhfaGFzaF9rZXkiOnsicyI6ImUzNjlhYzgwLTQ1NzctMTFlOS1hZTA4LTliZWRjNDc5MGI4NCIsInNzIjpbXSwibnMiOltdLCJicyI6W10sIm0iOnt9LCJsIjpbXX0sInRpbWVzdGFtcCI6eyJuIjoiMTU4ODA1ODc2Nzk0OCIsInNzIjpbXSwibnMiOltdLCJicyI6W10sIm0iOnt9LCJsIjpbXX19"
1037
+ // }
1038
+ //
1039
+ const depositHistory = this.safeValue (response, 'deposit_history', []);
1040
+ return this.parseTransactions (depositHistory, currency, since, limit, { 'type': 'deposit' });
1041
+ }
1042
+
1043
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
1044
+ await this.loadMarkets ();
1045
+ const request = {
1046
+ // 'cursor': 'string', // pointer specifying the position from which the next pages should be returned
1047
+ };
1048
+ let currency = undefined;
1049
+ if (code !== undefined) {
1050
+ currency = this.currency (code);
1051
+ request['currency_code'] = currency['id'];
1052
+ }
1053
+ if (limit !== undefined) {
1054
+ request['max_page_size'] = limit;
1055
+ }
1056
+ if (since !== undefined) {
1057
+ const to = this.safeString (params, 'to');
1058
+ if (to === undefined) {
1059
+ throw new ArgumentsRequired (this.id + ' fetchWithdrawals() requires a "to" iso8601 string param with the since argument is specified');
1060
+ }
1061
+ request['from'] = this.iso8601 (since);
1062
+ }
1063
+ const response = await this.privateGetAccountWithdrawals (this.extend (request, params));
1064
+ //
1065
+ // {
1066
+ // "withdrawal_history": [
1067
+ // {
1068
+ // "account_id": "e369ac80-4577-11e9-ae08-9bedc4790b84",
1069
+ // "amount": "0.1",
1070
+ // "currency": "BTC",
1071
+ // "fee_amount": "0.00002",
1072
+ // "fee_currency": "BTC",
1073
+ // "funds_source": "EXTERNAL",
1074
+ // "related_transaction_id": "e298341a-3855-405e-bce3-92db368a3157",
1075
+ // "time": "2020-05-05T11:11:32.110Z",
1076
+ // "transaction_id": "6693ff40-bb10-4dcf-ada7-3b287727c882",
1077
+ // "type": "CRYPTO"
1078
+ // },
1079
+ // {
1080
+ // "account_id": "e369ac80-4577-11e9-ae08-9bedc4790b84",
1081
+ // "amount": "0.1",
1082
+ // "currency": "BTC",
1083
+ // "fee_amount": "0.0",
1084
+ // "fee_currency": "BTC",
1085
+ // "funds_source": "INTERNAL",
1086
+ // "time": "2020-05-05T10:29:53.464Z",
1087
+ // "transaction_id": "ec9703b1-954b-4f76-adea-faac66eabc0b",
1088
+ // "type": "CRYPTO"
1089
+ // }
1090
+ // ],
1091
+ // "cursor": "eyJhY2NvdW50X2lkIjp7InMiOiJlMzY5YWM4MC00NTc3LTExZTktYWUwOC05YmVkYzQ3OTBiODQiLCJzcyI6W10sIm5zIjpbXSwiYnMiOltdLCJtIjp7fSwibCI6W119LCJpdGVtX2tleSI6eyJzIjoiV0lUSERSQVdBTDo6ZWM5NzAzYjEtOTU0Yi00Zjc2LWFkZWEtZmFhYzY2ZWFiYzBiIiwic3MiOltdLCJucyI6W10sImJzIjpbXSwibSI6e30sImwiOltdfSwiZ2xvYmFsX3dpdGhkcmF3YWxfaW5kZXhfaGFzaF9rZXkiOnsicyI6ImUzNjlhYzgwLTQ1NzctMTFlOS1hZTA4LTliZWRjNDc5MGI4NCIsInNzIjpbXSwibnMiOltdLCJicyI6W10sIm0iOnt9LCJsIjpbXX0sInRpbWVzdGFtcCI6eyJuIjoiMTU4ODY3NDU5MzQ2NCIsInNzIjpbXSwibnMiOltdLCJicyI6W10sIm0iOnt9LCJsIjpbXX19",
1092
+ // "max_page_size": 2
1093
+ // }
1094
+ //
1095
+ const withdrawalHistory = this.safeValue (response, 'withdrawal_history', []);
1096
+ return this.parseTransactions (withdrawalHistory, currency, since, limit, { 'type': 'withdrawal' });
1097
+ }
1098
+
1099
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1100
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1101
+ this.checkAddress (address);
1102
+ await this.loadMarkets ();
1103
+ const currency = this.currency (code);
1104
+ const request = {
1105
+ 'currency': code,
1106
+ 'amount': this.currencyToPrecision (code, amount),
1107
+ // 'payout_account_id': '66756a10-3e86-48f4-9678-b634c4b135b2', // fiat only
1108
+ // 'recipient': { // crypto only
1109
+ // 'address': address,
1110
+ // // 'destination_tag': '',
1111
+ // },
1112
+ };
1113
+ const options = this.safeValue (this.options, 'fiat', []);
1114
+ const isFiat = this.inArray (code, options);
1115
+ const method = isFiat ? 'privatePostAccountWithdrawFiat' : 'privatePostAccountWithdrawCrypto';
1116
+ if (isFiat) {
1117
+ const payoutAccountId = this.safeString (params, 'payout_account_id');
1118
+ if (payoutAccountId === undefined) {
1119
+ throw ArgumentsRequired (this.id + ' withdraw() requires a payout_account_id param for fiat ' + code + ' withdrawals');
1120
+ }
1121
+ } else {
1122
+ const recipient = { 'address': address };
1123
+ if (tag !== undefined) {
1124
+ recipient['destination_tag'] = tag;
1125
+ }
1126
+ request['recipient'] = recipient;
1127
+ }
1128
+ const response = await this[method] (this.extend (request, params));
1129
+ //
1130
+ // crypto
1131
+ //
1132
+ // {
1133
+ // "amount": "1234.5678",
1134
+ // "fee": "1234.5678",
1135
+ // "recipient": "3NacQ7rzZdhfyAtfJ5a11k8jFPdcMP2Bq7",
1136
+ // "destination_tag": "",
1137
+ // "transaction_id": "d0f8529f-f832-4e6a-9dc5-b8d5797badb2"
1138
+ // }
1139
+ //
1140
+ // fiat
1141
+ //
1142
+ // {
1143
+ // "transaction_id": "54236cd0-4413-11e9-93fb-5fea7e5b5df6"
1144
+ // }
1145
+ //
1146
+ return this.parseTransaction (response, currency);
1147
+ }
1148
+
1149
+ parseTransaction (transaction, currency = undefined) {
1150
+ //
1151
+ // fetchDeposits, fetchWithdrawals
1152
+ //
1153
+ // {
1154
+ // "transaction_id": "C2b42efcd-d5b7-4a56-8e12-b69ffd68c5ef",
1155
+ // "type": "FIAT",
1156
+ // "account_id": "c2d0076a-c20d-41f8-9e9a-1a1d028b2b58",
1157
+ // "amount": "1234.5678",
1158
+ // "time": "2019-08-24T14:15:22Z",
1159
+ // "funds_source": "INTERNAL",
1160
+ // "currency": "BTC",
1161
+ // "fee_amount": "1234.5678",
1162
+ // "fee_currency": "BTC",
1163
+ // "blockchain_transaction_id": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
1164
+ // "related_transaction_id": "e298341a-3855-405e-bce3-92db368a3157"
1165
+ // }
1166
+ //
1167
+ // withdraw
1168
+ //
1169
+ //
1170
+ // crypto
1171
+ //
1172
+ // {
1173
+ // "amount": "1234.5678",
1174
+ // "fee": "1234.5678",
1175
+ // "recipient": "3NacQ7rzZdhfyAtfJ5a11k8jFPdcMP2Bq7",
1176
+ // "destination_tag": "",
1177
+ // "transaction_id": "d0f8529f-f832-4e6a-9dc5-b8d5797badb2"
1178
+ // }
1179
+ //
1180
+ // fiat
1181
+ //
1182
+ // {
1183
+ // "transaction_id": "54236cd0-4413-11e9-93fb-5fea7e5b5df6"
1184
+ // }
1185
+ //
1186
+ const id = this.safeString (transaction, 'transaction_id');
1187
+ const amount = this.safeNumber (transaction, 'amount');
1188
+ const timestamp = this.parse8601 (this.safeString (transaction, 'time'));
1189
+ const currencyId = this.safeString (transaction, 'currency');
1190
+ currency = this.safeCurrency (currencyId, currency);
1191
+ const status = 'ok'; // the exchange returns cleared transactions only
1192
+ const feeCost = this.safeNumber2 (transaction, 'fee_amount', 'fee');
1193
+ let fee = undefined;
1194
+ const addressTo = this.safeString (transaction, 'recipient');
1195
+ const tagTo = this.safeString (transaction, 'destination_tag');
1196
+ if (feeCost !== undefined) {
1197
+ const feeCurrencyId = this.safeString (transaction, 'fee_currency', currencyId);
1198
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
1199
+ fee = {
1200
+ 'cost': feeCost,
1201
+ 'currency': feeCurrencyCode,
1202
+ };
1203
+ }
1204
+ return {
1205
+ 'info': transaction,
1206
+ 'id': id,
1207
+ 'currency': currency['code'],
1208
+ 'amount': amount,
1209
+ 'network': undefined,
1210
+ 'address': addressTo,
1211
+ 'addressFrom': undefined,
1212
+ 'addressTo': addressTo,
1213
+ 'tag': tagTo,
1214
+ 'tagFrom': undefined,
1215
+ 'tagTo': tagTo,
1216
+ 'status': status,
1217
+ 'type': undefined,
1218
+ 'updated': undefined,
1219
+ 'txid': this.safeString (transaction, 'blockchain_transaction_id'),
1220
+ 'timestamp': timestamp,
1221
+ 'datetime': this.iso8601 (timestamp),
1222
+ 'fee': fee,
1223
+ };
1224
+ }
1225
+
1226
+ parseOrderStatus (status) {
1227
+ const statuses = {
1228
+ 'FILLED': 'open',
1229
+ 'FILLED_FULLY': 'closed',
1230
+ 'FILLED_CLOSED': 'canceled',
1231
+ 'FILLED_REJECTED': 'rejected',
1232
+ 'OPEN': 'open',
1233
+ 'REJECTED': 'rejected',
1234
+ 'CLOSED': 'canceled',
1235
+ 'FAILED': 'failed',
1236
+ 'STOP_TRIGGERED': 'triggered',
1237
+ };
1238
+ return this.safeString (statuses, status, status);
1239
+ }
1240
+
1241
+ parseOrder (order, market = undefined) {
1242
+ //
1243
+ // createOrder
1244
+ //
1245
+ // {
1246
+ // "order_id": "d5492c24-2995-4c18-993a-5b8bf8fffc0d",
1247
+ // "client_id": "d75fb03b-b599-49e9-b926-3f0b6d103206",
1248
+ // "account_id": "a4c699f6-338d-4a26-941f-8f9853bfc4b9",
1249
+ // "instrument_code": "BTC_EUR",
1250
+ // "time": "2019-08-01T08:00:44.026Z",
1251
+ // "side": "BUY",
1252
+ // "price": "5000",
1253
+ // "amount": "1",
1254
+ // "filled_amount": "0.5",
1255
+ // "type": "LIMIT",
1256
+ // "time_in_force": "GOOD_TILL_CANCELLED"
1257
+ // }
1258
+ //
1259
+ // fetchOrder, fetchOpenOrders, fetchClosedOrders
1260
+ //
1261
+ // {
1262
+ // "order": {
1263
+ // "order_id": "66756a10-3e86-48f4-9678-b634c4b135b2",
1264
+ // "account_id": "1eb2ad5d-55f1-40b5-bc92-7dc05869e905",
1265
+ // "instrument_code": "BTC_EUR",
1266
+ // "amount": "1234.5678",
1267
+ // "filled_amount": "1234.5678",
1268
+ // "side": "BUY",
1269
+ // "type": "LIMIT",
1270
+ // "status": "OPEN",
1271
+ // "sequence": 123456789,
1272
+ // "price": "1234.5678",
1273
+ // "average_price": "1234.5678",
1274
+ // "reason": "INSUFFICIENT_FUNDS",
1275
+ // "time": "2019-08-24T14:15:22Z",
1276
+ // "time_in_force": "GOOD_TILL_CANCELLED",
1277
+ // "time_last_updated": "2019-08-24T14:15:22Z",
1278
+ // "expire_after": "2019-08-24T14:15:22Z",
1279
+ // "is_post_only": false,
1280
+ // "time_triggered": "2019-08-24T14:15:22Z",
1281
+ // "trigger_price": "1234.5678"
1282
+ // },
1283
+ // "trades": [
1284
+ // {
1285
+ // "fee": {
1286
+ // "fee_amount": "0.0014",
1287
+ // "fee_currency": "BTC",
1288
+ // "fee_percentage": "0.1",
1289
+ // "fee_group_id": "default",
1290
+ // "fee_type": "TAKER",
1291
+ // "running_trading_volume": "0.0"
1292
+ // },
1293
+ // "trade": {
1294
+ // "trade_id": "fdff2bcc-37d6-4a2d-92a5-46e09c868664",
1295
+ // "order_id": "36bb2437-7402-4794-bf26-4bdf03526439",
1296
+ // "account_id": "a4c699f6-338d-4a26-941f-8f9853bfc4b9",
1297
+ // "amount": "1.4",
1298
+ // "side": "BUY",
1299
+ // "instrument_code": "BTC_EUR",
1300
+ // "price": "7341.4",
1301
+ // "time": "2019-09-27T15:05:32.564Z",
1302
+ // "sequence": 48670
1303
+ // }
1304
+ // }
1305
+ // ]
1306
+ // }
1307
+ //
1308
+ const rawOrder = this.safeValue (order, 'order', order);
1309
+ const id = this.safeString (rawOrder, 'order_id');
1310
+ const clientOrderId = this.safeString (rawOrder, 'client_id');
1311
+ const timestamp = this.parse8601 (this.safeString (rawOrder, 'time'));
1312
+ const rawStatus = this.parseOrderStatus (this.safeString (rawOrder, 'status'));
1313
+ const status = this.parseOrderStatus (rawStatus);
1314
+ const marketId = this.safeString (rawOrder, 'instrument_code');
1315
+ const symbol = this.safeSymbol (marketId, market, '_');
1316
+ const price = this.safeString (rawOrder, 'price');
1317
+ const amount = this.safeString (rawOrder, 'amount');
1318
+ const filled = this.safeString (rawOrder, 'filled_amount');
1319
+ const side = this.safeStringLower (rawOrder, 'side');
1320
+ const type = this.safeStringLower (rawOrder, 'type');
1321
+ const timeInForce = this.parseTimeInForce (this.safeString (rawOrder, 'time_in_force'));
1322
+ const stopPrice = this.safeNumber (rawOrder, 'trigger_price');
1323
+ const postOnly = this.safeValue (rawOrder, 'is_post_only');
1324
+ const rawTrades = this.safeValue (order, 'trades', []);
1325
+ return this.safeOrder ({
1326
+ 'id': id,
1327
+ 'clientOrderId': clientOrderId,
1328
+ 'info': order,
1329
+ 'timestamp': timestamp,
1330
+ 'datetime': this.iso8601 (timestamp),
1331
+ 'lastTradeTimestamp': undefined,
1332
+ 'symbol': symbol,
1333
+ 'type': type,
1334
+ 'timeInForce': timeInForce,
1335
+ 'postOnly': postOnly,
1336
+ 'side': side,
1337
+ 'price': price,
1338
+ 'stopPrice': stopPrice,
1339
+ 'amount': amount,
1340
+ 'cost': undefined,
1341
+ 'average': undefined,
1342
+ 'filled': filled,
1343
+ 'remaining': undefined,
1344
+ 'status': status,
1345
+ // 'fee': undefined,
1346
+ 'trades': rawTrades,
1347
+ }, market);
1348
+ }
1349
+
1350
+ parseTimeInForce (timeInForce) {
1351
+ const timeInForces = {
1352
+ 'GOOD_TILL_CANCELLED': 'GTC',
1353
+ 'GOOD_TILL_TIME': 'GTT',
1354
+ 'IMMEDIATE_OR_CANCELLED': 'IOC',
1355
+ 'FILL_OR_KILL': 'FOK',
1356
+ };
1357
+ return this.safeString (timeInForces, timeInForce, timeInForce);
1358
+ }
1359
+
1360
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1361
+ await this.loadMarkets ();
1362
+ const market = this.market (symbol);
1363
+ const uppercaseType = type.toUpperCase ();
1364
+ const request = {
1365
+ 'instrument_code': market['id'],
1366
+ 'type': uppercaseType, // LIMIT, MARKET, STOP
1367
+ 'side': side.toUpperCase (), // or SELL
1368
+ 'amount': this.amountToPrecision (symbol, amount),
1369
+ // "price": "1234.5678", // required for LIMIT and STOP orders
1370
+ // "client_id": "d75fb03b-b599-49e9-b926-3f0b6d103206", // optional
1371
+ // "time_in_force": "GOOD_TILL_CANCELLED", // limit orders only, GOOD_TILL_CANCELLED, GOOD_TILL_TIME, IMMEDIATE_OR_CANCELLED and FILL_OR_KILL
1372
+ // "expire_after": "2020-07-02T19:40:13Z", // required for GOOD_TILL_TIME
1373
+ // "is_post_only": false, // limit orders only, optional
1374
+ // "trigger_price": "1234.5678" // required for stop orders
1375
+ };
1376
+ let priceIsRequired = false;
1377
+ if (uppercaseType === 'LIMIT' || uppercaseType === 'STOP') {
1378
+ priceIsRequired = true;
1379
+ }
1380
+ if (uppercaseType === 'STOP') {
1381
+ const triggerPrice = this.safeNumber (params, 'trigger_price');
1382
+ if (triggerPrice === undefined) {
1383
+ throw new ArgumentsRequired (this.id + ' createOrder() requires a trigger_price param for ' + type + ' orders');
1384
+ }
1385
+ request['trigger_price'] = this.priceToPrecision (symbol, triggerPrice);
1386
+ params = this.omit (params, 'trigger_price');
1387
+ }
1388
+ if (priceIsRequired) {
1389
+ request['price'] = this.priceToPrecision (symbol, price);
1390
+ }
1391
+ const clientOrderId = this.safeString2 (params, 'clientOrderId', 'client_id');
1392
+ if (clientOrderId !== undefined) {
1393
+ request['client_id'] = clientOrderId;
1394
+ params = this.omit (params, [ 'clientOrderId', 'client_id' ]);
1395
+ }
1396
+ const response = await this.privatePostAccountOrders (this.extend (request, params));
1397
+ //
1398
+ // {
1399
+ // "order_id": "d5492c24-2995-4c18-993a-5b8bf8fffc0d",
1400
+ // "client_id": "d75fb03b-b599-49e9-b926-3f0b6d103206",
1401
+ // "account_id": "a4c699f6-338d-4a26-941f-8f9853bfc4b9",
1402
+ // "instrument_code": "BTC_EUR",
1403
+ // "time": "2019-08-01T08:00:44.026Z",
1404
+ // "side": "BUY",
1405
+ // "price": "5000",
1406
+ // "amount": "1",
1407
+ // "filled_amount": "0.5",
1408
+ // "type": "LIMIT",
1409
+ // "time_in_force": "GOOD_TILL_CANCELLED"
1410
+ // }
1411
+ //
1412
+ return this.parseOrder (response, market);
1413
+ }
1414
+
1415
+ async cancelOrder (id, symbol = undefined, params = {}) {
1416
+ await this.loadMarkets ();
1417
+ const clientOrderId = this.safeString2 (params, 'clientOrderId', 'client_id');
1418
+ params = this.omit (params, [ 'clientOrderId', 'client_id' ]);
1419
+ let method = 'privateDeleteAccountOrdersOrderId';
1420
+ const request = {};
1421
+ if (clientOrderId !== undefined) {
1422
+ method = 'privateDeleteAccountOrdersClientClientId';
1423
+ request['client_id'] = clientOrderId;
1424
+ } else {
1425
+ request['order_id'] = id;
1426
+ }
1427
+ const response = await this[method] (this.extend (request, params));
1428
+ //
1429
+ // responds with an empty body
1430
+ //
1431
+ return response;
1432
+ }
1433
+
1434
+ async cancelAllOrders (symbol = undefined, params = {}) {
1435
+ await this.loadMarkets ();
1436
+ const request = {};
1437
+ if (symbol !== undefined) {
1438
+ const market = this.market (symbol);
1439
+ request['instrument_code'] = market['id'];
1440
+ }
1441
+ const response = await this.privateDeleteAccountOrders (this.extend (request, params));
1442
+ //
1443
+ // [
1444
+ // "a10e9bd1-8f72-4cfe-9f1b-7f1c8a9bd8ee"
1445
+ // ]
1446
+ //
1447
+ return response;
1448
+ }
1449
+
1450
+ async cancelOrders (ids, symbol = undefined, params = {}) {
1451
+ await this.loadMarkets ();
1452
+ const request = {
1453
+ 'ids': ids.join (','),
1454
+ };
1455
+ const response = await this.privateDeleteAccountOrders (this.extend (request, params));
1456
+ //
1457
+ // [
1458
+ // "a10e9bd1-8f72-4cfe-9f1b-7f1c8a9bd8ee"
1459
+ // ]
1460
+ //
1461
+ return response;
1462
+ }
1463
+
1464
+ async fetchOrder (id, symbol = undefined, params = {}) {
1465
+ await this.loadMarkets ();
1466
+ const request = {
1467
+ 'order_id': id,
1468
+ };
1469
+ const response = await this.privateGetAccountOrdersOrderId (this.extend (request, params));
1470
+ //
1471
+ // {
1472
+ // "order": {
1473
+ // "order_id": "36bb2437-7402-4794-bf26-4bdf03526439",
1474
+ // "account_id": "a4c699f6-338d-4a26-941f-8f9853bfc4b9",
1475
+ // "time_last_updated": "2019-09-27T15:05:35.096Z",
1476
+ // "sequence": 48782,
1477
+ // "price": "7349.2",
1478
+ // "filled_amount": "100.0",
1479
+ // "status": "FILLED_FULLY",
1480
+ // "amount": "100.0",
1481
+ // "instrument_code": "BTC_EUR",
1482
+ // "side": "BUY",
1483
+ // "time": "2019-09-27T15:05:32.063Z",
1484
+ // "type": "MARKET"
1485
+ // },
1486
+ // "trades": [
1487
+ // {
1488
+ // "fee": {
1489
+ // "fee_amount": "0.0014",
1490
+ // "fee_currency": "BTC",
1491
+ // "fee_percentage": "0.1",
1492
+ // "fee_group_id": "default",
1493
+ // "fee_type": "TAKER",
1494
+ // "running_trading_volume": "0.0"
1495
+ // },
1496
+ // "trade": {
1497
+ // "trade_id": "fdff2bcc-37d6-4a2d-92a5-46e09c868664",
1498
+ // "order_id": "36bb2437-7402-4794-bf26-4bdf03526439",
1499
+ // "account_id": "a4c699f6-338d-4a26-941f-8f9853bfc4b9",
1500
+ // "amount": "1.4",
1501
+ // "side": "BUY",
1502
+ // "instrument_code": "BTC_EUR",
1503
+ // "price": "7341.4",
1504
+ // "time": "2019-09-27T15:05:32.564Z",
1505
+ // "sequence": 48670
1506
+ // }
1507
+ // }
1508
+ // ]
1509
+ // }
1510
+ //
1511
+ return this.parseOrder (response);
1512
+ }
1513
+
1514
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1515
+ await this.loadMarkets ();
1516
+ const request = {
1517
+ // 'from': this.iso8601 (since),
1518
+ // 'to': this.iso8601 (this.milliseconds ()), // max range is 100 days
1519
+ // 'instrument_code': market['id'],
1520
+ // 'with_cancelled_and_rejected': false, // default is false, orders which have been cancelled by the user before being filled or rejected by the system as invalid, additionally, all inactive filled orders which would return with "with_just_filled_inactive"
1521
+ // 'with_just_filled_inactive': false, // orders which have been filled and are no longer open, use of "with_cancelled_and_rejected" extends "with_just_filled_inactive" and in case both are specified the latter is ignored
1522
+ // 'with_just_orders': false, // do not return any trades corresponsing to the orders, it may be significanly faster and should be used if user is not interesting in trade information
1523
+ // 'max_page_size': 100,
1524
+ // 'cursor': 'string', // pointer specifying the position from which the next pages should be returned
1525
+ };
1526
+ let market = undefined;
1527
+ if (symbol !== undefined) {
1528
+ market = this.market (symbol);
1529
+ request['instrument_code'] = market['id'];
1530
+ }
1531
+ if (since !== undefined) {
1532
+ const to = this.safeString (params, 'to');
1533
+ if (to === undefined) {
1534
+ throw new ArgumentsRequired (this.id + ' fetchOrders() requires a "to" iso8601 string param with the since argument is specified, max range is 100 days');
1535
+ }
1536
+ request['from'] = this.iso8601 (since);
1537
+ }
1538
+ if (limit !== undefined) {
1539
+ request['max_page_size'] = limit;
1540
+ }
1541
+ const response = await this.privateGetAccountOrders (this.extend (request, params));
1542
+ //
1543
+ // {
1544
+ // "order_history": [
1545
+ // {
1546
+ // "order": {
1547
+ // "trigger_price": "12089.88",
1548
+ // "order_id": "d453ca12-c650-46dd-9dee-66910d96bfc0",
1549
+ // "account_id": "ef3a5f4c-cfcd-415e-ba89-5a9abf47b28a",
1550
+ // "instrument_code": "BTC_USDT",
1551
+ // "time": "2019-08-23T10:02:31.663Z",
1552
+ // "side": "SELL",
1553
+ // "price": "10159.76",
1554
+ // "average_price": "10159.76",
1555
+ // "amount": "0.2",
1556
+ // "filled_amount": "0.2",
1557
+ // "type": "STOP",
1558
+ // "sequence": 8,
1559
+ // "status": "FILLED_FULLY"
1560
+ // },
1561
+ // "trades": [
1562
+ // {
1563
+ // "fee": {
1564
+ // "fee_amount": "0.4188869",
1565
+ // "fee_currency": "USDT",
1566
+ // "fee_percentage": "0.1",
1567
+ // "fee_group_id": "default",
1568
+ // "fee_type": "TAKER",
1569
+ // "running_trading_volume": "0.0"
1570
+ // },
1571
+ // "trade": {
1572
+ // "trade_id": "ec82896f-fd1b-4cbb-89df-a9da85ccbb4b",
1573
+ // "order_id": "d453ca12-c650-46dd-9dee-66910d96bfc0",
1574
+ // "account_id": "ef3a5f4c-cfcd-415e-ba89-5a9abf47b28a",
1575
+ // "amount": "0.2",
1576
+ // "side": "SELL",
1577
+ // "instrument_code": "BTC_USDT",
1578
+ // "price": "10159.76",
1579
+ // "time": "2019-08-23T10:02:32.663Z",
1580
+ // "sequence": 9
1581
+ // }
1582
+ // }
1583
+ // ]
1584
+ // },
1585
+ // {
1586
+ // "order": {
1587
+ // "order_id": "5151a99e-f414-418f-8cf1-2568d0a63ea5",
1588
+ // "account_id": "ef3a5f4c-cfcd-415e-ba89-5a9abf47b28a",
1589
+ // "instrument_code": "BTC_USDT",
1590
+ // "time": "2019-08-23T10:01:36.773Z",
1591
+ // "side": "SELL",
1592
+ // "price": "12289.88",
1593
+ // "amount": "0.5",
1594
+ // "filled_amount": "0.0",
1595
+ // "type": "LIMIT",
1596
+ // "sequence": 7,
1597
+ // "status": "OPEN"
1598
+ // },
1599
+ // "trades": []
1600
+ // },
1601
+ // {
1602
+ // "order": {
1603
+ // "order_id": "ac80d857-75e1-4733-9070-fd4288395fdc",
1604
+ // "account_id": "ef3a5f4c-cfcd-415e-ba89-5a9abf47b28a",
1605
+ // "instrument_code": "BTC_USDT",
1606
+ // "time": "2019-08-23T10:01:25.031Z",
1607
+ // "side": "SELL",
1608
+ // "price": "11089.88",
1609
+ // "amount": "0.1",
1610
+ // "filled_amount": "0.0",
1611
+ // "type": "LIMIT",
1612
+ // "sequence": 6,
1613
+ // "status": "OPEN"
1614
+ // },
1615
+ // "trades": []
1616
+ // }
1617
+ // ],
1618
+ // "max_page_size": 100
1619
+ // }
1620
+ //
1621
+ const orderHistory = this.safeValue (response, 'order_history', []);
1622
+ return this.parseOrders (orderHistory, market, since, limit);
1623
+ }
1624
+
1625
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1626
+ const request = {
1627
+ 'with_cancelled_and_rejected': true, // default is false, orders which have been cancelled by the user before being filled or rejected by the system as invalid, additionally, all inactive filled orders which would return with "with_just_filled_inactive"
1628
+ };
1629
+ return await this.fetchOpenOrders (symbol, since, limit, this.extend (request, params));
1630
+ }
1631
+
1632
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1633
+ await this.loadMarkets ();
1634
+ const request = {
1635
+ 'order_id': id,
1636
+ // 'max_page_size': 100,
1637
+ // 'cursor': 'string', // pointer specifying the position from which the next pages should be returned
1638
+ };
1639
+ if (limit !== undefined) {
1640
+ request['max_page_size'] = limit;
1641
+ }
1642
+ const response = await this.privateGetAccountOrdersOrderIdTrades (this.extend (request, params));
1643
+ //
1644
+ // {
1645
+ // "trade_history": [
1646
+ // {
1647
+ // "trade": {
1648
+ // "trade_id": "2b42efcd-d5b7-4a56-8e12-b69ffd68c5ef",
1649
+ // "order_id": "66756a10-3e86-48f4-9678-b634c4b135b2",
1650
+ // "account_id": "c2d0076a-c20d-41f8-9e9a-1a1d028b2b58",
1651
+ // "amount": "1234.5678",
1652
+ // "side": "BUY",
1653
+ // "instrument_code": "BTC_EUR",
1654
+ // "price": "1234.5678",
1655
+ // "time": "2019-08-24T14:15:22Z",
1656
+ // "price_tick_sequence": 0,
1657
+ // "sequence": 123456789
1658
+ // },
1659
+ // "fee": {
1660
+ // "fee_amount": "1234.5678",
1661
+ // "fee_percentage": "1234.5678",
1662
+ // "fee_group_id": "default",
1663
+ // "running_trading_volume": "1234.5678",
1664
+ // "fee_currency": "BTC",
1665
+ // "fee_type": "TAKER"
1666
+ // }
1667
+ // }
1668
+ // ],
1669
+ // "max_page_size": 0,
1670
+ // "cursor": "string"
1671
+ // }
1672
+ //
1673
+ const tradeHistory = this.safeValue (response, 'trade_history', []);
1674
+ let market = undefined;
1675
+ if (symbol !== undefined) {
1676
+ market = this.market (symbol);
1677
+ }
1678
+ return this.parseTrades (tradeHistory, market, since, limit);
1679
+ }
1680
+
1681
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1682
+ await this.loadMarkets ();
1683
+ const request = {
1684
+ // 'from': this.iso8601 (since),
1685
+ // 'to': this.iso8601 (this.milliseconds ()), // max range is 100 days
1686
+ // 'instrument_code': market['id'],
1687
+ // 'max_page_size': 100,
1688
+ // 'cursor': 'string', // pointer specifying the position from which the next pages should be returned
1689
+ };
1690
+ let market = undefined;
1691
+ if (symbol !== undefined) {
1692
+ market = this.market (symbol);
1693
+ request['instrument_code'] = market['id'];
1694
+ }
1695
+ if (since !== undefined) {
1696
+ const to = this.safeString (params, 'to');
1697
+ if (to === undefined) {
1698
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a "to" iso8601 string param with the since argument is specified, max range is 100 days');
1699
+ }
1700
+ request['from'] = this.iso8601 (since);
1701
+ }
1702
+ if (limit !== undefined) {
1703
+ request['max_page_size'] = limit;
1704
+ }
1705
+ const response = await this.privateGetAccountTrades (this.extend (request, params));
1706
+ //
1707
+ // {
1708
+ // "trade_history": [
1709
+ // {
1710
+ // "trade": {
1711
+ // "trade_id": "2b42efcd-d5b7-4a56-8e12-b69ffd68c5ef",
1712
+ // "order_id": "66756a10-3e86-48f4-9678-b634c4b135b2",
1713
+ // "account_id": "c2d0076a-c20d-41f8-9e9a-1a1d028b2b58",
1714
+ // "amount": "1234.5678",
1715
+ // "side": "BUY",
1716
+ // "instrument_code": "BTC_EUR",
1717
+ // "price": "1234.5678",
1718
+ // "time": "2019-08-24T14:15:22Z",
1719
+ // "price_tick_sequence": 0,
1720
+ // "sequence": 123456789
1721
+ // },
1722
+ // "fee": {
1723
+ // "fee_amount": "1234.5678",
1724
+ // "fee_percentage": "1234.5678",
1725
+ // "fee_group_id": "default",
1726
+ // "running_trading_volume": "1234.5678",
1727
+ // "fee_currency": "BTC",
1728
+ // "fee_type": "TAKER"
1729
+ // }
1730
+ // }
1731
+ // ],
1732
+ // "max_page_size": 0,
1733
+ // "cursor": "string"
1734
+ // }
1735
+ //
1736
+ const tradeHistory = this.safeValue (response, 'trade_history', []);
1737
+ return this.parseTrades (tradeHistory, market, since, limit);
1738
+ }
1739
+
1740
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1741
+ let url = this.urls['api'][api] + '/' + this.version + '/' + this.implodeParams (path, params);
1742
+ const query = this.omit (params, this.extractParams (path));
1743
+ if (api === 'public') {
1744
+ if (Object.keys (query).length) {
1745
+ url += '?' + this.urlencode (query);
1746
+ }
1747
+ } else if (api === 'private') {
1748
+ this.checkRequiredCredentials ();
1749
+ headers = {
1750
+ 'Accept': 'application/json',
1751
+ 'Authorization': 'Bearer ' + this.apiKey,
1752
+ };
1753
+ if (method === 'POST') {
1754
+ body = this.json (query);
1755
+ headers['Content-Type'] = 'application/json';
1756
+ } else {
1757
+ if (Object.keys (query).length) {
1758
+ url += '?' + this.urlencode (query);
1759
+ }
1760
+ }
1761
+ }
1762
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1763
+ }
1764
+
1765
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1766
+ if (response === undefined) {
1767
+ return;
1768
+ }
1769
+ //
1770
+ // {"error":"MISSING_FROM_PARAM"}
1771
+ // {"error":"MISSING_TO_PARAM"}
1772
+ // {"error":"CANDLESTICKS_TIME_RANGE_TOO_BIG"}
1773
+ //
1774
+ const message = this.safeString (response, 'error');
1775
+ if (message !== undefined) {
1776
+ const feedback = this.id + ' ' + body;
1777
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
1778
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
1779
+ throw new ExchangeError (feedback); // unknown message
1780
+ }
1781
+ }
1782
+ };