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/qtrade.js ADDED
@@ -0,0 +1,1588 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, InvalidOrder, InsufficientFunds, AuthenticationError, RateLimitExceeded, BadSymbol } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class qtrade extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'qtrade',
15
+ 'name': 'qTrade',
16
+ 'countries': [ 'US' ],
17
+ 'rateLimit': 1000,
18
+ 'version': 'v1',
19
+ 'urls': {
20
+ 'logo': 'https://user-images.githubusercontent.com/51840849/80491487-74a99c00-896b-11ea-821e-d307e832f13e.jpg',
21
+ 'api': 'https://api.qtrade.io',
22
+ 'www': 'https://qtrade.io',
23
+ 'doc': 'https://qtrade-exchange.github.io/qtrade-docs',
24
+ 'referral': 'https://qtrade.io/?ref=BKOQWVFGRH2C',
25
+ 'fees': 'https://qtrade.io/fees',
26
+ },
27
+ 'has': {
28
+ 'CORS': undefined,
29
+ 'spot': true,
30
+ 'margin': false,
31
+ 'swap': false,
32
+ 'future': false,
33
+ 'option': false,
34
+ 'addMargin': false,
35
+ 'cancelOrder': true,
36
+ 'createMarketOrder': undefined,
37
+ 'createOrder': true,
38
+ 'createReduceOnlyOrder': false,
39
+ 'fetchBalance': true,
40
+ 'fetchBorrowRate': false,
41
+ 'fetchBorrowRateHistories': false,
42
+ 'fetchBorrowRateHistory': false,
43
+ 'fetchBorrowRates': false,
44
+ 'fetchBorrowRatesPerSymbol': false,
45
+ 'fetchClosedOrders': true,
46
+ 'fetchCurrencies': true,
47
+ 'fetchDeposit': true,
48
+ 'fetchDepositAddress': true,
49
+ 'fetchDeposits': true,
50
+ 'fetchFundingHistory': false,
51
+ 'fetchFundingRate': false,
52
+ 'fetchFundingRateHistory': false,
53
+ 'fetchFundingRates': false,
54
+ 'fetchIndexOHLCV': false,
55
+ 'fetchLeverage': false,
56
+ 'fetchLeverageTiers': false,
57
+ 'fetchMarkets': true,
58
+ 'fetchMarkOHLCV': false,
59
+ 'fetchMyTrades': true,
60
+ 'fetchOHLCV': true,
61
+ 'fetchOpenOrders': true,
62
+ 'fetchOrder': true,
63
+ 'fetchOrderBook': true,
64
+ 'fetchOrders': true,
65
+ 'fetchPosition': false,
66
+ 'fetchPositions': false,
67
+ 'fetchPositionsRisk': false,
68
+ 'fetchPremiumIndexOHLCV': false,
69
+ 'fetchTicker': true,
70
+ 'fetchTickers': true,
71
+ 'fetchTrades': true,
72
+ 'fetchTradingFee': true,
73
+ 'fetchTradingFees': false,
74
+ 'fetchTransactions': undefined,
75
+ 'fetchWithdrawal': true,
76
+ 'fetchWithdrawals': true,
77
+ 'reduceMargin': false,
78
+ 'setLeverage': false,
79
+ 'setMarginMode': false,
80
+ 'setPositionMode': false,
81
+ 'withdraw': true,
82
+ },
83
+ 'timeframes': {
84
+ '5m': 'fivemin',
85
+ '15m': 'fifteenmin',
86
+ '30m': 'thirtymin',
87
+ '1h': 'onehour',
88
+ '2h': 'twohour',
89
+ '4h': 'fourhour',
90
+ '1d': 'oneday',
91
+ },
92
+ 'api': {
93
+ 'public': {
94
+ 'get': [
95
+ 'ticker/{market_string}',
96
+ 'tickers',
97
+ 'currency/{code}',
98
+ 'currencies',
99
+ 'common',
100
+ 'market/{market_string}',
101
+ 'markets',
102
+ 'market/{market_string}/trades',
103
+ 'orderbook/{market_string}',
104
+ 'market/{market_string}/ohlcv/{interval}',
105
+ ],
106
+ },
107
+ 'private': {
108
+ 'get': [
109
+ 'me',
110
+ 'balances',
111
+ 'balances_all', // undocumented
112
+ 'market/{market_string}',
113
+ 'orders',
114
+ 'order/{order_id}',
115
+ 'trades',
116
+ 'withdraw/{withdraw_id}',
117
+ 'withdraws',
118
+ 'deposit/{deposit_id}',
119
+ 'deposits',
120
+ 'transfers',
121
+ ],
122
+ 'post': [
123
+ 'cancel_order',
124
+ 'withdraw',
125
+ 'deposit_address/{currency}',
126
+ 'sell_limit',
127
+ 'buy_limit',
128
+ ],
129
+ },
130
+ },
131
+ 'fees': {
132
+ 'trading': {
133
+ 'feeSide': 'quote',
134
+ 'tierBased': true,
135
+ 'percentage': true,
136
+ 'taker': this.parseNumber ('0.005'),
137
+ 'maker': this.parseNumber ('0.0'),
138
+ },
139
+ 'funding': {
140
+ 'withdraw': {},
141
+ },
142
+ },
143
+ 'commonCurrencies': {
144
+ 'BTM': 'Bitmark',
145
+ },
146
+ 'exceptions': {
147
+ 'exact': {
148
+ 'invalid_auth': AuthenticationError,
149
+ 'insuff_funds': InsufficientFunds,
150
+ 'market_not_found': BadSymbol, // {"errors":[{"code":"market_not_found","title":"Requested market does not exist"}]}
151
+ 'too_small': InvalidOrder,
152
+ 'limit_exceeded': RateLimitExceeded, // {"errors":[{"code":"limit_exceeded","title":"You have exceeded the windowed rate limit. Please see docs."}]}
153
+ },
154
+ },
155
+ });
156
+ }
157
+
158
+ async fetchMarkets (params = {}) {
159
+ const response = await this.publicGetMarkets (params);
160
+ //
161
+ // {
162
+ // "data":{
163
+ // "markets":[
164
+ // {
165
+ // "id":5,
166
+ // "market_currency":"BAC",
167
+ // "base_currency":"BTC",
168
+ // "maker_fee":"0.0025",
169
+ // "taker_fee":"0.0025",
170
+ // "metadata":{
171
+ // "delisting_date":"7/15/2018",
172
+ // "market_notices":[
173
+ // {
174
+ // "message":"Delisting Notice: This market has been delisted due to low volume. Please cancel your orders and withdraw your funds by 7/15/2018.",
175
+ // "type":"warning"
176
+ // }
177
+ // ]
178
+ // },
179
+ // "can_trade":false,
180
+ // "can_cancel":true,
181
+ // "can_view":false,
182
+ // "market_string":"BAC_BTC",
183
+ // "minimum_sell_amount":"0.0001",
184
+ // "minimum_buy_value":"0.0001",
185
+ // "market_precision":8,
186
+ // "base_precision":8
187
+ // },
188
+ // ],
189
+ // }
190
+ // }
191
+ //
192
+ const data = this.safeValue (response, 'data', {});
193
+ const markets = this.safeValue (data, 'markets', []);
194
+ const result = [];
195
+ for (let i = 0; i < markets.length; i++) {
196
+ const market = markets[i];
197
+ const marketId = this.safeString (market, 'market_string');
198
+ const numericId = this.safeInteger (market, 'id');
199
+ const baseId = this.safeString (market, 'market_currency');
200
+ const quoteId = this.safeString (market, 'base_currency');
201
+ const base = this.safeCurrencyCode (baseId);
202
+ const quote = this.safeCurrencyCode (quoteId);
203
+ const canView = this.safeValue (market, 'can_view', false);
204
+ const canTrade = this.safeValue (market, 'can_trade', false);
205
+ const active = canTrade && canView;
206
+ result.push ({
207
+ 'id': marketId,
208
+ 'numericId': numericId,
209
+ 'symbol': base + '/' + quote,
210
+ 'base': base,
211
+ 'quote': quote,
212
+ 'settle': undefined,
213
+ 'baseId': baseId,
214
+ 'quoteId': quoteId,
215
+ 'settleId': undefined,
216
+ 'type': 'spot',
217
+ 'spot': true,
218
+ 'margin': false,
219
+ 'swap': false,
220
+ 'future': false,
221
+ 'option': false,
222
+ 'active': active,
223
+ 'contract': false,
224
+ 'linear': undefined,
225
+ 'inverse': undefined,
226
+ 'taker': this.safeNumber (market, 'taker_fee'),
227
+ 'maker': this.safeNumber (market, 'maker_fee'),
228
+ 'contractSize': undefined,
229
+ 'expiry': undefined,
230
+ 'expiryDatetime': undefined,
231
+ 'strike': undefined,
232
+ 'optionType': undefined,
233
+ 'precision': {
234
+ 'amount': this.safeInteger (market, 'market_precision'),
235
+ 'price': this.safeInteger (market, 'base_precision'),
236
+ },
237
+ 'limits': {
238
+ 'leverage': {
239
+ 'min': undefined,
240
+ 'max': undefined,
241
+ },
242
+ 'amount': {
243
+ 'min': this.safeNumber (market, 'minimum_sell_value'),
244
+ 'max': undefined,
245
+ },
246
+ 'price': {
247
+ 'min': undefined,
248
+ 'max': undefined,
249
+ },
250
+ 'cost': {
251
+ 'min': this.safeNumber (market, 'minimum_buy_value'),
252
+ 'max': undefined,
253
+ },
254
+ },
255
+ 'info': market,
256
+ });
257
+ }
258
+ return result;
259
+ }
260
+
261
+ async fetchCurrencies (params = {}) {
262
+ const response = await this.publicGetCurrencies (params);
263
+ //
264
+ // {
265
+ // "data":{
266
+ // "currencies":[
267
+ // {
268
+ // "code":"DGB",
269
+ // "long_name":"Digibyte",
270
+ // "type":"bitcoin_like",
271
+ // "precision":8,
272
+ // "config":{
273
+ // "price":0.0035,
274
+ // "withdraw_fee":"10",
275
+ // "deposit_types":[
276
+ // {
277
+ // "label":"Address",
278
+ // "lookup_mode":"address",
279
+ // "render_type":"address",
280
+ // "deposit_type":"address",
281
+ // "lookup_config":{}
282
+ // }
283
+ // ],
284
+ // "default_signer":103,
285
+ // "address_version":30,
286
+ // "satoshi_per_byte":300,
287
+ // "required_confirmations":200,
288
+ // "required_generate_confirmations":300
289
+ // },
290
+ // "metadata":{},
291
+ // "minimum_order":"0.0001",
292
+ // "status":"ok",
293
+ // "can_withdraw":true,
294
+ // "delisted":false,
295
+ // "deposit_disabled":false,
296
+ // "withdraw_disabled":false,
297
+ // "deposit_warn_codes":[],
298
+ // "withdraw_warn_codes":[]
299
+ // },
300
+ // ],
301
+ // }
302
+ // }
303
+ //
304
+ const data = this.safeValue (response, 'data', {});
305
+ const currencies = this.safeValue (data, 'currencies', []);
306
+ const result = {};
307
+ for (let i = 0; i < currencies.length; i++) {
308
+ const currency = currencies[i];
309
+ const id = this.safeString (currency, 'code');
310
+ const code = this.safeCurrencyCode (id);
311
+ const name = this.safeString (currency, 'long_name');
312
+ const type = this.safeString (currency, 'type');
313
+ const canWithdraw = this.safeValue (currency, 'can_withdraw', true);
314
+ const withdrawDisabled = this.safeValue (currency, 'withdraw_disabled', false);
315
+ const depositDisabled = this.safeValue (currency, 'deposit_disabled', false);
316
+ const deposit = !depositDisabled;
317
+ const withdraw = canWithdraw && !withdrawDisabled;
318
+ const config = this.safeValue (currency, 'config', {});
319
+ const status = this.safeString (currency, 'status');
320
+ const active = withdraw && deposit && (status === 'ok');
321
+ result[code] = {
322
+ 'id': id,
323
+ 'code': code,
324
+ 'info': currency,
325
+ 'type': type,
326
+ 'name': name,
327
+ 'fee': this.safeNumber (config, 'withdraw_fee'),
328
+ 'precision': this.safeInteger (currency, 'precision'),
329
+ 'active': active,
330
+ 'deposit': deposit,
331
+ 'withdraw': withdraw,
332
+ 'limits': {
333
+ 'amount': {
334
+ 'min': this.safeNumber (currency, 'minimum_order'),
335
+ 'max': undefined,
336
+ },
337
+ 'withdraw': {
338
+ 'min': undefined,
339
+ 'max': undefined,
340
+ },
341
+ },
342
+ };
343
+ }
344
+ return result;
345
+ }
346
+
347
+ parseOHLCV (ohlcv, market = undefined) {
348
+ //
349
+ // {
350
+ // "time":"2019-12-07T22:55:00Z",
351
+ // "open":"0.00197",
352
+ // "high":"0.00197",
353
+ // "low":"0.00197",
354
+ // "close":"0.00197",
355
+ // "volume":"0.00016676",
356
+ // "market_volume":"0.08465047"
357
+ // }
358
+ //
359
+ return [
360
+ this.parse8601 (this.safeString (ohlcv, 'time')),
361
+ this.safeNumber (ohlcv, 'open'),
362
+ this.safeNumber (ohlcv, 'high'),
363
+ this.safeNumber (ohlcv, 'low'),
364
+ this.safeNumber (ohlcv, 'close'),
365
+ this.safeNumber (ohlcv, 'market_volume'),
366
+ ];
367
+ }
368
+
369
+ async fetchOHLCV (symbol, timeframe = '5m', since = undefined, limit = undefined, params = {}) {
370
+ await this.loadMarkets ();
371
+ const market = this.market (symbol);
372
+ const request = {
373
+ 'market_string': market['id'],
374
+ 'interval': this.timeframes[timeframe],
375
+ };
376
+ const response = await this.publicGetMarketMarketStringOhlcvInterval (this.extend (request, params));
377
+ //
378
+ // {
379
+ // "data":{
380
+ // "slices":[
381
+ // {"time":"2019-12-07T22:55:00Z","open":"0.00197","high":"0.00197","low":"0.00197","close":"0.00197","volume":"0.00016676","market_volume":"0.08465047"},
382
+ // {"time":"2019-12-07T23:00:00Z","open":"0.00197","high":"0.00197","low":"0.00197","close":"0.00197","volume":"0","market_volume":"0"},
383
+ // {"time":"2019-12-07T23:05:00Z","open":"0.00197","high":"0.00197","low":"0.00197","close":"0.00197","volume":"0","market_volume":"0"},
384
+ // ]
385
+ // }
386
+ // }
387
+ //
388
+ const data = this.safeValue (response, 'data', {});
389
+ const ohlcvs = this.safeValue (data, 'slices', []);
390
+ return this.parseOHLCVs (ohlcvs, market, timeframe, since, limit);
391
+ }
392
+
393
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
394
+ await this.loadMarkets ();
395
+ const marketId = this.marketId (symbol);
396
+ const request = { 'market_string': marketId };
397
+ const response = await this.publicGetOrderbookMarketString (this.extend (request, params));
398
+ //
399
+ // {
400
+ // "data":{
401
+ // "buy":{
402
+ // "0.00700015":"4.76196367",
403
+ // "0.00700017":"1.89755391",
404
+ // "0.00700018":"2.13214088",
405
+ // },
406
+ // "last_change":1588539869958811,
407
+ // "sell":{
408
+ // "0.02418662":"0.19513696",
409
+ // "0.02465627":"0.2439212",
410
+ // "0.02530277":"0.663475931274359255",
411
+ // }
412
+ // }
413
+ // }
414
+ //
415
+ const data = this.safeValue (response, 'data', {});
416
+ const orderbook = {};
417
+ const sides = { 'buy': 'bids', 'sell': 'asks' };
418
+ const keys = Object.keys (sides);
419
+ for (let i = 0; i < keys.length; i++) {
420
+ const key = keys[i];
421
+ const side = sides[key];
422
+ const bidasks = this.safeValue (data, key, {});
423
+ const prices = Object.keys (bidasks);
424
+ const result = [];
425
+ for (let j = 0; j < prices.length; j++) {
426
+ const priceAsString = prices[j];
427
+ const price = this.safeNumber (prices, j);
428
+ const amount = this.safeNumber (bidasks, priceAsString);
429
+ result.push ([ price, amount ]);
430
+ }
431
+ orderbook[side] = result;
432
+ }
433
+ const timestamp = this.safeIntegerProduct (data, 'last_change', 0.001);
434
+ return this.parseOrderBook (orderbook, symbol, timestamp);
435
+ }
436
+
437
+ parseTicker (ticker, market = undefined) {
438
+ //
439
+ // fetchTicker, fetchTickers
440
+ //
441
+ // {
442
+ // "ask":"0.02423119",
443
+ // "bid":"0.0230939",
444
+ // "day_avg_price":"0.0247031874349301",
445
+ // "day_change":"-0.0237543162270376",
446
+ // "day_high":"0.02470552",
447
+ // "day_low":"0.02470172",
448
+ // "day_open":"0.02530277",
449
+ // "day_volume_base":"0.00268074",
450
+ // "day_volume_market":"0.10851798",
451
+ // "id":41,
452
+ // "id_hr":"ETH_BTC",
453
+ // "last":"0.02470172",
454
+ // "last_change":1588533365354609
455
+ // }
456
+ //
457
+ const marketId = this.safeString (ticker, 'id_hr');
458
+ const symbol = this.safeSymbol (marketId, market, '_');
459
+ const timestamp = this.safeIntegerProduct (ticker, 'last_change', 0.001);
460
+ const previous = this.safeString (ticker, 'day_open');
461
+ const last = this.safeString (ticker, 'last');
462
+ const day_change = this.safeString (ticker, 'day_change');
463
+ const average = this.safeString (ticker, 'day_avg_price');
464
+ const baseVolume = this.safeString (ticker, 'day_volume_market');
465
+ const quoteVolume = this.safeString (ticker, 'day_volume_base');
466
+ const percentage = Precise.stringMul (day_change, '100');
467
+ const change = Precise.stringMul (day_change, previous);
468
+ return this.safeTicker ({
469
+ 'symbol': symbol,
470
+ 'timestamp': timestamp,
471
+ 'datetime': this.iso8601 (timestamp),
472
+ 'high': this.safeString (ticker, 'day_high'),
473
+ 'low': this.safeString (ticker, 'day_low'),
474
+ 'bid': this.safeString (ticker, 'bid'),
475
+ 'bidVolume': undefined,
476
+ 'ask': this.safeString (ticker, 'ask'),
477
+ 'askVolume': undefined,
478
+ 'vwap': undefined,
479
+ 'open': previous,
480
+ 'close': last,
481
+ 'last': last,
482
+ 'previousClose': undefined,
483
+ 'change': change,
484
+ 'percentage': percentage,
485
+ 'average': average,
486
+ 'baseVolume': baseVolume,
487
+ 'quoteVolume': quoteVolume,
488
+ 'info': ticker,
489
+ }, market, false);
490
+ }
491
+
492
+ async fetchTickers (symbols = undefined, params = {}) {
493
+ await this.loadMarkets ();
494
+ const response = await this.publicGetTickers (params);
495
+ //
496
+ // {
497
+ // "data":{
498
+ // "markets":[
499
+ // {
500
+ // "ask":"0.0000003",
501
+ // "bid":"0.00000029",
502
+ // "day_avg_price":"0.0000002999979728",
503
+ // "day_change":"0.0344827586206897",
504
+ // "day_high":"0.0000003",
505
+ // "day_low":"0.0000003",
506
+ // "day_open":"0.00000029",
507
+ // "day_volume_base":"0.00591958",
508
+ // "day_volume_market":"19732.06666665",
509
+ // "id":36,
510
+ // "id_hr":"DOGE_BTC",
511
+ // "last":"0.0000003",
512
+ // "last_change":1588534202130778
513
+ // },
514
+ // ]
515
+ // }
516
+ // }
517
+ //
518
+ const data = this.safeValue (response, 'data', {});
519
+ const tickers = this.safeValue (data, 'markets', []);
520
+ const result = {};
521
+ for (let i = 0; i < tickers.length; i++) {
522
+ const ticker = this.parseTicker (tickers[i]);
523
+ const symbol = ticker['symbol'];
524
+ result[symbol] = ticker;
525
+ }
526
+ return this.filterByArray (result, 'symbol', symbols);
527
+ }
528
+
529
+ async fetchTicker (symbol, params = {}) {
530
+ await this.loadMarkets ();
531
+ const market = this.market (symbol);
532
+ const request = {
533
+ 'market_string': market['id'],
534
+ };
535
+ const response = await this.publicGetTickerMarketString (this.extend (request, params));
536
+ //
537
+ // {
538
+ // "data":{
539
+ // "ask":"0.02423119",
540
+ // "bid":"0.0230939",
541
+ // "day_avg_price":"0.0247031874349301",
542
+ // "day_change":"-0.0237543162270376",
543
+ // "day_high":"0.02470552",
544
+ // "day_low":"0.02470172",
545
+ // "day_open":"0.02530277",
546
+ // "day_volume_base":"0.00268074",
547
+ // "day_volume_market":"0.10851798",
548
+ // "id":41,
549
+ // "id_hr":"ETH_BTC",
550
+ // "last":"0.02470172",
551
+ // "last_change":1588533365354609
552
+ // }
553
+ // }
554
+ //
555
+ const data = this.safeValue (response, 'data', {});
556
+ return this.parseTicker (data, market);
557
+ }
558
+
559
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
560
+ await this.loadMarkets ();
561
+ const market = this.market (symbol);
562
+ const request = {
563
+ 'market_string': market['id'],
564
+ // 'older_than': 123, // returns trades with id < older_than
565
+ // 'newer_than': 123, // returns trades with id > newer_than
566
+ };
567
+ const response = await this.publicGetMarketMarketStringTrades (this.extend (request, params));
568
+ //
569
+ // {
570
+ // "data":{
571
+ // "trades":[
572
+ // {
573
+ // "id":85507,
574
+ // "amount":"0.09390502",
575
+ // "price":"0.02556325",
576
+ // "base_volume":"0.00240051",
577
+ // "seller_taker":true,
578
+ // "side":"sell",
579
+ // "created_at":"0001-01-01T00:00:00Z",
580
+ // "created_at_ts":1581560391338718
581
+ // },
582
+ // ]
583
+ // }
584
+ // }
585
+ //
586
+ const data = this.safeValue (response, 'data', {});
587
+ const trades = this.safeValue (data, 'trades', []);
588
+ return this.parseTrades (trades, market, since, limit);
589
+ }
590
+
591
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
592
+ await this.loadMarkets ();
593
+ const request = {
594
+ 'desc': true, // Returns newest trades first when true
595
+ // 'older_than': 123, // returns trades with id < older_than
596
+ // 'newer_than': 123, // returns trades with id > newer_than
597
+ };
598
+ let market = undefined;
599
+ const numericId = this.safeValue (params, 'market_id');
600
+ if (numericId !== undefined) {
601
+ request['market_id'] = numericId; // mutually exclusive with market_string
602
+ } else if (symbol !== undefined) {
603
+ market = this.market (symbol);
604
+ request['market_string'] = market['id'];
605
+ }
606
+ const response = await this.privateGetTrades (this.extend (request, params));
607
+ //
608
+ // {
609
+ // "data":{
610
+ // "trades":[
611
+ // {
612
+ // "id":107331,
613
+ // "market_amount":"0.1082536946986",
614
+ // "price":"0.0230939",
615
+ // "base_amount":"0.00249999",
616
+ // "order_id":13790596,
617
+ // "market_id":41,
618
+ // "market_string":"ETH_BTC",
619
+ // "taker":true,
620
+ // "base_fee":"0.00001249",
621
+ // "side":"sell",
622
+ // "created_at":"2020-05-04T06:08:18.513413Z"
623
+ // }
624
+ // ]
625
+ // }
626
+ // }
627
+ //
628
+ const data = this.safeValue (response, 'data', {});
629
+ const trades = this.safeValue (data, 'trades', []);
630
+ return this.parseTrades (trades, market, since, limit);
631
+ }
632
+
633
+ parseTrade (trade, market = undefined) {
634
+ //
635
+ // fetchTrades (public)
636
+ //
637
+ // {
638
+ // "id":85507,
639
+ // "amount":"0.09390502",
640
+ // "price":"0.02556325",
641
+ // "base_volume":"0.00240051",
642
+ // "seller_taker":true,
643
+ // "side":"sell",
644
+ // "created_at":"0001-01-01T00:00:00Z",
645
+ // "created_at_ts":1581560391338718
646
+ // }
647
+ //
648
+ // fetchMyTrades (private)
649
+ //
650
+ // {
651
+ // "id":107331,
652
+ // "market_amount":"0.1082536946986",
653
+ // "price":"0.0230939",
654
+ // "base_amount":"0.00249999",
655
+ // "order_id":13790596,
656
+ // "market_id":41,
657
+ // "market_string":"ETH_BTC",
658
+ // "taker":true,
659
+ // "base_fee":"0.00001249",
660
+ // "side":"sell",
661
+ // "created_at":"2020-05-04T06:08:18.513413Z"
662
+ // }
663
+ //
664
+ // createOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders
665
+ //
666
+ // {
667
+ // "base_amount": "9.58970687",
668
+ // "base_fee": "0.02397426",
669
+ // "created_at": "0001-01-01T00:00:00Z",
670
+ // "id": 0,
671
+ // "market_amount": "0.97179355",
672
+ // "price": "9.86804952",
673
+ // "taker": true
674
+ // }
675
+ //
676
+ const id = this.safeString (trade, 'id');
677
+ let timestamp = this.safeIntegerProduct (trade, 'created_at_ts', 0.001);
678
+ if (timestamp === undefined) {
679
+ timestamp = this.parse8601 (this.safeString (trade, 'created_at'));
680
+ }
681
+ const side = this.safeString (trade, 'side');
682
+ const marketId = this.safeString (trade, 'market_string');
683
+ market = this.safeMarket (marketId, market);
684
+ const cost = this.safeString2 (trade, 'base_volume', 'base_amount');
685
+ const price = this.safeString (trade, 'price');
686
+ const amount = this.safeString2 (trade, 'market_amount', 'amount');
687
+ let fee = undefined;
688
+ const feeCost = this.safeString (trade, 'base_fee');
689
+ if (feeCost !== undefined) {
690
+ const feeCurrencyCode = (market === undefined) ? undefined : market['quote'];
691
+ fee = {
692
+ 'currency': feeCurrencyCode,
693
+ 'cost': feeCost,
694
+ };
695
+ }
696
+ const taker = this.safeValue (trade, 'taker', true);
697
+ const takerOrMaker = taker ? 'taker' : 'maker';
698
+ const orderId = this.safeString (trade, 'order_id');
699
+ return this.safeTrade ({
700
+ 'id': id,
701
+ 'info': trade,
702
+ 'timestamp': timestamp,
703
+ 'datetime': this.iso8601 (timestamp),
704
+ 'symbol': market['symbol'],
705
+ 'order': orderId,
706
+ 'type': undefined,
707
+ 'side': side,
708
+ 'takerOrMaker': takerOrMaker,
709
+ 'price': price,
710
+ 'amount': amount,
711
+ 'cost': cost,
712
+ 'fee': fee,
713
+ }, market);
714
+ }
715
+
716
+ async fetchTradingFee (symbol, params = {}) {
717
+ await this.loadMarkets ();
718
+ const market = this.market (symbol);
719
+ const request = {
720
+ 'market_string': market['id'],
721
+ };
722
+ const response = await this.publicGetMarketMarketString (this.extend (request, params));
723
+ //
724
+ // {
725
+ // data: {
726
+ // market: {
727
+ // id: '41',
728
+ // market_currency: 'ETH',
729
+ // base_currency: 'BTC',
730
+ // maker_fee: '0',
731
+ // taker_fee: '0.005',
732
+ // metadata: {},
733
+ // can_trade: true,
734
+ // can_cancel: true,
735
+ // can_view: true,
736
+ // market_string: 'ETH_BTC',
737
+ // minimum_sell_amount: '0.001',
738
+ // minimum_buy_value: '0.0001',
739
+ // market_precision: '18',
740
+ // base_precision: '8'
741
+ // },
742
+ // recent_trades: []
743
+ // }
744
+ // }
745
+ //
746
+ const data = this.safeValue (response, 'data', {});
747
+ const marketData = this.safeValue (data, 'market', {});
748
+ return {
749
+ 'info': marketData,
750
+ 'symbol': symbol,
751
+ 'maker': this.safeNumber (marketData, 'maker_fee'),
752
+ 'taker': this.safeNumber (marketData, 'taker_fee'),
753
+ 'percentage': true,
754
+ 'tierBased': true,
755
+ };
756
+ }
757
+
758
+ parseBalance (response) {
759
+ const data = this.safeValue (response, 'data', {});
760
+ let balances = this.safeValue (data, 'balances', []);
761
+ const result = {
762
+ 'info': response,
763
+ 'timestamp': undefined,
764
+ 'datetime': undefined,
765
+ };
766
+ for (let i = 0; i < balances.length; i++) {
767
+ const balance = balances[i];
768
+ const currencyId = this.safeString (balance, 'currency');
769
+ const code = this.safeCurrencyCode (currencyId);
770
+ const account = (code in result) ? result[code] : this.account ();
771
+ account['free'] = this.safeString (balance, 'balance');
772
+ account['used'] = '0';
773
+ result[code] = account;
774
+ }
775
+ balances = this.safeValue (data, 'order_balances', []);
776
+ for (let i = 0; i < balances.length; i++) {
777
+ const balance = balances[i];
778
+ const currencyId = this.safeString (balance, 'currency');
779
+ const code = this.safeCurrencyCode (currencyId);
780
+ const account = (code in result) ? result[code] : this.account ();
781
+ account['used'] = this.safeString (balance, 'balance');
782
+ result[code] = account;
783
+ }
784
+ return this.safeBalance (result);
785
+ }
786
+
787
+ async fetchBalance (params = {}) {
788
+ await this.loadMarkets ();
789
+ const response = await this.privateGetBalancesAll (params);
790
+ //
791
+ // {
792
+ // "data":{
793
+ // "balances": [
794
+ // { "balance": "100000000", "currency": "BCH" },
795
+ // { "balance": "99992435.78253015", "currency": "LTC" },
796
+ // { "balance": "99927153.76074182", "currency": "BTC" },
797
+ // ],
798
+ // "order_balances":[],
799
+ // "limit_used":0,
800
+ // "limit_remaining":4000,
801
+ // "limit":4000
802
+ // }
803
+ // }
804
+ //
805
+ return this.parseBalance (response);
806
+ }
807
+
808
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
809
+ if (type !== 'limit') {
810
+ throw new InvalidOrder (this.id + ' createOrder() allows limit orders only');
811
+ }
812
+ await this.loadMarkets ();
813
+ const market = this.market (symbol);
814
+ const request = {
815
+ 'amount': this.amountToPrecision (symbol, amount),
816
+ 'market_id': market['numericId'],
817
+ 'price': this.priceToPrecision (symbol, price),
818
+ };
819
+ const method = (side === 'sell') ? 'privatePostSellLimit' : 'privatePostBuyLimit';
820
+ const response = await this[method] (this.extend (request, params));
821
+ //
822
+ // {
823
+ // "data": {
824
+ // "order": {
825
+ // "created_at": "2018-04-06T20:46:52.899248Z",
826
+ // "id": 13253,
827
+ // "market_amount": "1",
828
+ // "market_amount_remaining": "0",
829
+ // "market_id": 1,
830
+ // "open": false,
831
+ // "order_type": "sell_limit",
832
+ // "price": "0.01",
833
+ // "trades": [
834
+ // {
835
+ // "base_amount": "0.27834267",
836
+ // "base_fee": "0.00069585",
837
+ // "created_at": "0001-01-01T00:00:00Z",
838
+ // "id": 0,
839
+ // "market_amount": "0.02820645",
840
+ // "price": "9.86805058",
841
+ // "taker": true
842
+ // },
843
+ // {
844
+ // "base_amount": "9.58970687",
845
+ // "base_fee": "0.02397426",
846
+ // "created_at": "0001-01-01T00:00:00Z",
847
+ // "id": 0,
848
+ // "market_amount": "0.97179355",
849
+ // "price": "9.86804952",
850
+ // "taker": true
851
+ // }
852
+ // ]
853
+ // }
854
+ // }
855
+ // }
856
+ //
857
+ const data = this.safeValue (response, 'data', {});
858
+ const order = this.safeValue (data, 'order', {});
859
+ return this.parseOrder (order, market);
860
+ }
861
+
862
+ parseOrder (order, market = undefined) {
863
+ //
864
+ // createOrder
865
+ //
866
+ // {
867
+ // "created_at": "2018-04-06T20:46:52.899248Z",
868
+ // "id": 13253,
869
+ // "market_amount": "1",
870
+ // "market_amount_remaining": "0",
871
+ // "market_id": 1,
872
+ // "open": false,
873
+ // "order_type": "sell_limit",
874
+ // "price": "0.01",
875
+ // "trades": [
876
+ // {
877
+ // "base_amount": "0.27834267",
878
+ // "base_fee": "0.00069585",
879
+ // "created_at": "0001-01-01T00:00:00Z",
880
+ // "id": 0,
881
+ // "market_amount": "0.02820645",
882
+ // "price": "9.86805058",
883
+ // "taker": true
884
+ // },
885
+ // {
886
+ // "base_amount": "9.58970687",
887
+ // "base_fee": "0.02397426",
888
+ // "created_at": "0001-01-01T00:00:00Z",
889
+ // "id": 0,
890
+ // "market_amount": "0.97179355",
891
+ // "price": "9.86804952",
892
+ // "taker": true
893
+ // }
894
+ // ]
895
+ // }
896
+ //
897
+ // fetchOrder
898
+ //
899
+ // {
900
+ // id: 13790596,
901
+ // market_amount: "0.15",
902
+ // market_amount_remaining: "0",
903
+ // created_at: "2020-05-04T06:08:18.513413Z",
904
+ // price: "0.0230939",
905
+ // base_amount: "0",
906
+ // order_type: "sell_limit",
907
+ // market_id: 41,
908
+ // market_string: "ETH_BTC",
909
+ // open: false,
910
+ // trades: [
911
+ // {
912
+ // id: 107331,
913
+ // market_amount: "0.1082536946986",
914
+ // price: "0.0230939",
915
+ // base_amount: "0.00249999",
916
+ // taker: true,
917
+ // base_fee: "0.00001249",
918
+ // created_at: "2020-05-04T06:08:18.513413Z",
919
+ // }
920
+ // ],
921
+ // close_reason: "canceled"
922
+ // }
923
+ //
924
+ const id = this.safeString (order, 'id');
925
+ const timestamp = this.parse8601 (this.safeString (order, 'created_at'));
926
+ const sideType = this.safeString (order, 'order_type');
927
+ let orderType = undefined;
928
+ let side = undefined;
929
+ if (sideType !== undefined) {
930
+ const parts = sideType.split ('_');
931
+ side = this.safeString (parts, 0);
932
+ orderType = this.safeString (parts, 1);
933
+ }
934
+ const price = this.safeString (order, 'price');
935
+ const amount = this.safeString (order, 'market_amount');
936
+ const remaining = this.safeString (order, 'market_amount_remaining');
937
+ const open = this.safeValue (order, 'open', false);
938
+ const closeReason = this.safeString (order, 'close_reason');
939
+ let status = undefined;
940
+ if (open) {
941
+ status = 'open';
942
+ } else if (closeReason === 'canceled') {
943
+ status = 'canceled';
944
+ } else {
945
+ status = 'closed';
946
+ }
947
+ const marketId = this.safeString (order, 'market_string');
948
+ market = this.safeMarket (marketId, market, '_');
949
+ const symbol = market['symbol'];
950
+ const rawTrades = this.safeValue (order, 'trades', []);
951
+ return this.safeOrder ({
952
+ 'info': order,
953
+ 'id': id,
954
+ 'clientOrderId': undefined,
955
+ 'timestamp': timestamp,
956
+ 'datetime': this.iso8601 (timestamp),
957
+ 'lastTradeTimestamp': undefined,
958
+ 'symbol': symbol,
959
+ 'type': orderType,
960
+ 'timeInForce': undefined,
961
+ 'postOnly': undefined,
962
+ 'side': side,
963
+ 'price': price,
964
+ 'stopPrice': undefined,
965
+ 'average': undefined,
966
+ 'amount': amount,
967
+ 'remaining': remaining,
968
+ 'filled': undefined,
969
+ 'status': status,
970
+ 'fee': undefined,
971
+ 'fees': undefined,
972
+ 'cost': undefined,
973
+ 'trades': rawTrades,
974
+ }, market);
975
+ }
976
+
977
+ async cancelOrder (id, symbol = undefined, params = {}) {
978
+ const request = {
979
+ 'id': parseInt (id),
980
+ };
981
+ // successful cancellation returns 200 with no payload
982
+ return await this.privatePostCancelOrder (this.extend (request, params));
983
+ }
984
+
985
+ async fetchOrder (id, symbol = undefined, params = {}) {
986
+ await this.loadMarkets ();
987
+ const request = { 'order_id': id };
988
+ const response = await this.privateGetOrderOrderId (this.extend (request, params));
989
+ //
990
+ // {
991
+ // "data":{
992
+ // "order":{
993
+ // "id":13790596,
994
+ // "market_amount":"0.15",
995
+ // "market_amount_remaining":"0.0417463053014",
996
+ // "created_at":"2020-05-04T06:08:18.513413Z",
997
+ // "price":"0.0230939",
998
+ // "order_type":"sell_limit",
999
+ // "market_id":41,
1000
+ // "market_string":"ETH_BTC",
1001
+ // "open":true,
1002
+ // "trades":[
1003
+ // {
1004
+ // "id":107331,
1005
+ // "market_amount":"0.1082536946986",
1006
+ // "price":"0.0230939",
1007
+ // "base_amount":"0.00249999",
1008
+ // "taker":true,
1009
+ // "base_fee":"0.00001249",
1010
+ // "created_at":"2020-05-04T06:08:18.513413Z"
1011
+ // }
1012
+ // ]
1013
+ // }
1014
+ // }
1015
+ // }
1016
+ //
1017
+ const data = this.safeValue (response, 'data', {});
1018
+ const order = this.safeValue (data, 'order', {});
1019
+ return this.parseOrder (order);
1020
+ }
1021
+
1022
+ async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1023
+ await this.loadMarkets ();
1024
+ const request = {
1025
+ // 'open': true,
1026
+ // 'older_than': 123, // returns orders with id < older_than
1027
+ // 'newer_than': 123, // returns orders with id > newer_than
1028
+ };
1029
+ let market = undefined;
1030
+ const numericId = this.safeValue (params, 'market_id');
1031
+ if (numericId !== undefined) {
1032
+ request['market_id'] = numericId; // mutually exclusive with market_string
1033
+ } else if (symbol !== undefined) {
1034
+ market = this.market (symbol);
1035
+ request['market_string'] = market['id'];
1036
+ }
1037
+ const response = await this.privateGetOrders (this.extend (request, params));
1038
+ //
1039
+ // {
1040
+ // "data":{
1041
+ // "orders":[
1042
+ // {
1043
+ // "id":13790596,
1044
+ // "market_amount":"0.15",
1045
+ // "market_amount_remaining":"0.0417463053014",
1046
+ // "created_at":"2020-05-04T06:08:18.513413Z",
1047
+ // "price":"0.0230939",
1048
+ // "order_type":"sell_limit",
1049
+ // "market_id":41,
1050
+ // "market_string":"ETH_BTC",
1051
+ // "open":true,
1052
+ // "trades":[
1053
+ // {
1054
+ // "id":107331,
1055
+ // "market_amount":"0.1082536946986",
1056
+ // "price":"0.0230939",
1057
+ // "base_amount":"0.00249999",
1058
+ // "taker":true,
1059
+ // "base_fee":"0.00001249",
1060
+ // "created_at":"2020-05-04T06:08:18.513413Z"
1061
+ // }
1062
+ // ]
1063
+ // }
1064
+ // ]
1065
+ // }
1066
+ // }
1067
+ //
1068
+ const data = this.safeValue (response, 'data', {});
1069
+ const orders = this.safeValue (data, 'orders', []);
1070
+ return this.parseOrders (orders, market, since, limit);
1071
+ }
1072
+
1073
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1074
+ const request = { 'open': true };
1075
+ return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
1076
+ }
1077
+
1078
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1079
+ const request = { 'open': false };
1080
+ return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
1081
+ }
1082
+
1083
+ parseDepositAddress (depositAddress, currency = undefined) {
1084
+ //
1085
+ // {
1086
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1087
+ // "currency_status":"ok",
1088
+ // "deposit_methods":{
1089
+ // "address":{
1090
+ // "deposit_type":"address",
1091
+ // "render_type":"address",
1092
+ // "label":"Address",
1093
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1094
+ // },
1095
+ // },
1096
+ // }
1097
+ //
1098
+ const code = (currency === undefined) ? undefined : currency['code'];
1099
+ let address = this.safeString (depositAddress, 'address');
1100
+ let tag = undefined;
1101
+ if (address !== undefined) {
1102
+ const parts = address.split (':');
1103
+ address = this.safeString (parts, 0);
1104
+ tag = this.safeString (parts, 1);
1105
+ }
1106
+ this.checkAddress (address);
1107
+ return {
1108
+ 'currency': code,
1109
+ 'address': address,
1110
+ 'tag': tag,
1111
+ 'network': undefined,
1112
+ 'info': depositAddress,
1113
+ };
1114
+ }
1115
+
1116
+ async fetchDepositAddress (code, params = {}) {
1117
+ await this.loadMarkets ();
1118
+ const currency = this.currency (code);
1119
+ const request = {
1120
+ 'currency': currency['id'],
1121
+ };
1122
+ const response = await this.privatePostDepositAddressCurrency (this.extend (request, params));
1123
+ //
1124
+ // {
1125
+ // "data":{
1126
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1127
+ // "currency_status":"ok",
1128
+ // "deposit_methods":{
1129
+ // "address":{
1130
+ // "deposit_type":"address",
1131
+ // "render_type":"address",
1132
+ // "label":"Address",
1133
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1134
+ // },
1135
+ // },
1136
+ // },
1137
+ // }
1138
+ //
1139
+ const data = this.safeValue (response, 'data', {});
1140
+ return this.parseDepositAddress (data, currency);
1141
+ }
1142
+
1143
+ async fetchDeposit (id, code = undefined, params = {}) {
1144
+ await this.loadMarkets ();
1145
+ const request = {
1146
+ 'deposit_id': id,
1147
+ };
1148
+ const response = await this.privateGetDepositDepositId (this.extend (request, params));
1149
+ //
1150
+ // {
1151
+ // "data":{
1152
+ // "deposit":{
1153
+ // "id":"0xaa6e65ed274c4786e5dec3671de96f81021cacdbc453b1a133ab84356f3620a0",
1154
+ // "amount":"0.13",
1155
+ // "currency":"ETH",
1156
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1157
+ // "status":"credited",
1158
+ // "relay_status":"",
1159
+ // "network_data":{
1160
+ // "confirms":87,
1161
+ // "sweep_txid":"0xa16e65ed274d4686e5dec3671de96f81021cacdbc453b1a133ab85356f3630a0",
1162
+ // "sweep_balance":"0.150000000000000000",
1163
+ // "confirms_required":80,
1164
+ // "unsigned_sweep_tx":{
1165
+ // "chainId":1,
1166
+ // "from":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1167
+ // "gas":"0x5208",
1168
+ // "gasPrice":"0x19b45a500",
1169
+ // "nonce":"0x0",
1170
+ // "to":"0x76Cd80202a2C31e9D8F595a31ed071CE7F75BB93",
1171
+ // "value":"0x214646b6347d800"
1172
+ // },
1173
+ // "txid":"0xaa6e65ed274c4786e5dec3671de96f81021cacdbc453b1a133ab84356f3620a0",
1174
+ // "tx_index":"0x6f",
1175
+ // "tx_value":"0.130000000000000000",
1176
+ // "key_index":311,
1177
+ // "blockheight":9877869,
1178
+ // "signed_sweep_tx":{
1179
+ // "hash":"0xa16e65ed274d4686e5dec3671de96f81021cacdbc453b1a133ab85356f3630a0",
1180
+ // "rawTransaction":"0xd86c8085019b45a1008252099476cb80202b2c31e9d7f595a31fd071ce7f75bb93880214646b6347d8008046a08c6e3bfe8b25bff2b6851c87ea17c63d7b23591210ab0779a568eaa43dc40435a030e964bb2b667072ea7cbc8ab554403e3f3ead9b554743f2fdc2b1e06e998df9"
1181
+ // },
1182
+ // "estimated_sweep_tx_fee":144900000000000
1183
+ // },
1184
+ // "created_at":"2020-05-04T05:38:42.145162Z"
1185
+ // }
1186
+ // }
1187
+ // }
1188
+ const data = this.safeValue (response, 'data', {});
1189
+ const deposit = this.safeValue (data, 'deposit', {});
1190
+ return this.parseTransaction (deposit);
1191
+ }
1192
+
1193
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
1194
+ await this.loadMarkets ();
1195
+ let currency = undefined;
1196
+ if (code !== undefined) {
1197
+ currency = this.currency (code);
1198
+ }
1199
+ const response = await this.privateGetDeposits (params);
1200
+ //
1201
+ // {
1202
+ // "data":{
1203
+ // "deposits":[
1204
+ // {
1205
+ // "id":"0xaa6e65ed274c4786e5dec3671de96f81021cacdbc453b1a133ab84356f3620a0",
1206
+ // "amount":"0.13",
1207
+ // "currency":"ETH",
1208
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1209
+ // "status":"credited",
1210
+ // "relay_status":"",
1211
+ // "network_data":{
1212
+ // "confirms":87,
1213
+ // "sweep_txid":"0xa16e65ed274d4686e5dec3671de96f81021cacdbc453b1a133ab85356f3630a0",
1214
+ // "sweep_balance":"0.150000000000000000",
1215
+ // "confirms_required":80,
1216
+ // "unsigned_sweep_tx":{
1217
+ // "chainId":1,
1218
+ // "from":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1219
+ // "gas":"0x5208",
1220
+ // "gasPrice":"0x19b45a500",
1221
+ // "nonce":"0x0",
1222
+ // "to":"0x76Cd80202a2C31e9D8F595a31ed071CE7F75BB93",
1223
+ // "value":"0x214646b6347d800"
1224
+ // },
1225
+ // "txid":"0xaa6e65ed274c4786e5dec3671de96f81021cacdbc453b1a133ab84356f3620a0",
1226
+ // "tx_index":"0x6f",
1227
+ // "tx_value":"0.130000000000000000",
1228
+ // "key_index":311,
1229
+ // "blockheight":9877869,
1230
+ // "signed_sweep_tx":{
1231
+ // "hash":"0xa16e65ed274d4686e5dec3671de96f81021cacdbc453b1a133ab85356f3630a0",
1232
+ // "rawTransaction":"0xd86c8085019b45a1008252099476cb80202b2c31e9d7f595a31fd071ce7f75bb93880214646b6347d8008046a08c6e3bfe8b25bff2b6851c87ea17c63d7b23591210ab0779a568eaa43dc40435a030e964bb2b667072ea7cbc8ab554403e3f3ead9b554743f2fdc2b1e06e998df9"
1233
+ // },
1234
+ // "estimated_sweep_tx_fee":144900000000000
1235
+ // },
1236
+ // "created_at":"2020-05-04T05:38:42.145162Z"
1237
+ // }
1238
+ // ]
1239
+ // }
1240
+ // }
1241
+ //
1242
+ const data = this.safeValue (response, 'data', {});
1243
+ const deposits = this.safeValue (data, 'deposits', []);
1244
+ return this.parseTransactions (deposits, currency, since, limit);
1245
+ }
1246
+
1247
+ async fetchWithdrawal (id, code = undefined, params = {}) {
1248
+ await this.loadMarkets ();
1249
+ const request = {
1250
+ 'withdraw_id': id,
1251
+ };
1252
+ const response = await this.privateGetWithdrawWithdrawId (this.extend (request, params));
1253
+ //
1254
+ // {
1255
+ // data: {
1256
+ // withdraw: {
1257
+ // "id":25524,
1258
+ // "amount":"0.0417463053014",
1259
+ // "user_id":0,
1260
+ // "currency":"ETH",
1261
+ // "network_data":{
1262
+ // "unsigned_tx":{
1263
+ // "chainId":1,
1264
+ // "from":"0x76Cd80202a2C31e9D8F595a31ed071CE7F75BB93",
1265
+ // "gas":"0x5208",
1266
+ // "gasPrice":"0x20c8558e9",
1267
+ // "nonce":"0xf3",
1268
+ // "to":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1269
+ // "value":"0x71712bcd113308"
1270
+ // },
1271
+ // "estimated_tx_fee":184800004893000,
1272
+ // "confirms_required":80,
1273
+ // "txid":"0x79439b62473d61d99ce1dc6c3b8a417da36d45323a394bb0d4af870608fef38d",
1274
+ // "confirms":83,
1275
+ // "signed_tx":{
1276
+ // "hash":"0x79439b62473d61d99ce1dc6c3b8a417da36d45323a394bb0d4af870608fef38d",
1277
+ // "rawTransaction":"0xf86c81f385021c8558e98252089401b0a9b7b4cde774af0f3e87cb4f1c2ccdba08068771712acd1133078025a0088157d119d924d47413c81b91b9f18ff148623a2ef13dab1895ca3ba546b771a046a021b1e1f64d1a60bb66c19231f641b352326188a9ed3b931b698a939f78d0"
1278
+ // }
1279
+ // },
1280
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1281
+ // "status":"confirmed",
1282
+ // "relay_status":"",
1283
+ // "created_at":"2020-05-05T06:32:19.907061Z",
1284
+ // "cancel_requested":false
1285
+ // }
1286
+ // }
1287
+ // }
1288
+ //
1289
+ const data = this.safeValue (response, 'data', {});
1290
+ const withdrawal = this.safeValue (data, 'withdraw', {});
1291
+ return this.parseTransaction (withdrawal);
1292
+ }
1293
+
1294
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
1295
+ await this.loadMarkets ();
1296
+ let currency = undefined;
1297
+ if (code !== undefined) {
1298
+ currency = this.currency (code);
1299
+ }
1300
+ const response = await this.privateGetWithdraws (params);
1301
+ // {
1302
+ // "data":{
1303
+ // "withdraws":[
1304
+ // {
1305
+ // "id":25524,
1306
+ // "amount":"0.0417463053014",
1307
+ // "user_id":0,
1308
+ // "currency":"ETH",
1309
+ // "network_data":{
1310
+ // "unsigned_tx":{
1311
+ // "chainId":1,
1312
+ // "from":"0x76Cd80202a2C31e9D8F595a31ed071CE7F75BB93",
1313
+ // "gas":"0x5208",
1314
+ // "gasPrice":"0x20c8558e9",
1315
+ // "nonce":"0xf3",
1316
+ // "to":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1317
+ // "value":"0x71712bcd113308"
1318
+ // },
1319
+ // "estimated_tx_fee":184800004893000,
1320
+ // "confirms_required":80,
1321
+ // "txid":"0x79439b62473d61d99ce1dc6c3b8a417da36d45323a394bb0d4af870608fef38d",
1322
+ // "confirms":83,
1323
+ // "signed_tx":{
1324
+ // "hash":"0x79439b62473d61d99ce1dc6c3b8a417da36d45323a394bb0d4af870608fef38d",
1325
+ // "rawTransaction":"0xf86c81f385021c8558e98252089401b0a9b7b4cde774af0f3e87cb4f1c2ccdba08068771712acd1133078025a0088157d119d924d47413c81b91b9f18ff148623a2ef13dab1895ca3ba546b771a046a021b1e1f64d1a60bb66c19231f641b352326188a9ed3b931b698a939f78d0"
1326
+ // }
1327
+ // },
1328
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1329
+ // "status":"confirmed",
1330
+ // "relay_status":"",
1331
+ // "created_at":"2020-05-05T06:32:19.907061Z",
1332
+ // "cancel_requested":false
1333
+ // }
1334
+ // ]
1335
+ // }
1336
+ // }
1337
+ //
1338
+ const data = this.safeValue (response, 'data', {});
1339
+ const withdrawals = this.safeValue (data, 'withdraws', []);
1340
+ return this.parseTransactions (withdrawals, currency, since, limit);
1341
+ }
1342
+
1343
+ parseTransaction (transaction, currency = undefined) {
1344
+ //
1345
+ // fetchDeposits, fetchDeposit
1346
+ //
1347
+ // {
1348
+ // "id":"0xaa6e65ed274c4786e5dec3671de96f81021cacdbc453b1a133ab84356f3620a0",
1349
+ // "amount":"0.13",
1350
+ // "currency":"ETH",
1351
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1352
+ // "status":"credited",
1353
+ // "relay_status":"",
1354
+ // "network_data":{
1355
+ // "confirms":87,
1356
+ // "sweep_txid":"0xa16e65ed274d4686e5dec3671de96f81021cacdbc453b1a133ab85356f3630a0",
1357
+ // "sweep_balance":"0.150000000000000000",
1358
+ // "confirms_required":80,
1359
+ // "unsigned_sweep_tx":{
1360
+ // "chainId":1,
1361
+ // "from":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1362
+ // "gas":"0x5208",
1363
+ // "gasPrice":"0x19b45a500",
1364
+ // "nonce":"0x0",
1365
+ // "to":"0x76Cd80202a2C31e9D8F595a31ed071CE7F75BB93",
1366
+ // "value":"0x214646b6347d800"
1367
+ // },
1368
+ // "txid":"0xaa6e65ed274c4786e5dec3671de96f81021cacdbc453b1a133ab84356f3620a0",
1369
+ // "tx_index":"0x6f",
1370
+ // "tx_value":"0.130000000000000000",
1371
+ // "key_index":311,
1372
+ // "blockheight":9877869,
1373
+ // "signed_sweep_tx":{
1374
+ // "hash":"0xa16e65ed274d4686e5dec3671de96f81021cacdbc453b1a133ab85356f3630a0",
1375
+ // "rawTransaction":"0xd86c8085019b45a1008252099476cb80202b2c31e9d7f595a31fd071ce7f75bb93880214646b6347d8008046a08c6e3bfe8b25bff2b6851c87ea17c63d7b23591210ab0779a568eaa43dc40435a030e964bb2b667072ea7cbc8ab554403e3f3ead9b554743f2fdc2b1e06e998df9"
1376
+ // },
1377
+ // "estimated_sweep_tx_fee":144900000000000
1378
+ // },
1379
+ // "created_at":"2020-05-04T05:38:42.145162Z"
1380
+ // }
1381
+ //
1382
+ // fetchWithdrawals, fetchWithdrawal
1383
+ //
1384
+ // {
1385
+ // "id":25524,
1386
+ // "amount":"0.0417463053014",
1387
+ // "user_id":0,
1388
+ // "currency":"ETH",
1389
+ // "network_data":{
1390
+ // "unsigned_tx":{
1391
+ // "chainId":1,
1392
+ // "from":"0x76Cd80202a2C31e9D8F595a31ed071CE7F75BB93",
1393
+ // "gas":"0x5208",
1394
+ // "gasPrice":"0x20c8558e9",
1395
+ // "nonce":"0xf3",
1396
+ // "to":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1397
+ // "value":"0x71712bcd113308"
1398
+ // },
1399
+ // "estimated_tx_fee":184800004893000,
1400
+ // "confirms_required":80,
1401
+ // "txid":"0x79439b62473d61d99ce1dc6c3b8a417da36d45323a394bb0d4af870608fef38d",
1402
+ // "confirms":83,
1403
+ // "signed_tx":{
1404
+ // "hash":"0x79439b62473d61d99ce1dc6c3b8a417da36d45323a394bb0d4af870608fef38d",
1405
+ // "rawTransaction":"0xf86c81f385021c8558e98252089401b0a9b7b4cde774af0f3e87cb4f1c2ccdba08068771712acd1133078025a0088157d119d924d47413c81b91b9f18ff148623a2ef13dab1895ca3ba546b771a046a021b1e1f64d1a60bb66c19231f641b352326188a9ed3b931b698a939f78d0"
1406
+ // }
1407
+ // },
1408
+ // "address":"0xe0cd26f9A60118555247aE6769A5d241D91f07f2",
1409
+ // "status":"confirmed",
1410
+ // "relay_status":"",
1411
+ // "created_at":"2020-05-05T06:32:19.907061Z",
1412
+ // "cancel_requested":false
1413
+ // }
1414
+ //
1415
+ // withdraw
1416
+ //
1417
+ // {
1418
+ // "code": "initiated",
1419
+ // "id": 3,
1420
+ // "result": "Withdraw initiated. Please allow 3-5 minutes for our system to process."
1421
+ // }
1422
+ //
1423
+ const timestamp = this.parse8601 (this.safeString (transaction, 'created_at'));
1424
+ const id = this.safeString (transaction, 'id');
1425
+ const networkData = this.safeValue (transaction, 'network_data', {});
1426
+ const unsignedTx = this.safeValue (networkData, 'unsigned_tx', {});
1427
+ const addressFrom = this.safeString (unsignedTx, 'from');
1428
+ const txid = this.safeString (networkData, 'txid');
1429
+ let address = this.safeString (transaction, 'address');
1430
+ let tag = undefined;
1431
+ if (address !== undefined) {
1432
+ const parts = address.split (':');
1433
+ const numParts = parts.length;
1434
+ if (numParts > 1) {
1435
+ address = this.safeString (parts, 0);
1436
+ tag = this.safeString (parts, 1);
1437
+ }
1438
+ }
1439
+ const addressTo = address;
1440
+ const tagFrom = undefined;
1441
+ const tagTo = tag;
1442
+ const cancelRequested = this.safeValue (transaction, 'cancel_requested');
1443
+ const type = (cancelRequested === undefined) ? 'deposit' : 'withdrawal';
1444
+ const amount = this.safeNumber (transaction, 'amount');
1445
+ const currencyId = this.safeString (transaction, 'currency');
1446
+ const code = this.safeCurrencyCode (currencyId);
1447
+ let status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
1448
+ const statusCode = this.safeString (transaction, 'code');
1449
+ if (cancelRequested) {
1450
+ status = 'canceled';
1451
+ } else if (status === undefined) {
1452
+ status = this.parseTransactionStatus (statusCode);
1453
+ }
1454
+ const fee = undefined;
1455
+ return {
1456
+ 'info': transaction,
1457
+ 'id': id,
1458
+ 'txid': txid,
1459
+ 'timestamp': timestamp,
1460
+ 'datetime': this.iso8601 (timestamp),
1461
+ 'network': undefined,
1462
+ 'addressFrom': addressFrom,
1463
+ 'addressTo': addressTo,
1464
+ 'address': address,
1465
+ 'tagFrom': tagFrom,
1466
+ 'tagTo': tagTo,
1467
+ 'tag': tag,
1468
+ 'type': type,
1469
+ 'amount': amount,
1470
+ 'currency': code,
1471
+ 'status': status,
1472
+ 'updated': undefined,
1473
+ 'fee': fee,
1474
+ };
1475
+ }
1476
+
1477
+ parseTransactionStatus (status) {
1478
+ const statuses = {
1479
+ 'initiated': 'pending',
1480
+ 'needs_create': 'pending',
1481
+ 'credited': 'ok',
1482
+ 'confirmed': 'ok',
1483
+ };
1484
+ return this.safeString (statuses, status, status);
1485
+ }
1486
+
1487
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1488
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1489
+ await this.loadMarkets ();
1490
+ const currency = this.currency (code);
1491
+ const request = {
1492
+ 'address': address,
1493
+ 'amount': amount,
1494
+ 'currency': currency['id'],
1495
+ };
1496
+ if (tag !== undefined) {
1497
+ request['address'] += ':' + tag;
1498
+ }
1499
+ const response = await this.privatePostWithdraw (this.extend (request, params));
1500
+ //
1501
+ // {
1502
+ // "data": {
1503
+ // "code": "initiated",
1504
+ // "id": 3,
1505
+ // "result": "Withdraw initiated. Please allow 3-5 minutes for our system to process."
1506
+ // }
1507
+ // }
1508
+ //
1509
+ const data = this.safeValue (response, 'data', {});
1510
+ const result = this.parseTransaction (data);
1511
+ return this.extend (result, {
1512
+ 'currency': code,
1513
+ 'address': address,
1514
+ 'addressTo': address,
1515
+ 'tag': tag,
1516
+ 'tagTo': tag,
1517
+ 'amount': amount,
1518
+ });
1519
+ }
1520
+
1521
+ nonce () {
1522
+ return this.milliseconds ();
1523
+ }
1524
+
1525
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1526
+ let url = '/' + this.version + '/';
1527
+ if (api === 'private') {
1528
+ url += 'user/';
1529
+ }
1530
+ url += this.implodeParams (path, params);
1531
+ const request = this.omit (params, this.extractParams (path));
1532
+ if (method === 'POST') {
1533
+ body = this.json (request);
1534
+ } else {
1535
+ if (Object.keys (request).length) {
1536
+ url += '?' + this.urlencode (request);
1537
+ }
1538
+ }
1539
+ if (api === 'private') {
1540
+ const timestamp = this.milliseconds ().toString ();
1541
+ const bodyAsString = (method === 'POST') ? body : '';
1542
+ const auth = [
1543
+ method,
1544
+ url,
1545
+ timestamp,
1546
+ bodyAsString,
1547
+ this.secret,
1548
+ ].join ("\n"); // eslint-disable-line quotes
1549
+ const hash = this.hash (this.encode (auth), 'sha256', 'base64');
1550
+ let key = this.apiKey;
1551
+ if (typeof key !== 'string') {
1552
+ key = key.toString ();
1553
+ }
1554
+ const signature = 'HMAC-SHA256 ' + key + ':' + hash;
1555
+ headers = {
1556
+ 'Authorization': signature,
1557
+ 'HMAC-Timestamp': timestamp,
1558
+ };
1559
+ if (method === 'POST') {
1560
+ headers['Content-Type'] = 'application/json';
1561
+ }
1562
+ }
1563
+ url = this.urls['api'] + url;
1564
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1565
+ }
1566
+
1567
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1568
+ //
1569
+ // {"errors":[{"code":"insuff_funds","title":"Your available balance is too low for that action"}]}
1570
+ // {"errors":[{"code": "invalid_auth","title": "Invalid HMAC signature"}]}
1571
+ //
1572
+ if (response === undefined) {
1573
+ return;
1574
+ }
1575
+ const errors = this.safeValue (response, 'errors', []);
1576
+ const numErrors = errors.length;
1577
+ if (numErrors < 1) {
1578
+ return;
1579
+ }
1580
+ const feedback = this.id + ' ' + body;
1581
+ for (let i = 0; i < errors.length; i++) {
1582
+ const error = errors[i];
1583
+ const errorCode = this.safeString (error, 'code');
1584
+ this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
1585
+ }
1586
+ throw new ExchangeError (feedback); // unknown message
1587
+ }
1588
+ };