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/luno.js ADDED
@@ -0,0 +1,873 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, ArgumentsRequired } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class luno extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'luno',
15
+ 'name': 'luno',
16
+ 'countries': [ 'GB', 'SG', 'ZA' ],
17
+ // 300 calls per minute = 5 calls per second = 1000ms / 5 = 200ms between requests
18
+ 'rateLimit': 200,
19
+ 'version': '1',
20
+ 'has': {
21
+ 'CORS': undefined,
22
+ 'spot': true,
23
+ 'margin': false,
24
+ 'swap': false,
25
+ 'future': false,
26
+ 'option': false,
27
+ 'addMargin': false,
28
+ 'cancelOrder': true,
29
+ 'createOrder': true,
30
+ 'createReduceOnlyOrder': false,
31
+ 'fetchAccounts': true,
32
+ 'fetchBalance': true,
33
+ 'fetchBorrowRate': false,
34
+ 'fetchBorrowRateHistory': false,
35
+ 'fetchBorrowRates': false,
36
+ 'fetchBorrowRatesPerSymbol': false,
37
+ 'fetchClosedOrders': true,
38
+ 'fetchFundingHistory': false,
39
+ 'fetchFundingRate': false,
40
+ 'fetchFundingRateHistory': false,
41
+ 'fetchFundingRates': false,
42
+ 'fetchIndexOHLCV': false,
43
+ 'fetchLedger': true,
44
+ 'fetchLeverage': false,
45
+ 'fetchLeverageTiers': false,
46
+ 'fetchMarkets': true,
47
+ 'fetchMarkOHLCV': false,
48
+ 'fetchMyTrades': true,
49
+ 'fetchOpenOrders': true,
50
+ 'fetchOrder': true,
51
+ 'fetchOrderBook': true,
52
+ 'fetchOrders': true,
53
+ 'fetchPosition': false,
54
+ 'fetchPositions': false,
55
+ 'fetchPositionsRisk': false,
56
+ 'fetchPremiumIndexOHLCV': false,
57
+ 'fetchTicker': true,
58
+ 'fetchTickers': true,
59
+ 'fetchTrades': true,
60
+ 'fetchTradingFees': true,
61
+ 'reduceMargin': false,
62
+ 'setLeverage': false,
63
+ 'setMarginMode': false,
64
+ 'setPositionMode': false,
65
+ },
66
+ 'urls': {
67
+ 'referral': 'https://www.luno.com/invite/44893A',
68
+ 'logo': 'https://user-images.githubusercontent.com/1294454/27766607-8c1a69d8-5ede-11e7-930c-540b5eb9be24.jpg',
69
+ 'api': {
70
+ 'public': 'https://api.luno.com/api',
71
+ 'private': 'https://api.luno.com/api',
72
+ 'exchange': 'https://api.luno.com/api/exchange',
73
+ },
74
+ 'www': 'https://www.luno.com',
75
+ 'doc': [
76
+ 'https://www.luno.com/en/api',
77
+ 'https://npmjs.org/package/bitx',
78
+ 'https://github.com/bausmeier/node-bitx',
79
+ ],
80
+ },
81
+ 'api': {
82
+ 'exchange': {
83
+ 'get': {
84
+ 'markets': 1,
85
+ },
86
+ },
87
+ 'public': {
88
+ 'get': {
89
+ 'orderbook': 1,
90
+ 'orderbook_top': 1,
91
+ 'ticker': 1,
92
+ 'tickers': 1,
93
+ 'trades': 1,
94
+ },
95
+ },
96
+ 'private': {
97
+ 'get': {
98
+ 'accounts/{id}/pending': 1,
99
+ 'accounts/{id}/transactions': 1,
100
+ 'balance': 1,
101
+ 'beneficiaries': 1,
102
+ 'fee_info': 1,
103
+ 'funding_address': 1,
104
+ 'listorders': 1,
105
+ 'listtrades': 1,
106
+ 'orders/{id}': 1,
107
+ 'quotes/{id}': 1,
108
+ 'withdrawals': 1,
109
+ 'withdrawals/{id}': 1,
110
+ 'transfers': 1,
111
+ // GET /api/exchange/2/listorders
112
+ // GET /api/exchange/2/orders/{id}
113
+ // GET /api/exchange/3/order
114
+ },
115
+ 'post': {
116
+ 'accounts': 1,
117
+ 'accounts/{id}/name': 1,
118
+ 'postorder': 1,
119
+ 'marketorder': 1,
120
+ 'stoporder': 1,
121
+ 'funding_address': 1,
122
+ 'withdrawals': 1,
123
+ 'send': 1,
124
+ 'quotes': 1,
125
+ 'oauth2/grant': 1,
126
+ },
127
+ 'put': {
128
+ 'accounts/{id}/name': 1,
129
+ 'quotes/{id}': 1,
130
+ },
131
+ 'delete': {
132
+ 'quotes/{id}': 1,
133
+ 'withdrawals/{id}': 1,
134
+ },
135
+ },
136
+ },
137
+ 'fees': {
138
+ 'trading': {
139
+ 'tierBased': true, // based on volume from your primary currency (not the same for everyone)
140
+ 'percentage': true,
141
+ 'taker': this.parseNumber ('0.001'),
142
+ 'maker': this.parseNumber ('0'),
143
+ },
144
+ },
145
+ });
146
+ }
147
+
148
+ async fetchMarkets (params = {}) {
149
+ const response = await this.exchangeGetMarkets (params);
150
+ //
151
+ // {
152
+ // "markets":[
153
+ // {
154
+ // "market_id":"BCHXBT",
155
+ // "trading_status":"ACTIVE",
156
+ // "base_currency":"BCH",
157
+ // "counter_currency":"XBT",
158
+ // "min_volume":"0.01",
159
+ // "max_volume":"100.00",
160
+ // "volume_scale":2,
161
+ // "min_price":"0.0001",
162
+ // "max_price":"1.00",
163
+ // "price_scale":6,
164
+ // "fee_scale":8,
165
+ // },
166
+ // ]
167
+ // }
168
+ //
169
+ const result = [];
170
+ const markets = this.safeValue (response, 'markets', []);
171
+ for (let i = 0; i < markets.length; i++) {
172
+ const market = markets[i];
173
+ const id = this.safeString (market, 'market_id');
174
+ const baseId = this.safeString (market, 'base_currency');
175
+ const quoteId = this.safeString (market, 'counter_currency');
176
+ const base = this.safeCurrencyCode (baseId);
177
+ const quote = this.safeCurrencyCode (quoteId);
178
+ const status = this.safeString (market, 'trading_status');
179
+ result.push ({
180
+ 'id': id,
181
+ 'symbol': base + '/' + quote,
182
+ 'base': base,
183
+ 'quote': quote,
184
+ 'settle': undefined,
185
+ 'baseId': baseId,
186
+ 'quoteId': quoteId,
187
+ 'settleId': undefined,
188
+ 'type': 'spot',
189
+ 'spot': true,
190
+ 'margin': false,
191
+ 'swap': false,
192
+ 'future': false,
193
+ 'option': false,
194
+ 'active': (status === 'ACTIVE'),
195
+ 'contract': false,
196
+ 'linear': undefined,
197
+ 'inverse': undefined,
198
+ 'contractSize': undefined,
199
+ 'expiry': undefined,
200
+ 'expiryDatetime': undefined,
201
+ 'strike': undefined,
202
+ 'optionType': undefined,
203
+ 'precision': {
204
+ 'amount': this.safeInteger (market, 'volume_scale'),
205
+ 'price': this.safeInteger (market, 'price_scale'),
206
+ },
207
+ 'limits': {
208
+ 'leverage': {
209
+ 'min': undefined,
210
+ 'max': undefined,
211
+ },
212
+ 'amount': {
213
+ 'min': this.safeNumber (market, 'min_volume'),
214
+ 'max': this.safeNumber (market, 'max_volume'),
215
+ },
216
+ 'price': {
217
+ 'min': this.safeNumber (market, 'min_price'),
218
+ 'max': this.safeNumber (market, 'max_price'),
219
+ },
220
+ 'cost': {
221
+ 'min': undefined,
222
+ 'max': undefined,
223
+ },
224
+ },
225
+ 'info': market,
226
+ });
227
+ }
228
+ return result;
229
+ }
230
+
231
+ async fetchAccounts (params = {}) {
232
+ const response = await this.privateGetBalance (params);
233
+ const wallets = this.safeValue (response, 'balance', []);
234
+ const result = [];
235
+ for (let i = 0; i < wallets.length; i++) {
236
+ const account = wallets[i];
237
+ const accountId = this.safeString (account, 'account_id');
238
+ const currencyId = this.safeString (account, 'asset');
239
+ const code = this.safeCurrencyCode (currencyId);
240
+ result.push ({
241
+ 'id': accountId,
242
+ 'type': undefined,
243
+ 'currency': code,
244
+ 'info': account,
245
+ });
246
+ }
247
+ return result;
248
+ }
249
+
250
+ parseBalance (response) {
251
+ const wallets = this.safeValue (response, 'balance', []);
252
+ const result = {
253
+ 'info': response,
254
+ 'timestamp': undefined,
255
+ 'datetime': undefined,
256
+ };
257
+ for (let i = 0; i < wallets.length; i++) {
258
+ const wallet = wallets[i];
259
+ const currencyId = this.safeString (wallet, 'asset');
260
+ const code = this.safeCurrencyCode (currencyId);
261
+ const reserved = this.safeString (wallet, 'reserved');
262
+ const unconfirmed = this.safeString (wallet, 'unconfirmed');
263
+ const balance = this.safeString (wallet, 'balance');
264
+ const reservedUnconfirmed = Precise.stringAdd (reserved, unconfirmed);
265
+ const balanceUnconfirmed = Precise.stringAdd (balance, unconfirmed);
266
+ if (code in result) {
267
+ result[code]['used'] = Precise.stringAdd (result[code]['used'], reservedUnconfirmed);
268
+ result[code]['total'] = Precise.stringAdd (result[code]['total'], balanceUnconfirmed);
269
+ } else {
270
+ const account = this.account ();
271
+ account['used'] = reservedUnconfirmed;
272
+ account['total'] = balanceUnconfirmed;
273
+ result[code] = account;
274
+ }
275
+ }
276
+ return this.safeBalance (result);
277
+ }
278
+
279
+ async fetchBalance (params = {}) {
280
+ await this.loadMarkets ();
281
+ const response = await this.privateGetBalance (params);
282
+ //
283
+ // {
284
+ // 'balance': [
285
+ // {'account_id': '119...1336','asset': 'XBT','balance': '0.00','reserved': '0.00','unconfirmed': '0.00'},
286
+ // {'account_id': '66...289','asset': 'XBT','balance': '0.00','reserved': '0.00','unconfirmed': '0.00'},
287
+ // {'account_id': '718...5300','asset': 'ETH','balance': '0.00','reserved': '0.00','unconfirmed': '0.00'},
288
+ // {'account_id': '818...7072','asset': 'ZAR','balance': '0.001417','reserved': '0.00','unconfirmed': '0.00'}]}
289
+ // ]
290
+ // }
291
+ //
292
+ return this.parseBalance (response);
293
+ }
294
+
295
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
296
+ await this.loadMarkets ();
297
+ let method = 'publicGetOrderbook';
298
+ if (limit !== undefined) {
299
+ if (limit <= 100) {
300
+ method += 'Top'; // get just the top of the orderbook when limit is low
301
+ }
302
+ }
303
+ const request = {
304
+ 'pair': this.marketId (symbol),
305
+ };
306
+ const response = await this[method] (this.extend (request, params));
307
+ const timestamp = this.safeInteger (response, 'timestamp');
308
+ return this.parseOrderBook (response, symbol, timestamp, 'bids', 'asks', 'price', 'volume');
309
+ }
310
+
311
+ parseOrderStatus (status) {
312
+ const statuses = {
313
+ // todo add other statuses
314
+ 'PENDING': 'open',
315
+ };
316
+ return this.safeString (statuses, status, status);
317
+ }
318
+
319
+ parseOrder (order, market = undefined) {
320
+ //
321
+ // {
322
+ // "base": "string",
323
+ // "completed_timestamp": "string",
324
+ // "counter": "string",
325
+ // "creation_timestamp": "string",
326
+ // "expiration_timestamp": "string",
327
+ // "fee_base": "string",
328
+ // "fee_counter": "string",
329
+ // "limit_price": "string",
330
+ // "limit_volume": "string",
331
+ // "order_id": "string",
332
+ // "pair": "string",
333
+ // "state": "PENDING",
334
+ // "type": "BID"
335
+ // }
336
+ //
337
+ const timestamp = this.safeInteger (order, 'creation_timestamp');
338
+ let status = this.parseOrderStatus (this.safeString (order, 'state'));
339
+ status = (status === 'open') ? status : status;
340
+ let side = undefined;
341
+ const orderType = this.safeString (order, 'type');
342
+ if ((orderType === 'ASK') || (orderType === 'SELL')) {
343
+ side = 'sell';
344
+ } else if ((orderType === 'BID') || (orderType === 'BUY')) {
345
+ side = 'buy';
346
+ }
347
+ const marketId = this.safeString (order, 'pair');
348
+ market = this.safeMarket (marketId, market);
349
+ const price = this.safeString (order, 'limit_price');
350
+ const amount = this.safeString (order, 'limit_volume');
351
+ const quoteFee = this.safeNumber (order, 'fee_counter');
352
+ const baseFee = this.safeNumber (order, 'fee_base');
353
+ const filled = this.safeString (order, 'base');
354
+ const cost = this.safeString (order, 'counter');
355
+ let fee = undefined;
356
+ if (quoteFee !== undefined) {
357
+ fee = {
358
+ 'cost': quoteFee,
359
+ 'currency': market['quote'],
360
+ };
361
+ } else if (baseFee !== undefined) {
362
+ fee = {
363
+ 'cost': baseFee,
364
+ 'currency': market['base'],
365
+ };
366
+ }
367
+ const id = this.safeString (order, 'order_id');
368
+ return this.safeOrder ({
369
+ 'id': id,
370
+ 'clientOrderId': undefined,
371
+ 'datetime': this.iso8601 (timestamp),
372
+ 'timestamp': timestamp,
373
+ 'lastTradeTimestamp': undefined,
374
+ 'status': status,
375
+ 'symbol': market['symbol'],
376
+ 'type': undefined,
377
+ 'timeInForce': undefined,
378
+ 'postOnly': undefined,
379
+ 'side': side,
380
+ 'price': price,
381
+ 'stopPrice': undefined,
382
+ 'amount': amount,
383
+ 'filled': filled,
384
+ 'cost': cost,
385
+ 'remaining': undefined,
386
+ 'trades': undefined,
387
+ 'fee': fee,
388
+ 'info': order,
389
+ 'average': undefined,
390
+ }, market);
391
+ }
392
+
393
+ async fetchOrder (id, symbol = undefined, params = {}) {
394
+ await this.loadMarkets ();
395
+ const request = {
396
+ 'id': id,
397
+ };
398
+ const response = await this.privateGetOrdersId (this.extend (request, params));
399
+ return this.parseOrder (response);
400
+ }
401
+
402
+ async fetchOrdersByState (state = undefined, symbol = undefined, since = undefined, limit = undefined, params = {}) {
403
+ await this.loadMarkets ();
404
+ const request = {};
405
+ let market = undefined;
406
+ if (state !== undefined) {
407
+ request['state'] = state;
408
+ }
409
+ if (symbol !== undefined) {
410
+ market = this.market (symbol);
411
+ request['pair'] = market['id'];
412
+ }
413
+ const response = await this.privateGetListorders (this.extend (request, params));
414
+ const orders = this.safeValue (response, 'orders', []);
415
+ return this.parseOrders (orders, market, since, limit);
416
+ }
417
+
418
+ async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
419
+ return await this.fetchOrdersByState (undefined, symbol, since, limit, params);
420
+ }
421
+
422
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
423
+ return await this.fetchOrdersByState ('PENDING', symbol, since, limit, params);
424
+ }
425
+
426
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
427
+ return await this.fetchOrdersByState ('COMPLETE', symbol, since, limit, params);
428
+ }
429
+
430
+ parseTicker (ticker, market = undefined) {
431
+ // {
432
+ // "pair":"XBTAUD",
433
+ // "timestamp":1642201439301,
434
+ // "bid":"59972.30000000",
435
+ // "ask":"59997.99000000",
436
+ // "last_trade":"59997.99000000",
437
+ // "rolling_24_hour_volume":"1.89510000",
438
+ // "status":"ACTIVE"
439
+ // }
440
+ const timestamp = this.safeInteger (ticker, 'timestamp');
441
+ const marketId = this.safeString (ticker, 'pair');
442
+ const symbol = this.safeSymbol (marketId, market);
443
+ const last = this.safeString (ticker, 'last_trade');
444
+ return this.safeTicker ({
445
+ 'symbol': symbol,
446
+ 'timestamp': timestamp,
447
+ 'datetime': this.iso8601 (timestamp),
448
+ 'high': undefined,
449
+ 'low': undefined,
450
+ 'bid': this.safeString (ticker, 'bid'),
451
+ 'bidVolume': undefined,
452
+ 'ask': this.safeString (ticker, 'ask'),
453
+ 'askVolume': undefined,
454
+ 'vwap': undefined,
455
+ 'open': undefined,
456
+ 'close': last,
457
+ 'last': last,
458
+ 'previousClose': undefined,
459
+ 'change': undefined,
460
+ 'percentage': undefined,
461
+ 'average': undefined,
462
+ 'baseVolume': this.safeString (ticker, 'rolling_24_hour_volume'),
463
+ 'quoteVolume': undefined,
464
+ 'info': ticker,
465
+ }, market, false);
466
+ }
467
+
468
+ async fetchTickers (symbols = undefined, params = {}) {
469
+ await this.loadMarkets ();
470
+ const response = await this.publicGetTickers (params);
471
+ const tickers = this.indexBy (response['tickers'], 'pair');
472
+ const ids = Object.keys (tickers);
473
+ const result = {};
474
+ for (let i = 0; i < ids.length; i++) {
475
+ const id = ids[i];
476
+ const market = this.safeMarket (id);
477
+ const symbol = market['symbol'];
478
+ const ticker = tickers[id];
479
+ result[symbol] = this.parseTicker (ticker, market);
480
+ }
481
+ return this.filterByArray (result, 'symbol', symbols);
482
+ }
483
+
484
+ async fetchTicker (symbol, params = {}) {
485
+ await this.loadMarkets ();
486
+ const market = this.market (symbol);
487
+ const request = {
488
+ 'pair': market['id'],
489
+ };
490
+ const response = await this.publicGetTicker (this.extend (request, params));
491
+ // {
492
+ // "pair":"XBTAUD",
493
+ // "timestamp":1642201439301,
494
+ // "bid":"59972.30000000",
495
+ // "ask":"59997.99000000",
496
+ // "last_trade":"59997.99000000",
497
+ // "rolling_24_hour_volume":"1.89510000",
498
+ // "status":"ACTIVE"
499
+ // }
500
+ return this.parseTicker (response, market);
501
+ }
502
+
503
+ parseTrade (trade, market) {
504
+ //
505
+ // fetchTrades (public)
506
+ //
507
+ // {
508
+ // "sequence":276989,
509
+ // "timestamp":1648651276949,
510
+ // "price":"35773.20000000",
511
+ // "volume":"0.00300000",
512
+ // "is_buy":false
513
+ // }
514
+ //
515
+ // fetchMyTrades (private)
516
+ //
517
+ // {
518
+ // "pair":"LTCXBT",
519
+ // "sequence":3256813,
520
+ // "order_id":"BXEX6XHHDT5EGW2",
521
+ // "type":"ASK",
522
+ // "timestamp":1648652135235,
523
+ // "price":"0.002786",
524
+ // "volume":"0.10",
525
+ // "base":"0.10",
526
+ // "counter":"0.0002786",
527
+ // "fee_base":"0.0001",
528
+ // "fee_counter":"0.00",
529
+ // "is_buy":false,
530
+ // "client_order_id":""
531
+ // }
532
+ //
533
+ // For public trade data (is_buy === True) indicates 'buy' side but for private trade data
534
+ // is_buy indicates maker or taker. The value of "type" (ASK/BID) indicate sell/buy side.
535
+ // Private trade data includes ID field which public trade data does not.
536
+ const orderId = this.safeString (trade, 'order_id');
537
+ const id = this.safeString (trade, 'sequence');
538
+ let takerOrMaker = undefined;
539
+ let side = undefined;
540
+ if (orderId !== undefined) {
541
+ const type = this.safeString (trade, 'type');
542
+ if ((type === 'ASK') || (type === 'SELL')) {
543
+ side = 'sell';
544
+ } else if ((type === 'BID') || (type === 'BUY')) {
545
+ side = 'buy';
546
+ }
547
+ if (side === 'sell' && trade['is_buy']) {
548
+ takerOrMaker = 'maker';
549
+ } else if (side === 'buy' && !trade['is_buy']) {
550
+ takerOrMaker = 'maker';
551
+ } else {
552
+ takerOrMaker = 'taker';
553
+ }
554
+ } else {
555
+ side = trade['is_buy'] ? 'buy' : 'sell';
556
+ }
557
+ const feeBaseString = this.safeString (trade, 'fee_base');
558
+ const feeCounterString = this.safeString (trade, 'fee_counter');
559
+ let feeCurrency = undefined;
560
+ let feeCost = undefined;
561
+ if (feeBaseString !== undefined) {
562
+ if (!Precise.stringEquals (feeBaseString, '0.0')) {
563
+ feeCurrency = market['base'];
564
+ feeCost = feeBaseString;
565
+ }
566
+ } else if (feeCounterString !== undefined) {
567
+ if (!Precise.stringEquals (feeCounterString, '0.0')) {
568
+ feeCurrency = market['quote'];
569
+ feeCost = feeCounterString;
570
+ }
571
+ }
572
+ const timestamp = this.safeInteger (trade, 'timestamp');
573
+ return this.safeTrade ({
574
+ 'info': trade,
575
+ 'id': id,
576
+ 'timestamp': timestamp,
577
+ 'datetime': this.iso8601 (timestamp),
578
+ 'symbol': market['symbol'],
579
+ 'order': orderId,
580
+ 'type': undefined,
581
+ 'side': side,
582
+ 'takerOrMaker': takerOrMaker,
583
+ 'price': this.safeString (trade, 'price'),
584
+ 'amount': this.safeString (trade, 'volume'),
585
+ // Does not include potential fee costs
586
+ 'cost': this.safeString (trade, 'counter'),
587
+ 'fee': {
588
+ 'cost': feeCost,
589
+ 'currency': feeCurrency,
590
+ },
591
+ }, market);
592
+ }
593
+
594
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
595
+ await this.loadMarkets ();
596
+ const market = this.market (symbol);
597
+ const request = {
598
+ 'pair': market['id'],
599
+ };
600
+ if (since !== undefined) {
601
+ request['since'] = since;
602
+ }
603
+ const response = await this.publicGetTrades (this.extend (request, params));
604
+ //
605
+ // {
606
+ // "trades":[
607
+ // {
608
+ // "sequence":276989,
609
+ // "timestamp":1648651276949,
610
+ // "price":"35773.20000000",
611
+ // "volume":"0.00300000",
612
+ // "is_buy":false
613
+ // },...
614
+ // ]
615
+ // }
616
+ //
617
+ const trades = this.safeValue (response, 'trades', []);
618
+ return this.parseTrades (trades, market, since, limit);
619
+ }
620
+
621
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
622
+ if (symbol === undefined) {
623
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument');
624
+ }
625
+ await this.loadMarkets ();
626
+ const market = this.market (symbol);
627
+ const request = {
628
+ 'pair': market['id'],
629
+ };
630
+ if (since !== undefined) {
631
+ request['since'] = since;
632
+ }
633
+ if (limit !== undefined) {
634
+ request['limit'] = limit;
635
+ }
636
+ const response = await this.privateGetListtrades (this.extend (request, params));
637
+ //
638
+ // {
639
+ // "trades":[
640
+ // {
641
+ // "pair":"LTCXBT",
642
+ // "sequence":3256813,
643
+ // "order_id":"BXEX6XHHDT5EGW2",
644
+ // "type":"ASK",
645
+ // "timestamp":1648652135235,
646
+ // "price":"0.002786",
647
+ // "volume":"0.10",
648
+ // "base":"0.10",
649
+ // "counter":"0.0002786",
650
+ // "fee_base":"0.0001",
651
+ // "fee_counter":"0.00",
652
+ // "is_buy":false,
653
+ // "client_order_id":""
654
+ // },...
655
+ // ]
656
+ // }
657
+ //
658
+ const trades = this.safeValue (response, 'trades', []);
659
+ return this.parseTrades (trades, market, since, limit);
660
+ }
661
+
662
+ async fetchTradingFees (params = {}) {
663
+ await this.loadMarkets ();
664
+ const response = await this.privateGetFeeInfo (params);
665
+ return {
666
+ 'info': response,
667
+ 'maker': this.safeNumber (response, 'maker_fee'),
668
+ 'taker': this.safeNumber (response, 'taker_fee'),
669
+ };
670
+ }
671
+
672
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
673
+ await this.loadMarkets ();
674
+ let method = 'privatePost';
675
+ const request = {
676
+ 'pair': this.marketId (symbol),
677
+ };
678
+ if (type === 'market') {
679
+ method += 'Marketorder';
680
+ request['type'] = side.toUpperCase ();
681
+ // todo add createMarketBuyOrderRequires price logic as it is implemented in the other exchanges
682
+ if (side === 'buy') {
683
+ request['counter_volume'] = parseFloat (this.amountToPrecision (symbol, amount));
684
+ } else {
685
+ request['base_volume'] = parseFloat (this.amountToPrecision (symbol, amount));
686
+ }
687
+ } else {
688
+ method += 'Postorder';
689
+ request['volume'] = parseFloat (this.amountToPrecision (symbol, amount));
690
+ request['price'] = parseFloat (this.priceToPrecision (symbol, price));
691
+ request['type'] = (side === 'buy') ? 'BID' : 'ASK';
692
+ }
693
+ const response = await this[method] (this.extend (request, params));
694
+ return {
695
+ 'info': response,
696
+ 'id': response['order_id'],
697
+ };
698
+ }
699
+
700
+ async cancelOrder (id, symbol = undefined, params = {}) {
701
+ await this.loadMarkets ();
702
+ const request = {
703
+ 'order_id': id,
704
+ };
705
+ return await this.privatePostStoporder (this.extend (request, params));
706
+ }
707
+
708
+ async fetchLedgerByEntries (code = undefined, entry = -1, limit = 1, params = {}) {
709
+ // by default without entry number or limit number, return most recent entry
710
+ const since = undefined;
711
+ const request = {
712
+ 'min_row': entry,
713
+ 'max_row': this.sum (entry, limit),
714
+ };
715
+ return await this.fetchLedger (code, since, limit, this.extend (request, params));
716
+ }
717
+
718
+ async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
719
+ await this.loadMarkets ();
720
+ await this.loadAccounts ();
721
+ let currency = undefined;
722
+ let id = this.safeString (params, 'id'); // account id
723
+ let min_row = this.safeValue (params, 'min_row');
724
+ let max_row = this.safeValue (params, 'max_row');
725
+ if (id === undefined) {
726
+ if (code === undefined) {
727
+ throw new ArgumentsRequired (this.id + ' fetchLedger() requires a currency code argument if no account id specified in params');
728
+ }
729
+ currency = this.currency (code);
730
+ const accountsByCurrencyCode = this.indexBy (this.accounts, 'currency');
731
+ const account = this.safeValue (accountsByCurrencyCode, code);
732
+ if (account === undefined) {
733
+ throw new ExchangeError (this.id + ' fetchLedger() could not find account id for ' + code);
734
+ }
735
+ id = account['id'];
736
+ }
737
+ if (min_row === undefined && max_row === undefined) {
738
+ max_row = 0; // Default to most recent transactions
739
+ min_row = -1000; // Maximum number of records supported
740
+ } else if (min_row === undefined || max_row === undefined) {
741
+ throw new ExchangeError (this.id + " fetchLedger() require both params 'max_row' and 'min_row' or neither to be defined");
742
+ }
743
+ if (limit !== undefined && max_row - min_row > limit) {
744
+ if (max_row <= 0) {
745
+ min_row = max_row - limit;
746
+ } else if (min_row > 0) {
747
+ max_row = min_row + limit;
748
+ }
749
+ }
750
+ if (max_row - min_row > 1000) {
751
+ throw new ExchangeError (this.id + " fetchLedger() requires the params 'max_row' - 'min_row' <= 1000");
752
+ }
753
+ const request = {
754
+ 'id': id,
755
+ 'min_row': min_row,
756
+ 'max_row': max_row,
757
+ };
758
+ const response = await this.privateGetAccountsIdTransactions (this.extend (params, request));
759
+ const entries = this.safeValue (response, 'transactions', []);
760
+ return this.parseLedger (entries, currency, since, limit);
761
+ }
762
+
763
+ parseLedgerComment (comment) {
764
+ const words = comment.split (' ');
765
+ const types = {
766
+ 'Withdrawal': 'fee',
767
+ 'Trading': 'fee',
768
+ 'Payment': 'transaction',
769
+ 'Sent': 'transaction',
770
+ 'Deposit': 'transaction',
771
+ 'Received': 'transaction',
772
+ 'Released': 'released',
773
+ 'Reserved': 'reserved',
774
+ 'Sold': 'trade',
775
+ 'Bought': 'trade',
776
+ 'Failure': 'failed',
777
+ };
778
+ let referenceId = undefined;
779
+ const firstWord = this.safeString (words, 0);
780
+ const thirdWord = this.safeString (words, 2);
781
+ const fourthWord = this.safeString (words, 3);
782
+ let type = this.safeString (types, firstWord, undefined);
783
+ if ((type === undefined) && (thirdWord === 'fee')) {
784
+ type = 'fee';
785
+ }
786
+ if ((type === 'reserved') && (fourthWord === 'order')) {
787
+ referenceId = this.safeString (words, 4);
788
+ }
789
+ return {
790
+ 'type': type,
791
+ 'referenceId': referenceId,
792
+ };
793
+ }
794
+
795
+ parseLedgerEntry (entry, currency = undefined) {
796
+ // const details = this.safeValue (entry, 'details', {});
797
+ const id = this.safeString (entry, 'row_index');
798
+ const account_id = this.safeString (entry, 'account_id');
799
+ const timestamp = this.safeValue (entry, 'timestamp');
800
+ const currencyId = this.safeString (entry, 'currency');
801
+ const code = this.safeCurrencyCode (currencyId, currency);
802
+ const available_delta = this.safeNumber (entry, 'available_delta');
803
+ const balance_delta = this.safeNumber (entry, 'balance_delta');
804
+ const after = this.safeNumber (entry, 'balance');
805
+ const comment = this.safeString (entry, 'description');
806
+ let before = after;
807
+ let amount = 0.0;
808
+ const result = this.parseLedgerComment (comment);
809
+ const type = result['type'];
810
+ const referenceId = result['referenceId'];
811
+ let direction = undefined;
812
+ let status = undefined;
813
+ if (balance_delta !== 0.0) {
814
+ before = after - balance_delta; // TODO: float precision
815
+ status = 'ok';
816
+ amount = Math.abs (balance_delta);
817
+ } else if (available_delta < 0.0) {
818
+ status = 'pending';
819
+ amount = Math.abs (available_delta);
820
+ } else if (available_delta > 0.0) {
821
+ status = 'canceled';
822
+ amount = Math.abs (available_delta);
823
+ }
824
+ if (balance_delta > 0 || available_delta > 0) {
825
+ direction = 'in';
826
+ } else if (balance_delta < 0 || available_delta < 0) {
827
+ direction = 'out';
828
+ }
829
+ return {
830
+ 'id': id,
831
+ 'direction': direction,
832
+ 'account': account_id,
833
+ 'referenceId': referenceId,
834
+ 'referenceAccount': undefined,
835
+ 'type': type,
836
+ 'currency': code,
837
+ 'amount': amount,
838
+ 'timestamp': timestamp,
839
+ 'datetime': this.iso8601 (timestamp),
840
+ 'before': before,
841
+ 'after': after,
842
+ 'status': status,
843
+ 'fee': undefined,
844
+ 'info': entry,
845
+ };
846
+ }
847
+
848
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
849
+ let url = this.urls['api'][api] + '/' + this.version + '/' + this.implodeParams (path, params);
850
+ const query = this.omit (params, this.extractParams (path));
851
+ if (Object.keys (query).length) {
852
+ url += '?' + this.urlencode (query);
853
+ }
854
+ if (api === 'private') {
855
+ this.checkRequiredCredentials ();
856
+ const auth = this.stringToBase64 (this.apiKey + ':' + this.secret);
857
+ headers = {
858
+ 'Authorization': 'Basic ' + this.decode (auth),
859
+ };
860
+ }
861
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
862
+ }
863
+
864
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
865
+ if (response === undefined) {
866
+ return;
867
+ }
868
+ const error = this.safeValue (response, 'error');
869
+ if (error !== undefined) {
870
+ throw new ExchangeError (this.id + ' ' + this.json (response));
871
+ }
872
+ }
873
+ };