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/therock.js ADDED
@@ -0,0 +1,1431 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidAddress } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class therock extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'therock',
15
+ 'name': 'TheRockTrading',
16
+ 'countries': [ 'MT' ],
17
+ // 10 requests per second => 1000ms / 10 => 100 ms between requests (all endpoints)
18
+ 'rateLimit': 100,
19
+ 'version': 'v1',
20
+ 'has': {
21
+ 'CORS': undefined,
22
+ 'spot': true,
23
+ 'margin': undefined, // has but unimplemented
24
+ 'swap': false,
25
+ 'future': false,
26
+ 'option': false,
27
+ 'cancelOrder': true,
28
+ 'createOrder': true,
29
+ 'fetchBalance': true,
30
+ 'fetchClosedOrders': true,
31
+ 'fetchDeposits': true,
32
+ 'fetchFundingHistory': false,
33
+ 'fetchFundingRate': false,
34
+ 'fetchFundingRateHistories': false,
35
+ 'fetchFundingRateHistory': false,
36
+ 'fetchFundingRates': false,
37
+ 'fetchIndexOHLCV': false,
38
+ 'fetchLedger': true,
39
+ 'fetchMarkets': true,
40
+ 'fetchMarkOHLCV': false,
41
+ 'fetchMyTrades': true,
42
+ 'fetchOpenOrders': true,
43
+ 'fetchOrder': true,
44
+ 'fetchOrderBook': true,
45
+ 'fetchOrders': true,
46
+ 'fetchPremiumIndexOHLCV': false,
47
+ 'fetchTicker': true,
48
+ 'fetchTickers': true,
49
+ 'fetchTrades': true,
50
+ 'fetchTradingFee': true,
51
+ 'fetchTradingFees': true,
52
+ 'fetchTransactions': 'emulated',
53
+ 'fetchWithdrawals': true,
54
+ },
55
+ 'urls': {
56
+ 'logo': 'https://user-images.githubusercontent.com/1294454/27766869-75057fa2-5ee9-11e7-9a6f-13e641fa4707.jpg',
57
+ 'api': 'https://api.therocktrading.com',
58
+ 'www': 'https://therocktrading.com',
59
+ 'doc': [
60
+ 'https://api.therocktrading.com/doc/v1/index.html',
61
+ 'https://api.therocktrading.com/doc/',
62
+ ],
63
+ },
64
+ 'api': {
65
+ 'public': {
66
+ 'get': {
67
+ 'funds': 1,
68
+ 'funds/{id}': 1,
69
+ 'funds/{id}/orderbook': 1,
70
+ 'funds/{id}/ticker': 1,
71
+ 'funds/{id}/trades': 1,
72
+ 'funds/tickers': 1,
73
+ },
74
+ },
75
+ 'private': {
76
+ 'get': {
77
+ 'balances': 1,
78
+ 'balances/{id}': 1,
79
+ 'discounts': 1,
80
+ 'discounts/{id}': 1,
81
+ 'funds': 1,
82
+ 'funds/{id}': 1,
83
+ 'funds/{id}/trades': 1,
84
+ 'funds/{fund_id}/orders': 1,
85
+ 'funds/{fund_id}/orders/{id}': 1,
86
+ 'funds/{fund_id}/position_balances': 1,
87
+ 'funds/{fund_id}/positions': 1,
88
+ 'funds/{fund_id}/positions/{id}': 1,
89
+ 'transactions': 1,
90
+ 'transactions/{id}': 1,
91
+ 'withdraw_limits/{id}': 1,
92
+ 'withdraw_limits': 1,
93
+ },
94
+ 'post': {
95
+ 'atms/withdraw': 1,
96
+ 'funds/{fund_id}/orders': 1,
97
+ },
98
+ 'delete': {
99
+ 'funds/{fund_id}/orders/{id}': 1,
100
+ 'funds/{fund_id}/orders/remove_all': 1,
101
+ },
102
+ },
103
+ },
104
+ 'fees': {
105
+ 'trading': {
106
+ 'maker': this.parseNumber ('0.002'),
107
+ 'taker': this.parseNumber ('0.002'),
108
+ },
109
+ 'funding': {
110
+ 'tierBased': false,
111
+ 'percentage': false,
112
+ 'withdraw': {},
113
+ 'deposit': {
114
+ 'BTC': 0,
115
+ 'BCH': 0,
116
+ 'PPC': 0,
117
+ 'ETH': 0,
118
+ 'ZEC': 0,
119
+ 'LTC': 0,
120
+ 'EUR': 0,
121
+ },
122
+ },
123
+ },
124
+ 'exceptions': {
125
+ 'exact': {
126
+ 'Request already running': BadRequest,
127
+ 'cannot specify multiple address types': BadRequest,
128
+ 'Currency is not included in the list': BadRequest,
129
+ 'Record not found': OrderNotFound,
130
+ },
131
+ 'broad': {
132
+ 'before must be greater than after param': BadRequest,
133
+ 'must be shorter than 60 days': BadRequest,
134
+ 'must be a multiple of (period param) in minutes': BadRequest,
135
+ 'Address allocation limit reached for currency': InvalidAddress,
136
+ 'is not a valid value for param currency': BadRequest,
137
+ ' is invalid': InvalidAddress,
138
+ },
139
+ },
140
+ });
141
+ }
142
+
143
+ async fetchMarkets (params = {}) {
144
+ const response = await this.publicGetFunds (params);
145
+ //
146
+ // {
147
+ // funds: [
148
+ // {
149
+ // id: "BTCEUR",
150
+ // description: "Trade Bitcoin with Euro",
151
+ // type: "currency",
152
+ // base_currency: "EUR",
153
+ // trade_currency: "BTC",
154
+ // buy_fee: 0.2,
155
+ // sell_fee: 0.2,
156
+ // minimum_price_offer: 0.01,
157
+ // minimum_quantity_offer: 0.0005,
158
+ // base_currency_decimals: 2,
159
+ // trade_currency_decimals: 4,
160
+ // leverages: []
161
+ // },
162
+ // ...
163
+ // ]
164
+ // }
165
+ //
166
+ const markets = this.safeValue (response, 'funds');
167
+ const result = [];
168
+ if (markets === undefined) {
169
+ throw new ExchangeError (this.id + ' fetchMarkets() got an unexpected response');
170
+ } else {
171
+ for (let i = 0; i < markets.length; i++) {
172
+ const market = markets[i];
173
+ const id = this.safeString (market, 'id');
174
+ const baseId = this.safeString (market, 'trade_currency');
175
+ const quoteId = this.safeString (market, 'base_currency');
176
+ const base = this.safeCurrencyCode (baseId);
177
+ const quote = this.safeCurrencyCode (quoteId);
178
+ const buy_fee = this.safeString (market, 'buy_fee');
179
+ const sell_fee = this.safeString (market, 'sell_fee');
180
+ let taker = Precise.stringMax (buy_fee, sell_fee);
181
+ taker = this.parseNumber (Precise.stringDiv (taker, '100'));
182
+ const leverages = this.safeValue (market, 'leverages');
183
+ const leveragesLength = leverages.length;
184
+ result.push ({
185
+ 'id': id,
186
+ 'symbol': base + '/' + quote,
187
+ 'base': base,
188
+ 'quote': quote,
189
+ 'settle': undefined,
190
+ 'baseId': baseId,
191
+ 'quoteId': quoteId,
192
+ 'settleId': undefined,
193
+ 'type': 'spot',
194
+ 'spot': true,
195
+ 'margin': leveragesLength > 0,
196
+ 'swap': false,
197
+ 'future': false,
198
+ 'option': false,
199
+ 'contract': false,
200
+ 'linear': undefined,
201
+ 'inverse': undefined,
202
+ 'taker': taker,
203
+ 'maker': taker,
204
+ 'contractSize': undefined,
205
+ 'active': true,
206
+ 'expiry': undefined,
207
+ 'expiryDatetime': undefined,
208
+ 'strike': undefined,
209
+ 'optionType': undefined,
210
+ 'precision': {
211
+ 'amount': this.safeInteger (market, 'trade_currency_decimals'),
212
+ 'price': this.safeInteger (market, 'base_currency_decimals'),
213
+ },
214
+ 'limits': {
215
+ 'leverage': {
216
+ 'min': 1,
217
+ 'max': this.safeValue (leverages, leveragesLength - 1, 1),
218
+ },
219
+ 'amount': {
220
+ 'min': this.safeNumber (market, 'minimum_quantity_offer'),
221
+ 'max': undefined,
222
+ },
223
+ 'price': {
224
+ 'min': this.safeNumber (market, 'minimum_price_offer'),
225
+ 'max': undefined,
226
+ },
227
+ 'cost': {
228
+ 'min': undefined,
229
+ 'max': undefined,
230
+ },
231
+ },
232
+ 'info': market,
233
+ });
234
+ }
235
+ }
236
+ return result;
237
+ }
238
+
239
+ parseBalance (response) {
240
+ const balances = this.safeValue (response, 'balances', []);
241
+ const result = { 'info': response };
242
+ for (let i = 0; i < balances.length; i++) {
243
+ const balance = balances[i];
244
+ const currencyId = this.safeString (balance, 'currency');
245
+ const code = this.safeCurrencyCode (currencyId);
246
+ const account = this.account ();
247
+ account['free'] = this.safeString (balance, 'trading_balance');
248
+ account['total'] = this.safeString (balance, 'balance');
249
+ result[code] = account;
250
+ }
251
+ return this.safeBalance (result);
252
+ }
253
+
254
+ async fetchBalance (params = {}) {
255
+ await this.loadMarkets ();
256
+ const response = await this.privateGetBalances (params);
257
+ return this.parseBalance (response);
258
+ }
259
+
260
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
261
+ await this.loadMarkets ();
262
+ const request = {
263
+ 'id': this.marketId (symbol),
264
+ };
265
+ const orderbook = await this.publicGetFundsIdOrderbook (this.extend (request, params));
266
+ const timestamp = this.parse8601 (this.safeString (orderbook, 'date'));
267
+ return this.parseOrderBook (orderbook, symbol, timestamp, 'bids', 'asks', 'price', 'amount');
268
+ }
269
+
270
+ parseTicker (ticker, market = undefined) {
271
+ //
272
+ // {
273
+ // "date":"2022-01-16T00:05:08.192Z",
274
+ // "fund_id":"ETHBTC",
275
+ // "bid":0.07707802,
276
+ // "ask":0.07733404,
277
+ // "last":0.07739053,
278
+ // "open":0.07628192,
279
+ // "close":0.07687651,
280
+ // "low":0.07612047,
281
+ // "high":0.07703306,
282
+ // "volume":1.10179665,
283
+ // "volume_traded":14.273
284
+ // }
285
+ //
286
+ const timestamp = this.parse8601 (this.safeString (ticker, 'date'));
287
+ market = this.safeMarket (undefined, market);
288
+ const last = this.safeString (ticker, 'last');
289
+ return this.safeTicker ({
290
+ 'symbol': market['symbol'],
291
+ 'timestamp': timestamp,
292
+ 'datetime': this.iso8601 (timestamp),
293
+ 'high': this.safeString (ticker, 'high'),
294
+ 'low': this.safeString (ticker, 'low'),
295
+ 'bid': this.safeString (ticker, 'bid'),
296
+ 'bidVolume': undefined,
297
+ 'ask': this.safeString (ticker, 'ask'),
298
+ 'askVolume': undefined,
299
+ 'vwap': undefined,
300
+ 'open': this.safeString (ticker, 'open'),
301
+ 'close': last,
302
+ 'last': last,
303
+ 'previousClose': this.safeString (ticker, 'close'), // previous day close, if any
304
+ 'change': undefined,
305
+ 'percentage': undefined,
306
+ 'average': undefined,
307
+ 'baseVolume': this.safeString (ticker, 'volume_traded'),
308
+ 'quoteVolume': this.safeString (ticker, 'volume'),
309
+ 'info': ticker,
310
+ }, market, false);
311
+ }
312
+
313
+ async fetchTickers (symbols = undefined, params = {}) {
314
+ await this.loadMarkets ();
315
+ const response = await this.publicGetFundsTickers (params);
316
+ const tickers = this.indexBy (response['tickers'], 'fund_id');
317
+ const ids = Object.keys (tickers);
318
+ const result = {};
319
+ for (let i = 0; i < ids.length; i++) {
320
+ const id = ids[i];
321
+ const market = this.safeMarket (id);
322
+ const symbol = market['symbol'];
323
+ const ticker = tickers[id];
324
+ result[symbol] = this.parseTicker (ticker, market);
325
+ }
326
+ return this.filterByArray (result, 'symbol', symbols);
327
+ }
328
+
329
+ async fetchTicker (symbol, params = {}) {
330
+ await this.loadMarkets ();
331
+ const market = this.market (symbol);
332
+ const request = {
333
+ 'id': market['id'],
334
+ };
335
+ const response = await this.publicGetFundsIdTicker (this.extend (request, params));
336
+ //
337
+ // {
338
+ // "date":"2022-01-16T00:05:08.192Z",
339
+ // "fund_id":"ETHBTC",
340
+ // "bid":0.07707802,
341
+ // "ask":0.07733404,
342
+ // "last":0.07739053,
343
+ // "open":0.07628192,
344
+ // "close":0.07687651,
345
+ // "low":0.07612047,
346
+ // "high":0.07703306,
347
+ // "volume":1.10179665,
348
+ // "volume_traded":14.273
349
+ // }
350
+ //
351
+ return this.parseTicker (response, market);
352
+ }
353
+
354
+ parseTrade (trade, market = undefined) {
355
+ //
356
+ // fetchTrades, fetchOrder trades
357
+ //
358
+ // { id: 4493548,
359
+ // fund_id: "ETHBTC",
360
+ // amount: 0.203,
361
+ // price: 0.02783576,
362
+ // side: "buy",
363
+ // dark: false,
364
+ // date: "2018-11-30T08:19:18.236Z" }
365
+ //
366
+ // fetchMyTrades
367
+ //
368
+ // { id: 237338,
369
+ // fund_id: "BTCEUR",
370
+ // amount: 0.348,
371
+ // price: 348,
372
+ // side: "sell",
373
+ // dark: false,
374
+ // order_id: 14920648,
375
+ // date: "2015-06-03T00:49:49.000Z",
376
+ // transactions: [ { id: 2770768,
377
+ // date: "2015-06-03T00:49:49.000Z",
378
+ // type: "sold_currency_to_fund",
379
+ // price: 121.1,
380
+ // currency: "EUR" },
381
+ // { id: 2770769,
382
+ // date: "2015-06-03T00:49:49.000Z",
383
+ // type: "released_currency_to_fund",
384
+ // price: 0.348,
385
+ // currency: "BTC" },
386
+ // { id: 2770772,
387
+ // date: "2015-06-03T00:49:49.000Z",
388
+ // type: "paid_commission",
389
+ // price: 0.06,
390
+ // currency: "EUR",
391
+ // trade_id: 440492 } ] }
392
+ //
393
+ const marketId = this.safeString (trade, 'fund_id');
394
+ const symbol = this.safeSymbol (marketId, market);
395
+ const timestamp = this.parse8601 (this.safeString (trade, 'date'));
396
+ const id = this.safeString (trade, 'id');
397
+ const orderId = this.safeString (trade, 'order_id');
398
+ const side = this.safeString (trade, 'side');
399
+ const priceString = this.safeString (trade, 'price');
400
+ const amountString = this.safeString (trade, 'amount');
401
+ let fee = undefined;
402
+ let feeCostString = undefined;
403
+ const transactions = this.safeValue (trade, 'transactions', []);
404
+ const transactionsByType = this.groupBy (transactions, 'type');
405
+ const feeTransactions = this.safeValue (transactionsByType, 'paid_commission', []);
406
+ for (let i = 0; i < feeTransactions.length; i++) {
407
+ if (feeCostString === undefined) {
408
+ feeCostString = '0.0';
409
+ }
410
+ feeCostString = Precise.stringAdd (feeCostString, this.safeString (feeTransactions[i], 'price'));
411
+ }
412
+ if (feeCostString !== undefined) {
413
+ fee = {
414
+ 'cost': feeCostString,
415
+ 'currency': market['quote'],
416
+ };
417
+ }
418
+ return this.safeTrade ({
419
+ 'info': trade,
420
+ 'id': id,
421
+ 'order': orderId,
422
+ 'timestamp': timestamp,
423
+ 'datetime': this.iso8601 (timestamp),
424
+ 'symbol': symbol,
425
+ 'type': undefined,
426
+ 'side': side,
427
+ 'takerOrMaker': undefined,
428
+ 'price': priceString,
429
+ 'amount': amountString,
430
+ 'cost': undefined,
431
+ 'fee': fee,
432
+ }, market);
433
+ }
434
+
435
+ parseLedgerEntryDirection (direction) {
436
+ const directions = {
437
+ 'affiliate_earnings': 'in',
438
+ 'atm_payment': 'in',
439
+ 'bought_currency_from_fund': 'out',
440
+ 'bought_shares': 'out',
441
+ 'paid_commission': 'out',
442
+ 'paypal_payment': 'in',
443
+ 'pos_payment': 'in',
444
+ 'released_currency_to_fund': 'out',
445
+ 'rollover_commission': 'out',
446
+ 'sold_currency_to_fund': 'in',
447
+ 'sold_shares': 'in',
448
+ 'transfer_received': 'in',
449
+ 'transfer_sent': 'out',
450
+ 'withdraw': 'out',
451
+ // commented types will be shown as-is
452
+ // 'acquired_currency_from_fund': '',
453
+ // 'acquired_insurance': '',
454
+ // 'dividend_distributed_to_holders': '',
455
+ // 'dividend_from_shares': '',
456
+ // 'exposed_position': '',
457
+ // 'insurances_reimbursement': '',
458
+ // 'lent_currency': '',
459
+ // 'linden_lab_assessment': '',
460
+ // 'position_transfer_received': '',
461
+ // 'return_lent_currency': '',
462
+ // 'returned_lent_currency': '',
463
+ // 'the_rock_assessment': '',
464
+ };
465
+ return this.safeString (directions, direction, direction);
466
+ }
467
+
468
+ parseLedgerEntryType (type) {
469
+ const types = {
470
+ 'affiliate_earnings': 'referral',
471
+ 'atm_payment': 'transaction',
472
+ 'bought_currency_from_fund': 'trade',
473
+ 'bought_shares': 'trade',
474
+ 'paid_commission': 'fee',
475
+ 'paypal_payment': 'transaction',
476
+ 'pos_payment': 'transaction',
477
+ 'released_currency_to_fund': 'trade',
478
+ 'rollover_commission': 'fee',
479
+ 'sold_currency_to_fund': 'trade',
480
+ 'sold_shares': 'trade',
481
+ 'transfer_received': 'transfer',
482
+ 'transfer_sent': 'transfer',
483
+ 'withdraw': 'transaction',
484
+ // commented types will be shown as-is
485
+ // 'acquired_currency_from_fund': '',
486
+ // 'acquired_insurance': '',
487
+ // 'dividend_distributed_to_holders': '',
488
+ // 'dividend_from_shares': '',
489
+ // 'exposed_position': '',
490
+ // 'insurances_reimbursement': '',
491
+ // 'lent_currency': '',
492
+ // 'linden_lab_assessment': '',
493
+ // 'position_transfer_received': '',
494
+ // 'return_lent_currency': '',
495
+ // 'returned_lent_currency': '',
496
+ // 'the_rock_assessment': '',
497
+ };
498
+ return this.safeString (types, type, type);
499
+ }
500
+
501
+ parseLedgerEntry (item, currency = undefined) {
502
+ //
503
+ // withdrawal
504
+ //
505
+ // {
506
+ // "id": 21311223,
507
+ // "date": "2015-06-30T13:55:11.000Z",
508
+ // "type": "withdraw",
509
+ // "price": 103.00,
510
+ // "currency": "EUR",
511
+ // "fund_id": null,
512
+ // "order_id": null,
513
+ // "trade_id": null,
514
+ // "transfer_detail": {
515
+ // "method": "wire_transfer",
516
+ // "id": "F112DD3",
517
+ // "recipient": "IT123456789012",
518
+ // "confirmations": 0
519
+ // }
520
+ // }
521
+ //
522
+ // deposit
523
+ //
524
+ // {
525
+ // "id": 21311222,
526
+ // "date": "2015-06-30T13:55:11.000Z",
527
+ // "type": "atm_payment",
528
+ // "price": 2.01291,
529
+ // "currency": "BTC",
530
+ // "fund_id": "null",
531
+ // "order_id": null,
532
+ // "trade_id": null,
533
+ // "transfer_detail": {
534
+ // "method": "bitcoin",
535
+ // "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
536
+ // "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf",
537
+ // "confirmations": 3
538
+ // }
539
+ // }
540
+ //
541
+ // trade fee
542
+ //
543
+ // {
544
+ // "id": 21311221,
545
+ // "date": "2015-06-30T13:55:11.000Z",
546
+ // "type": "paid_commission",
547
+ // "price": 0.0001,
548
+ // "fund_id": "BTCEUR",
549
+ // "order_id": 12832371,
550
+ // "trade_id": 12923212,
551
+ // "currency": "BTC",
552
+ // "transfer_detail": null
553
+ // }
554
+ //
555
+ const id = this.safeString (item, 'id');
556
+ let referenceId = undefined;
557
+ let type = this.safeString (item, 'type');
558
+ const direction = this.parseLedgerEntryDirection (type);
559
+ type = this.parseLedgerEntryType (type);
560
+ if (type === 'trade' || type === 'fee') {
561
+ referenceId = this.safeString (item, 'trade_id');
562
+ }
563
+ const currencyId = this.safeString (item, 'currency');
564
+ const code = this.safeCurrencyCode (currencyId);
565
+ const amount = this.safeNumber (item, 'price');
566
+ const timestamp = this.parse8601 (this.safeString (item, 'date'));
567
+ const status = 'ok';
568
+ return {
569
+ 'info': item,
570
+ 'id': id,
571
+ 'direction': direction,
572
+ 'account': undefined,
573
+ 'referenceId': referenceId,
574
+ 'referenceAccount': undefined,
575
+ 'type': type,
576
+ 'currency': code,
577
+ 'amount': amount,
578
+ 'before': undefined,
579
+ 'after': undefined,
580
+ 'status': status,
581
+ 'timestamp': timestamp,
582
+ 'datetime': this.iso8601 (timestamp),
583
+ 'fee': undefined,
584
+ };
585
+ }
586
+
587
+ async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
588
+ await this.loadMarkets ();
589
+ const request = {
590
+ // 'page': 1,
591
+ // 'fund_id': 'ETHBTC', // filter by fund symbol
592
+ // 'currency': 'BTC', // filter by currency
593
+ // 'after': '2015-02-06T08:47:26Z', // filter after a certain timestamp
594
+ // 'before': '2015-02-06T08:47:26Z',
595
+ // 'type': 'withdraw',
596
+ // 'order_id': '12832371', // filter by a specific order ID
597
+ // 'trade_id': '12923212', // filter by a specific trade ID
598
+ // 'transfer_method': 'bitcoin', // wire_transfer, ripple, greenaddress, bitcoin, litecoin, namecoin, peercoin, dogecoin
599
+ // 'transfer_recipient': '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm', // filter by a specific recipient (e.g. Bitcoin address, IBAN)
600
+ // 'transfer_id': '8261949194985b01985006724dca5d6059989e096fa95608271d00dd902327fa', // filter by a specific transfer ID (e.g. Bitcoin TX hash)
601
+ };
602
+ let currency = undefined;
603
+ if (code !== undefined) {
604
+ currency = this.currency (code);
605
+ request['currency'] = currency['id'];
606
+ }
607
+ if (since !== undefined) {
608
+ request['after'] = this.iso8601 (since);
609
+ }
610
+ const response = await this.privateGetTransactions (this.extend (request, params));
611
+ //
612
+ // {
613
+ // "transactions": [
614
+ // {
615
+ // "id": 21311223,
616
+ // "date": "2015-06-30T13:55:11.000Z",
617
+ // "type": "withdraw",
618
+ // "price": 103.00,
619
+ // "currency": "EUR",
620
+ // "fund_id": null,
621
+ // "order_id": null,
622
+ // "trade_id": null,
623
+ // "transfer_detail": {
624
+ // "method": "wire_transfer",
625
+ // "id": "F112DD3",
626
+ // "recipient": "IT123456789012",
627
+ // "confirmations": 0
628
+ // }
629
+ // },
630
+ // {
631
+ // "id": 21311222,
632
+ // "date": "2015-06-30T13:55:11.000Z",
633
+ // "type": "atm_payment",
634
+ // "price": 2.01291,
635
+ // "currency": "BTC",
636
+ // "fund_id": "null",
637
+ // "order_id": null,
638
+ // "trade_id": null,
639
+ // "transfer_detail": {
640
+ // "method": "bitcoin",
641
+ // "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
642
+ // "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf",
643
+ // "confirmations": 3
644
+ // }
645
+ // },
646
+ // {
647
+ // "id": 21311221,
648
+ // "date": "2015-06-30T13:55:11.000Z",
649
+ // "type": "paid_commission",
650
+ // "price": 0.0001,
651
+ // "fund_id": "BTCEUR",
652
+ // "order_id": 12832371,
653
+ // "trade_id": 12923212,
654
+ // "currency": "BTC",
655
+ // "transfer_detail": null
656
+ // }
657
+ // ],
658
+ // "meta": {
659
+ // "total_count": 1221,
660
+ // "first": { "page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1" },
661
+ // "previous": null,
662
+ // "current": { "page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1" },
663
+ // "next": { "page": 2, "href": "https://api.therocktrading.com/v1/transactions?page=2" },
664
+ // "last": { "page": 1221, "href": "https://api.therocktrading.com/v1/transactions?page=1221" }
665
+ // }
666
+ // }
667
+ //
668
+ const transactions = this.safeValue (response, 'transactions', []);
669
+ return this.parseLedger (transactions, currency, since, limit);
670
+ }
671
+
672
+ parseTransactionType (type) {
673
+ const types = {
674
+ 'withdraw': 'withdrawal',
675
+ 'atm_payment': 'deposit',
676
+ };
677
+ return this.safeString (types, type, type);
678
+ }
679
+
680
+ parseTransaction (transaction, currency = undefined) {
681
+ //
682
+ // fetchWithdrawals
683
+ //
684
+ // // fiat
685
+ //
686
+ // {
687
+ // "id": 21311223,
688
+ // "date": "2015-06-30T13:55:11.000Z",
689
+ // "type": "withdraw",
690
+ // "price": 103.00,
691
+ // "currency": "EUR",
692
+ // "fund_id": null,
693
+ // "order_id": null,
694
+ // "trade_id": null,
695
+ // "transfer_detail": {
696
+ // "method": "wire_transfer",
697
+ // "id": "F112DD3",
698
+ // "recipient": "IT123456789012",
699
+ // "confirmations": 0
700
+ // }
701
+ // }
702
+ //
703
+ // {
704
+ // "id": 12564223,
705
+ // "date": "2017-08-07T08:13:50.023Z",
706
+ // "note": "GB7IDL401573388",
707
+ // "type": "withdraw",
708
+ // "price": 4345.93,
709
+ // "fund_id": null,
710
+ // "currency": "EUR",
711
+ // "order_id": null,
712
+ // "trade_id": null,
713
+ // "transfer_detail": {
714
+ // "id": "EXECUTEDBUTUNCHECKED",
715
+ // "method": "wire_transfer",
716
+ // "recipient": "GB7IDL401573388",
717
+ // "confirmations": 0
718
+ // }
719
+ // }
720
+ //
721
+ // // crypto
722
+ //
723
+ // {
724
+ // id: 20914695,
725
+ // date: '2018-02-24T07:13:23.002Z',
726
+ // type: 'withdraw',
727
+ // price: 2.70883607,
728
+ // currency: 'BCH',
729
+ // fund_id: null,
730
+ // order_id: null,
731
+ // trade_id: null,
732
+ // note: '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm',
733
+ // transfer_detail: {
734
+ // method: 'bitcoin_cash',
735
+ // id: '8261949194985b01985006724dca5d6059989e096fa95608271d00dd902327fa',
736
+ // recipient: '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm',
737
+ // confirmations: 0
738
+ // }
739
+ // }
740
+ //
741
+ //
742
+ // fetchDeposits
743
+ //
744
+ // // fiat
745
+ //
746
+ // {
747
+ // id: 16176632,
748
+ // date: '2017-11-20T21:00:13.355Z',
749
+ // type: 'atm_payment',
750
+ // price: 5000,
751
+ // currency: 'EUR',
752
+ // fund_id: null,
753
+ // order_id: null,
754
+ // trade_id: null,
755
+ // note: 'Mistral deposit',
756
+ // transfer_detail: {
757
+ // method: 'wire_transfer',
758
+ // id: '972JQ49337DX769T',
759
+ // recipient: null,
760
+ // confirmations: 0
761
+ // }
762
+ // }
763
+ //
764
+ // // crypto
765
+ //
766
+ // {
767
+ // "id": 21311222,
768
+ // "date": "2015-06-30T13:55:11.000Z",
769
+ // "type": "atm_payment",
770
+ // "price": 2.01291,
771
+ // "currency": "BTC",
772
+ // "fund_id": "null",
773
+ // "order_id": null,
774
+ // "trade_id": null,
775
+ // "transfer_detail": {
776
+ // "method": "bitcoin",
777
+ // "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
778
+ // "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf",
779
+ // "confirmations": 3
780
+ // }
781
+ // }
782
+ //
783
+ const id = this.safeString (transaction, 'id');
784
+ const type = this.parseTransactionType (this.safeString (transaction, 'type'));
785
+ const detail = this.safeValue (transaction, 'transfer_detail', {});
786
+ const method = this.safeString (detail, 'method');
787
+ let txid = undefined;
788
+ let address = undefined;
789
+ if (method !== undefined) {
790
+ if (method !== 'wire_transfer') {
791
+ txid = this.safeString (detail, 'id');
792
+ address = this.safeString (detail, 'recipient');
793
+ }
794
+ }
795
+ const currencyId = this.safeString (transaction, 'currency');
796
+ const code = this.safeCurrencyCode (currencyId);
797
+ const amount = this.safeNumber (transaction, 'price');
798
+ const timestamp = this.parse8601 (this.safeString (transaction, 'date'));
799
+ const status = 'ok';
800
+ const network = this.safeString (detail, 'method');
801
+ // todo parse tags
802
+ return {
803
+ 'info': transaction,
804
+ 'id': id,
805
+ 'currency': code,
806
+ 'amount': amount,
807
+ 'network': network,
808
+ 'addressFrom': undefined,
809
+ 'addressTo': address,
810
+ 'address': address,
811
+ 'tagFrom': undefined,
812
+ 'tagTo': undefined,
813
+ 'tag': undefined,
814
+ 'status': status,
815
+ 'type': type,
816
+ 'updated': undefined,
817
+ 'txid': txid,
818
+ 'timestamp': timestamp,
819
+ 'datetime': this.iso8601 (timestamp),
820
+ 'fee': undefined,
821
+ };
822
+ }
823
+
824
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
825
+ const request = {
826
+ 'type': 'withdraw',
827
+ };
828
+ return await this.fetchTransactions (code, since, limit, this.extend (request, params));
829
+ }
830
+
831
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
832
+ const request = {
833
+ 'type': 'atm_payment',
834
+ };
835
+ return await this.fetchTransactions (code, since, limit, this.extend (request, params));
836
+ }
837
+
838
+ async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
839
+ await this.loadMarkets ();
840
+ const request = {
841
+ // 'page': 1,
842
+ // 'fund_id': 'ETHBTC', // filter by fund symbol
843
+ // 'currency': 'BTC', // filter by currency
844
+ // 'after': '2015-02-06T08:47:26Z', // filter after a certain timestamp
845
+ // 'before': '2015-02-06T08:47:26Z',
846
+ // 'type': 'withdraw',
847
+ // 'order_id': '12832371', // filter by a specific order ID
848
+ // 'trade_id': '12923212', // filter by a specific trade ID
849
+ // 'transfer_method': 'bitcoin', // wire_transfer, ripple, greenaddress, bitcoin, litecoin, namecoin, peercoin, dogecoin
850
+ // 'transfer_recipient': '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm', // filter by a specific recipient (e.g. Bitcoin address, IBAN)
851
+ // 'transfer_id': '8261949194985b01985006724dca5d6059989e096fa95608271d00dd902327fa', // filter by a specific transfer ID (e.g. Bitcoin TX hash)
852
+ };
853
+ let currency = undefined;
854
+ if (code !== undefined) {
855
+ currency = this.currency (code);
856
+ request['currency'] = currency['id'];
857
+ }
858
+ if (since !== undefined) {
859
+ request['after'] = this.iso8601 (since);
860
+ }
861
+ params = this.extend (request, params);
862
+ const response = await this.privateGetTransactions (params);
863
+ //
864
+ // {
865
+ // "transactions": [
866
+ // {
867
+ // "id": 21311223,
868
+ // "date": "2015-06-30T13:55:11.000Z",
869
+ // "type": "withdraw",
870
+ // "price": 103.00,
871
+ // "currency": "EUR",
872
+ // "fund_id": null,
873
+ // "order_id": null,
874
+ // "trade_id": null,
875
+ // "transfer_detail": {
876
+ // "method": "wire_transfer",
877
+ // "id": "F112DD3",
878
+ // "recipient": "IT123456789012",
879
+ // "confirmations": 0
880
+ // }
881
+ // },
882
+ // {
883
+ // "id": 21311222,
884
+ // "date": "2015-06-30T13:55:11.000Z",
885
+ // "type": "atm_payment",
886
+ // "price": 2.01291,
887
+ // "currency": "BTC",
888
+ // "fund_id": "null",
889
+ // "order_id": null,
890
+ // "trade_id": null,
891
+ // "transfer_detail": {
892
+ // "method": "bitcoin",
893
+ // "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
894
+ // "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf",
895
+ // "confirmations": 3
896
+ // }
897
+ // },
898
+ // {
899
+ // "id": 21311221,
900
+ // "date": "2015-06-30T13:55:11.000Z",
901
+ // "type": "paid_commission",
902
+ // "price": 0.0001,
903
+ // "fund_id": "BTCEUR",
904
+ // "order_id": 12832371,
905
+ // "trade_id": 12923212,
906
+ // "currency": "BTC",
907
+ // "transfer_detail": null
908
+ // }
909
+ // ],
910
+ // "meta": {
911
+ // "total_count": 1221,
912
+ // "first": { "page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1" },
913
+ // "previous": null,
914
+ // "current": { "page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1" },
915
+ // "next": { "page": 2, "href": "https://api.therocktrading.com/v1/transactions?page=2" },
916
+ // "last": { "page": 1221, "href": "https://api.therocktrading.com/v1/transactions?page=1221" }
917
+ // }
918
+ // }
919
+ //
920
+ const transactions = this.safeValue (response, 'transactions', []);
921
+ const transactionTypes = [ 'withdraw', 'atm_payment' ];
922
+ const depositsAndWithdrawals = this.filterByArray (transactions, 'type', transactionTypes, false);
923
+ return this.parseTransactions (depositsAndWithdrawals, currency, since, limit);
924
+ }
925
+
926
+ parseOrderStatus (status) {
927
+ const statuses = {
928
+ 'active': 'open',
929
+ 'executed': 'closed',
930
+ 'deleted': 'canceled',
931
+ // don't know what this status means
932
+ // 'conditional': '?',
933
+ };
934
+ return this.safeString (statuses, status, status);
935
+ }
936
+
937
+ parseOrder (order, market = undefined) {
938
+ //
939
+ // {
940
+ // "id": 4325578,
941
+ // "fund_id":"BTCEUR",
942
+ // "side":"buy",
943
+ // "type":"limit",
944
+ // "status":"executed",
945
+ // "price":0.0102,
946
+ // "amount": 50.0,
947
+ // "amount_unfilled": 0.0,
948
+ // "conditional_type": null,
949
+ // "conditional_price": null,
950
+ // "date":"2015-06-03T00:49:48.000Z",
951
+ // "close_on": nil,
952
+ // "leverage": 1.0,
953
+ // "position_id": null,
954
+ // "trades": [
955
+ // {
956
+ // "id":237338,
957
+ // "fund_id":"BTCEUR",
958
+ // "amount":50,
959
+ // "price":0.0102,
960
+ // "side":"buy",
961
+ // "dark":false,
962
+ // "date":"2015-06-03T00:49:49.000Z"
963
+ // }
964
+ // ]
965
+ // }
966
+ //
967
+ const id = this.safeString (order, 'id');
968
+ const marketId = this.safeString (order, 'fund_id');
969
+ const symbol = this.safeSymbol (marketId, market);
970
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
971
+ const timestamp = this.parse8601 (this.safeString (order, 'date'));
972
+ const type = this.safeString (order, 'type');
973
+ const side = this.safeString (order, 'side');
974
+ const amount = this.safeNumber (order, 'amount');
975
+ const remaining = this.safeNumber (order, 'amount_unfilled');
976
+ let filled = undefined;
977
+ if (amount !== undefined) {
978
+ if (remaining !== undefined) {
979
+ filled = amount - remaining;
980
+ }
981
+ }
982
+ const price = this.safeNumber (order, 'price');
983
+ let trades = this.safeValue (order, 'trades');
984
+ let cost = undefined;
985
+ let average = undefined;
986
+ let lastTradeTimestamp = undefined;
987
+ if (trades !== undefined) {
988
+ const numTrades = trades.length;
989
+ if (numTrades > 0) {
990
+ trades = this.parseTrades (trades, market, undefined, undefined, {
991
+ 'orderId': id,
992
+ });
993
+ // todo: determine the cost and the average price from trades
994
+ cost = 0;
995
+ filled = 0;
996
+ for (let i = 0; i < numTrades; i++) {
997
+ const trade = trades[i];
998
+ cost = this.sum (cost, trade['cost']);
999
+ filled = this.sum (filled, trade['amount']);
1000
+ }
1001
+ if (filled > 0) {
1002
+ average = cost / filled;
1003
+ }
1004
+ lastTradeTimestamp = trades[numTrades - 1]['timestamp'];
1005
+ } else {
1006
+ cost = 0;
1007
+ }
1008
+ }
1009
+ const stopPrice = this.safeNumber (order, 'conditional_price');
1010
+ return {
1011
+ 'id': id,
1012
+ 'clientOrderId': undefined,
1013
+ 'info': order,
1014
+ 'timestamp': timestamp,
1015
+ 'datetime': this.iso8601 (timestamp),
1016
+ 'lastTradeTimestamp': lastTradeTimestamp,
1017
+ 'status': status,
1018
+ 'symbol': symbol,
1019
+ 'type': type,
1020
+ 'timeInForce': undefined,
1021
+ 'postOnly': undefined,
1022
+ 'side': side,
1023
+ 'price': price,
1024
+ 'stopPrice': stopPrice,
1025
+ 'cost': cost,
1026
+ 'amount': amount,
1027
+ 'filled': filled,
1028
+ 'average': average,
1029
+ 'remaining': remaining,
1030
+ 'fee': undefined,
1031
+ 'trades': trades,
1032
+ };
1033
+ }
1034
+
1035
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1036
+ const request = {
1037
+ 'status': 'active',
1038
+ };
1039
+ return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
1040
+ }
1041
+
1042
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1043
+ const request = {
1044
+ 'status': 'executed',
1045
+ };
1046
+ return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
1047
+ }
1048
+
1049
+ async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1050
+ if (symbol === undefined) {
1051
+ throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument');
1052
+ }
1053
+ await this.loadMarkets ();
1054
+ const market = this.market (symbol);
1055
+ const request = {
1056
+ 'fund_id': market['id'],
1057
+ // 'after': '2015-02-06T08:47:26Z',
1058
+ // 'before': '2015-02-06T08:47:26Z'
1059
+ // 'status': 'active', // 'executed', 'conditional'
1060
+ // 'side': 'buy', // 'sell'
1061
+ // 'position_id': 123, // filter orders by margin position id
1062
+ };
1063
+ if (since !== undefined) {
1064
+ request['after'] = this.iso8601 (since);
1065
+ }
1066
+ const response = await this.privateGetFundsFundIdOrders (this.extend (request, params));
1067
+ //
1068
+ // {
1069
+ // orders: [
1070
+ // {
1071
+ // id: 299333648,
1072
+ // fund_id: 'BTCEUR',
1073
+ // side: 'sell',
1074
+ // type: 'limit',
1075
+ // status: 'executed',
1076
+ // price: 5821,
1077
+ // amount: 0.1,
1078
+ // amount_unfilled: 0,
1079
+ // conditional_type: null,
1080
+ // conditional_price: null,
1081
+ // date: '2018-06-18T17:38:16.129Z',
1082
+ // close_on: null,
1083
+ // dark: false,
1084
+ // leverage: 1,
1085
+ // position_id: 0
1086
+ // }
1087
+ // ]
1088
+ // }
1089
+ //
1090
+ const orders = this.safeValue (response, 'orders', []);
1091
+ return this.parseOrders (orders, market, since, limit);
1092
+ }
1093
+
1094
+ async fetchOrder (id, symbol = undefined, params = {}) {
1095
+ if (symbol === undefined) {
1096
+ throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument');
1097
+ }
1098
+ await this.loadMarkets ();
1099
+ const market = this.market (symbol);
1100
+ const request = {
1101
+ 'id': id,
1102
+ 'fund_id': market['id'],
1103
+ };
1104
+ const response = await this.privateGetFundsFundIdOrdersId (this.extend (request, params));
1105
+ //
1106
+ // {
1107
+ // "id": 4325578,
1108
+ // "fund_id":"BTCEUR",
1109
+ // "side":"buy",
1110
+ // "type":"limit",
1111
+ // "status":"executed",
1112
+ // "price":0.0102,
1113
+ // "amount": 50.0,
1114
+ // "amount_unfilled": 0.0,
1115
+ // "conditional_type": null,
1116
+ // "conditional_price": null,
1117
+ // "date":"2015-06-03T00:49:48.000Z",
1118
+ // "close_on": null,
1119
+ // "leverage": 1.0,
1120
+ // "position_id": null,
1121
+ // "trades": [
1122
+ // {
1123
+ // "id":237338,
1124
+ // "fund_id":"BTCEUR",
1125
+ // "amount":50,
1126
+ // "price":0.0102,
1127
+ // "side":"buy",
1128
+ // "dark":false,
1129
+ // "date":"2015-06-03T00:49:49.000Z"
1130
+ // }
1131
+ // ]
1132
+ // }
1133
+ //
1134
+ return this.parseOrder (response);
1135
+ }
1136
+
1137
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1138
+ await this.loadMarkets ();
1139
+ if (type === 'market') {
1140
+ price = 0;
1141
+ }
1142
+ const request = {
1143
+ 'fund_id': this.marketId (symbol),
1144
+ 'side': side,
1145
+ 'amount': amount,
1146
+ 'price': price,
1147
+ };
1148
+ const response = await this.privatePostFundsFundIdOrders (this.extend (request, params));
1149
+ return this.parseOrder (response);
1150
+ }
1151
+
1152
+ async cancelOrder (id, symbol = undefined, params = {}) {
1153
+ await this.loadMarkets ();
1154
+ const request = {
1155
+ 'id': id,
1156
+ 'fund_id': this.marketId (symbol),
1157
+ };
1158
+ const response = await this.privateDeleteFundsFundIdOrdersId (this.extend (request, params));
1159
+ return this.parseOrder (response);
1160
+ }
1161
+
1162
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1163
+ if (symbol === undefined) {
1164
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument');
1165
+ }
1166
+ await this.loadMarkets ();
1167
+ const market = this.market (symbol);
1168
+ const request = {
1169
+ 'id': market['id'],
1170
+ };
1171
+ if (limit !== undefined) {
1172
+ request['per_page'] = limit; // default 25 max 200
1173
+ }
1174
+ if (since !== undefined) {
1175
+ request['after'] = this.iso8601 (since);
1176
+ }
1177
+ const response = await this.privateGetFundsIdTrades (this.extend (request, params));
1178
+ //
1179
+ // {
1180
+ // "trades": [
1181
+ // {
1182
+ // "id":237338,
1183
+ // "fund_id":"BTCEUR",
1184
+ // "amount":0.348,
1185
+ // "price":348.0,
1186
+ // "side":"sell",
1187
+ // "dark": false,
1188
+ // "order_id":14920648,
1189
+ // "date":"2015-06-03T00:49:49.000Z",
1190
+ // "transactions": [
1191
+ // { "id": 2770768, "date": "2015-06-03T00:49:49.000Z", "type": "sold_currency_to_fund", "price": 121.1, "currency": "EUR" },
1192
+ // { "id": 2770769, "date": "2015-06-03T00:49:49.000Z", "type": "released_currency_to_fund", "price": 0.348, "currency": "BTC" },
1193
+ // { "id": 2770772, "date": "2015-06-03T00:49:49.000Z", "type": "paid_commission", "price": 0.06, "currency": "EUR", "trade_id": 440492 },
1194
+ // ]
1195
+ // }
1196
+ // ],
1197
+ // "meta": {
1198
+ // "total_count": 31,
1199
+ // "first": { "href": "https://api.therocktrading.com/v1/funds/BTCXRP/trades?page=1" },
1200
+ // "previous": null,
1201
+ // "current": { "href": "https://api.therocktrading.com/v1/funds/BTCXRP/trades?page=1" },
1202
+ // "next": { "href": "https://api.therocktrading.com/v1/funds/BTCXRP/trades?page=2" },
1203
+ // "last":{ "href":"https://api.therocktrading.com/v1/funds/BTCXRP/trades?page=2" }
1204
+ // }
1205
+ // }
1206
+ //
1207
+ const trades = this.safeValue (response, 'trades', []);
1208
+ return this.parseTrades (trades, market, since, limit);
1209
+ }
1210
+
1211
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
1212
+ await this.loadMarkets ();
1213
+ const market = this.market (symbol);
1214
+ const request = {
1215
+ 'id': market['id'],
1216
+ };
1217
+ if (limit !== undefined) {
1218
+ request['per_page'] = limit; // default 25 max 200
1219
+ }
1220
+ if (since !== undefined) {
1221
+ request['after'] = this.iso8601 (since);
1222
+ }
1223
+ const response = await this.publicGetFundsIdTrades (this.extend (request, params));
1224
+ //
1225
+ // {
1226
+ // trades: [
1227
+ // {
1228
+ // id: 4493548,
1229
+ // fund_id: "ETHBTC",
1230
+ // amount: 0.203,
1231
+ // price: 0.02783576,
1232
+ // side: "buy",
1233
+ // dark: false,
1234
+ // date: "2018-11-30T08:19:18.236Z"
1235
+ // },
1236
+ // {
1237
+ // id: 4492926,
1238
+ // fund_id: "ETHBTC",
1239
+ // amount: 0.04,
1240
+ // price: 0.02767034,
1241
+ // side: "buy",
1242
+ // dark: false,
1243
+ // date: "2018-11-30T07:03:03.897Z"
1244
+ // }
1245
+ // ],
1246
+ // meta: {
1247
+ // total_count: null,
1248
+ // first: { page: 1, href: "https://api.therocktrading.com/v1/funds/ETHBTC/trades?page=1" },
1249
+ // previous: null,
1250
+ // current: { page: 1, href: "https://api.therocktrading.com/v1/funds/ETHBTC/trades?page=1" },
1251
+ // next: { page: 2, href: "https://api.therocktrading.com/v1/funds/ETHBTC/trades?page=2" },
1252
+ // last: null
1253
+ // }
1254
+ // }
1255
+ //
1256
+ return this.parseTrades (response['trades'], market, since, limit);
1257
+ }
1258
+
1259
+ async fetchTradingFee (symbol, params = {}) {
1260
+ await this.loadMarkets ();
1261
+ const market = this.market (symbol);
1262
+ let request = {
1263
+ 'id': market['id'],
1264
+ };
1265
+ const response = await this.publicGetFundsId (this.extend (request, params));
1266
+ //
1267
+ // {
1268
+ // id: 'ETHBTC',
1269
+ // description: 'Trade Ether with Bitcoin',
1270
+ // type: 'currency',
1271
+ // base_currency: 'BTC',
1272
+ // trade_currency: 'ETH',
1273
+ // buy_fee: '0.2',
1274
+ // sell_fee: '0.2',
1275
+ // minimum_price_offer: '0.00000001',
1276
+ // minimum_quantity_offer: '0.005',
1277
+ // base_currency_decimals: '8',
1278
+ // trade_currency_decimals: '3',
1279
+ // leverages: []
1280
+ // }
1281
+ //
1282
+ request = {
1283
+ 'id': market['quoteId'],
1284
+ };
1285
+ const discount = await this.privateGetDiscountsId (this.extend (request, params));
1286
+ //
1287
+ // {
1288
+ // "currency":"BTC",
1289
+ // "discount":50.0,
1290
+ // "details": {
1291
+ // "personal_discount": 50.0,
1292
+ // "commissions_related_discount": 0.0
1293
+ // }
1294
+ // }
1295
+ //
1296
+ return this.parseTradingFee (response, discount, market);
1297
+ }
1298
+
1299
+ async fetchTradingFees (params = {}) {
1300
+ await this.loadMarkets ();
1301
+ const response = await this.publicGetFunds (params);
1302
+ //
1303
+ // {
1304
+ // funds: [
1305
+ // {
1306
+ // id: 'BTCEUR',
1307
+ // description: 'Trade Bitcoin with Euro',
1308
+ // type: 'currency',
1309
+ // base_currency: 'EUR',
1310
+ // trade_currency: 'BTC',
1311
+ // buy_fee: '0.2',
1312
+ // sell_fee: '0.2',
1313
+ // minimum_price_offer: '0.01',
1314
+ // minimum_quantity_offer: '0.0005',
1315
+ // base_currency_decimals: '2',
1316
+ // trade_currency_decimals: '4',
1317
+ // leverages: []
1318
+ // },
1319
+ // ]
1320
+ // }
1321
+ //
1322
+ const discountsResponse = await this.privateGetDiscounts (params);
1323
+ //
1324
+ // {
1325
+ // "discounts": [
1326
+ // {
1327
+ // "currency":"BTC",
1328
+ // "discount":50.0,
1329
+ // "details": {
1330
+ // "personal_discount": 50.0,
1331
+ // "commissions_related_discount": 0.0
1332
+ // }
1333
+ // }
1334
+ // ]
1335
+ // }
1336
+ //
1337
+ const funds = this.safeValue (response, 'funds', []);
1338
+ const discounts = this.safeValue (discountsResponse, 'discounts', []);
1339
+ const result = {};
1340
+ for (let i = 0; i < funds.length; i++) {
1341
+ const fund = funds[i];
1342
+ const marketId = this.safeString (fund, 'id');
1343
+ const market = this.safeMarket (marketId);
1344
+ const quoteId = this.safeValue (market, 'quoteId');
1345
+ const discount = this.filterBy (discounts, 'currency', quoteId);
1346
+ const fee = this.parseTradingFee (fund, discount, market);
1347
+ const symbol = fee['symbol'];
1348
+ result[symbol] = fee;
1349
+ }
1350
+ return result;
1351
+ }
1352
+
1353
+ parseTradingFee (fee, discount = undefined, market = undefined) {
1354
+ const marketId = this.safeString (fee, 'id');
1355
+ const takerString = this.safeString (fee, 'buy_fee');
1356
+ const makerString = this.safeString (fee, 'sell_fee');
1357
+ // TotalFee = (100 - discount) * fee / 10000
1358
+ const discountString = this.safeString (discount, 'discount', '0');
1359
+ const feePercentage = Precise.stringSub ('100', discountString);
1360
+ const taker = this.parseNumber (Precise.stringDiv (Precise.stringMul (takerString, feePercentage), '10000'));
1361
+ const maker = this.parseNumber (Precise.stringDiv (Precise.stringMul (makerString, feePercentage), '10000'));
1362
+ return {
1363
+ 'info': fee,
1364
+ 'symbol': this.safeSymbol (marketId, market),
1365
+ 'maker': maker,
1366
+ 'taker': taker,
1367
+ 'percentage': true,
1368
+ 'tierBased': true,
1369
+ };
1370
+ }
1371
+
1372
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1373
+ let url = this.urls['api'] + '/' + this.version + '/' + this.implodeParams (path, params);
1374
+ const query = this.omit (params, this.extractParams (path));
1375
+ headers = (headers === undefined) ? {} : headers;
1376
+ if (api === 'private') {
1377
+ this.checkRequiredCredentials ();
1378
+ if (Object.keys (query).length) {
1379
+ if (method === 'POST') {
1380
+ body = this.json (query);
1381
+ headers['Content-Type'] = 'application/json';
1382
+ } else {
1383
+ const queryString = this.rawencode (query);
1384
+ if (queryString.length) {
1385
+ url += '?' + queryString;
1386
+ }
1387
+ }
1388
+ }
1389
+ const nonce = this.nonce ().toString ();
1390
+ const auth = nonce + url;
1391
+ headers['X-TRT-KEY'] = this.apiKey;
1392
+ headers['X-TRT-NONCE'] = nonce;
1393
+ headers['X-TRT-SIGN'] = this.hmac (this.encode (auth), this.encode (this.secret), 'sha512');
1394
+ } else if (api === 'public') {
1395
+ if (Object.keys (query).length) {
1396
+ url += '?' + this.rawencode (query);
1397
+ }
1398
+ }
1399
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1400
+ }
1401
+
1402
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1403
+ if (response === undefined) {
1404
+ return; // fallback to default error handler
1405
+ }
1406
+ //
1407
+ // {
1408
+ // "errors": [
1409
+ // { "message": ":currency is not a valid value for param currency","code": "11","meta": { "key":"currency","value":":currency"} },
1410
+ // { "message": "Address allocation limit reached for currency :currency.","code": "13" },
1411
+ // { "message": "Request already running", "code": "50"},
1412
+ // { "message": "cannot specify multiple address types", "code": "12" },
1413
+ // { "message": ":address_type is invalid", "code": "12" }
1414
+ // ]
1415
+ // }
1416
+ //
1417
+ const errors = this.safeValue (response, 'errors', []);
1418
+ const numErrors = errors.length;
1419
+ if (numErrors > 0) {
1420
+ const feedback = this.id + ' ' + body;
1421
+ // here we throw the first error we can identify
1422
+ for (let i = 0; i < numErrors; i++) {
1423
+ const error = errors[i];
1424
+ const message = this.safeString (error, 'message');
1425
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
1426
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
1427
+ }
1428
+ throw new ExchangeError (feedback); // unknown message
1429
+ }
1430
+ }
1431
+ };