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/tidex.js ADDED
@@ -0,0 +1,939 @@
1
+ 'use strict';
2
+
3
+ const Exchange = require ('./base/Exchange');
4
+ const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, DDoSProtection, InvalidOrder, AuthenticationError, PermissionDenied } = require ('./base/errors');
5
+ const Precise = require ('./base/Precise');
6
+
7
+ module.exports = class tidex extends Exchange {
8
+ describe () {
9
+ return this.deepExtend (super.describe (), {
10
+ 'id': 'tidex',
11
+ 'name': 'Tidex',
12
+ 'countries': [ 'UK' ],
13
+ 'rateLimit': 2000,
14
+ 'version': '3',
15
+ 'userAgent': this.userAgents['chrome'],
16
+ 'has': {
17
+ 'CORS': undefined,
18
+ 'spot': true,
19
+ 'margin': false,
20
+ 'swap': false,
21
+ 'future': false,
22
+ 'option': false,
23
+ 'addMargin': false,
24
+ 'cancelOrder': true,
25
+ 'createMarketOrder': undefined,
26
+ 'createOrder': true,
27
+ 'createReduceOnlyOrder': false,
28
+ 'fetchBalance': true,
29
+ 'fetchBorrowRate': false,
30
+ 'fetchBorrowRateHistories': false,
31
+ 'fetchBorrowRateHistory': false,
32
+ 'fetchBorrowRates': false,
33
+ 'fetchBorrowRatesPerSymbol': false,
34
+ 'fetchCurrencies': true,
35
+ 'fetchFundingHistory': false,
36
+ 'fetchFundingRate': false,
37
+ 'fetchFundingRateHistory': false,
38
+ 'fetchFundingRates': false,
39
+ 'fetchIndexOHLCV': false,
40
+ 'fetchLeverage': false,
41
+ 'fetchLeverageTiers': false,
42
+ 'fetchMarkets': true,
43
+ 'fetchMarkOHLCV': false,
44
+ 'fetchMyTrades': true,
45
+ 'fetchOpenOrders': true,
46
+ 'fetchOrder': true,
47
+ 'fetchOrderBook': true,
48
+ 'fetchOrderBooks': true,
49
+ 'fetchPosition': false,
50
+ 'fetchPositions': false,
51
+ 'fetchPositionsRisk': false,
52
+ 'fetchPremiumIndexOHLCV': false,
53
+ 'fetchTicker': true,
54
+ 'fetchTickers': true,
55
+ 'fetchTrades': true,
56
+ 'reduceMargin': false,
57
+ 'setLeverage': false,
58
+ 'setMarginMode': false,
59
+ 'setPositionMode': false,
60
+ 'withdraw': true,
61
+ },
62
+ 'urls': {
63
+ 'logo': 'https://user-images.githubusercontent.com/1294454/30781780-03149dc4-a12e-11e7-82bb-313b269d24d4.jpg',
64
+ 'api': {
65
+ 'web': 'https://gate.tidex.com/api',
66
+ 'public': 'https://api.tidex.com/api/3',
67
+ 'private': 'https://api.tidex.com/tapi',
68
+ },
69
+ 'www': 'https://tidex.com',
70
+ 'doc': 'https://tidex.com/exchange/public-api',
71
+ 'referral': 'https://tidex.com/exchange/?ref=57f5638d9cd7',
72
+ 'fees': [
73
+ 'https://tidex.com/exchange/assets-spec',
74
+ 'https://tidex.com/exchange/pairs-spec',
75
+ ],
76
+ },
77
+ 'api': {
78
+ 'web': {
79
+ 'get': [
80
+ 'currency',
81
+ 'pairs',
82
+ 'tickers',
83
+ 'orders',
84
+ 'ordershistory',
85
+ 'trade-data',
86
+ 'trade-data/{id}',
87
+ ],
88
+ },
89
+ 'public': {
90
+ 'get': [
91
+ 'info',
92
+ 'ticker/{pair}',
93
+ 'depth/{pair}',
94
+ 'trades/{pair}',
95
+ ],
96
+ },
97
+ 'private': {
98
+ 'post': [
99
+ 'getInfoExt',
100
+ 'getInfo',
101
+ 'Trade',
102
+ 'ActiveOrders',
103
+ 'OrderInfo',
104
+ 'CancelOrder',
105
+ 'TradeHistory',
106
+ 'getDepositAddress',
107
+ 'createWithdraw',
108
+ 'getWithdraw',
109
+ ],
110
+ },
111
+ },
112
+ 'fees': {
113
+ 'trading': {
114
+ 'feeSide': 'get',
115
+ 'tierBased': false,
116
+ 'percentage': true,
117
+ 'taker': this.parseNumber ('0.001'),
118
+ 'maker': this.parseNumber ('0.001'),
119
+ },
120
+ },
121
+ 'commonCurrencies': {
122
+ 'DSH': 'DASH',
123
+ 'EMGO': 'MGO',
124
+ 'MGO': 'WMGO',
125
+ },
126
+ 'exceptions': {
127
+ 'exact': {
128
+ '803': InvalidOrder, // "Count could not be less than 0.001." (selling below minAmount)
129
+ '804': InvalidOrder, // "Count could not be more than 10000." (buying above maxAmount)
130
+ '805': InvalidOrder, // "price could not be less than X." (minPrice violation on buy & sell)
131
+ '806': InvalidOrder, // "price could not be more than X." (maxPrice violation on buy & sell)
132
+ '807': InvalidOrder, // "cost could not be less than X." (minCost violation on buy & sell)
133
+ '831': InsufficientFunds, // "Not enougth X to create buy order." (buying with balance.quote < order.cost)
134
+ '832': InsufficientFunds, // "Not enougth X to create sell order." (selling with balance.base < order.amount)
135
+ '833': OrderNotFound, // "Order with id X was not found." (cancelling non-existent, closed and cancelled order)
136
+ },
137
+ 'broad': {
138
+ 'Invalid pair name': ExchangeError, // {"success":0,"error":"Invalid pair name: btc_eth"}
139
+ 'invalid api key': AuthenticationError,
140
+ 'invalid sign': AuthenticationError,
141
+ 'api key dont have trade permission': AuthenticationError,
142
+ 'invalid parameter': InvalidOrder,
143
+ 'invalid order': InvalidOrder,
144
+ 'Requests too often': DDoSProtection,
145
+ 'not available': ExchangeNotAvailable,
146
+ 'data unavailable': ExchangeNotAvailable,
147
+ 'external service unavailable': ExchangeNotAvailable,
148
+ 'IP restricted': PermissionDenied, // {"success":0,"code":0,"error":"IP restricted (223.xxx.xxx.xxx)"}
149
+ },
150
+ },
151
+ 'options': {
152
+ 'fetchTickersMaxLength': 2048,
153
+ },
154
+ 'orders': {}, // orders cache / emulation
155
+ });
156
+ }
157
+
158
+ async fetchCurrencies (params = {}) {
159
+ const response = await this.webGetCurrency (params);
160
+ //
161
+ // [
162
+ // {
163
+ // "id":2,
164
+ // "symbol":"BTC",
165
+ // "type":2,
166
+ // "name":"Bitcoin",
167
+ // "amountPoint":8,
168
+ // "depositEnable":true,
169
+ // "depositMinAmount":0.0005,
170
+ // "withdrawEnable":true,
171
+ // "withdrawFee":0.0004,
172
+ // "withdrawMinAmount":0.0005,
173
+ // "settings":{
174
+ // "Blockchain":"https://blockchair.com/bitcoin/",
175
+ // "TxUrl":"https://blockchair.com/bitcoin/transaction/{0}",
176
+ // "AddrUrl":"https://blockchair.com/bitcoin/address/{0}",
177
+ // "ConfirmationCount":3,
178
+ // "NeedMemo":false
179
+ // },
180
+ // "visible":true,
181
+ // "isDelisted":false
182
+ // }
183
+ // ]
184
+ //
185
+ const result = {};
186
+ for (let i = 0; i < response.length; i++) {
187
+ const currency = response[i];
188
+ const id = this.safeString (currency, 'symbol');
189
+ const precision = this.safeInteger (currency, 'amountPoint');
190
+ const code = this.safeCurrencyCode (id);
191
+ const visible = this.safeValue (currency, 'visible');
192
+ let active = visible === true;
193
+ const withdrawEnable = this.safeValue (currency, 'withdrawEnable', true);
194
+ const depositEnable = this.safeValue (currency, 'depositEnable', true);
195
+ if (!withdrawEnable || !depositEnable) {
196
+ active = false;
197
+ }
198
+ const name = this.safeString (currency, 'name');
199
+ const fee = this.safeNumber (currency, 'withdrawFee');
200
+ result[code] = {
201
+ 'id': id,
202
+ 'code': code,
203
+ 'name': name,
204
+ 'active': active,
205
+ 'deposit': depositEnable,
206
+ 'withdraw': withdrawEnable,
207
+ 'precision': precision,
208
+ 'funding': {
209
+ 'withdraw': {
210
+ 'active': withdrawEnable,
211
+ 'fee': fee,
212
+ },
213
+ 'deposit': {
214
+ 'active': depositEnable,
215
+ 'fee': this.parseNumber ('0'),
216
+ },
217
+ },
218
+ 'limits': {
219
+ 'amount': {
220
+ 'min': undefined,
221
+ 'max': undefined,
222
+ },
223
+ 'withdraw': {
224
+ 'min': this.safeNumber (currency, 'withdrawMinAmount'),
225
+ 'max': undefined,
226
+ },
227
+ 'deposit': {
228
+ 'min': this.safeNumber (currency, 'depositMinAmount'),
229
+ 'max': undefined,
230
+ },
231
+ },
232
+ 'info': currency,
233
+ };
234
+ }
235
+ return result;
236
+ }
237
+
238
+ async fetchMarkets (params = {}) {
239
+ const response = await this.publicGetInfo (params);
240
+ //
241
+ // {
242
+ // "server_time":1615861869,
243
+ // "pairs":{
244
+ // "ltc_btc":{
245
+ // "decimal_places":8,
246
+ // "min_price":0.00000001,
247
+ // "max_price":3.0,
248
+ // "min_amount":0.001,
249
+ // "max_amount":1000000.0,
250
+ // "min_total":0.0001,
251
+ // "hidden":0,
252
+ // "fee":0.1,
253
+ // },
254
+ // },
255
+ // }
256
+ //
257
+ const markets = response['pairs'];
258
+ const keys = Object.keys (markets);
259
+ const result = [];
260
+ for (let i = 0; i < keys.length; i++) {
261
+ const id = keys[i];
262
+ const market = markets[id];
263
+ const [ baseId, quoteId ] = id.split ('_');
264
+ const base = this.safeCurrencyCode (baseId);
265
+ const quote = this.safeCurrencyCode (quoteId);
266
+ const hidden = this.safeInteger (market, 'hidden');
267
+ let takerFeeString = this.safeString (market, 'fee');
268
+ takerFeeString = Precise.stringDiv (takerFeeString, '100');
269
+ result.push ({
270
+ 'id': id,
271
+ 'symbol': base + '/' + quote,
272
+ 'base': base,
273
+ 'quote': quote,
274
+ 'settle': undefined,
275
+ 'baseId': baseId,
276
+ 'quoteId': quoteId,
277
+ 'settleId': undefined,
278
+ 'type': 'spot',
279
+ 'spot': true,
280
+ 'margin': false,
281
+ 'swap': false,
282
+ 'future': false,
283
+ 'option': false,
284
+ 'active': (hidden === 0),
285
+ 'contract': false,
286
+ 'linear': undefined,
287
+ 'inverse': undefined,
288
+ 'taker': this.parseNumber (takerFeeString),
289
+ 'contractSize': undefined,
290
+ 'expiry': undefined,
291
+ 'expiryDatetime': undefined,
292
+ 'strike': undefined,
293
+ 'optionType': undefined,
294
+ 'precision': {
295
+ 'amount': this.safeInteger (market, 'decimal_places'),
296
+ 'price': this.safeInteger (market, 'decimal_places'),
297
+ },
298
+ 'limits': {
299
+ 'leverage': {
300
+ 'min': undefined,
301
+ 'max': undefined,
302
+ },
303
+ 'amount': {
304
+ 'min': this.safeNumber (market, 'min_amount'),
305
+ 'max': this.safeNumber (market, 'max_amount'),
306
+ },
307
+ 'price': {
308
+ 'min': this.safeNumber (market, 'min_price'),
309
+ 'max': this.safeNumber (market, 'max_price'),
310
+ },
311
+ 'cost': {
312
+ 'min': this.safeNumber (market, 'min_total'),
313
+ 'max': undefined,
314
+ },
315
+ },
316
+ 'info': market,
317
+ });
318
+ }
319
+ return result;
320
+ }
321
+
322
+ parseBalance (response) {
323
+ const balances = this.safeValue (response, 'return');
324
+ const timestamp = this.safeTimestamp (balances, 'server_time');
325
+ const result = {
326
+ 'info': response,
327
+ 'timestamp': timestamp,
328
+ 'datetime': this.iso8601 (timestamp),
329
+ };
330
+ const funds = this.safeValue (balances, 'funds', {});
331
+ const currencyIds = Object.keys (funds);
332
+ for (let i = 0; i < currencyIds.length; i++) {
333
+ const currencyId = currencyIds[i];
334
+ const code = this.safeCurrencyCode (currencyId);
335
+ const balance = this.safeValue (funds, currencyId, {});
336
+ const account = this.account ();
337
+ account['free'] = this.safeString (balance, 'value');
338
+ account['used'] = this.safeString (balance, 'inOrders');
339
+ result[code] = account;
340
+ }
341
+ return this.safeBalance (result);
342
+ }
343
+
344
+ async fetchBalance (params = {}) {
345
+ await this.loadMarkets ();
346
+ const response = await this.privatePostGetInfoExt (params);
347
+ //
348
+ // {
349
+ // "success":1,
350
+ // "return":{
351
+ // "funds":{
352
+ // "btc":{"value":0.0000499885629956,"inOrders":0.0},
353
+ // "eth":{"value":0.000000030741708,"inOrders":0.0},
354
+ // "tdx":{"value":0.0000000155385356,"inOrders":0.0}
355
+ // },
356
+ // "rights":{
357
+ // "info":true,
358
+ // "trade":true,
359
+ // "withdraw":false
360
+ // },
361
+ // "transaction_count":0,
362
+ // "open_orders":0,
363
+ // "server_time":1619436907
364
+ // },
365
+ // "stat":{
366
+ // "isSuccess":true,
367
+ // "serverTime":"00:00:00.0001157",
368
+ // "time":"00:00:00.0101364",
369
+ // "errors":null
370
+ // }
371
+ // }
372
+ //
373
+ return this.parseBalance (response);
374
+ }
375
+
376
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
377
+ await this.loadMarkets ();
378
+ const market = this.market (symbol);
379
+ const request = {
380
+ 'pair': market['id'],
381
+ };
382
+ if (limit !== undefined) {
383
+ request['limit'] = limit; // default = 150, max = 2000
384
+ }
385
+ const response = await this.publicGetDepthPair (this.extend (request, params));
386
+ const market_id_in_reponse = (market['id'] in response);
387
+ if (!market_id_in_reponse) {
388
+ throw new ExchangeError (this.id + ' ' + market['symbol'] + ' order book is empty or not available');
389
+ }
390
+ const orderbook = response[market['id']];
391
+ return this.parseOrderBook (orderbook, symbol);
392
+ }
393
+
394
+ async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
395
+ await this.loadMarkets ();
396
+ let ids = undefined;
397
+ if (symbols === undefined) {
398
+ ids = this.ids.join ('-');
399
+ // max URL length is 2083 symbols, including http schema, hostname, tld, etc...
400
+ if (ids.length > 2048) {
401
+ const numIds = this.ids.length;
402
+ throw new ExchangeError (this.id + ' fetchOrderBooks() has ' + numIds.toString () + ' symbols exceeding max URL length, you are required to specify a list of symbols in the first argument to fetchOrderBooks');
403
+ }
404
+ } else {
405
+ ids = this.marketIds (symbols);
406
+ ids = ids.join ('-');
407
+ }
408
+ const request = {
409
+ 'pair': ids,
410
+ };
411
+ if (limit !== undefined) {
412
+ request['limit'] = limit; // default = 150, max = 2000
413
+ }
414
+ const response = await this.publicGetDepthPair (this.extend (request, params));
415
+ const result = {};
416
+ ids = Object.keys (response);
417
+ for (let i = 0; i < ids.length; i++) {
418
+ const id = ids[i];
419
+ const symbol = this.safeSymbol (id);
420
+ result[symbol] = this.parseOrderBook (response[id]);
421
+ }
422
+ return result;
423
+ }
424
+
425
+ parseTicker (ticker, market = undefined) {
426
+ //
427
+ // {
428
+ // high: 0.03497582,
429
+ // low: 0.03248474,
430
+ // avg: 0.03373028,
431
+ // vol: 120.11485715062999,
432
+ // vol_cur: 3572.24914074,
433
+ // last: 0.0337611,
434
+ // buy: 0.0337442,
435
+ // sell: 0.03377798,
436
+ // updated: 1537522009
437
+ // }
438
+ //
439
+ const timestamp = this.safeTimestamp (ticker, 'updated');
440
+ market = this.safeMarket (undefined, market);
441
+ const last = this.safeString (ticker, 'last');
442
+ return this.safeTicker ({
443
+ 'symbol': market['symbol'],
444
+ 'timestamp': timestamp,
445
+ 'datetime': this.iso8601 (timestamp),
446
+ 'high': this.safeString (ticker, 'high'),
447
+ 'low': this.safeString (ticker, 'low'),
448
+ 'bid': this.safeString (ticker, 'buy'),
449
+ 'bidVolume': undefined,
450
+ 'ask': this.safeString (ticker, 'sell'),
451
+ 'askVolume': undefined,
452
+ 'vwap': undefined,
453
+ 'open': undefined,
454
+ 'close': last,
455
+ 'last': last,
456
+ 'previousClose': undefined,
457
+ 'change': undefined,
458
+ 'percentage': undefined,
459
+ 'average': this.safeString (ticker, 'avg'),
460
+ 'baseVolume': this.safeString (ticker, 'vol_cur'),
461
+ 'quoteVolume': this.safeString (ticker, 'vol'),
462
+ 'info': ticker,
463
+ }, market, false);
464
+ }
465
+
466
+ async fetchTickers (symbols = undefined, params = {}) {
467
+ await this.loadMarkets ();
468
+ let ids = this.ids;
469
+ if (symbols === undefined) {
470
+ const numIds = ids.length;
471
+ ids = ids.join ('-');
472
+ // max URL length is 2048 symbols, including http schema, hostname, tld, etc...
473
+ if (ids.length > this.options['fetchTickersMaxLength']) {
474
+ const maxLength = this.safeInteger (this.options, 'fetchTickersMaxLength', 2048);
475
+ throw new ArgumentsRequired (this.id + ' fetchTickers() has ' + numIds.toString () + ' markets exceeding max URL length for this endpoint (' + maxLength.toString () + ' characters), please, specify a list of symbols of interest in the first argument to fetchTickers');
476
+ }
477
+ } else {
478
+ ids = this.marketIds (symbols);
479
+ ids = ids.join ('-');
480
+ }
481
+ const request = {
482
+ 'pair': ids,
483
+ };
484
+ const response = await this.publicGetTickerPair (this.extend (request, params));
485
+ const result = {};
486
+ const keys = Object.keys (response);
487
+ for (let i = 0; i < keys.length; i++) {
488
+ const id = keys[i];
489
+ const market = this.safeMarket (id);
490
+ const symbol = market['symbol'];
491
+ result[symbol] = this.parseTicker (response[id], market);
492
+ }
493
+ return this.filterByArray (result, 'symbol', symbols);
494
+ }
495
+
496
+ async fetchTicker (symbol, params = {}) {
497
+ const tickers = await this.fetchTickers ([ symbol ], params);
498
+ return tickers[symbol];
499
+ }
500
+
501
+ parseTrade (trade, market = undefined) {
502
+ const timestamp = this.safeTimestamp (trade, 'timestamp');
503
+ let side = this.safeString (trade, 'type');
504
+ if (side === 'ask') {
505
+ side = 'sell';
506
+ } else if (side === 'bid') {
507
+ side = 'buy';
508
+ }
509
+ const priceString = this.safeString2 (trade, 'rate', 'price');
510
+ const id = this.safeString2 (trade, 'trade_id', 'tid');
511
+ const orderId = this.safeString (trade, 'order_id');
512
+ const marketId = this.safeString (trade, 'pair');
513
+ const symbol = this.safeSymbol (marketId, market);
514
+ const amountString = this.safeString (trade, 'amount');
515
+ const price = this.parseNumber (priceString);
516
+ const amount = this.parseNumber (amountString);
517
+ const cost = this.parseNumber (Precise.stringMul (priceString, amountString));
518
+ const type = 'limit'; // all trades are still limit trades
519
+ let takerOrMaker = undefined;
520
+ let fee = undefined;
521
+ const feeCost = this.safeNumber (trade, 'commission');
522
+ if (feeCost !== undefined) {
523
+ const feeCurrencyId = this.safeString (trade, 'commissionCurrency');
524
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
525
+ fee = {
526
+ 'cost': feeCost,
527
+ 'currency': feeCurrencyCode,
528
+ };
529
+ }
530
+ const isYourOrder = this.safeValue (trade, 'is_your_order');
531
+ if (isYourOrder !== undefined) {
532
+ takerOrMaker = 'taker';
533
+ if (isYourOrder) {
534
+ takerOrMaker = 'maker';
535
+ }
536
+ if (fee === undefined) {
537
+ fee = this.calculateFee (symbol, type, side, amount, price, takerOrMaker);
538
+ }
539
+ }
540
+ return {
541
+ 'id': id,
542
+ 'order': orderId,
543
+ 'timestamp': timestamp,
544
+ 'datetime': this.iso8601 (timestamp),
545
+ 'symbol': symbol,
546
+ 'type': type,
547
+ 'side': side,
548
+ 'takerOrMaker': takerOrMaker,
549
+ 'price': price,
550
+ 'amount': amount,
551
+ 'cost': cost,
552
+ 'fee': fee,
553
+ 'info': trade,
554
+ };
555
+ }
556
+
557
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
558
+ await this.loadMarkets ();
559
+ const market = this.market (symbol);
560
+ const request = {
561
+ 'pair': market['id'],
562
+ };
563
+ if (limit !== undefined) {
564
+ request['limit'] = limit;
565
+ }
566
+ const response = await this.publicGetTradesPair (this.extend (request, params));
567
+ if (Array.isArray (response)) {
568
+ const numElements = response.length;
569
+ if (numElements === 0) {
570
+ return [];
571
+ }
572
+ }
573
+ return this.parseTrades (response[market['id']], market, since, limit);
574
+ }
575
+
576
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
577
+ if (type === 'market') {
578
+ throw new ExchangeError (this.id + ' createOrder() allows limit orders only');
579
+ }
580
+ const amountString = amount.toString ();
581
+ const priceString = price.toString ();
582
+ await this.loadMarkets ();
583
+ const market = this.market (symbol);
584
+ const request = {
585
+ 'pair': market['id'],
586
+ 'type': side,
587
+ 'amount': this.amountToPrecision (symbol, amount),
588
+ 'rate': this.priceToPrecision (symbol, price),
589
+ };
590
+ const response = await this.privatePostTrade (this.extend (request, params));
591
+ let id = undefined;
592
+ let status = 'open';
593
+ let filledString = '0.0';
594
+ let remainingString = amountString;
595
+ const returnResult = this.safeValue (response, 'return');
596
+ if (returnResult !== undefined) {
597
+ id = this.safeString (returnResult, 'order_id');
598
+ if (id === '0') {
599
+ id = this.safeString (returnResult, 'init_order_id');
600
+ status = 'closed';
601
+ }
602
+ filledString = this.safeString (returnResult, 'received', filledString);
603
+ remainingString = this.safeString (returnResult, 'remains', amountString);
604
+ }
605
+ const timestamp = this.milliseconds ();
606
+ return this.safeOrder ({
607
+ 'id': id,
608
+ 'timestamp': timestamp,
609
+ 'datetime': this.iso8601 (timestamp),
610
+ 'lastTradeTimestamp': undefined,
611
+ 'status': status,
612
+ 'symbol': symbol,
613
+ 'type': type,
614
+ 'side': side,
615
+ 'price': priceString,
616
+ 'cost': undefined,
617
+ 'amount': amountString,
618
+ 'remaining': remainingString,
619
+ 'filled': filledString,
620
+ 'fee': undefined,
621
+ // 'trades': this.parseTrades (order['trades'], market),
622
+ 'info': response,
623
+ 'clientOrderId': undefined,
624
+ 'average': undefined,
625
+ 'trades': undefined,
626
+ }, market);
627
+ }
628
+
629
+ async cancelOrder (id, symbol = undefined, params = {}) {
630
+ await this.loadMarkets ();
631
+ const request = {
632
+ 'order_id': parseInt (id),
633
+ };
634
+ return await this.privatePostCancelOrder (this.extend (request, params));
635
+ }
636
+
637
+ parseOrderStatus (status) {
638
+ const statuses = {
639
+ '0': 'open',
640
+ '1': 'closed',
641
+ '2': 'canceled',
642
+ '3': 'canceled', // or partially-filled and still open? https://github.com/ccxt/ccxt/issues/1594
643
+ };
644
+ return this.safeString (statuses, status, status);
645
+ }
646
+
647
+ parseOrder (order, market = undefined) {
648
+ const id = this.safeString (order, 'id');
649
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
650
+ const timestamp = this.safeTimestamp (order, 'timestamp_created');
651
+ const marketId = this.safeString (order, 'pair');
652
+ const symbol = this.safeSymbol (marketId, market);
653
+ let remaining = undefined;
654
+ let amount = undefined;
655
+ const price = this.safeString (order, 'rate');
656
+ if ('start_amount' in order) {
657
+ amount = this.safeString (order, 'start_amount');
658
+ remaining = this.safeString (order, 'amount');
659
+ } else {
660
+ remaining = this.safeString (order, 'amount');
661
+ }
662
+ const fee = undefined;
663
+ return this.safeOrder ({
664
+ 'info': order,
665
+ 'id': id,
666
+ 'clientOrderId': undefined,
667
+ 'symbol': symbol,
668
+ 'timestamp': timestamp,
669
+ 'datetime': this.iso8601 (timestamp),
670
+ 'lastTradeTimestamp': undefined,
671
+ 'type': 'limit',
672
+ 'timeInForce': undefined,
673
+ 'postOnly': undefined,
674
+ 'side': this.safeString (order, 'type'),
675
+ 'price': price,
676
+ 'stopPrice': undefined,
677
+ 'cost': undefined,
678
+ 'amount': amount,
679
+ 'remaining': remaining,
680
+ 'filled': undefined,
681
+ 'status': status,
682
+ 'fee': fee,
683
+ 'average': undefined,
684
+ 'trades': undefined,
685
+ }, market);
686
+ }
687
+
688
+ async fetchOrder (id, symbol = undefined, params = {}) {
689
+ await this.loadMarkets ();
690
+ const request = {
691
+ 'order_id': parseInt (id),
692
+ };
693
+ const response = await this.privatePostOrderInfo (this.extend (request, params));
694
+ id = id.toString ();
695
+ const result = this.safeValue (response, 'return', {});
696
+ const order = this.safeValue (result, id);
697
+ return this.parseOrder (this.extend ({ 'id': id }, order));
698
+ }
699
+
700
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
701
+ await this.loadMarkets ();
702
+ const request = {};
703
+ let market = undefined;
704
+ if (symbol !== undefined) {
705
+ market = this.market (symbol);
706
+ request['pair'] = market['id'];
707
+ }
708
+ const response = await this.privatePostActiveOrders (this.extend (request, params));
709
+ //
710
+ // {
711
+ // "success":1,
712
+ // "return":{
713
+ // "1255468911":{
714
+ // "status":0,
715
+ // "pair":"spike_usdt",
716
+ // "type":"sell",
717
+ // "amount":35028.44256388,
718
+ // "rate":0.00199989,
719
+ // "timestamp_created":1602684432
720
+ // }
721
+ // },
722
+ // "stat":{
723
+ // "isSuccess":true,
724
+ // "serverTime":"00:00:00.0000826",
725
+ // "time":"00:00:00.0091423",
726
+ // "errors":null
727
+ // }
728
+ // }
729
+ //
730
+ // it can only return 'open' orders (i.e. no way to fetch 'closed' orders)
731
+ const orders = this.safeValue (response, 'return', []);
732
+ return this.parseOrders (orders, market, since, limit);
733
+ }
734
+
735
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
736
+ await this.loadMarkets ();
737
+ let market = undefined;
738
+ // some derived classes use camelcase notation for request fields
739
+ const request = {
740
+ // 'from': 123456789, // trade ID, from which the display starts numerical 0 (test result: liqui ignores this field)
741
+ // 'count': 1000, // the number of trades for display numerical, default = 1000
742
+ // 'from_id': trade ID, from which the display starts numerical 0
743
+ // 'end_id': trade ID on which the display ends numerical ∞
744
+ // 'order': 'ASC', // sorting, default = DESC (test result: liqui ignores this field, most recent trade always goes last)
745
+ // 'since': 1234567890, // UTC start time, default = 0 (test result: liqui ignores this field)
746
+ // 'end': 1234567890, // UTC end time, default = ∞ (test result: liqui ignores this field)
747
+ // 'pair': 'eth_btc', // default = all markets
748
+ };
749
+ if (symbol !== undefined) {
750
+ market = this.market (symbol);
751
+ request['pair'] = market['id'];
752
+ }
753
+ if (limit !== undefined) {
754
+ request['count'] = parseInt (limit);
755
+ }
756
+ if (since !== undefined) {
757
+ request['since'] = parseInt (since / 1000);
758
+ }
759
+ const response = await this.privatePostTradeHistory (this.extend (request, params));
760
+ const trades = this.safeValue (response, 'return', []);
761
+ return this.parseTrades (trades, market, since, limit);
762
+ }
763
+
764
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
765
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
766
+ this.checkAddress (address);
767
+ await this.loadMarkets ();
768
+ const currency = this.currency (code);
769
+ const request = {
770
+ 'asset': currency['id'],
771
+ 'amount': parseFloat (amount),
772
+ 'address': address,
773
+ };
774
+ if (tag !== undefined) {
775
+ request['memo'] = tag;
776
+ }
777
+ const response = await this.privatePostCreateWithdraw (this.extend (request, params));
778
+ //
779
+ // {
780
+ // "success":1,
781
+ // "return":{
782
+ // "withdraw_id":1111,
783
+ // "withdraw_info":{
784
+ // "id":1111,
785
+ // "asset_id":1,
786
+ // "asset":"BTC",
787
+ // "amount":0.0093,
788
+ // "fee":0.0007,
789
+ // "create_time":1575128018,
790
+ // "status":"Created",
791
+ // "data":{
792
+ // "address":"1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY",
793
+ // "memo":"memo",
794
+ // "tx":null,
795
+ // "error":null
796
+ // },
797
+ // "in_blockchain":false
798
+ // }
799
+ // }
800
+ // }
801
+ //
802
+ const result = this.safeValue (response, 'return', {});
803
+ const withdrawInfo = this.safeValue (result, 'withdraw_info', {});
804
+ return this.parseTransaction (withdrawInfo, currency);
805
+ }
806
+
807
+ parseTransaction (transaction, currency = undefined) {
808
+ //
809
+ // {
810
+ // "id":1111,
811
+ // "asset_id":1,
812
+ // "asset":"BTC",
813
+ // "amount":0.0093,
814
+ // "fee":0.0007,
815
+ // "create_time":1575128018,
816
+ // "status":"Created",
817
+ // "data":{
818
+ // "address":"1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY",
819
+ // "memo":"memo",
820
+ // "tx":null,
821
+ // "error":null
822
+ // },
823
+ // "in_blockchain":false
824
+ // }
825
+ //
826
+ currency = this.safeCurrency (undefined, currency);
827
+ return {
828
+ 'id': this.safeString (transaction, 'id'),
829
+ 'txid': undefined,
830
+ 'timestamp': undefined,
831
+ 'datetime': undefined,
832
+ 'network': undefined,
833
+ 'addressFrom': undefined,
834
+ 'address': undefined,
835
+ 'addressTo': undefined,
836
+ 'amount': undefined,
837
+ 'type': undefined,
838
+ 'currency': currency['code'],
839
+ 'status': undefined,
840
+ 'updated': undefined,
841
+ 'tagFrom': undefined,
842
+ 'tag': undefined,
843
+ 'tagTo': undefined,
844
+ 'comment': undefined,
845
+ 'fee': undefined,
846
+ 'info': transaction,
847
+ };
848
+ }
849
+
850
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
851
+ let url = this.urls['api'][api];
852
+ const query = this.omit (params, this.extractParams (path));
853
+ if (api === 'private') {
854
+ this.checkRequiredCredentials ();
855
+ const nonce = this.nonce ();
856
+ body = this.urlencode (this.extend ({
857
+ 'nonce': nonce,
858
+ 'method': path,
859
+ }, query));
860
+ const signature = this.hmac (this.encode (body), this.encode (this.secret), 'sha512');
861
+ headers = {
862
+ 'Content-Type': 'application/x-www-form-urlencoded',
863
+ 'Key': this.apiKey,
864
+ 'Sign': signature,
865
+ };
866
+ } else if (api === 'public') {
867
+ url += '/' + this.implodeParams (path, params);
868
+ if (Object.keys (query).length) {
869
+ url += '?' + this.urlencode (query);
870
+ }
871
+ } else {
872
+ url += '/' + this.implodeParams (path, params);
873
+ if (method === 'GET') {
874
+ if (Object.keys (query).length) {
875
+ url += '?' + this.urlencode (query);
876
+ }
877
+ } else {
878
+ if (Object.keys (query).length) {
879
+ body = this.json (query);
880
+ headers = {
881
+ 'Content-Type': 'application/json',
882
+ };
883
+ }
884
+ }
885
+ }
886
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
887
+ }
888
+
889
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
890
+ if (response === undefined) {
891
+ return; // fallback to default error handler
892
+ }
893
+ if ('success' in response) {
894
+ //
895
+ // 1 - The exchange only returns the integer 'success' key from their private API
896
+ //
897
+ // { "success": 1, ... } httpCode === 200
898
+ // { "success": 0, ... } httpCode === 200
899
+ //
900
+ // 2 - However, derived exchanges can return non-integers
901
+ //
902
+ // It can be a numeric string
903
+ // { "sucesss": "1", ... }
904
+ // { "sucesss": "0", ... }, httpCode >= 200 (can be 403, 502, etc)
905
+ //
906
+ // Or just a string
907
+ // { "success": "true", ... }
908
+ // { "success": "false", ... }, httpCode >= 200
909
+ //
910
+ // Or a boolean
911
+ // { "success": true, ... }
912
+ // { "success": false, ... }, httpCode >= 200
913
+ //
914
+ // 3 - Oversimplified, Python PEP8 forbids comparison operator (===) of different types
915
+ //
916
+ // 4 - We do not want to copy-paste and duplicate the code of this handler to other exchanges derived from Liqui
917
+ //
918
+ // To cover points 1, 2, 3 and 4 combined this handler should work like this:
919
+ //
920
+ let success = this.safeValue (response, 'success', false);
921
+ if (typeof success === 'string') {
922
+ if ((success === 'true') || (success === '1')) {
923
+ success = true;
924
+ } else {
925
+ success = false;
926
+ }
927
+ }
928
+ if (!success) {
929
+ const code = this.safeString (response, 'code');
930
+ const message = this.safeString (response, 'error');
931
+ const feedback = this.id + ' ' + body;
932
+ this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback);
933
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
934
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
935
+ throw new ExchangeError (feedback); // unknown message
936
+ }
937
+ }
938
+ }
939
+ };