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/stex.js ADDED
@@ -0,0 +1,1925 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, OrderNotFound, PermissionDenied, BadRequest, BadSymbol, DDoSProtection, InvalidOrder, AccountSuspended } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class stex extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'stex',
15
+ 'name': 'STEX', // formerly known as stocks.exchange
16
+ 'countries': [ 'EE' ], // Estonia
17
+ 'rateLimit': 1000 / 3, // https://help.stex.com/en/articles/2815043-api-3-rate-limits
18
+ 'certified': false,
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
+ 'createDepositAddress': true,
31
+ 'createMarketOrder': undefined, // limit orders only
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
+ 'fetchClosedOrder': true,
41
+ 'fetchCurrencies': true,
42
+ 'fetchDepositAddress': true,
43
+ 'fetchDeposits': true,
44
+ 'fetchFundingFees': true,
45
+ 'fetchFundingHistory': false,
46
+ 'fetchFundingRate': false,
47
+ 'fetchFundingRateHistory': false,
48
+ 'fetchFundingRates': false,
49
+ 'fetchIndexOHLCV': false,
50
+ 'fetchLeverage': false,
51
+ 'fetchLeverageTiers': false,
52
+ 'fetchMarkets': true,
53
+ 'fetchMarkOHLCV': false,
54
+ 'fetchMyTrades': true,
55
+ 'fetchOHLCV': true,
56
+ 'fetchOpenOrders': true,
57
+ 'fetchOrder': true,
58
+ 'fetchOrderBook': true,
59
+ 'fetchOrderTrades': true,
60
+ 'fetchPosition': false,
61
+ 'fetchPositions': false,
62
+ 'fetchPositionsRisk': false,
63
+ 'fetchPremiumIndexOHLCV': false,
64
+ 'fetchTicker': true,
65
+ 'fetchTickers': true,
66
+ 'fetchTime': true,
67
+ 'fetchTrades': true,
68
+ 'fetchTradingFee': true,
69
+ 'fetchTradingFees': false,
70
+ 'fetchWithdrawals': true,
71
+ 'reduceMargin': false,
72
+ 'setLeverage': false,
73
+ 'setMarginMode': false,
74
+ 'setPositionMode': false,
75
+ 'withdraw': true,
76
+ },
77
+ 'version': 'v3',
78
+ 'urls': {
79
+ 'logo': 'https://user-images.githubusercontent.com/1294454/69680782-03fd0b80-10bd-11ea-909e-7f603500e9cc.jpg',
80
+ 'api': 'https://api3.stex.com',
81
+ 'www': 'https://www.stex.com',
82
+ 'doc': [
83
+ 'https://help.stex.com/en/collections/1593608-api-v3-documentation',
84
+ ],
85
+ 'fees': 'https://app.stex.com/en/pairs-specification',
86
+ 'referral': 'https://app.stex.com?ref=36416021',
87
+ },
88
+ 'requiredCredentials': {
89
+ 'apiKey': false,
90
+ 'secret': false,
91
+ 'token': true,
92
+ },
93
+ 'timeframes': {
94
+ '1m': '1',
95
+ '5m': '5',
96
+ '30m': '30',
97
+ '1h': '60',
98
+ '4h': '240',
99
+ '12h': '720',
100
+ '1d': '1D', // default
101
+ },
102
+ 'api': {
103
+ 'public': {
104
+ 'get': {
105
+ 'currencies': 1, // Available Currencies
106
+ 'currencies/{currencyId}': 1, // Get currency info
107
+ 'markets': 1, // Available markets
108
+ 'pairs-groups': 1, // Available currency pairs groups (as displayed at stex trading page)
109
+ 'currency_pairs/list/{code}': 1, // Available currency pairs
110
+ 'currency_pairs/group/{currencyPairGroupId}': 1, // Available currency pairs for a given group
111
+ 'currency_pairs/{currencyPairId}': 1, // Get currency pair information
112
+ 'ticker': 1, // Tickers list for all currency pairs
113
+ 'ticker/{currencyPairId}': 1, // Ticker for currency pair
114
+ 'trades/{currencyPairId}': 1, // Trades for given currency pair
115
+ 'orderbook/{currencyPairId}': 1, // Orderbook for given currency pair
116
+ 'chart/{currencyPairId}/{candlesType}': 1, // A list of candles for given currency pair
117
+ 'deposit-statuses': 1, // Available Deposit Statuses
118
+ 'deposit-statuses/{statusId}': 1, // Get deposit status info
119
+ 'withdrawal-statuses': 1, // Available Withdrawal Statuses
120
+ 'withdrawal-statuses/{statusId}': 1, // Get status info
121
+ 'ping': 1, // Test API is working and get server time
122
+ 'mobile-versions': 1, // Shows the official mobile applications data
123
+ 'twitter': 1, // Get the last 20 posts (stex.com) on Twitter
124
+ },
125
+ },
126
+ 'trading': {
127
+ 'get': {
128
+ 'fees/{currencyPairId}': 1, // Returns the user's fees for a given currency pair
129
+ 'orders': 12, // List your currently open orders
130
+ 'orders/{currencyPairId}': 6, // List your currently open orders for given currency pair
131
+ 'order/{orderId}': 12, // Get a single order
132
+ },
133
+ 'post': {
134
+ 'orders/{currencyPairId}': 1.5, // Create new order and put it to the orders processing queue
135
+ 'orders/bulk/{currencyPairId}': 12, // Create new orders in a bulk and put it to the orders processing queue
136
+ },
137
+ 'delete': {
138
+ 'orders': 30, // Delete all active orders
139
+ 'orders/{currencyPairId}': 12, // Delete active orders for given currency pair
140
+ 'order/{orderId}': 1.5, // Cancel order
141
+ },
142
+ },
143
+ 'reports': {
144
+ 'get': {
145
+ 'currencies': 12, // Get a list of currencies user had any activity in
146
+ 'currency_pairs': 12, // Gets the list of currency pairs the user had orders in for all the time
147
+ 'orders': 12, // Get past orders
148
+ 'orders/{orderId}': 12, // Get specified order details
149
+ 'trades/{currencyPairId}': 12, // Get a list of user trades according to request parameters
150
+ 'background/{listMode}': 12, // Get reports list for category
151
+ 'background/{id}': 12, // Get some report info
152
+ 'background/download/{id}': 12, // Get file by id
153
+ },
154
+ 'post': {
155
+ 'background/create': 12, // Create new report
156
+ },
157
+ 'delete': {
158
+ 'background/{id}': 12, // Remove report by id
159
+ },
160
+ },
161
+ 'profile': {
162
+ 'get': {
163
+ 'info': 3, // Account information
164
+ 'wallets': 3, // Get a list of user wallets
165
+ 'wallets/{walletId}': 3, // Single wallet information
166
+ 'wallets/address/{walletId}': 3, // Get deposit address for given wallet
167
+ 'deposits': 3, // Get a list of deposits made by user
168
+ 'deposits/{id}': 3, // Get deposit by id
169
+ 'rewards': 3, // Get a list of rewards obtained by user (e.g. in trading competitions)
170
+ 'rewards/{id}': 3, // Get reward by id
171
+ 'addressbook': 3, // Get a list of user address book items
172
+ 'addressbook/{itemId}': 3, // Single address book item
173
+ 'withdrawals': 3, // Get a list of withdrawals made by user
174
+ 'withdrawals/{id}': 3, // Get withdrawal by id
175
+ 'notifications': 3, // Get notifications
176
+ 'notifications/price': 3, // Get a list of active price alerts
177
+ 'favorite/currency_pairs': 3, // Get favorite currency pairs
178
+ 'token-scopes': 3, // Get current token scopes
179
+ },
180
+ 'post': {
181
+ 'wallets/burn/{walletId}': 3, // Burns the given wallet
182
+ 'wallets/{walletId}/hold_amount': 3, // Move a part of the funds on the wallet to the "hold" to keep it safe from trading
183
+ 'wallets/{currencyId}': 3, // Create a wallet for given currency
184
+ 'wallets/address/{walletId}': 3, // Create new deposit address
185
+ 'addressbook/disable_item/{itemId}': 3, // Disables the address book item
186
+ 'addressbook/enable_item/{itemId}': 3, // Enable the address book item
187
+ 'addressbook/enable_strict_wd': 3, // Restrict the withdrawals to only addresses that are active in addressbook
188
+ 'addressbook/disable_strict_wd': 3, // Remove restriction to withdraw to only addresses that are active in addressbook. E.g. allow to withdraw to any address.
189
+ 'withdraw': 30, // Create withdrawal request
190
+ 'notifications/price': 3, // Create new price alert
191
+ 'referral/program': 3, // Create referral program
192
+ 'referral/insert/{code}': 3, // Insert referral code
193
+ 'referral/bonus_transfer/{currencyId}': 3, // Transfer referral bonuses balance to main balance for given currency
194
+ },
195
+ 'put': {
196
+ 'favorite/currency_pairs/set': 3, // Set favorite currency pairs
197
+ },
198
+ 'delete': {
199
+ 'addressbook/{itemId}': 3, // Deletes address book item
200
+ 'withdraw/{withdrawalId}': 30, // Cancel unconfirmed withdrawal
201
+ 'notifications/price/{priceAlertId}': 3, // Delete the price alert by ID
202
+ },
203
+ },
204
+ 'verification': {
205
+ 'get': {
206
+ 'countries': 1, // Countries list, beta
207
+ 'status': 1, // Get status verify
208
+ 'fractal/url': 1, // Generate verify url from Fractal
209
+ 'smart-id': 1, // Check Smart-ID verify
210
+ 'stex': 1, // Get information about your KYC, beta
211
+ 'cryptonomica/code': 1, // Get Discount code for Cryptonomica
212
+ },
213
+ 'post': {
214
+ 'smart-id': 1, // Initialization Smart-ID verify (Send request to Smart-ID App)
215
+ 'stex': 1, // Update information regarding of your KYC verification, beta
216
+ 'cryptonomica': 1, // Add verification from Cryptonomica
217
+ },
218
+ },
219
+ 'settings': {
220
+ 'get': {
221
+ 'notifications/{event}': 1, // User event notification settings
222
+ 'notifications': 1, // User events notification settings
223
+ },
224
+ 'put': {
225
+ 'notifications': 1, // Set notification settings
226
+ 'notifications/set': 1,
227
+ },
228
+ },
229
+ },
230
+ 'fees': {
231
+ 'trading': {
232
+ 'tierBased': false,
233
+ 'percentage': true,
234
+ 'taker': this.parseNumber ('0.002'),
235
+ 'maker': this.parseNumber ('0.002'),
236
+ },
237
+ },
238
+ 'commonCurrencies': {
239
+ 'BC': 'Bitcoin Confidential',
240
+ 'BITS': 'Bitcoinus',
241
+ 'BITSW': 'BITS',
242
+ 'BHD': 'Bithold',
243
+ 'BTH': 'Bithereum',
244
+ 'MPH': 'Chasyr Token',
245
+ 'SBTC': 'SBTCT', // SiamBitcoin
246
+ },
247
+ 'options': {
248
+ 'parseOrderToPrecision': false,
249
+ 'networks': {
250
+ 'ERC20': 5,
251
+ 'ETH': 5,
252
+ 'OMNI': 10,
253
+ 'XLM': 20,
254
+ 'BEP2': 22,
255
+ 'TRC20': 24,
256
+ 'TRX': 24,
257
+ 'SOL': 25,
258
+ 'BEP20': 501,
259
+ },
260
+ },
261
+ 'exceptions': {
262
+ 'exact': {
263
+ // {"success":false,"message":"Wrong parameters","errors":{"candleType":["Invalid Candle Type!"]}}
264
+ // {"success":false,"message":"Wrong parameters","errors":{"time":["timeStart or timeEnd is less then 1"]}}
265
+ 'Wrong parameters': BadRequest,
266
+ 'Unauthenticated.': AuthenticationError, // {"message":"Unauthenticated."}
267
+ 'Server Error': ExchangeError, // { "message": "Server Error" }
268
+ 'This feature is only enabled for users verifies by Cryptonomica': PermissionDenied, // {"success":false,"message":"This feature is only enabled for users verifies by Cryptonomica"}
269
+ 'Too Many Attempts.': DDoSProtection, // { "message": "Too Many Attempts." }
270
+ 'Selected Pair is disabled': BadSymbol, // {"success":false,"message":"Selected Pair is disabled"}
271
+ 'Invalid scope(s) provided.': PermissionDenied, // { "message": "Invalid scope(s) provided." }
272
+ 'The maximum amount of open orders with the same price cannot exceed 10': InvalidOrder, // { "success":false,"message":"The maximum amount of open orders with the same price cannot exceed 10" }
273
+ 'Your account not verified!': AccountSuspended, // {"success":false,"message":"Your account not verified!","unified_message":{"message_id":"verification_required_to_continue","substitutions":null},"notice":"Please be informed that parameter `message` is deprecated and will be removed. Use unified_message instead."}
274
+ },
275
+ 'broad': {
276
+ 'Not enough': InsufficientFunds, // {"success":false,"message":"Not enough ETH"}
277
+ },
278
+ },
279
+ });
280
+ }
281
+
282
+ async fetchCurrencies (params = {}) {
283
+ const response = await this.publicGetCurrencies (params);
284
+ //
285
+ // {
286
+ // "success":true,
287
+ // "data":[
288
+ // {
289
+ // "id":1,
290
+ // "code":"BTC",
291
+ // "name":"Bitcoin",
292
+ // "active":true,
293
+ // "delisted":false,
294
+ // "precision":8,
295
+ // "minimum_tx_confirmations":1,
296
+ // "minimum_withdrawal_amount":"0.00200000",
297
+ // "minimum_deposit_amount":"0.00000000",
298
+ // "deposit_fee_currency_id":1,
299
+ // "deposit_fee_currency_code":"BTC",
300
+ // "deposit_fee_const":"0.00000000",
301
+ // "deposit_fee_percent":"0.00000000",
302
+ // "withdrawal_fee_currency_id":1,
303
+ // "withdrawal_fee_currency_code":"BTC",
304
+ // "withdrawal_fee_const":"0.00100000",
305
+ // "withdrawal_fee_percent":"0.00000000",
306
+ // "block_explorer_url":"https:\/\/blockchain.info\/tx\/",
307
+ // "protocol_specific_settings":null
308
+ // },
309
+ // ]
310
+ // }
311
+ //
312
+ const result = {};
313
+ const currencies = this.safeValue (response, 'data', []);
314
+ for (let i = 0; i < currencies.length; i++) {
315
+ const currency = currencies[i];
316
+ const id = this.safeString (currency, 'id');
317
+ const numericId = this.safeInteger (currency, 'id');
318
+ // todo: will need to rethink the fees
319
+ // to add support for multiple withdrawal/deposit methods and
320
+ // differentiated fees for each particular method
321
+ const code = this.safeCurrencyCode (this.safeString (currency, 'code'));
322
+ const precision = this.safeString (currency, 'precision');
323
+ const amountLimit = this.parsePrecision (precision);
324
+ const fee = this.safeNumber (currency, 'withdrawal_fee_const'); // todo: redesign
325
+ const active = this.safeValue (currency, 'active', true);
326
+ result[code] = {
327
+ 'id': id,
328
+ 'numericId': numericId,
329
+ 'code': code,
330
+ 'info': currency,
331
+ 'type': undefined,
332
+ 'name': this.safeString (currency, 'name'),
333
+ 'active': active,
334
+ 'deposit': undefined,
335
+ 'withdraw': undefined,
336
+ 'fee': fee,
337
+ 'precision': parseInt (precision),
338
+ 'limits': {
339
+ 'amount': {
340
+ 'min': this.parseNumber (amountLimit),
341
+ 'max': undefined,
342
+ },
343
+ 'deposit': {
344
+ 'min': this.safeNumber (currency, 'minimum_deposit_amount'),
345
+ 'max': undefined,
346
+ },
347
+ 'withdraw': {
348
+ 'min': this.safeNumber (currency, 'minimum_withdrawal_amount'),
349
+ 'max': undefined,
350
+ },
351
+ },
352
+ };
353
+ }
354
+ return result;
355
+ }
356
+
357
+ async fetchMarkets (params = {}) {
358
+ const request = {
359
+ 'code': 'ALL',
360
+ };
361
+ const response = await this.publicGetCurrencyPairsListCode (this.extend (request, params));
362
+ //
363
+ // {
364
+ // "success":true,
365
+ // "data":[
366
+ // {
367
+ // "id":935,
368
+ // "currency_id":662,
369
+ // "currency_code":"ABET",
370
+ // "currency_name":"Altbet",
371
+ // "market_currency_id":1,
372
+ // "market_code":"BTC",
373
+ // "market_name":"Bitcoin",
374
+ // "min_order_amount":"0.00000010",
375
+ // "min_buy_price":"0.00000001",
376
+ // "min_sell_price":"0.00000001",
377
+ // "buy_fee_percent":"0.20000000",
378
+ // "sell_fee_percent":"0.20000000",
379
+ // "active":true,
380
+ // "delisted":false,
381
+ // "pair_message":"",
382
+ // "currency_precision":8,
383
+ // "market_precision":8,
384
+ // "symbol":"ABET_BTC",
385
+ // "group_name":"BTC",
386
+ // "group_id":1
387
+ // }
388
+ // ]
389
+ // }
390
+ //
391
+ const result = [];
392
+ const markets = this.safeValue (response, 'data', []);
393
+ for (let i = 0; i < markets.length; i++) {
394
+ const market = markets[i];
395
+ const id = this.safeString (market, 'id');
396
+ const numericId = this.safeInteger (market, 'id');
397
+ const baseId = this.safeString (market, 'currency_id');
398
+ const quoteId = this.safeString (market, 'market_currency_id');
399
+ const baseNumericId = this.safeInteger (market, 'currency_id');
400
+ const quoteNumericId = this.safeInteger (market, 'market_currency_id');
401
+ const base = this.safeCurrencyCode (this.safeString (market, 'currency_code'));
402
+ const quote = this.safeCurrencyCode (this.safeString (market, 'market_code'));
403
+ const minBuyPrice = this.safeString (market, 'min_buy_price');
404
+ const minSellPrice = this.safeString (market, 'min_sell_price');
405
+ const minPrice = Precise.stringMax (minBuyPrice, minSellPrice);
406
+ const buyFee = Precise.stringDiv (this.safeString (market, 'buy_fee_percent'), '100');
407
+ const sellFee = Precise.stringDiv (this.safeString (market, 'sell_fee_percent'), '100');
408
+ const fee = Precise.stringMax (buyFee, sellFee);
409
+ result.push ({
410
+ 'id': id,
411
+ 'numericId': numericId,
412
+ 'symbol': base + '/' + quote,
413
+ 'base': base,
414
+ 'quote': quote,
415
+ 'settle': undefined,
416
+ 'baseId': baseId,
417
+ 'quoteId': quoteId,
418
+ 'settleId': undefined,
419
+ 'baseNumericId': baseNumericId,
420
+ 'quoteNumericId': quoteNumericId,
421
+ 'type': 'spot',
422
+ 'spot': true,
423
+ 'margin': false,
424
+ 'swap': false,
425
+ 'future': false,
426
+ 'option': false,
427
+ 'active': this.safeValue (market, 'active'),
428
+ 'contract': false,
429
+ 'linear': undefined,
430
+ 'inverse': undefined,
431
+ 'taker': fee,
432
+ 'maker': fee,
433
+ 'contractSize': undefined,
434
+ 'expiry': undefined,
435
+ 'expiryDatetime': undefined,
436
+ 'strike': undefined,
437
+ 'optionType': undefined,
438
+ 'precision': {
439
+ 'amount': this.safeInteger (market, 'currency_precision'),
440
+ 'price': this.safeInteger (market, 'market_precision'),
441
+ },
442
+ 'limits': {
443
+ 'leverage': {
444
+ 'min': undefined,
445
+ 'max': undefined,
446
+ },
447
+ 'amount': {
448
+ 'min': this.safeNumber (market, 'min_order_amount'),
449
+ 'max': undefined,
450
+ },
451
+ 'price': {
452
+ 'min': minPrice,
453
+ 'max': undefined,
454
+ },
455
+ 'cost': {
456
+ 'min': undefined,
457
+ 'max': undefined,
458
+ },
459
+ },
460
+ 'info': market,
461
+ });
462
+ }
463
+ return result;
464
+ }
465
+
466
+ async fetchTicker (symbol, params = {}) {
467
+ await this.loadMarkets ();
468
+ const market = this.market (symbol);
469
+ const request = {
470
+ 'currencyPairId': market['id'],
471
+ };
472
+ const response = await this.publicGetTickerCurrencyPairId (this.extend (request, params));
473
+ //
474
+ // {
475
+ // "success": true,
476
+ // "data": {
477
+ // "id": 2,
478
+ // "amount_multiplier": 1,
479
+ // "currency_code": "ETH",
480
+ // "market_code": "BTC",
481
+ // "currency_name": "Ethereum",
482
+ // "market_name": "Bitcoin",
483
+ // "symbol": "ETH_BTC",
484
+ // "group_name": "BTC",
485
+ // "group_id": 1,
486
+ // "ask": "0.02069998",
487
+ // "bid": "0.02028622",
488
+ // "last": "0.02049224",
489
+ // "open": "0.02059605",
490
+ // "low": "0.01977744",
491
+ // "high": "0.02097005",
492
+ // "volume": "480.43248971",
493
+ // "volumeQuote": "23491.29826130",
494
+ // "count": "7384",
495
+ // "fiatsRate": {
496
+ // "USD": 7230.86,
497
+ // "EUR": 6590.79,
498
+ // "UAH": 173402,
499
+ // "AUD": 10595.51,
500
+ // "IDR": 101568085,
501
+ // "CNY": 50752,
502
+ // "KRW": 8452295,
503
+ // "JPY": 784607,
504
+ // "VND": 167315119,
505
+ // "INR": 517596,
506
+ // "GBP": 5607.25,
507
+ // "CAD": 9602.63,
508
+ // "BRL": 30472,
509
+ // "RUB": 460718
510
+ // },
511
+ // "timestamp": 1574698235601
512
+ // }
513
+ // }
514
+ //
515
+ const ticker = this.safeValue (response, 'data', {});
516
+ return this.parseTicker (ticker, market);
517
+ }
518
+
519
+ async fetchTime (params = {}) {
520
+ const response = await this.publicGetPing (params);
521
+ //
522
+ // {
523
+ // "success": true,
524
+ // "data": {
525
+ // "server_datetime": {
526
+ // "date": "2019-01-22 15:13:34.233796",
527
+ // "timezone_type": 3,
528
+ // "timezone": "UTC"
529
+ // },
530
+ // "server_timestamp": 1548170014
531
+ // }
532
+ // }
533
+ //
534
+ const data = this.safeValue (response, 'data', {});
535
+ const serverDatetime = this.safeValue (data, 'server_datetime', {});
536
+ return this.parse8601 (this.safeString (serverDatetime, 'date'));
537
+ }
538
+
539
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
540
+ await this.loadMarkets ();
541
+ const market = this.market (symbol);
542
+ const request = {
543
+ 'currencyPairId': market['id'],
544
+ };
545
+ if (limit !== undefined) {
546
+ request['limit_bids'] = limit; // returns all if set to 0, default 100
547
+ request['limit_asks'] = limit; // returns all if set to 0, default 100
548
+ }
549
+ const response = await this.publicGetOrderbookCurrencyPairId (this.extend (request, params));
550
+ //
551
+ // {
552
+ // "success": true,
553
+ // "data": {
554
+ // "ask": [
555
+ // { "currency_pair_id": 2, "amount": "2.17865373", "price": "0.02062917", "amount2": "0.04494382", "count": 1, "cumulative_amount": 2.17865373 },
556
+ // { "currency_pair_id": 2, "amount": "2.27521743", "price": "0.02062918", "amount2": "0.04693587", "count": 1, "cumulative_amount": 4.45387116 },
557
+ // { "currency_pair_id": 2, "amount": "1.26980049", "price": "0.02063170", "amount2": "0.02619814", "count": 1, "cumulative_amount": 5.72367165 },
558
+ // ],
559
+ // "bid": [
560
+ // { "currency_pair_id": 2, "amount": "0.00978005", "price": "0.02057000", "amount2": "0.00020118", "count": 1, "cumulative_amount": 0.00978005 },
561
+ // { "currency_pair_id": 2, "amount": "0.00500000", "price": "0.02056000", "amount2": "0.00010280", "count": 1, "cumulative_amount": 0.01478005 },
562
+ // { "currency_pair_id": 2, "amount": "0.77679882", "price": "0.02054001", "amount2": "0.01595546", "count": 1, "cumulative_amount": 0.79157887 },
563
+ // ],
564
+ // "ask_total_amount": 2555.749174609999,
565
+ // "bid_total_amount": 29.180037330000005
566
+ // }
567
+ // }
568
+ //
569
+ const orderbook = this.safeValue (response, 'data', {});
570
+ return this.parseOrderBook (orderbook, symbol, undefined, 'bid', 'ask', 'price', 'amount');
571
+ }
572
+
573
+ parseTicker (ticker, market = undefined) {
574
+ //
575
+ // {
576
+ // "id": 2,
577
+ // "amount_multiplier": 1,
578
+ // "currency_code": "ETH",
579
+ // "market_code": "BTC",
580
+ // "currency_name": "Ethereum",
581
+ // "market_name": "Bitcoin",
582
+ // "symbol": "ETH_BTC",
583
+ // "group_name": "BTC",
584
+ // "group_id": 1,
585
+ // "ask": "0.02069998",
586
+ // "bid": "0.02028622",
587
+ // "last": "0.02049224",
588
+ // "open": "0.02059605",
589
+ // "low": "0.01977744",
590
+ // "high": "0.02097005",
591
+ // "volume": "480.43248971",
592
+ // "volumeQuote": "23491.29826130",
593
+ // "count": "7384",
594
+ // "fiatsRate": {
595
+ // "USD": 7230.86,
596
+ // "EUR": 6590.79,
597
+ // "UAH": 173402,
598
+ // "AUD": 10595.51,
599
+ // "IDR": 101568085,
600
+ // "CNY": 50752,
601
+ // "KRW": 8452295,
602
+ // "JPY": 784607,
603
+ // "VND": 167315119,
604
+ // "INR": 517596,
605
+ // "GBP": 5607.25,
606
+ // "CAD": 9602.63,
607
+ // "BRL": 30472,
608
+ // "RUB": 460718
609
+ // },
610
+ // "timestamp": 1574698235601
611
+ // }
612
+ //
613
+ const timestamp = this.safeInteger (ticker, 'timestamp');
614
+ const marketId = this.safeString2 (ticker, 'id', 'symbol');
615
+ const symbol = this.safeSymbol (marketId, market, '_');
616
+ const last = this.safeString (ticker, 'last');
617
+ const open = this.safeString (ticker, 'open');
618
+ return this.safeTicker ({
619
+ 'symbol': symbol,
620
+ 'timestamp': timestamp,
621
+ 'datetime': this.iso8601 (timestamp),
622
+ 'high': this.safeString (ticker, 'high'),
623
+ 'low': this.safeString (ticker, 'low'),
624
+ 'bid': this.safeString (ticker, 'bid'),
625
+ 'bidVolume': undefined,
626
+ 'ask': this.safeString (ticker, 'ask'),
627
+ 'askVolume': undefined,
628
+ 'vwap': undefined,
629
+ 'open': open,
630
+ 'close': last,
631
+ 'last': last,
632
+ 'previousClose': undefined, // previous day close
633
+ 'change': undefined,
634
+ 'percentage': undefined,
635
+ 'average': undefined,
636
+ 'baseVolume': this.safeString (ticker, 'volumeQuote'),
637
+ 'quoteVolume': this.safeString (ticker, 'volume'),
638
+ 'info': ticker,
639
+ }, market, false);
640
+ }
641
+
642
+ async fetchTickers (symbols = undefined, params = {}) {
643
+ await this.loadMarkets ();
644
+ const response = await this.publicGetTicker (params);
645
+ //
646
+ // {
647
+ // "success":true,
648
+ // "data":[
649
+ // {
650
+ // "id":262,
651
+ // "amount_multiplier":1,
652
+ // "currency_code":"ARDR",
653
+ // "market_code":"BTC",
654
+ // "currency_name":"ARDOR",
655
+ // "market_name":"Bitcoin",
656
+ // "symbol":"ARDR_BTC",
657
+ // "group_name":"BTC",
658
+ // "group_id":1,
659
+ // "ask":"0.00000630",
660
+ // "bid":"0.00000613",
661
+ // "last":"0.00000617",
662
+ // "open":"0.00000620",
663
+ // "low":"0.00000614",
664
+ // "high":"0.00000630",
665
+ // "volume":"30.37795305",
666
+ // "volumeQuote":"4911487.01996544",
667
+ // "count":"710",
668
+ // "fiatsRate":{
669
+ // "USD":7230.86,
670
+ // "EUR":6590.79,
671
+ // "UAH":173402,
672
+ // "AUD":10744.52,
673
+ // "IDR":101568085,
674
+ // "CNY":50752,
675
+ // "KRW":8452295,
676
+ // "JPY":784607,
677
+ // "VND":167315119,
678
+ // "INR":517596,
679
+ // "GBP":5607.25,
680
+ // "CAD":9602.63,
681
+ // "BRL":30472,
682
+ // "RUB":467358
683
+ // },
684
+ // "timestamp":1574698617304,
685
+ // "group_position":1
686
+ // },
687
+ // ]
688
+ // }
689
+ //
690
+ const tickers = this.safeValue (response, 'data', []);
691
+ return this.parseTickers (tickers, symbols);
692
+ }
693
+
694
+ parseOHLCV (ohlcv, market = undefined) {
695
+ //
696
+ // {
697
+ // "time": 1566086400000,
698
+ // "close": 0.01895,
699
+ // "open": 0.01812427,
700
+ // "high": 0.0191588,
701
+ // "low": 0.01807001,
702
+ // "volume": 2588.597813750006
703
+ // }
704
+ //
705
+ return [
706
+ this.safeInteger (ohlcv, 'time'),
707
+ this.safeNumber (ohlcv, 'open'),
708
+ this.safeNumber (ohlcv, 'high'),
709
+ this.safeNumber (ohlcv, 'low'),
710
+ this.safeNumber (ohlcv, 'close'),
711
+ this.safeNumber (ohlcv, 'volume'),
712
+ ];
713
+ }
714
+
715
+ async fetchOHLCV (symbol, timeframe = '1d', since = undefined, limit = undefined, params = {}) {
716
+ await this.loadMarkets ();
717
+ const market = this.market (symbol);
718
+ const request = {
719
+ 'currencyPairId': market['id'],
720
+ 'candlesType': this.timeframes[timeframe], // default 1d
721
+ // 'timeStart': 1574709092, // unix timestamp in seconds, required
722
+ // 'timeEnd': 1574709092, // unix timestamp in seconds, required
723
+ // 'limit': 100, // default 100, optional
724
+ // 'offset' 100, // optional, pagination within timerange
725
+ };
726
+ if (limit === undefined) {
727
+ limit = 100;
728
+ } else {
729
+ request['limit'] = limit;
730
+ }
731
+ const duration = this.parseTimeframe (timeframe);
732
+ const timerange = limit * duration;
733
+ if (since === undefined) {
734
+ request['timeEnd'] = this.seconds ();
735
+ request['timeStart'] = request['timeEnd'] - timerange;
736
+ } else {
737
+ request['timeStart'] = parseInt (since / 1000);
738
+ request['timeEnd'] = this.sum (request['timeStart'], timerange);
739
+ }
740
+ const response = await this.publicGetChartCurrencyPairIdCandlesType (this.extend (request, params));
741
+ //
742
+ // {
743
+ // "success": true,
744
+ // "data": [
745
+ // {
746
+ // "time": 1566086400000,
747
+ // "close": 0.01895,
748
+ // "open": 0.01812427,
749
+ // "high": 0.0191588,
750
+ // "low": 0.01807001,
751
+ // "volume": 2588.597813750006
752
+ // },
753
+ // ]
754
+ // }
755
+ //
756
+ const data = this.safeValue (response, 'data', []);
757
+ return this.parseOHLCVs (data, market, timeframe, since, limit);
758
+ }
759
+
760
+ parseTrade (trade, market = undefined) {
761
+ //
762
+ // public fetchTrades
763
+ //
764
+ // {
765
+ // "id": 35989317,
766
+ // "price": "0.02033813",
767
+ // "amount": "3.60000000",
768
+ // "type": "BUY",
769
+ // "timestamp": "1574713503"
770
+ // }
771
+ //
772
+ // private fetchMyTrades, fetchClosedOrder, fetchOrderTrades
773
+ //
774
+ // {
775
+ // "id": 658745,
776
+ // "buy_order_id": 6587453,
777
+ // "sell_order_id": 6587459,
778
+ // "price": 0.012285,
779
+ // "amount": 6.35,
780
+ // "trade_type": "SELL",
781
+ // "timestamp": "1538737692"
782
+ // }
783
+ //
784
+ const id = this.safeString (trade, 'id');
785
+ const timestamp = this.safeTimestamp (trade, 'timestamp');
786
+ const priceString = this.safeString (trade, 'price');
787
+ const amountString = this.safeString (trade, 'amount');
788
+ let symbol = undefined;
789
+ if ((symbol === undefined) && (market !== undefined)) {
790
+ symbol = market['symbol'];
791
+ }
792
+ const side = this.safeStringLower2 (trade, 'type', 'trade_type');
793
+ return this.safeTrade ({
794
+ 'info': trade,
795
+ 'timestamp': timestamp,
796
+ 'datetime': this.iso8601 (timestamp),
797
+ 'symbol': symbol,
798
+ 'id': id,
799
+ 'order': undefined,
800
+ 'type': undefined,
801
+ 'takerOrMaker': undefined,
802
+ 'side': side,
803
+ 'price': priceString,
804
+ 'amount': amountString,
805
+ 'cost': undefined,
806
+ 'fee': undefined,
807
+ }, market);
808
+ }
809
+
810
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
811
+ await this.loadMarkets ();
812
+ const market = this.market (symbol);
813
+ const request = {
814
+ 'currencyPairId': market['id'],
815
+ // 'sort': 'ASC', // ASC or DESC, default DESC
816
+ // 'from': 1574709092, // unix timestamp, optional
817
+ // 'till': 1574709092, // unix timestamp, optional
818
+ // 'limit': 100, // default 100, optional
819
+ // 'offset': 100, // optional
820
+ };
821
+ if (limit !== undefined) {
822
+ request['limit'] = limit; // currently limited to 100 or fewer
823
+ }
824
+ if (since !== undefined) {
825
+ request['sort'] = 'ASC'; // needed to make the from param work
826
+ request['from'] = parseInt (since / 1000);
827
+ }
828
+ const response = await this.publicGetTradesCurrencyPairId (this.extend (request, params));
829
+ //
830
+ // {
831
+ // "success": true,
832
+ // "data": [
833
+ // {
834
+ // "id": 35989317,
835
+ // "price": "0.02033813",
836
+ // "amount": "3.60000000",
837
+ // "type": "BUY",
838
+ // "timestamp": "1574713503"
839
+ // },
840
+ // ]
841
+ // }
842
+ //
843
+ const trades = this.safeValue (response, 'data', []);
844
+ return this.parseTrades (trades, market, since, limit);
845
+ }
846
+
847
+ async fetchTradingFee (symbol, params = {}) {
848
+ await this.loadMarkets ();
849
+ const market = this.market (symbol);
850
+ const request = {
851
+ 'currencyPairId': market['id'],
852
+ };
853
+ const response = await this.tradingGetFeesCurrencyPairId (this.extend (request, params));
854
+ //
855
+ // {
856
+ // success: true,
857
+ // data: { buy_fee: '0.00200000', sell_fee: '0.00200000' },
858
+ // unified_message: { message_id: 'operation_successful', substitutions: [] }
859
+ // }
860
+ //
861
+ const data = this.safeValue (response, 'data');
862
+ return {
863
+ 'info': response,
864
+ 'symbol': market['symbol'],
865
+ 'maker': this.safeNumber (data, 'sell_fee'),
866
+ 'taker': this.safeNumber (data, 'buy_fee'),
867
+ 'percentage': true,
868
+ 'tierBased': true,
869
+ };
870
+ }
871
+
872
+ parseBalance (response) {
873
+ const result = {
874
+ 'info': response,
875
+ 'timestamp': undefined,
876
+ 'datetime': undefined,
877
+ };
878
+ const balances = this.safeValue (response, 'data', []);
879
+ for (let i = 0; i < balances.length; i++) {
880
+ const balance = balances[i];
881
+ const code = this.safeCurrencyCode (this.safeString (balance, 'currency_id'));
882
+ const account = this.account ();
883
+ account['free'] = this.safeString (balance, 'balance');
884
+ account['used'] = this.safeString (balance, 'frozen_balance');
885
+ result[code] = account;
886
+ }
887
+ return this.safeBalance (result);
888
+ }
889
+
890
+ async fetchBalance (params = {}) {
891
+ await this.loadMarkets ();
892
+ // await this.loadAccounts ();
893
+ const response = await this.profileGetWallets (params);
894
+ //
895
+ // {
896
+ // "success": true,
897
+ // "data": [
898
+ // {
899
+ // "id": null,
900
+ // "currency_id": 665,
901
+ // "delisted": false,
902
+ // "disabled": false,
903
+ // "disable_deposits": false,
904
+ // "currency_code": "ORM",
905
+ // "currency_name": "Orium",
906
+ // "currency_type_id": 5,
907
+ // "balance": "0",
908
+ // "frozen_balance": "0",
909
+ // "bonus_balance": "0",
910
+ // "total_balance": "0",
911
+ // "protocol_specific_settings": null,
912
+ // "rates": { "BTC": "0.00000000020", "USD": "0.00000147" },
913
+ // },
914
+ // {
915
+ // "id": null,
916
+ // "currency_id": 272,
917
+ // "delisted": false,
918
+ // "disabled": false,
919
+ // "disable_deposits": false,
920
+ // "currency_code": "USDT",
921
+ // "currency_name": "TetherUSD",
922
+ // "currency_type_id": 23,
923
+ // "balance": "0",
924
+ // "frozen_balance": "0",
925
+ // "bonus_balance": "0",
926
+ // "total_balance": "0",
927
+ // "protocol_specific_settings": [
928
+ // { "protocol_name": "OMNI", "protocol_id": 10, "active": true, "withdrawal_fee_currency_id": 272, "withdrawal_fee_const": 10, "withdrawal_fee_percent": 0, "block_explorer_url": "https://omniexplorer.info/search/" },
929
+ // { "protocol_name": "ERC20", "protocol_id": 5, "active": true, "withdrawal_fee_const": 1.2, "withdrawal_fee_percent": 0, "block_explorer_url": "https://etherscan.io/tx/" },
930
+ // { "protocol_name": "TRON", "protocol_id": 24, "active": true, "withdrawal_fee_currency_id": 272, "withdrawal_fee_const": 0.2, "withdrawal_fee_percent": 0, "block_explorer_url": "https://tronscan.org/#/transaction/" }
931
+ // ],
932
+ // "rates": { "BTC": "0.00013893", "USD": "1" },
933
+ // },
934
+ // ]
935
+ // }
936
+ //
937
+ return this.parseBalance (response);
938
+ }
939
+
940
+ parseOrderStatus (status) {
941
+ const statuses = {
942
+ 'PROCESSING': 'open',
943
+ 'PENDING': 'open',
944
+ 'PARTIAL': 'open',
945
+ 'FINISHED': 'closed',
946
+ 'CANCELLED': 'canceled',
947
+ };
948
+ return this.safeString (statuses, status, status);
949
+ }
950
+
951
+ parseOrder (order, market = undefined) {
952
+ //
953
+ // createOrder, fetchOpenOrders, fetchClosedOrders, cancelOrder, fetchOrder, fetchClosedOrder
954
+ //
955
+ // {
956
+ // "id": 828680665,
957
+ // "currency_pair_id": 1,
958
+ // "currency_pair_name": "NXT_BTC",
959
+ // "price": "0.011384",
960
+ // "trigger_price": 0.011385,
961
+ // "initial_amount": "13.942",
962
+ // "processed_amount": "3.724", // missing in fetchClosedOrder
963
+ // "type": "SELL",
964
+ // "original_type": "STOP_LIMIT_SELL",
965
+ // "created": "2019-01-17 10:14:48",
966
+ // "timestamp": "1547720088",
967
+ // "status": "PARTIAL"
968
+ // // fetchClosedOrder only
969
+ // "trades": [
970
+ // {
971
+ // "id": 658745,
972
+ // "buy_order_id": 658745,
973
+ // "sell_order_id": 828680665,
974
+ // "price": 0.012285,
975
+ // "amount": 6.35,
976
+ // "trade_type": "SELL",
977
+ // "timestamp": "1538737692"
978
+ // }
979
+ // ],
980
+ // // fetchClosedOrder only
981
+ // "fees": [
982
+ // {
983
+ // "id": 1234567,
984
+ // "currency_id": 1,
985
+ // "amount": 0.00025,
986
+ // "timestamp": "1548149238"
987
+ // }
988
+ // ]
989
+ // }
990
+ //
991
+ const id = this.safeString (order, 'id');
992
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
993
+ const marketId = this.safeString2 (order, 'currency_pair_id', 'currency_pair_name');
994
+ const symbol = this.safeSymbol (marketId, market, '_');
995
+ const timestamp = this.safeTimestamp (order, 'timestamp');
996
+ const price = this.safeNumber (order, 'price');
997
+ const amount = this.safeNumber (order, 'initial_amount');
998
+ const filled = this.safeNumber (order, 'processed_amount');
999
+ let remaining = undefined;
1000
+ let cost = undefined;
1001
+ if (filled !== undefined) {
1002
+ if (amount !== undefined) {
1003
+ remaining = amount - filled;
1004
+ if (this.options['parseOrderToPrecision']) {
1005
+ remaining = parseFloat (this.amountToPrecision (symbol, remaining));
1006
+ }
1007
+ remaining = Math.max (remaining, 0.0);
1008
+ }
1009
+ if (price !== undefined) {
1010
+ if (cost === undefined) {
1011
+ cost = price * filled;
1012
+ }
1013
+ }
1014
+ }
1015
+ let type = this.safeString (order, 'original_type');
1016
+ if ((type === 'BUY') || (type === 'SELL')) {
1017
+ type = undefined;
1018
+ }
1019
+ const side = this.safeStringLower (order, 'type');
1020
+ const rawTrades = this.safeValue (order, 'trades');
1021
+ let trades = undefined;
1022
+ if (rawTrades !== undefined) {
1023
+ trades = this.parseTrades (rawTrades, market, undefined, undefined, {
1024
+ 'symbol': symbol,
1025
+ 'order': id,
1026
+ });
1027
+ }
1028
+ const stopPrice = this.safeNumber (order, 'trigger_price');
1029
+ const result = {
1030
+ 'info': order,
1031
+ 'id': id,
1032
+ 'clientOrderId': undefined,
1033
+ 'timestamp': timestamp,
1034
+ 'datetime': this.iso8601 (timestamp),
1035
+ 'lastTradeTimestamp': undefined,
1036
+ 'symbol': symbol,
1037
+ 'type': type,
1038
+ 'timeInForce': undefined,
1039
+ 'postOnly': undefined,
1040
+ 'side': side,
1041
+ 'price': price,
1042
+ 'stopPrice': stopPrice,
1043
+ 'amount': amount,
1044
+ 'cost': cost,
1045
+ 'average': undefined,
1046
+ 'filled': filled,
1047
+ 'remaining': remaining,
1048
+ 'status': status,
1049
+ 'trades': trades,
1050
+ };
1051
+ const fees = this.safeValue (order, 'fees');
1052
+ if (fees === undefined) {
1053
+ result['fee'] = undefined;
1054
+ } else {
1055
+ const numFees = fees.length;
1056
+ if (numFees > 0) {
1057
+ result['fees'] = [];
1058
+ for (let i = 0; i < fees.length; i++) {
1059
+ const feeCost = this.safeNumber (fees[i], 'amount');
1060
+ if (feeCost !== undefined) {
1061
+ const feeCurrencyId = this.safeString (fees[i], 'currency_id');
1062
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
1063
+ result['fees'].push ({
1064
+ 'cost': feeCost,
1065
+ 'currency': feeCurrencyCode,
1066
+ });
1067
+ }
1068
+ }
1069
+ } else {
1070
+ result['fee'] = undefined;
1071
+ }
1072
+ }
1073
+ return result;
1074
+ }
1075
+
1076
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1077
+ if (type === 'market') {
1078
+ throw new ExchangeError (this.id + ' createOrder() allows limit orders only');
1079
+ }
1080
+ await this.loadMarkets ();
1081
+ const market = this.market (symbol);
1082
+ if (type === 'limit') {
1083
+ type = side;
1084
+ }
1085
+ const request = {
1086
+ 'currencyPairId': market['id'],
1087
+ 'type': type.toUpperCase (), // 'BUY', 'SELL', 'STOP_LIMIT_BUY', 'STOP_LIMIT_SELL'
1088
+ 'amount': parseFloat (this.amountToPrecision (symbol, amount)), // required
1089
+ 'price': parseFloat (this.priceToPrecision (symbol, price)), // required
1090
+ // 'trigger_price': 123.45 // required for STOP_LIMIT_BUY or STOP_LIMIT_SELL
1091
+ };
1092
+ const response = await this.tradingPostOrdersCurrencyPairId (this.extend (request, params));
1093
+ //
1094
+ // {
1095
+ // "success": true,
1096
+ // "data": {
1097
+ // "id": 828680665,
1098
+ // "currency_pair_id": 1,
1099
+ // "currency_pair_name": "NXT_BTC",
1100
+ // "price": "0.011384",
1101
+ // "trigger_price": 0.011385,
1102
+ // "initial_amount": "13.942",
1103
+ // "processed_amount": "3.724",
1104
+ // "type": "SELL",
1105
+ // "original_type": "STOP_LIMIT_SELL",
1106
+ // "created": "2019-01-17 10:14:48",
1107
+ // "timestamp": "1547720088",
1108
+ // "status": "PARTIAL"
1109
+ // }
1110
+ // }
1111
+ //
1112
+ const data = this.safeValue (response, 'data', {});
1113
+ return this.parseOrder (data, market);
1114
+ }
1115
+
1116
+ async fetchOrder (id, symbol = undefined, params = {}) {
1117
+ await this.loadMarkets ();
1118
+ const request = {
1119
+ 'orderId': id,
1120
+ };
1121
+ const response = await this.tradingGetOrderOrderId (this.extend (request, params));
1122
+ //
1123
+ // {
1124
+ // "success": true,
1125
+ // "data": {
1126
+ // "id": 828680665,
1127
+ // "currency_pair_id": 1,
1128
+ // "currency_pair_name": "NXT_BTC",
1129
+ // "price": "0.011384",
1130
+ // "trigger_price": 0.011385,
1131
+ // "initial_amount": "13.942",
1132
+ // "processed_amount": "3.724",
1133
+ // "type": "SELL",
1134
+ // "original_type": "STOP_LIMIT_SELL",
1135
+ // "created": "2019-01-17 10:14:48",
1136
+ // "timestamp": "1547720088",
1137
+ // "status": "PARTIAL"
1138
+ // }
1139
+ // }
1140
+ //
1141
+ const data = this.safeValue (response, 'data', {});
1142
+ let market = undefined;
1143
+ if (symbol !== undefined) {
1144
+ market = this.market (symbol);
1145
+ }
1146
+ return this.parseOrder (data, market);
1147
+ }
1148
+
1149
+ async fetchClosedOrder (id, symbol = undefined, params = {}) {
1150
+ await this.loadMarkets ();
1151
+ const request = {
1152
+ 'orderId': id,
1153
+ };
1154
+ const response = await this.reportsGetOrdersOrderId (this.extend (request, params));
1155
+ //
1156
+ // {
1157
+ // "success": true,
1158
+ // "data": {
1159
+ // "id": 5478965,
1160
+ // "currency_pair_id": 1,
1161
+ // "currency_pair_name": "NXT_BTC",
1162
+ // "price": "0.00013800",
1163
+ // "initial_amount": "1.00000000",
1164
+ // "type": "BUY",
1165
+ // "created": "2019-01-22 09:27:17",
1166
+ // "timestamp": 1548149237,
1167
+ // "status": "FINISHED",
1168
+ // "trades": [
1169
+ // {
1170
+ // "id": 658745,
1171
+ // "buy_order_id": 6587453,
1172
+ // "sell_order_id": 6587459,
1173
+ // "price": 0.012285,
1174
+ // "amount": 6.35,
1175
+ // "trade_type": "SELL",
1176
+ // "timestamp": "1538737692"
1177
+ // }
1178
+ // ],
1179
+ // "fees": [
1180
+ // {
1181
+ // "id": 1234567,
1182
+ // "currency_id": 1,
1183
+ // "amount": 0.00025,
1184
+ // "timestamp": "1548149238"
1185
+ // }
1186
+ // ]
1187
+ // }
1188
+ // }
1189
+ //
1190
+ const data = this.safeValue (response, 'data', {});
1191
+ let market = undefined;
1192
+ if (symbol !== undefined) {
1193
+ market = this.market (symbol);
1194
+ }
1195
+ return this.parseOrder (data, market);
1196
+ }
1197
+
1198
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1199
+ const order = await this.fetchClosedOrder (id, symbol, params);
1200
+ return order['trades'];
1201
+ }
1202
+
1203
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1204
+ await this.loadMarkets ();
1205
+ let market = undefined;
1206
+ let method = 'tradingGetOrders';
1207
+ const request = {
1208
+ // 'limit': 100, // default 100
1209
+ // 'offset': 100,
1210
+ };
1211
+ if (symbol !== undefined) {
1212
+ method = 'tradingGetOrdersCurrencyPairId';
1213
+ market = this.market (symbol);
1214
+ request['currencyPairId'] = market['id'];
1215
+ }
1216
+ if (limit !== undefined) {
1217
+ request['limit'] = limit;
1218
+ }
1219
+ const response = await this[method] (this.extend (request, params));
1220
+ //
1221
+ // {
1222
+ // "success": true,
1223
+ // "data": [
1224
+ // {
1225
+ // "id": 828680665,
1226
+ // "currency_pair_id": 1,
1227
+ // "currency_pair_name": "NXT_BTC",
1228
+ // "price": "0.011384",
1229
+ // "trigger_price": 0.011385,
1230
+ // "initial_amount": "13.942",
1231
+ // "processed_amount": "3.724",
1232
+ // "type": "SELL",
1233
+ // "original_type": "STOP_LIMIT_SELL",
1234
+ // "created": "2019-01-17 10:14:48",
1235
+ // "timestamp": "1547720088",
1236
+ // "status": "PARTIAL"
1237
+ // }
1238
+ // ]
1239
+ // }
1240
+ //
1241
+ const data = this.safeValue (response, 'data', []);
1242
+ return this.parseOrders (data, market, since, limit);
1243
+ }
1244
+
1245
+ async cancelOrder (id, symbol = undefined, params = {}) {
1246
+ await this.loadMarkets ();
1247
+ const request = {
1248
+ 'orderId': id,
1249
+ };
1250
+ const response = await this.tradingDeleteOrderOrderId (this.extend (request, params));
1251
+ //
1252
+ // {
1253
+ // "success": true,
1254
+ // "data": {
1255
+ // "put_into_processing_queue": [
1256
+ // {
1257
+ // "id": 828680665,
1258
+ // "currency_pair_id": 1,
1259
+ // "currency_pair_name": "NXT_BTC",
1260
+ // "price": "0.011384",
1261
+ // "trigger_price": 0.011385,
1262
+ // "initial_amount": "13.942",
1263
+ // "processed_amount": "3.724",
1264
+ // "type": "SELL",
1265
+ // "original_type": "STOP_LIMIT_SELL",
1266
+ // "created": "2019-01-17 10:14:48",
1267
+ // "timestamp": "1547720088",
1268
+ // "status": "PARTIAL"
1269
+ // }
1270
+ // ],
1271
+ // "not_put_into_processing_queue": [
1272
+ // {
1273
+ // "id": 828680665,
1274
+ // "currency_pair_id": 1,
1275
+ // "currency_pair_name": "NXT_BTC",
1276
+ // "price": "0.011384",
1277
+ // "trigger_price": 0.011385,
1278
+ // "initial_amount": "13.942",
1279
+ // "processed_amount": "3.724",
1280
+ // "type": "SELL",
1281
+ // "original_type": "STOP_LIMIT_SELL",
1282
+ // "created": "2019-01-17 10:14:48",
1283
+ // "timestamp": "1547720088",
1284
+ // "status": "PARTIAL"
1285
+ // }
1286
+ // ],
1287
+ // "message": "string"
1288
+ // }
1289
+ // }
1290
+ //
1291
+ const data = this.safeValue (response, 'data', {});
1292
+ const acceptedOrders = this.safeValue (data, 'put_into_processing_queue', []);
1293
+ const rejectedOrders = this.safeValue (data, 'not_put_into_processing_queue', []);
1294
+ const numAcceptedOrders = acceptedOrders.length;
1295
+ const numRejectedOrders = rejectedOrders.length;
1296
+ if (numAcceptedOrders < 1) {
1297
+ if (numRejectedOrders < 1) {
1298
+ throw new OrderNotFound (this.id + ' cancelOrder() received an empty response: ' + this.json (response));
1299
+ } else {
1300
+ return this.parseOrder (rejectedOrders[0]);
1301
+ }
1302
+ } else {
1303
+ if (numRejectedOrders < 1) {
1304
+ return this.parseOrder (acceptedOrders[0]);
1305
+ } else {
1306
+ throw new OrderNotFound (this.id + ' cancelOrder() received an empty response: ' + this.json (response));
1307
+ }
1308
+ }
1309
+ }
1310
+
1311
+ async cancelAllOrders (symbol = undefined, params = {}) {
1312
+ await this.loadMarkets ();
1313
+ const request = {};
1314
+ let method = 'tradingDeleteOrders';
1315
+ if (symbol !== undefined) {
1316
+ const market = this.market (symbol);
1317
+ request['currencyPairId'] = market['id'];
1318
+ method = 'tradingDeleteOrdersCurrencyPairId';
1319
+ }
1320
+ const response = await this[method] (this.extend (request, params));
1321
+ //
1322
+ // {
1323
+ // "success":true,
1324
+ // "data":{
1325
+ // "put_into_processing_queue":[],
1326
+ // "not_put_into_processing_queue":[],
1327
+ // "message":"Orders operations are handled in processing queue, therefore cancelling is not immediate."
1328
+ // }
1329
+ // }
1330
+ //
1331
+ return response;
1332
+ }
1333
+
1334
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1335
+ if (symbol === undefined) {
1336
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument');
1337
+ }
1338
+ await this.loadMarkets ();
1339
+ const market = this.market (symbol);
1340
+ const request = {
1341
+ 'currencyPairId': market['id'],
1342
+ // 'timeStart': '2019-11-26T19:54:55.901Z', // datetime in iso format
1343
+ // 'timeEnd': '2019-11-26T19:54:55.901Z', // datetime in iso format
1344
+ // 'limit': 100, // default 100
1345
+ // 'offset': 100,
1346
+ };
1347
+ if (since !== undefined) {
1348
+ request['timeStart'] = this.iso8601 (since);
1349
+ }
1350
+ if (limit !== undefined) {
1351
+ request['limit'] = limit;
1352
+ }
1353
+ const response = await this.reportsGetTradesCurrencyPairId (this.extend (request, params));
1354
+ //
1355
+ // {
1356
+ // "success": true,
1357
+ // "data": [
1358
+ // {
1359
+ // "id": 658745,
1360
+ // "buy_order_id": 6587453,
1361
+ // "sell_order_id": 6587459,
1362
+ // "price": 0.012285,
1363
+ // "amount": 6.35,
1364
+ // "trade_type": "SELL",
1365
+ // "timestamp": "1538737692"
1366
+ // }
1367
+ // ]
1368
+ // }
1369
+ //
1370
+ const trades = this.safeValue (response, 'data', []);
1371
+ return this.parseTrades (trades, market, since, limit);
1372
+ }
1373
+
1374
+ async createDepositAddress (code, params = {}) {
1375
+ await this.loadMarkets ();
1376
+ const currency = this.currency (code);
1377
+ const request = {
1378
+ 'currencyId': currency['id'],
1379
+ // Default value is the value that represents legacy protocol.
1380
+ // In case of USDT it is 10 as Tether OMNI was the default previously.
1381
+ // The list of protocols can be obtained from the /public/currencies/{currencyId}
1382
+ // 'protocol_id': 10,
1383
+ };
1384
+ const response = await this.profilePostWalletsCurrencyId (this.extend (request, params));
1385
+ //
1386
+ // {
1387
+ // "success": true,
1388
+ // "data": {
1389
+ // "id": 45875,
1390
+ // "currency_id": 1,
1391
+ // "delisted": false,
1392
+ // "disabled": false,
1393
+ // "disable_deposits": false,
1394
+ // "code": "BTC",
1395
+ // "balance": "0.198752",
1396
+ // "frozen_balance": "1.5784",
1397
+ // "bonus_balance": "0.000",
1398
+ // "deposit_address": {
1399
+ // "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
1400
+ // "address_name": "Address",
1401
+ // "additional_address_parameter": "qwertyuiopasdfghjkl",
1402
+ // "additional_address_parameter_name": "Destination Tag",
1403
+ // "notification": "",
1404
+ // "protocol_id": 10,
1405
+ // "protocol_name": "Tether OMNI",
1406
+ // "supports_new_address_creation": false
1407
+ // },
1408
+ // "multi_deposit_addresses": [
1409
+ // {
1410
+ // "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
1411
+ // "address_name": "Address",
1412
+ // "additional_address_parameter": "qwertyuiopasdfghjkl",
1413
+ // "additional_address_parameter_name": "Destination Tag",
1414
+ // "notification": "",
1415
+ // "protocol_id": 10,
1416
+ // "protocol_name": "Tether OMNI",
1417
+ // "supports_new_address_creation": false
1418
+ // }
1419
+ // ],
1420
+ // "withdrawal_additional_field_name": "Payment ID (optional)",
1421
+ // "rates": { "BTC": 0.000001 },
1422
+ // "protocol_specific_settings": [
1423
+ // {
1424
+ // "protocol_name": "Tether OMNI",
1425
+ // "protocol_id": 10,
1426
+ // "active": true,
1427
+ // "withdrawal_fee_currency_id": 1,
1428
+ // "withdrawal_fee_const": 0.002,
1429
+ // "withdrawal_fee_percent": 0,
1430
+ // "block_explorer_url": "https://omniexplorer.info/search/"
1431
+ // }
1432
+ // ]
1433
+ // }
1434
+ // }
1435
+ //
1436
+ const data = this.safeValue (response, 'data', {});
1437
+ const depositAddress = this.safeValue (data, 'deposit_address', {});
1438
+ const address = this.safeString (depositAddress, 'address');
1439
+ const tag = this.safeString (depositAddress, 'additional_address_parameter');
1440
+ this.checkAddress (address);
1441
+ return {
1442
+ 'currency': code,
1443
+ 'address': address,
1444
+ 'tag': tag,
1445
+ 'info': response,
1446
+ };
1447
+ }
1448
+
1449
+ async fetchDepositAddress (code, params = {}) {
1450
+ await this.loadMarkets ();
1451
+ const balance = await this.fetchBalance ();
1452
+ const wallets = this.safeValue (balance['info'], 'data', []);
1453
+ const walletsByCurrencyId = this.indexBy (wallets, 'currency_id');
1454
+ const currency = this.currency (code);
1455
+ const wallet = this.safeValue (walletsByCurrencyId, currency['id']);
1456
+ if (wallet === undefined) {
1457
+ throw new ExchangeError (this.id + ' fetchDepositAddress() could not find the wallet id for currency code ' + code + ', try to call createDepositAddress() first');
1458
+ }
1459
+ const walletId = this.safeInteger (wallet, 'id');
1460
+ if (walletId === undefined) {
1461
+ throw new ExchangeError (this.id + ' fetchDepositAddress() could not find the wallet id for currency code ' + code + ', try to call createDepositAddress() first');
1462
+ }
1463
+ const request = {
1464
+ 'walletId': walletId,
1465
+ };
1466
+ const response = await this.profileGetWalletsWalletId (this.extend (request, params));
1467
+ //
1468
+ // {
1469
+ // "success": true,
1470
+ // "data": {
1471
+ // "id": 45875,
1472
+ // "currency_id": 1,
1473
+ // "delisted": false,
1474
+ // "disabled": false,
1475
+ // "disable_deposits": false,
1476
+ // "code": "BTC",
1477
+ // "balance": "0.198752",
1478
+ // "frozen_balance": "1.5784",
1479
+ // "bonus_balance": "0.000",
1480
+ // "deposit_address": {
1481
+ // "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
1482
+ // "address_name": "Address",
1483
+ // "additional_address_parameter": "qwertyuiopasdfghjkl",
1484
+ // "additional_address_parameter_name": "Destination Tag",
1485
+ // "notification": "",
1486
+ // "protocol_id": 10,
1487
+ // "protocol_name": "Tether OMNI",
1488
+ // "supports_new_address_creation": false
1489
+ // },
1490
+ // "multi_deposit_addresses": [
1491
+ // {
1492
+ // "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
1493
+ // "address_name": "Address",
1494
+ // "additional_address_parameter": "qwertyuiopasdfghjkl",
1495
+ // "additional_address_parameter_name": "Destination Tag",
1496
+ // "notification": "",
1497
+ // "protocol_id": 10,
1498
+ // "protocol_name": "Tether OMNI",
1499
+ // "supports_new_address_creation": false
1500
+ // }
1501
+ // ],
1502
+ // "withdrawal_additional_field_name": "Payment ID (optional)",
1503
+ // "rates": { "BTC": 0.000001 },
1504
+ // "protocol_specific_settings": [
1505
+ // {
1506
+ // "protocol_name": "Tether OMNI",
1507
+ // "protocol_id": 10,
1508
+ // "active": true,
1509
+ // "withdrawal_fee_currency_id": 1,
1510
+ // "withdrawal_fee_const": 0.002,
1511
+ // "withdrawal_fee_percent": 0,
1512
+ // "block_explorer_url": "https://omniexplorer.info/search/"
1513
+ // }
1514
+ // ]
1515
+ // }
1516
+ // }
1517
+ //
1518
+ const data = this.safeValue (response, 'data', []);
1519
+ const depositAddress = this.safeValue (data, 'deposit_address', {});
1520
+ const address = this.safeString (depositAddress, 'address');
1521
+ const tag = this.safeString (depositAddress, 'additional_address_parameter');
1522
+ this.checkAddress (address);
1523
+ return {
1524
+ 'currency': code,
1525
+ 'address': address,
1526
+ 'tag': tag,
1527
+ 'network': undefined,
1528
+ 'info': response,
1529
+ };
1530
+ }
1531
+
1532
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1533
+ let url = this.urls['api'] + '/' + api + '/' + this.implodeParams (path, params);
1534
+ const query = this.omit (params, this.extractParams (path));
1535
+ if (api === 'public') {
1536
+ if (Object.keys (query).length) {
1537
+ url += '?' + this.urlencode (query);
1538
+ }
1539
+ } else {
1540
+ this.checkRequiredCredentials ();
1541
+ headers = {
1542
+ 'Authorization': 'Bearer ' + this.token,
1543
+ };
1544
+ if (method === 'GET' || method === 'DELETE') {
1545
+ if (Object.keys (query).length) {
1546
+ url += '?' + this.urlencode (query);
1547
+ }
1548
+ } else {
1549
+ body = this.json (query);
1550
+ if (Object.keys (query).length) {
1551
+ headers['Content-Type'] = 'application/json';
1552
+ }
1553
+ }
1554
+ }
1555
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1556
+ }
1557
+
1558
+ parseTransactionStatus (status) {
1559
+ const statuses = {
1560
+ 'processing': 'pending',
1561
+ 'checking by system': 'pending',
1562
+ 'hodl': 'pending',
1563
+ 'amount too low': 'failed',
1564
+ 'not confirmed': 'pending',
1565
+ 'cancelled by user': 'canceled',
1566
+ 'approved': 'pending',
1567
+ 'finished': 'ok',
1568
+ 'withdrawal error': 'failed',
1569
+ 'deposit error': 'failed',
1570
+ 'cancelled by admin': 'canceled',
1571
+ 'awaiting': 'pending',
1572
+ };
1573
+ return this.safeString (statuses, status, status);
1574
+ }
1575
+
1576
+ parseTransaction (transaction, currency = undefined) {
1577
+ //
1578
+ // fetchDeposits
1579
+ //
1580
+ // {
1581
+ // "id": 123654789,
1582
+ // "currency_id": 1,
1583
+ // "currency_code": "BTC",
1584
+ // "deposit_fee_currency_id": 1,
1585
+ // "deposit_fee_currency_code": "BTC",
1586
+ // "amount": 0.25,
1587
+ // "fee": 0.00025,
1588
+ // "txid": "qwertyuhgfdsasdfgh",
1589
+ // "protocol_id": 0,
1590
+ // "deposit_status_id": 1,
1591
+ // "status": "PROCESSING",
1592
+ // "status_color": "#BC3D51",
1593
+ // "created_at": "2018-11-28 12:32:08",
1594
+ // "timestamp": "1543409389",
1595
+ // "confirmations": "1 of 2"
1596
+ // }
1597
+ //
1598
+ // fetchWithdrawals
1599
+ //
1600
+ // {
1601
+ // "id": 65899,
1602
+ // "amount": "0.00600000",
1603
+ // "currency_id": 1,
1604
+ // "currency_code": "BTC",
1605
+ // "fee": "0.00400000",
1606
+ // "fee_currency_id": 1,
1607
+ // "fee_currency_code": "BTC",
1608
+ // "withdrawal_status_id": 1,
1609
+ // "status": "Not Confirmed",
1610
+ // "status_color": "#BC3D51",
1611
+ // "created_at": "2019-01-21 09:36:05",
1612
+ // "created_ts": "1548063365",
1613
+ // "updated_at": "2019-01-21 09:36:05",
1614
+ // "updated_ts": "1548063365",
1615
+ // "txid": null,
1616
+ // "protocol_id": 0,
1617
+ // "withdrawal_address": {
1618
+ // "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
1619
+ // "address_name": "Address",
1620
+ // "additional_address_parameter": "qwertyuiopasdfghjkl",
1621
+ // "additional_address_parameter_name": "Destination Tag",
1622
+ // "notification": "",
1623
+ // "protocol_id": 10,
1624
+ // "protocol_name": "Tether OMNI",
1625
+ // "supports_new_address_creation": false
1626
+ // }
1627
+ // }
1628
+ //
1629
+ const id = this.safeString (transaction, 'id');
1630
+ const withdrawalAddress = this.safeValue (transaction, 'withdrawal_address', {});
1631
+ const address = this.safeString (withdrawalAddress, 'address');
1632
+ const tag = this.safeString (withdrawalAddress, 'additional_address_parameter');
1633
+ const currencyId = this.safeString (transaction, 'currency_id');
1634
+ let code = undefined;
1635
+ if (currencyId in this.currencies_by_id) {
1636
+ currency = this.currencies_by_id[currencyId];
1637
+ } else {
1638
+ code = this.commonCurrencyCode (this.safeString (transaction, 'currency_code'));
1639
+ }
1640
+ if ((code === undefined) && (currency !== undefined)) {
1641
+ code = currency['code'];
1642
+ }
1643
+ const type = ('deposit_status_id' in transaction) ? 'deposit' : 'withdrawal';
1644
+ const amount = this.safeNumber (transaction, 'amount');
1645
+ const status = this.parseTransactionStatus (this.safeStringLower (transaction, 'status'));
1646
+ const timestamp = this.safeTimestamp2 (transaction, 'timestamp', 'created_ts');
1647
+ const updated = this.safeTimestamp (transaction, 'updated_ts');
1648
+ const txid = this.safeString (transaction, 'txid');
1649
+ let fee = undefined;
1650
+ const feeCost = this.safeNumber (transaction, 'fee');
1651
+ if (feeCost !== undefined) {
1652
+ const feeCurrencyId = this.safeString (transaction, 'fee_currency_id', 'deposit_fee_currency_id');
1653
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
1654
+ fee = {
1655
+ 'cost': feeCost,
1656
+ 'currency': feeCurrencyCode,
1657
+ };
1658
+ }
1659
+ const network = this.safeString (withdrawalAddress, 'protocol_name');
1660
+ return {
1661
+ 'info': transaction,
1662
+ 'id': id,
1663
+ 'txid': txid,
1664
+ 'timestamp': timestamp,
1665
+ 'datetime': this.iso8601 (timestamp),
1666
+ 'network': network,
1667
+ 'addressFrom': undefined,
1668
+ 'address': address,
1669
+ 'addressTo': address,
1670
+ 'tagFrom': undefined,
1671
+ 'tag': tag,
1672
+ 'tagTo': tag,
1673
+ 'type': type,
1674
+ 'amount': amount,
1675
+ 'currency': code,
1676
+ 'status': status,
1677
+ 'updated': updated,
1678
+ 'fee': fee,
1679
+ };
1680
+ }
1681
+
1682
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
1683
+ await this.loadMarkets ();
1684
+ let currency = undefined;
1685
+ const request = {};
1686
+ if (code !== undefined) {
1687
+ currency = this.currency (code);
1688
+ request['currencyId'] = currency['id'];
1689
+ }
1690
+ if (limit !== undefined) {
1691
+ request['limit'] = limit;
1692
+ }
1693
+ if (since !== undefined) {
1694
+ request['timeStart'] = since;
1695
+ }
1696
+ const response = await this.profileGetDeposits (this.extend (request, params));
1697
+ //
1698
+ // {
1699
+ // "success": true,
1700
+ // "data": [
1701
+ // {
1702
+ // "id": 123654789,
1703
+ // "currency_id": 1,
1704
+ // "currency_code": "BTC",
1705
+ // "deposit_fee_currency_id": 1,
1706
+ // "deposit_fee_currency_code": "BTC",
1707
+ // "amount": 0.25,
1708
+ // "fee": 0.00025,
1709
+ // "txid": "qwertyuhgfdsasdfgh",
1710
+ // "protocol_id": 0,
1711
+ // "deposit_status_id": 1,
1712
+ // "status": "PROCESSING",
1713
+ // "status_color": "#BC3D51",
1714
+ // "created_at": "2018-11-28 12:32:08",
1715
+ // "timestamp": "1543409389",
1716
+ // "confirmations": "1 of 2",
1717
+ // "protocol_specific_settings": {
1718
+ // "protocol_name": "Tether OMNI",
1719
+ // "protocol_id": 10,
1720
+ // "block_explorer_url": "https://omniexplorer.info/search/"
1721
+ // }
1722
+ // }
1723
+ // ]
1724
+ // }
1725
+ //
1726
+ const deposits = this.safeValue (response, 'data', []);
1727
+ return this.parseTransactions (deposits, code, since, limit);
1728
+ }
1729
+
1730
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
1731
+ await this.loadMarkets ();
1732
+ let currency = undefined;
1733
+ const request = {};
1734
+ if (code !== undefined) {
1735
+ currency = this.currency (code);
1736
+ request['currencyId'] = currency['id'];
1737
+ }
1738
+ if (limit !== undefined) {
1739
+ request['limit'] = limit;
1740
+ }
1741
+ if (since !== undefined) {
1742
+ request['timeStart'] = since;
1743
+ }
1744
+ const response = await this.profileGetWithdrawals (this.extend (request, params));
1745
+ //
1746
+ // {
1747
+ // "success": true,
1748
+ // "data": [
1749
+ // {
1750
+ // "id": 65899,
1751
+ // "amount": "0.00600000",
1752
+ // "currency_id": 1,
1753
+ // "currency_code": "BTC",
1754
+ // "fee": "0.00400000",
1755
+ // "fee_currency_id": 1,
1756
+ // "fee_currency_code": "BTC",
1757
+ // "withdrawal_status_id": 1,
1758
+ // "status": "Not Confirmed",
1759
+ // "status_color": "#BC3D51",
1760
+ // "created_at": "2019-01-21 09:36:05",
1761
+ // "created_ts": "1548063365",
1762
+ // "updated_at": "2019-01-21 09:36:05",
1763
+ // "updated_ts": "1548063365",
1764
+ // "txid": null,
1765
+ // "protocol_id": 0,
1766
+ // "withdrawal_address": {
1767
+ // "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
1768
+ // "address_name": "Address",
1769
+ // "additional_address_parameter": "qwertyuiopasdfghjkl",
1770
+ // "additional_address_parameter_name": "Destination Tag",
1771
+ // "notification": "",
1772
+ // "protocol_id": 10,
1773
+ // "protocol_name": "Tether OMNI",
1774
+ // "supports_new_address_creation": false
1775
+ // },
1776
+ // "protocol_specific_settings": {
1777
+ // "protocol_name": "Tether OMNI",
1778
+ // "protocol_id": 10,
1779
+ // "block_explorer_url": "https://omniexplorer.info/search/"
1780
+ // }
1781
+ // }
1782
+ // ]
1783
+ // }
1784
+ //
1785
+ const withdrawals = this.safeValue (response, 'data', []);
1786
+ return this.parseTransactions (withdrawals, code, since, limit);
1787
+ }
1788
+
1789
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1790
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1791
+ this.checkAddress (address);
1792
+ await this.loadMarkets ();
1793
+ const currency = this.currency (code);
1794
+ const request = {
1795
+ 'currency_id': currency['id'],
1796
+ 'amount': parseFloat (this.currencyToPrecision (code, amount)),
1797
+ 'address': address,
1798
+ // 'protocol_id': 10, // optional, to be used with multicurrency wallets like USDT
1799
+ // 'additional_address_parameter': tag, // optional
1800
+ };
1801
+ if (tag !== undefined) {
1802
+ request['additional_address_parameter'] = tag;
1803
+ }
1804
+ const networks = this.safeValue (this.options, 'networks', {});
1805
+ let network = this.safeStringUpper (params, 'network'); // this line allows the user to specify either ERC20 or ETH
1806
+ network = this.safeInteger (networks, network, network); // handle ERC20>ETH alias
1807
+ if (network !== undefined) {
1808
+ request['protocol_id'] = network;
1809
+ params = this.omit (params, 'network');
1810
+ }
1811
+ const response = await this.profilePostWithdraw (this.extend (request, params));
1812
+ //
1813
+ // {
1814
+ // "success": true,
1815
+ // "data": {
1816
+ // "id": 65899,
1817
+ // "amount": "0.00600000",
1818
+ // "currency_id": 1,
1819
+ // "currency_code": "BTC",
1820
+ // "fee": "0.00400000",
1821
+ // "fee_currency_id": 1,
1822
+ // "fee_currency_code": "BTC",
1823
+ // "withdrawal_status_id": 1,
1824
+ // "status": "Not Confirmed",
1825
+ // "status_color": "#BC3D51",
1826
+ // "created_at": "2019-01-21 09:36:05",
1827
+ // "created_ts": "1548063365",
1828
+ // "updated_at": "2019-01-21 09:36:05",
1829
+ // "updated_ts": "1548063365",
1830
+ // "txid": null,
1831
+ // "protocol_id": 0,
1832
+ // "withdrawal_address": {
1833
+ // "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
1834
+ // "address_name": "Address",
1835
+ // "additional_address_parameter": "qwertyuiopasdfghjkl",
1836
+ // "additional_address_parameter_name": "Destination Tag",
1837
+ // "notification": "",
1838
+ // "protocol_id": 10,
1839
+ // "protocol_name": "Tether OMNI",
1840
+ // "supports_new_address_creation": false
1841
+ // }
1842
+ // }
1843
+ // }
1844
+ //
1845
+ const data = this.safeValue (response, 'data', {});
1846
+ return this.parseTransaction (data, currency);
1847
+ }
1848
+
1849
+ async fetchFundingFees (codes = undefined, params = {}) {
1850
+ await this.loadMarkets ();
1851
+ const response = await this.publicGetCurrencies (params);
1852
+ //
1853
+ // {
1854
+ // "success": true,
1855
+ // "data": [
1856
+ // {
1857
+ // "id": 1,
1858
+ // "code": "BTC",
1859
+ // "name": "Bitcoin",
1860
+ // "active": true,
1861
+ // "delisted": false,
1862
+ // "precision": 8,
1863
+ // "minimum_tx_confirmations": 24,
1864
+ // "minimum_withdrawal_amount": "0.009",
1865
+ // "minimum_deposit_amount": "0.000003",
1866
+ // "deposit_fee_currency_id": 1,
1867
+ // "deposit_fee_currency_code": "ETH",
1868
+ // "deposit_fee_const": "0.00001",
1869
+ // "deposit_fee_percent": "0",
1870
+ // "withdrawal_fee_currency_id": 1,
1871
+ // "withdrawal_fee_currency_code": "ETH",
1872
+ // "withdrawal_fee_const": "0.0015",
1873
+ // "withdrawal_fee_percent": "0",
1874
+ // "withdrawal_limit": "string",
1875
+ // "block_explorer_url": "https://blockchain.info/tx/",
1876
+ // "protocol_specific_settings": [
1877
+ // {
1878
+ // "protocol_name": "Tether OMNI",
1879
+ // "protocol_id": 10,
1880
+ // "active": true,
1881
+ // "withdrawal_fee_currency_id": 1,
1882
+ // "withdrawal_fee_const": 0.002,
1883
+ // "withdrawal_fee_percent": 0,
1884
+ // "block_explorer_url": "https://omniexplorer.info/search/"
1885
+ // }
1886
+ // ]
1887
+ // }
1888
+ // ]
1889
+ // }
1890
+ //
1891
+ const data = this.safeValue (response, 'data', []);
1892
+ const withdrawFees = {};
1893
+ const depositFees = {};
1894
+ for (let i = 0; i < data.length; i++) {
1895
+ const id = this.safeString (data[i], 'id');
1896
+ const code = this.safeCurrencyCode (id);
1897
+ withdrawFees[code] = this.safeNumber (data[i], 'withdrawal_fee_const');
1898
+ depositFees[code] = this.safeNumber (data[i], 'deposit_fee_const');
1899
+ }
1900
+ return {
1901
+ 'withdraw': withdrawFees,
1902
+ 'deposit': depositFees,
1903
+ 'info': response,
1904
+ };
1905
+ }
1906
+
1907
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1908
+ if (response === undefined) {
1909
+ return; // fallback to default error handler
1910
+ }
1911
+ //
1912
+ // {"success":false,"message":"Wrong parameters","errors":{"candleType":["Invalid Candle Type!"]}}
1913
+ // {"success":false,"message":"Wrong parameters","errors":{"time":["timeStart or timeEnd is less then 1"]}}
1914
+ // {"success":false,"message":"Not enough ETH"}
1915
+ //
1916
+ const success = this.safeValue (response, 'success', false);
1917
+ if (!success) {
1918
+ const message = this.safeString (response, 'message');
1919
+ const feedback = this.id + ' ' + body;
1920
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
1921
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
1922
+ throw new ExchangeError (feedback); // unknown message
1923
+ }
1924
+ }
1925
+ };