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/bittrex.js ADDED
@@ -0,0 +1,1876 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ArgumentsRequired, BadSymbol, ExchangeError, ExchangeNotAvailable, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound, DDoSProtection, PermissionDenied, AddressPending, OnMaintenance, BadRequest, InvalidAddress } = require ('./base/errors');
7
+ const { TRUNCATE, DECIMAL_PLACES } = require ('./base/functions/number');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class bittrex extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'bittrex',
15
+ 'name': 'Bittrex',
16
+ 'countries': [ 'US' ],
17
+ 'version': 'v3',
18
+ 'rateLimit': 1500,
19
+ 'certified': false,
20
+ 'pro': true,
21
+ // new metainfo interface
22
+ 'has': {
23
+ 'CORS': undefined,
24
+ 'spot': true,
25
+ 'margin': false,
26
+ 'swap': false,
27
+ 'future': false,
28
+ 'option': false,
29
+ 'addMargin': false,
30
+ 'cancelAllOrders': true,
31
+ 'cancelOrder': true,
32
+ 'createDepositAddress': true,
33
+ 'createMarketOrder': true,
34
+ 'createOrder': true,
35
+ 'createReduceOnlyOrder': false,
36
+ 'createStopLimitOrder': true,
37
+ 'createStopMarketOrder': true,
38
+ 'createStopOrder': true,
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
+ 'fetchDepositAddress': true,
48
+ 'fetchDeposits': true,
49
+ 'fetchFundingFees': undefined,
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': 'emulated',
60
+ 'fetchOHLCV': true,
61
+ 'fetchOpenOrders': true,
62
+ 'fetchOrder': true,
63
+ 'fetchOrderBook': true,
64
+ 'fetchOrderTrades': true,
65
+ 'fetchPosition': false,
66
+ 'fetchPositions': false,
67
+ 'fetchPositionsRisk': false,
68
+ 'fetchPremiumIndexOHLCV': false,
69
+ 'fetchTicker': true,
70
+ 'fetchTickers': true,
71
+ 'fetchTime': true,
72
+ 'fetchTrades': true,
73
+ 'fetchTradingFee': true,
74
+ 'fetchTradingFees': true,
75
+ 'fetchTransactions': undefined,
76
+ 'fetchWithdrawals': true,
77
+ 'reduceMargin': false,
78
+ 'setLeverage': false,
79
+ 'setMarginMode': false,
80
+ 'setPositionMode': false,
81
+ 'withdraw': true,
82
+ },
83
+ 'timeframes': {
84
+ '1m': 'MINUTE_1',
85
+ '5m': 'MINUTE_5',
86
+ '1h': 'HOUR_1',
87
+ '1d': 'DAY_1',
88
+ },
89
+ 'hostname': 'bittrex.com',
90
+ 'urls': {
91
+ 'logo': 'https://user-images.githubusercontent.com/51840849/87153921-edf53180-c2c0-11ea-96b9-f2a9a95a455b.jpg',
92
+ 'api': {
93
+ 'public': 'https://api.bittrex.com',
94
+ 'private': 'https://api.bittrex.com',
95
+ },
96
+ 'www': 'https://bittrex.com',
97
+ 'doc': [
98
+ 'https://bittrex.github.io/api/v3',
99
+ ],
100
+ 'fees': [
101
+ 'https://bittrex.zendesk.com/hc/en-us/articles/115003684371-BITTREX-SERVICE-FEES-AND-WITHDRAWAL-LIMITATIONS',
102
+ 'https://bittrex.zendesk.com/hc/en-us/articles/115000199651-What-fees-does-Bittrex-charge-',
103
+ ],
104
+ 'referral': 'https://bittrex.com/Account/Register?referralCode=1ZE-G0G-M3B',
105
+ },
106
+ 'api': {
107
+ 'public': {
108
+ 'get': [
109
+ 'ping',
110
+ 'currencies',
111
+ 'currencies/{symbol}',
112
+ 'markets',
113
+ 'markets/tickers',
114
+ 'markets/summaries',
115
+ 'markets/{marketSymbol}',
116
+ 'markets/{marketSymbol}/summary',
117
+ 'markets/{marketSymbol}/orderbook',
118
+ 'markets/{marketSymbol}/trades',
119
+ 'markets/{marketSymbol}/ticker',
120
+ 'markets/{marketSymbol}/candles/{candleInterval}/recent',
121
+ 'markets/{marketSymbol}/candles/{candleInterval}/historical/{year}/{month}/{day}',
122
+ 'markets/{marketSymbol}/candles/{candleInterval}/historical/{year}/{month}',
123
+ 'markets/{marketSymbol}/candles/{candleInterval}/historical/{year}',
124
+ ],
125
+ },
126
+ 'private': {
127
+ 'get': [
128
+ 'account',
129
+ 'account/fees/fiat',
130
+ 'account/fees/fiat/{currencySymbol}',
131
+ 'account/fees/trading',
132
+ 'account/fees/trading/{marketSymbol}',
133
+ 'account/volume',
134
+ 'addresses',
135
+ 'addresses/{currencySymbol}',
136
+ 'balances',
137
+ 'balances/{currencySymbol}',
138
+ 'deposits/open',
139
+ 'deposits/closed',
140
+ 'deposits/ByTxId/{txId}',
141
+ 'deposits/{depositId}',
142
+ 'orders/closed',
143
+ 'orders/open',
144
+ 'orders/{orderId}',
145
+ 'orders/{orderId}/executions',
146
+ 'ping',
147
+ 'subaccounts/{subaccountId}',
148
+ 'subaccounts',
149
+ 'withdrawals/open',
150
+ 'withdrawals/closed',
151
+ 'withdrawals/ByTxId/{txId}',
152
+ 'withdrawals/{withdrawalId}',
153
+ 'withdrawals/whitelistAddresses',
154
+ 'conditional-orders/{conditionalOrderId}',
155
+ 'conditional-orders/closed',
156
+ 'conditional-orders/open',
157
+ 'transfers/sent',
158
+ 'transfers/received',
159
+ 'transfers/{transferId}',
160
+ ],
161
+ 'post': [
162
+ 'addresses',
163
+ 'orders',
164
+ 'subaccounts',
165
+ 'withdrawals',
166
+ 'conditional-orders',
167
+ 'transfers',
168
+ ],
169
+ 'delete': [
170
+ 'orders/open',
171
+ 'orders/{orderId}',
172
+ 'withdrawals/{withdrawalId}',
173
+ 'conditional-orders/{conditionalOrderId}',
174
+ ],
175
+ },
176
+ },
177
+ 'fees': {
178
+ 'trading': {
179
+ 'tierBased': true,
180
+ 'percentage': true,
181
+ 'maker': this.parseNumber ('0.0075'),
182
+ 'taker': this.parseNumber ('0.0075'),
183
+ },
184
+ 'funding': {
185
+ 'tierBased': false,
186
+ 'percentage': false,
187
+ },
188
+ },
189
+ 'exceptions': {
190
+ 'exact': {
191
+ 'BAD_REQUEST': BadRequest, // {"code":"BAD_REQUEST","detail":"Refer to the data field for specific field validation failures.","data":{"invalidRequestParameter":"day"}}
192
+ 'STARTDATE_OUT_OF_RANGE': BadRequest, // {"code":"STARTDATE_OUT_OF_RANGE"}
193
+ // 'Call to Cancel was throttled. Try again in 60 seconds.': DDoSProtection,
194
+ // 'Call to GetBalances was throttled. Try again in 60 seconds.': DDoSProtection,
195
+ 'APISIGN_NOT_PROVIDED': AuthenticationError,
196
+ 'APIKEY_INVALID': AuthenticationError,
197
+ 'INVALID_SIGNATURE': AuthenticationError,
198
+ 'INVALID_CURRENCY': ExchangeError,
199
+ 'INVALID_PERMISSION': AuthenticationError,
200
+ 'INSUFFICIENT_FUNDS': InsufficientFunds,
201
+ 'INVALID_CEILING_MARKET_BUY': InvalidOrder,
202
+ 'INVALID_FIAT_ACCOUNT': InvalidOrder,
203
+ 'INVALID_ORDER_TYPE': InvalidOrder,
204
+ 'QUANTITY_NOT_PROVIDED': InvalidOrder,
205
+ 'MIN_TRADE_REQUIREMENT_NOT_MET': InvalidOrder,
206
+ 'NOT_FOUND': OrderNotFound,
207
+ 'ORDER_NOT_OPEN': OrderNotFound,
208
+ 'INVALID_ORDER': InvalidOrder,
209
+ 'UUID_INVALID': OrderNotFound,
210
+ 'RATE_NOT_PROVIDED': InvalidOrder, // createLimitBuyOrder ('ETH/BTC', 1, 0)
211
+ 'INVALID_MARKET': BadSymbol, // {"success":false,"message":"INVALID_MARKET","result":null,"explanation":null}
212
+ 'WHITELIST_VIOLATION_IP': PermissionDenied,
213
+ 'DUST_TRADE_DISALLOWED_MIN_VALUE': InvalidOrder,
214
+ 'RESTRICTED_MARKET': BadSymbol,
215
+ 'We are down for scheduled maintenance, but we\u2019ll be back up shortly.': OnMaintenance, // {"success":false,"message":"We are down for scheduled maintenance, but we\u2019ll be back up shortly.","result":null,"explanation":null}
216
+ },
217
+ 'broad': {
218
+ 'throttled': DDoSProtection,
219
+ 'problem': ExchangeNotAvailable,
220
+ },
221
+ },
222
+ 'options': {
223
+ 'fetchTicker': {
224
+ 'method': 'publicGetMarketsMarketSymbolTicker', // publicGetMarketsMarketSymbolSummary
225
+ },
226
+ 'fetchTickers': {
227
+ 'method': 'publicGetMarketsTickers', // publicGetMarketsSummaries
228
+ },
229
+ 'parseOrderStatus': false,
230
+ 'hasAlreadyAuthenticatedSuccessfully': false, // a workaround for APIKEY_INVALID
231
+ // With certain currencies, like
232
+ // AEON, BTS, GXS, NXT, SBD, STEEM, STR, XEM, XLM, XMR, XRP
233
+ // an additional tag / memo / payment id is usually required by exchanges.
234
+ // With Bittrex some currencies imply the "base address + tag" logic.
235
+ // The base address for depositing is stored on this.currencies[code]
236
+ // The base address identifies the exchange as the recipient
237
+ // while the tag identifies the user account within the exchange
238
+ // and the tag is retrieved with fetchDepositAddress.
239
+ 'tag': {
240
+ 'NXT': true, // NXT, BURST
241
+ 'CRYPTO_NOTE_PAYMENTID': true, // AEON, XMR
242
+ 'BITSHAREX': true, // BTS
243
+ 'RIPPLE': true, // XRP
244
+ 'NEM': true, // XEM
245
+ 'STELLAR': true, // XLM
246
+ 'STEEM': true, // SBD, GOLOS
247
+ // https://github.com/ccxt/ccxt/issues/4794
248
+ // 'LISK': true, // LSK
249
+ },
250
+ 'subaccountId': undefined,
251
+ // see the implementation of fetchClosedOrdersV3 below
252
+ // 'fetchClosedOrdersMethod': 'fetch_closed_orders_v3',
253
+ 'fetchClosedOrdersFilterBySince': true,
254
+ // 'createOrderMethod': 'create_order_v1',
255
+ },
256
+ 'commonCurrencies': {
257
+ 'BIFI': 'Bifrost Finance',
258
+ 'BTR': 'BTRIPS',
259
+ 'GMT': 'GMT Token',
260
+ 'MEME': 'Memetic', // conflict with Meme Inu
261
+ 'MER': 'Mercury', // conflict with Mercurial Finance
262
+ 'PROS': 'Pros.Finance',
263
+ 'REPV2': 'REP',
264
+ 'TON': 'Tokamak Network',
265
+ },
266
+ });
267
+ }
268
+
269
+ costToPrecision (symbol, cost) {
270
+ return this.decimalToPrecision (cost, TRUNCATE, this.markets[symbol]['precision']['price'], DECIMAL_PLACES);
271
+ }
272
+
273
+ feeToPrecision (symbol, fee) {
274
+ return this.decimalToPrecision (fee, TRUNCATE, this.markets[symbol]['precision']['price'], DECIMAL_PLACES);
275
+ }
276
+
277
+ async fetchMarkets (params = {}) {
278
+ const response = await this.publicGetMarkets (params);
279
+ //
280
+ // [
281
+ // {
282
+ // "symbol":"LTC-BTC",
283
+ // "baseCurrencySymbol":"LTC",
284
+ // "quoteCurrencySymbol":"BTC",
285
+ // "minTradeSize":"0.01686767",
286
+ // "precision":8,
287
+ // "status":"ONLINE", // "OFFLINE"
288
+ // "createdAt":"2014-02-13T00:00:00Z"
289
+ // },
290
+ // {
291
+ // "symbol":"VDX-USDT",
292
+ // "baseCurrencySymbol":"VDX",
293
+ // "quoteCurrencySymbol":"USDT",
294
+ // "minTradeSize":"300.00000000",
295
+ // "precision":8,
296
+ // "status":"ONLINE", // "OFFLINE"
297
+ // "createdAt":"2019-05-23T00:41:21.843Z",
298
+ // "notice":"USDT has swapped to an ERC20-based token as of August 5, 2019."
299
+ // }
300
+ // ]
301
+ //
302
+ const result = [];
303
+ for (let i = 0; i < response.length; i++) {
304
+ const market = response[i];
305
+ const baseId = this.safeString (market, 'baseCurrencySymbol');
306
+ const quoteId = this.safeString (market, 'quoteCurrencySymbol');
307
+ const base = this.safeCurrencyCode (baseId);
308
+ const quote = this.safeCurrencyCode (quoteId);
309
+ const status = this.safeString (market, 'status');
310
+ result.push ({
311
+ 'id': this.safeString (market, 'symbol'),
312
+ 'symbol': base + '/' + quote,
313
+ 'base': base,
314
+ 'quote': quote,
315
+ 'settle': undefined,
316
+ 'baseId': baseId,
317
+ 'quoteId': quoteId,
318
+ 'settleId': undefined,
319
+ 'type': 'spot',
320
+ 'spot': true,
321
+ 'margin': false,
322
+ 'swap': false,
323
+ 'future': false,
324
+ 'option': false,
325
+ 'active': (status === 'ONLINE'),
326
+ 'contract': false,
327
+ 'linear': undefined,
328
+ 'inverse': undefined,
329
+ 'contractSize': undefined,
330
+ 'expiry': undefined,
331
+ 'expiryDatetime': undefined,
332
+ 'strike': undefined,
333
+ 'optionType': undefined,
334
+ 'precision': {
335
+ 'amount': parseInt ('8'),
336
+ 'price': this.safeInteger (market, 'precision', 8),
337
+ },
338
+ 'limits': {
339
+ 'leverage': {
340
+ 'min': undefined,
341
+ 'max': undefined,
342
+ },
343
+ 'amount': {
344
+ 'min': this.safeNumber (market, 'minTradeSize'),
345
+ 'max': undefined,
346
+ },
347
+ 'price': {
348
+ 'min': undefined,
349
+ 'max': undefined,
350
+ },
351
+ 'cost': {
352
+ 'min': undefined,
353
+ 'max': undefined,
354
+ },
355
+ },
356
+ 'info': market,
357
+ });
358
+ }
359
+ return result;
360
+ }
361
+
362
+ parseBalance (response) {
363
+ const result = { 'info': response };
364
+ const indexed = this.indexBy (response, 'currencySymbol');
365
+ const currencyIds = Object.keys (indexed);
366
+ for (let i = 0; i < currencyIds.length; i++) {
367
+ const currencyId = currencyIds[i];
368
+ const code = this.safeCurrencyCode (currencyId);
369
+ const account = this.account ();
370
+ const balance = indexed[currencyId];
371
+ account['free'] = this.safeString (balance, 'available');
372
+ account['total'] = this.safeString (balance, 'total');
373
+ result[code] = account;
374
+ }
375
+ return this.safeBalance (result);
376
+ }
377
+
378
+ async fetchBalance (params = {}) {
379
+ await this.loadMarkets ();
380
+ const response = await this.privateGetBalances (params);
381
+ return this.parseBalance (response);
382
+ }
383
+
384
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
385
+ await this.loadMarkets ();
386
+ const request = {
387
+ 'marketSymbol': this.marketId (symbol),
388
+ };
389
+ if (limit !== undefined) {
390
+ if ((limit !== 1) && (limit !== 25) && (limit !== 500)) {
391
+ throw new BadRequest (this.id + ' fetchOrderBook() limit argument must be undefined, 1, 25 or 500, default is 25');
392
+ }
393
+ request['depth'] = limit;
394
+ }
395
+ const response = await this.publicGetMarketsMarketSymbolOrderbook (this.extend (request, params));
396
+ //
397
+ // {
398
+ // "bid":[
399
+ // {"quantity":"0.01250000","rate":"10718.56200003"},
400
+ // {"quantity":"0.10000000","rate":"10718.56200002"},
401
+ // {"quantity":"0.39648292","rate":"10718.56200001"},
402
+ // ],
403
+ // "ask":[
404
+ // {"quantity":"0.05100000","rate":"10724.30099631"},
405
+ // {"quantity":"0.10000000","rate":"10724.30099632"},
406
+ // {"quantity":"0.26000000","rate":"10724.30099634"},
407
+ // ]
408
+ // }
409
+ //
410
+ const sequence = this.safeInteger (this.last_response_headers, 'Sequence');
411
+ const orderbook = this.parseOrderBook (response, symbol, undefined, 'bid', 'ask', 'rate', 'quantity');
412
+ orderbook['nonce'] = sequence;
413
+ return orderbook;
414
+ }
415
+
416
+ async fetchCurrencies (params = {}) {
417
+ const response = await this.publicGetCurrencies (params);
418
+ //
419
+ // [
420
+ // {
421
+ // "symbol":"1ST",
422
+ // "name":"Firstblood",
423
+ // "coinType":"ETH_CONTRACT",
424
+ // "status":"ONLINE",
425
+ // "minConfirmations":36,
426
+ // "notice":"",
427
+ // "txFee":"4.50000000",
428
+ // "logoUrl":"https://bittrexblobstorage.blob.core.windows.net/public/5685a7be-1edf-4ba0-a313-b5309bb204f8.png",
429
+ // "prohibitedIn":[],
430
+ // "baseAddress":"0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98",
431
+ // "associatedTermsOfService":[]
432
+ // }
433
+ // ]
434
+ //
435
+ const result = {};
436
+ for (let i = 0; i < response.length; i++) {
437
+ const currency = response[i];
438
+ const id = this.safeString (currency, 'symbol');
439
+ const code = this.safeCurrencyCode (id);
440
+ const precision = 8; // default precision, todo: fix "magic constants"
441
+ const fee = this.safeNumber (currency, 'txFee'); // todo: redesign
442
+ const isActive = this.safeString (currency, 'status');
443
+ result[code] = {
444
+ 'id': id,
445
+ 'code': code,
446
+ 'address': this.safeString (currency, 'baseAddress'),
447
+ 'info': currency,
448
+ 'type': this.safeString (currency, 'coinType'),
449
+ 'name': this.safeString (currency, 'name'),
450
+ 'active': (isActive === 'ONLINE'),
451
+ 'deposit': undefined,
452
+ 'withdraw': undefined,
453
+ 'fee': fee,
454
+ 'precision': precision,
455
+ 'limits': {
456
+ 'amount': {
457
+ 'min': 1 / Math.pow (10, precision),
458
+ 'max': undefined,
459
+ },
460
+ 'withdraw': {
461
+ 'min': fee,
462
+ 'max': undefined,
463
+ },
464
+ },
465
+ };
466
+ }
467
+ return result;
468
+ }
469
+
470
+ parseTicker (ticker, market = undefined) {
471
+ //
472
+ // ticker
473
+ //
474
+ // {
475
+ // "symbol":"ETH-BTC",
476
+ // "lastTradeRate":"0.03284496",
477
+ // "bidRate":"0.03284523",
478
+ // "askRate":"0.03286857"
479
+ // }
480
+ //
481
+ // summary
482
+ //
483
+ // {
484
+ // "symbol":"ETH-BTC",
485
+ // "high":"0.03369528",
486
+ // "low":"0.03282442",
487
+ // "volume":"4307.83794556",
488
+ // "quoteVolume":"143.08608869",
489
+ // "percentChange":"0.79",
490
+ // "updatedAt":"2020-09-29T07:36:57.823Z"
491
+ // }
492
+ //
493
+ const timestamp = this.parse8601 (this.safeString (ticker, 'updatedAt'));
494
+ const marketId = this.safeString (ticker, 'symbol');
495
+ market = this.safeMarket (marketId, market, '-');
496
+ const symbol = market['symbol'];
497
+ const percentage = this.safeString (ticker, 'percentChange');
498
+ const last = this.safeString (ticker, 'lastTradeRate');
499
+ return this.safeTicker ({
500
+ 'symbol': symbol,
501
+ 'timestamp': timestamp,
502
+ 'datetime': this.iso8601 (timestamp),
503
+ 'high': this.safeString (ticker, 'high'),
504
+ 'low': this.safeString (ticker, 'low'),
505
+ 'bid': this.safeString (ticker, 'bidRate'),
506
+ 'bidVolume': undefined,
507
+ 'ask': this.safeString (ticker, 'askRate'),
508
+ 'askVolume': undefined,
509
+ 'vwap': undefined,
510
+ 'open': undefined,
511
+ 'close': last,
512
+ 'last': last,
513
+ 'previousClose': undefined,
514
+ 'change': undefined,
515
+ 'percentage': percentage,
516
+ 'average': undefined,
517
+ 'baseVolume': this.safeString (ticker, 'volume'),
518
+ 'quoteVolume': this.safeString (ticker, 'quoteVolume'),
519
+ 'info': ticker,
520
+ }, market, false);
521
+ }
522
+
523
+ async fetchTickers (symbols = undefined, params = {}) {
524
+ await this.loadMarkets ();
525
+ const options = this.safeValue (this.options, 'fetchTickers', {});
526
+ const defaultMethod = this.safeString (options, 'method', 'publicGetMarketsTickers');
527
+ const method = this.safeString (params, 'method', defaultMethod);
528
+ params = this.omit (params, 'method');
529
+ const response = await this[method] (params);
530
+ //
531
+ // publicGetMarketsTickers
532
+ //
533
+ // [
534
+ // {
535
+ // "symbol":"4ART-BTC",
536
+ // "lastTradeRate":"0.00000210",
537
+ // "bidRate":"0.00000210",
538
+ // "askRate":"0.00000215"
539
+ // }
540
+ // ]
541
+ //
542
+ // publicGetMarketsSummaries
543
+ //
544
+ // [
545
+ // {
546
+ // "symbol":"4ART-BTC",
547
+ // "high":"0.00000206",
548
+ // "low":"0.00000196",
549
+ // "volume":"14871.32000233",
550
+ // "quoteVolume":"0.02932756",
551
+ // "percentChange":"1.48",
552
+ // "updatedAt":"2020-09-29T07:34:32.757Z"
553
+ // }
554
+ // ]
555
+ //
556
+ const tickers = [];
557
+ for (let i = 0; i < response.length; i++) {
558
+ const ticker = this.parseTicker (response[i]);
559
+ tickers.push (ticker);
560
+ }
561
+ return this.filterByArray (tickers, 'symbol', symbols);
562
+ }
563
+
564
+ async fetchTicker (symbol, params = {}) {
565
+ await this.loadMarkets ();
566
+ const market = this.market (symbol);
567
+ const request = {
568
+ 'marketSymbol': market['id'],
569
+ };
570
+ const options = this.safeValue (this.options, 'fetchTicker', {});
571
+ const defaultMethod = this.safeString (options, 'method', 'publicGetMarketsMarketSymbolTicker');
572
+ const method = this.safeString (params, 'method', defaultMethod);
573
+ params = this.omit (params, 'method');
574
+ const response = await this[method] (this.extend (request, params));
575
+ //
576
+ // publicGetMarketsMarketSymbolTicker
577
+ //
578
+ // {
579
+ // "symbol":"ETH-BTC",
580
+ // "lastTradeRate":"0.03284496",
581
+ // "bidRate":"0.03284523",
582
+ // "askRate":"0.03286857"
583
+ // }
584
+ //
585
+ //
586
+ // publicGetMarketsMarketSymbolSummary
587
+ //
588
+ // {
589
+ // "symbol":"ETH-BTC",
590
+ // "high":"0.03369528",
591
+ // "low":"0.03282442",
592
+ // "volume":"4307.83794556",
593
+ // "quoteVolume":"143.08608869",
594
+ // "percentChange":"0.79",
595
+ // "updatedAt":"2020-09-29T07:36:57.823Z"
596
+ // }
597
+ //
598
+ return this.parseTicker (response, market);
599
+ }
600
+
601
+ parseTrade (trade, market = undefined) {
602
+ //
603
+ // public fetchTrades
604
+ //
605
+ // {
606
+ // "id": "8a614d4e-e455-45b0-9aac-502b0aeb433f",
607
+ // "executedAt": "2021-11-25T14:54:44.65Z",
608
+ // "quantity": "30.00000000",
609
+ // "rate": "1.72923112",
610
+ // "takerSide": "SELL"
611
+ // }
612
+ //
613
+ // private fetchOrderTrades
614
+ // {
615
+ // "id": "8a614d4e-e455-45b0-9aac-502b0aeb433f",
616
+ // "marketSymbol": "ADA-USDT",
617
+ // "executedAt": "2021-11-25T14:54:44.65Z",
618
+ // "quantity": "30.00000000",
619
+ // "rate": "1.72923112",
620
+ // "orderId": "6f7abf18-6901-4659-a48c-db0e88440ea4",
621
+ // "commission": "0.38907700",
622
+ // "isTaker": true
623
+ // }
624
+ //
625
+ const timestamp = this.parse8601 (this.safeString (trade, 'executedAt'));
626
+ const id = this.safeString (trade, 'id');
627
+ const order = this.safeString (trade, 'orderId');
628
+ const marketId = this.safeString (trade, 'marketSymbol');
629
+ market = this.safeMarket (marketId, market, '-');
630
+ const priceString = this.safeString (trade, 'rate');
631
+ const amountString = this.safeString (trade, 'quantity');
632
+ let takerOrMaker = undefined;
633
+ const isTaker = this.safeValue (trade, 'isTaker');
634
+ if (isTaker !== undefined) {
635
+ takerOrMaker = isTaker ? 'taker' : 'maker';
636
+ }
637
+ let fee = undefined;
638
+ const feeCostString = this.safeString (trade, 'commission');
639
+ if (feeCostString !== undefined) {
640
+ fee = {
641
+ 'cost': feeCostString,
642
+ 'currency': market['quote'],
643
+ };
644
+ }
645
+ const side = this.safeStringLower (trade, 'takerSide');
646
+ return this.safeTrade ({
647
+ 'info': trade,
648
+ 'timestamp': timestamp,
649
+ 'datetime': this.iso8601 (timestamp),
650
+ 'symbol': market['symbol'],
651
+ 'id': id,
652
+ 'order': order,
653
+ 'takerOrMaker': takerOrMaker,
654
+ 'type': undefined,
655
+ 'side': side,
656
+ 'price': priceString,
657
+ 'amount': amountString,
658
+ 'cost': undefined,
659
+ 'fee': fee,
660
+ }, market);
661
+ }
662
+
663
+ async fetchTime (params = {}) {
664
+ const response = await this.publicGetPing (params);
665
+ //
666
+ // {
667
+ // "serverTime": 1594596023162
668
+ // }
669
+ //
670
+ return this.safeInteger (response, 'serverTime');
671
+ }
672
+
673
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
674
+ await this.loadMarkets ();
675
+ const market = this.market (symbol);
676
+ const request = {
677
+ 'marketSymbol': this.marketId (symbol),
678
+ };
679
+ const response = await this.publicGetMarketsMarketSymbolTrades (this.extend (request, params));
680
+ //
681
+ // [
682
+ // {
683
+ // "id":"9c5589db-42fb-436c-b105-5e2edcb95673",
684
+ // "executedAt":"2020-10-03T11:48:43.38Z",
685
+ // "quantity":"0.17939626",
686
+ // "rate":"0.03297952",
687
+ // "takerSide":"BUY"
688
+ // }
689
+ // ]
690
+ //
691
+ return this.parseTrades (response, market, since, limit);
692
+ }
693
+
694
+ async fetchTradingFee (symbol, params = {}) {
695
+ await this.loadMarkets ();
696
+ const market = this.market (symbol);
697
+ const request = {
698
+ 'marketSymbol': market['id'],
699
+ };
700
+ const response = await this.privateGetAccountFeesTradingMarketSymbol (this.extend (request, params));
701
+ //
702
+ // {
703
+ // "marketSymbol":"1INCH-ETH",
704
+ // "makerRate":"0.00750000",
705
+ // "takerRate":"0.00750000"
706
+ // }
707
+ //
708
+ return this.parseTradingFee (response, market);
709
+ }
710
+
711
+ async fetchTradingFees (params = {}) {
712
+ await this.loadMarkets ();
713
+ const response = await this.privateGetAccountFeesTrading (params);
714
+ //
715
+ // [
716
+ // {"marketSymbol":"1ECO-BTC","makerRate":"0.00750000","takerRate":"0.00750000"},
717
+ // {"marketSymbol":"1ECO-USDT","makerRate":"0.00750000","takerRate":"0.00750000"},
718
+ // {"marketSymbol":"1INCH-BTC","makerRate":"0.00750000","takerRate":"0.00750000"},
719
+ // {"marketSymbol":"1INCH-ETH","makerRate":"0.00750000","takerRate":"0.00750000"},
720
+ // {"marketSymbol":"1INCH-USD","makerRate":"0.00750000","takerRate":"0.00750000"},
721
+ // ]
722
+ //
723
+ return this.parseTradingFees (response);
724
+ }
725
+
726
+ parseTradingFee (fee, market = undefined) {
727
+ const marketId = this.safeString (fee, 'marketSymbol');
728
+ const maker = this.safeNumber (fee, 'makerRate');
729
+ const taker = this.safeNumber (fee, 'takerRate');
730
+ return {
731
+ 'info': fee,
732
+ 'symbol': this.safeSymbol (marketId, market),
733
+ 'maker': maker,
734
+ 'taker': taker,
735
+ };
736
+ }
737
+
738
+ parseTradingFees (fees) {
739
+ const result = {
740
+ 'info': fees,
741
+ };
742
+ for (let i = 0; i < fees.length; i++) {
743
+ const fee = this.parseTradingFee (fees[i]);
744
+ const symbol = fee['symbol'];
745
+ result[symbol] = fee;
746
+ }
747
+ return result;
748
+ }
749
+
750
+ parseOHLCV (ohlcv, market = undefined) {
751
+ //
752
+ // {
753
+ // "startsAt":"2020-06-12T02:35:00Z",
754
+ // "open":"0.02493753",
755
+ // "high":"0.02493753",
756
+ // "low":"0.02493753",
757
+ // "close":"0.02493753",
758
+ // "volume":"0.09590123",
759
+ // "quoteVolume":"0.00239153"
760
+ // }
761
+ //
762
+ return [
763
+ this.parse8601 (this.safeString (ohlcv, 'startsAt')),
764
+ this.safeNumber (ohlcv, 'open'),
765
+ this.safeNumber (ohlcv, 'high'),
766
+ this.safeNumber (ohlcv, 'low'),
767
+ this.safeNumber (ohlcv, 'close'),
768
+ this.safeNumber (ohlcv, 'volume'),
769
+ ];
770
+ }
771
+
772
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
773
+ await this.loadMarkets ();
774
+ const market = this.market (symbol);
775
+ const reverseId = market['baseId'] + '-' + market['quoteId'];
776
+ const request = {
777
+ 'candleInterval': this.timeframes[timeframe],
778
+ 'marketSymbol': reverseId,
779
+ };
780
+ let method = 'publicGetMarketsMarketSymbolCandlesCandleIntervalRecent';
781
+ if (since !== undefined) {
782
+ const now = this.milliseconds ();
783
+ const difference = Math.abs (now - since);
784
+ const sinceDate = this.yyyymmdd (since);
785
+ const parts = sinceDate.split ('-');
786
+ const sinceYear = this.safeInteger (parts, 0);
787
+ const sinceMonth = this.safeInteger (parts, 1);
788
+ const sinceDay = this.safeInteger (parts, 2);
789
+ if (timeframe === '1d') {
790
+ // if the since argument is beyond one year into the past
791
+ if (difference > 31622400000) {
792
+ method = 'publicGetMarketsMarketSymbolCandlesCandleIntervalHistoricalYear';
793
+ request['year'] = sinceYear;
794
+ }
795
+ // request['year'] = year;
796
+ } else if (timeframe === '1h') {
797
+ // if the since argument is beyond 31 days into the past
798
+ if (difference > 2678400000) {
799
+ method = 'publicGetMarketsMarketSymbolCandlesCandleIntervalHistoricalYearMonth';
800
+ request['year'] = sinceYear;
801
+ request['month'] = sinceMonth;
802
+ }
803
+ } else {
804
+ // if the since argument is beyond 1 day into the past
805
+ if (difference > 86400000) {
806
+ method = 'publicGetMarketsMarketSymbolCandlesCandleIntervalHistoricalYearMonthDay';
807
+ request['year'] = sinceYear;
808
+ request['month'] = sinceMonth;
809
+ request['day'] = sinceDay;
810
+ }
811
+ }
812
+ }
813
+ const response = await this[method] (this.extend (request, params));
814
+ //
815
+ // [
816
+ // {"startsAt":"2020-06-12T02:35:00Z","open":"0.02493753","high":"0.02493753","low":"0.02493753","close":"0.02493753","volume":"0.09590123","quoteVolume":"0.00239153"},
817
+ // {"startsAt":"2020-06-12T02:40:00Z","open":"0.02491874","high":"0.02491874","low":"0.02490970","close":"0.02490970","volume":"0.04515695","quoteVolume":"0.00112505"},
818
+ // {"startsAt":"2020-06-12T02:45:00Z","open":"0.02490753","high":"0.02493143","low":"0.02490753","close":"0.02493143","volume":"0.17769640","quoteVolume":"0.00442663"}
819
+ // ]
820
+ //
821
+ return this.parseOHLCVs (response, market, timeframe, since, limit);
822
+ }
823
+
824
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
825
+ await this.loadMarkets ();
826
+ const request = {};
827
+ let market = undefined;
828
+ const stop = this.safeValue (params, 'stop');
829
+ if (symbol !== undefined) {
830
+ market = this.market (symbol);
831
+ request['marketSymbol'] = market['id'];
832
+ }
833
+ let method = 'privateGetOrdersOpen';
834
+ if (stop) {
835
+ method = 'privateGetConditionalOrdersOpen';
836
+ }
837
+ const query = this.omit (params, 'stop');
838
+ const response = await this[method] (this.extend (request, query));
839
+ //
840
+ // Spot
841
+ //
842
+ // [
843
+ // {
844
+ // "id": "df6cf5ee-fc27-4b61-991a-cc94b6459ac9",
845
+ // "marketSymbol": "BTC-USDT",
846
+ // "direction": "BUY",
847
+ // "type": "LIMIT",
848
+ // "quantity": "0.00023277",
849
+ // "limit": "30000.00000000",
850
+ // "timeInForce": "GOOD_TIL_CANCELLED",
851
+ // "fillQuantity": "0.00000000",
852
+ // "commission": "0.00000000",
853
+ // "proceeds": "0.00000000",
854
+ // "status": "OPEN",
855
+ // "createdAt": "2022-04-20T02:33:53.16Z",
856
+ // "updatedAt": "2022-04-20T02:33:53.16Z"
857
+ // }
858
+ // ]
859
+ //
860
+ // Stop
861
+ //
862
+ // [
863
+ // {
864
+ // "id": "f64f7c4f-295c-408b-9cbc-601981abf100",
865
+ // "marketSymbol": "BTC-USDT",
866
+ // "operand": "LTE",
867
+ // "triggerPrice": "0.10000000",
868
+ // "orderToCreate": {
869
+ // "marketSymbol": "BTC-USDT",
870
+ // "direction": "BUY",
871
+ // "type": "LIMIT",
872
+ // "quantity": "0.00020000",
873
+ // "limit": "30000.00000000",
874
+ // "timeInForce": "GOOD_TIL_CANCELLED"
875
+ // },
876
+ // "status": "OPEN",
877
+ // "createdAt": "2022-04-20T02:38:12.26Z",
878
+ // "updatedAt": "2022-04-20T02:38:12.26Z"
879
+ // }
880
+ // ]
881
+ //
882
+ return this.parseOrders (response, market, since, limit);
883
+ }
884
+
885
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
886
+ await this.loadMarkets ();
887
+ const request = {
888
+ 'orderId': id,
889
+ };
890
+ const response = await this.privateGetOrdersOrderIdExecutions (this.extend (request, params));
891
+ let market = undefined;
892
+ if (symbol !== undefined) {
893
+ market = this.market (symbol);
894
+ }
895
+ return this.parseTrades (response, market, since, limit);
896
+ }
897
+
898
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
899
+ // A ceiling order is a market or limit order that allows you to specify
900
+ // the amount of quote currency you want to spend (or receive, if selling)
901
+ // instead of the quantity of the market currency (e.g. buy $100 USD of BTC
902
+ // at the current market BTC price)
903
+ await this.loadMarkets ();
904
+ const market = this.market (symbol);
905
+ let uppercaseType = undefined;
906
+ if (type !== undefined) {
907
+ uppercaseType = type.toUpperCase ();
908
+ }
909
+ const reverseId = market['baseId'] + '-' + market['quoteId'];
910
+ const stop = this.safeValue (params, 'stop');
911
+ const stopPrice = this.safeNumber2 (params, 'triggerPrice', 'stopPrice');
912
+ const request = {
913
+ 'marketSymbol': reverseId, // SPOT and STOP
914
+ // 'direction': side.toUpperCase (), // SPOT, STOP 'orderToCreate'
915
+ // 'type': uppercaseType, // SPOT: LIMIT, MARKET, CEILING_LIMIT, CEILING_MARKET
916
+ // 'quantity': this.amountToPrecision (symbol, amount), // SPOT, required for limit orders, excluded for ceiling orders
917
+ // 'ceiling': this.priceToPrecision (symbol, price), // SPOT, required for ceiling orders, excluded for non-ceiling orders
918
+ // 'limit': this.priceToPrecision (symbol, price), // SPOT, required for limit orders, excluded for market orders
919
+ // 'timeInForce': 'GOOD_TIL_CANCELLED', // SPOT, IMMEDIATE_OR_CANCEL, FILL_OR_KILL, POST_ONLY_GOOD_TIL_CANCELLED
920
+ // 'useAwards': false, // SPOT, optional
921
+ // 'operand': 'LTE', // STOP, price above (GTE) or below (LTE) which the conditional order will trigger. either this or trailingStopPercent must be specified.
922
+ // 'triggerPrice': this.priceToPrecision (symbol, stopPrice), // STOP
923
+ // 'trailingStopPercent': this.priceToPrecision (symbol, stopPrice), // STOP, either this or triggerPrice must be set
924
+ // 'orderToCreate': {direction:side,type:uppercaseType}, // STOP, The spot order to be triggered
925
+ // 'orderToCancel': {id:'f03d5e98-b5ac-48fb-8647-dd4db828a297',type:uppercaseType}, // STOP, The spot order to be canceled
926
+ // 'clineConditionalOrderId': 'f03d5e98-b5ac-48fb-8647-dd4db828a297', // STOP
927
+ };
928
+ let method = 'privatePostOrders';
929
+ if (stop || stopPrice) {
930
+ method = 'privatePostConditionalOrders';
931
+ const operand = this.safeString (params, 'operand');
932
+ if (operand === undefined) {
933
+ throw new ArgumentsRequired (this.id + ' createOrder() requires an operand parameter');
934
+ }
935
+ const trailingStopPercent = this.safeNumber (params, 'trailingStopPercent');
936
+ const orderToCreate = this.safeValue (params, 'orderToCreate');
937
+ const orderToCancel = this.safeValue (params, 'orderToCancel');
938
+ if (stopPrice === undefined) {
939
+ request['trailingStopPercent'] = this.priceToPrecision (symbol, trailingStopPercent);
940
+ }
941
+ if (orderToCreate) {
942
+ const isCeilingLimit = (uppercaseType === 'CEILING_LIMIT');
943
+ const isCeilingMarket = (uppercaseType === 'CEILING_MARKET');
944
+ const isCeilingOrder = isCeilingLimit || isCeilingMarket;
945
+ let ceiling = undefined;
946
+ let limit = undefined;
947
+ let timeInForce = undefined;
948
+ if (isCeilingOrder) {
949
+ let cost = undefined;
950
+ if (isCeilingLimit) {
951
+ limit = this.priceToPrecision (symbol, price);
952
+ cost = this.safeNumber2 (params, 'ceiling', 'cost', amount);
953
+ } else if (isCeilingMarket) {
954
+ cost = this.safeNumber2 (params, 'ceiling', 'cost');
955
+ if (cost === undefined) {
956
+ if (price === undefined) {
957
+ cost = amount;
958
+ } else {
959
+ cost = amount * price;
960
+ }
961
+ }
962
+ }
963
+ ceiling = this.costToPrecision (symbol, cost);
964
+ timeInForce = 'IMMEDIATE_OR_CANCEL';
965
+ } else {
966
+ if (uppercaseType === 'LIMIT') {
967
+ limit = this.priceToPrecision (symbol, price);
968
+ timeInForce = 'GOOD_TIL_CANCELLED';
969
+ } else {
970
+ timeInForce = 'IMMEDIATE_OR_CANCEL';
971
+ }
972
+ }
973
+ request['orderToCreate'] = {
974
+ 'marketSymbol': reverseId,
975
+ 'direction': side.toUpperCase (),
976
+ 'type': uppercaseType,
977
+ 'quantity': this.amountToPrecision (symbol, amount),
978
+ 'ceiling': ceiling,
979
+ 'limit': limit,
980
+ 'timeInForce': timeInForce,
981
+ 'clientOrderId': this.safeString (params, 'clientOrderId'),
982
+ 'useAwards': this.safeValue (params, 'useAwards'),
983
+ };
984
+ }
985
+ if (orderToCancel) {
986
+ request['orderToCancel'] = orderToCancel;
987
+ }
988
+ request['triggerPrice'] = this.priceToPrecision (symbol, stopPrice);
989
+ request['operand'] = operand;
990
+ } else {
991
+ if (side !== undefined) {
992
+ request['direction'] = side.toUpperCase ();
993
+ }
994
+ request['type'] = uppercaseType;
995
+ const isCeilingLimit = (uppercaseType === 'CEILING_LIMIT');
996
+ const isCeilingMarket = (uppercaseType === 'CEILING_MARKET');
997
+ const isCeilingOrder = isCeilingLimit || isCeilingMarket;
998
+ if (isCeilingOrder) {
999
+ let cost = undefined;
1000
+ if (isCeilingLimit) {
1001
+ request['limit'] = this.priceToPrecision (symbol, price);
1002
+ cost = this.safeNumber2 (params, 'ceiling', 'cost', amount);
1003
+ } else if (isCeilingMarket) {
1004
+ cost = this.safeNumber2 (params, 'ceiling', 'cost');
1005
+ if (cost === undefined) {
1006
+ if (price === undefined) {
1007
+ cost = amount;
1008
+ } else {
1009
+ cost = amount * price;
1010
+ }
1011
+ }
1012
+ }
1013
+ request['ceiling'] = this.costToPrecision (symbol, cost);
1014
+ // bittrex only accepts IMMEDIATE_OR_CANCEL or FILL_OR_KILL for ceiling orders
1015
+ request['timeInForce'] = 'IMMEDIATE_OR_CANCEL';
1016
+ } else {
1017
+ request['quantity'] = this.amountToPrecision (symbol, amount);
1018
+ if (uppercaseType === 'LIMIT') {
1019
+ request['limit'] = this.priceToPrecision (symbol, price);
1020
+ request['timeInForce'] = 'GOOD_TIL_CANCELLED';
1021
+ } else {
1022
+ // bittrex does not allow GOOD_TIL_CANCELLED for market orders
1023
+ request['timeInForce'] = 'IMMEDIATE_OR_CANCEL';
1024
+ }
1025
+ }
1026
+ }
1027
+ const query = this.omit (params, [ 'stop', 'stopPrice', 'ceiling', 'cost', 'operand', 'trailingStopPercent', 'orderToCreate', 'orderToCancel' ]);
1028
+ const response = await this[method] (this.extend (request, query));
1029
+ //
1030
+ // Spot
1031
+ //
1032
+ // {
1033
+ // id: 'f03d5e98-b5ac-48fb-8647-dd4db828a297',
1034
+ // marketSymbol: 'BTC-USDT',
1035
+ // direction: 'SELL',
1036
+ // type: 'LIMIT',
1037
+ // quantity: '0.01',
1038
+ // limit: '6000',
1039
+ // timeInForce: 'GOOD_TIL_CANCELLED',
1040
+ // fillQuantity: '0.00000000',
1041
+ // commission: '0.00000000',
1042
+ // proceeds: '0.00000000',
1043
+ // status: 'OPEN',
1044
+ // createdAt: '2020-03-18T02:37:33.42Z',
1045
+ // updatedAt: '2020-03-18T02:37:33.42Z'
1046
+ // }
1047
+ //
1048
+ // Stop
1049
+ //
1050
+ // {
1051
+ // "id": "9791fe52-a3e5-4ac3-ae03-e327b2993571",
1052
+ // "marketSymbol": "BTC-USDT",
1053
+ // "operand": "LTE",
1054
+ // "triggerPrice": "0.1",
1055
+ // "orderToCreate": {
1056
+ // "marketSymbol": "BTC-USDT",
1057
+ // "direction": "BUY",
1058
+ // "type": "LIMIT",
1059
+ // "quantity": "0.0002",
1060
+ // "limit": "30000",
1061
+ // "timeInForce": "GOOD_TIL_CANCELLED"
1062
+ // },
1063
+ // "status": "OPEN",
1064
+ // "createdAt": "2022-04-19T21:02:14.17Z",
1065
+ // "updatedAt": "2022-04-19T21:02:14.17Z"
1066
+ // }
1067
+ //
1068
+ return this.parseOrder (response, market);
1069
+ }
1070
+
1071
+ async cancelOrder (id, symbol = undefined, params = {}) {
1072
+ await this.loadMarkets ();
1073
+ const stop = this.safeValue (params, 'stop');
1074
+ let request = {};
1075
+ let method = undefined;
1076
+ let market = undefined;
1077
+ if (symbol !== undefined) {
1078
+ market = this.market (symbol);
1079
+ }
1080
+ if (stop) {
1081
+ method = 'privateDeleteConditionalOrdersConditionalOrderId';
1082
+ request = {
1083
+ 'conditionalOrderId': id,
1084
+ };
1085
+ } else {
1086
+ method = 'privateDeleteOrdersOrderId';
1087
+ request = {
1088
+ 'orderId': id,
1089
+ };
1090
+ }
1091
+ const query = this.omit (params, 'stop');
1092
+ const response = await this[method] (this.extend (request, query));
1093
+ //
1094
+ // Spot
1095
+ //
1096
+ // [
1097
+ // {
1098
+ // "id": "df6cf5ee-fc27-4b61-991a-cc94b6459ac9",
1099
+ // "marketSymbol": "BTC-USDT",
1100
+ // "direction": "BUY",
1101
+ // "type": "LIMIT",
1102
+ // "quantity": "0.00023277",
1103
+ // "limit": "30000.00000000",
1104
+ // "timeInForce": "GOOD_TIL_CANCELLED",
1105
+ // "fillQuantity": "0.00000000",
1106
+ // "commission": "0.00000000",
1107
+ // "proceeds": "0.00000000",
1108
+ // "status": "CANCELLED",
1109
+ // "createdAt": "2022-04-20T02:33:53.16Z",
1110
+ // "updatedAt": "2022-04-20T02:33:53.16Z"
1111
+ // }
1112
+ // ]
1113
+ //
1114
+ // Stop
1115
+ //
1116
+ // [
1117
+ // {
1118
+ // "id": "f64f7c4f-295c-408b-9cbc-601981abf100",
1119
+ // "marketSymbol": "BTC-USDT",
1120
+ // "operand": "LTE",
1121
+ // "triggerPrice": "0.10000000",
1122
+ // "orderToCreate": {
1123
+ // "marketSymbol": "BTC-USDT",
1124
+ // "direction": "BUY",
1125
+ // "type": "LIMIT",
1126
+ // "quantity": "0.00020000",
1127
+ // "limit": "30000.00000000",
1128
+ // "timeInForce": "GOOD_TIL_CANCELLED"
1129
+ // },
1130
+ // "status": "CANCELLED",
1131
+ // "createdAt": "2022-04-20T02:38:12.26Z",
1132
+ // "updatedAt": "2022-04-20T02:38:12.26Z"
1133
+ // "closedAt": "2022-04-20T03:47:24.69Z"
1134
+ // }
1135
+ // ]
1136
+ //
1137
+ return this.extend (this.parseOrder (response, market), {
1138
+ 'id': id,
1139
+ 'info': response,
1140
+ 'status': 'canceled',
1141
+ });
1142
+ }
1143
+
1144
+ async cancelAllOrders (symbol = undefined, params = {}) {
1145
+ await this.loadMarkets ();
1146
+ const request = {};
1147
+ let market = undefined;
1148
+ if (symbol !== undefined) {
1149
+ market = this.market (symbol);
1150
+ request['marketSymbol'] = market['id'];
1151
+ }
1152
+ const response = await this.privateDeleteOrdersOpen (this.extend (request, params));
1153
+ //
1154
+ // [
1155
+ // {
1156
+ // "id":"66582be0-5337-4d8c-b212-c356dd525801",
1157
+ // "statusCode":"SUCCESS",
1158
+ // "result":{
1159
+ // "id":"66582be0-5337-4d8c-b212-c356dd525801",
1160
+ // "marketSymbol":"BTC-USDT",
1161
+ // "direction":"BUY",
1162
+ // "type":"LIMIT",
1163
+ // "quantity":"0.01000000",
1164
+ // "limit":"3000.00000000",
1165
+ // "timeInForce":"GOOD_TIL_CANCELLED",
1166
+ // "fillQuantity":"0.00000000",
1167
+ // "commission":"0.00000000",
1168
+ // "proceeds":"0.00000000",
1169
+ // "status":"CLOSED",
1170
+ // "createdAt":"2020-10-06T12:31:53.39Z",
1171
+ // "updatedAt":"2020-10-06T12:54:28.8Z",
1172
+ // "closedAt":"2020-10-06T12:54:28.8Z"
1173
+ // }
1174
+ // }
1175
+ // ]
1176
+ //
1177
+ const orders = [];
1178
+ for (let i = 0; i < response.length; i++) {
1179
+ const result = this.safeValue (response[i], 'result', {});
1180
+ orders.push (result);
1181
+ }
1182
+ return this.parseOrders (orders, market);
1183
+ }
1184
+
1185
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
1186
+ await this.loadMarkets ();
1187
+ // https://support.bittrex.com/hc/en-us/articles/115003723911
1188
+ const request = {};
1189
+ let currency = undefined;
1190
+ if (code !== undefined) {
1191
+ currency = this.currency (code);
1192
+ request['currencySymbol'] = currency['id'];
1193
+ }
1194
+ const response = await this.privateGetDepositsClosed (this.extend (request, params));
1195
+ // we cannot filter by `since` timestamp, as it isn't set by Bittrex
1196
+ // see https://github.com/ccxt/ccxt/issues/4067
1197
+ // return this.parseTransactions (response, currency, since, limit);
1198
+ return this.parseTransactions (response, currency, undefined, limit);
1199
+ }
1200
+
1201
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
1202
+ await this.loadMarkets ();
1203
+ // https://support.bittrex.com/hc/en-us/articles/115003723911
1204
+ const request = {};
1205
+ let currency = undefined;
1206
+ if (code !== undefined) {
1207
+ currency = this.currency (code);
1208
+ request['currencySymbol'] = currency['id'];
1209
+ }
1210
+ const response = await this.privateGetWithdrawalsClosed (this.extend (request, params));
1211
+ return this.parseTransactions (response, currency, since, limit);
1212
+ }
1213
+
1214
+ parseTransaction (transaction, currency = undefined) {
1215
+ //
1216
+ // fetchDeposits
1217
+ //
1218
+ // {
1219
+ // "id": "d00fdf2e-df9e-48f1-....",
1220
+ // "currencySymbol": "BTC",
1221
+ // "quantity": "0.00550000",
1222
+ // "cryptoAddress": "1PhmYjnJPZH5NUwV8AU...",
1223
+ // "txId": "d1f1afffe1b9b6614eaee7e8133c85d98...",
1224
+ // "confirmations": 2,
1225
+ // "updatedAt": "2020-01-12T16:49:30.41Z",
1226
+ // "completedAt": "2020-01-12T16:49:30.41Z",
1227
+ // "status": "COMPLETED",
1228
+ // "source": "BLOCKCHAIN"
1229
+ // }
1230
+ //
1231
+ // fetchWithdrawals
1232
+ //
1233
+ // {
1234
+ // "PaymentUuid" : "e293da98-788c-4188-a8f9-8ec2c33fdfcf",
1235
+ // "Currency" : "XC",
1236
+ // "Amount" : 7513.75121715,
1237
+ // "Address" : "EVnSMgAd7EonF2Dgc4c9K14L12RBaW5S5J",
1238
+ // "Opened" : "2014-07-08T23:13:31.83",
1239
+ // "Authorized" : true,
1240
+ // "PendingPayment" : false,
1241
+ // "TxCost" : 0.00002000,
1242
+ // "TxId" : "b4a575c2a71c7e56d02ab8e26bb1ef0a2f6cf2094f6ca2116476a569c1e84f6e",
1243
+ // "Canceled" : false,
1244
+ // "InvalidAddress" : false
1245
+ // }
1246
+ //
1247
+ // withdraw
1248
+ //
1249
+ // {
1250
+ // "currencySymbol": "string",
1251
+ // "quantity": "number (double)",
1252
+ // "cryptoAddress": "string",
1253
+ // "cryptoAddressTag": "string",
1254
+ // "fundsTransferMethodId": "string (uuid)",
1255
+ // "clientWithdrawalId": "string (uuid)"
1256
+ // }
1257
+ //
1258
+ const id = this.safeString2 (transaction, 'id', 'clientWithdrawalId');
1259
+ const amount = this.safeNumber (transaction, 'quantity');
1260
+ const address = this.safeString (transaction, 'cryptoAddress');
1261
+ const txid = this.safeString (transaction, 'txId');
1262
+ const updated = this.parse8601 (this.safeString (transaction, 'updatedAt'));
1263
+ const opened = this.parse8601 (this.safeString (transaction, 'createdAt'));
1264
+ const timestamp = opened ? opened : updated;
1265
+ const type = (opened === undefined) ? 'deposit' : 'withdrawal';
1266
+ const currencyId = this.safeString (transaction, 'currencySymbol');
1267
+ const code = this.safeCurrencyCode (currencyId, currency);
1268
+ let status = 'pending';
1269
+ if (type === 'deposit') {
1270
+ //
1271
+ // deposits numConfirmations never reach the minConfirmations number
1272
+ // we set all of them to 'ok', otherwise they'd all be 'pending'
1273
+ //
1274
+ // const numConfirmations = this.safeInteger (transaction, 'Confirmations', 0);
1275
+ // const minConfirmations = this.safeInteger (currency['info'], 'MinConfirmation');
1276
+ // if (numConfirmations >= minConfirmations) {
1277
+ // status = 'ok';
1278
+ // }
1279
+ //
1280
+ status = 'ok';
1281
+ } else {
1282
+ const responseStatus = this.safeString (transaction, 'status');
1283
+ if (responseStatus === 'ERROR_INVALID_ADDRESS') {
1284
+ status = 'failed';
1285
+ } else if (responseStatus === 'CANCELLED') {
1286
+ status = 'canceled';
1287
+ } else if (responseStatus === 'PENDING') {
1288
+ status = 'pending';
1289
+ } else if (responseStatus === 'COMPLETED') {
1290
+ status = 'ok';
1291
+ } else if (responseStatus === 'AUTHORIZED' && (txid !== undefined)) {
1292
+ status = 'ok';
1293
+ }
1294
+ }
1295
+ let feeCost = this.safeNumber (transaction, 'txCost');
1296
+ if (feeCost === undefined) {
1297
+ if (type === 'deposit') {
1298
+ // according to https://support.bittrex.com/hc/en-us/articles/115000199651-What-fees-does-Bittrex-charge-
1299
+ feeCost = 0;
1300
+ }
1301
+ }
1302
+ return {
1303
+ 'info': transaction,
1304
+ 'id': id,
1305
+ 'currency': code,
1306
+ 'amount': amount,
1307
+ 'network': undefined,
1308
+ 'address': address,
1309
+ 'addressTo': undefined,
1310
+ 'addressFrom': undefined,
1311
+ 'tag': undefined,
1312
+ 'tagTo': undefined,
1313
+ 'tagFrom': undefined,
1314
+ 'status': status,
1315
+ 'type': type,
1316
+ 'updated': updated,
1317
+ 'txid': txid,
1318
+ 'timestamp': timestamp,
1319
+ 'datetime': this.iso8601 (timestamp),
1320
+ 'fee': {
1321
+ 'currency': code,
1322
+ 'cost': feeCost,
1323
+ },
1324
+ };
1325
+ }
1326
+
1327
+ parseTimeInForce (timeInForce) {
1328
+ const timeInForces = {
1329
+ 'GOOD_TIL_CANCELLED': 'GTC',
1330
+ 'IMMEDIATE_OR_CANCEL': 'IOC',
1331
+ 'FILL_OR_KILL': 'FOK',
1332
+ 'POST_ONLY_GOOD_TIL_CANCELLED': 'PO',
1333
+ };
1334
+ return this.safeString (timeInForces, timeInForce, timeInForce);
1335
+ }
1336
+
1337
+ parseOrder (order, market = undefined) {
1338
+ //
1339
+ // Spot createOrder, fetchOpenOrders, fetchClosedOrders, fetchOrder, cancelOrder
1340
+ //
1341
+ // {
1342
+ // id: '1be35109-b763-44ce-b6ea-05b6b0735c0c',
1343
+ // marketSymbol: 'LTC-ETH',
1344
+ // direction: 'BUY',
1345
+ // type: 'LIMIT',
1346
+ // quantity: '0.50000000',
1347
+ // limit: '0.17846699',
1348
+ // timeInForce: 'GOOD_TIL_CANCELLED',
1349
+ // clientOrderId: 'ff156d39-fe01-44ca-8f21-b0afa19ef228',
1350
+ // fillQuantity: '0.50000000',
1351
+ // commission: '0.00022286',
1352
+ // proceeds: '0.08914915',
1353
+ // status: 'CLOSED',
1354
+ // createdAt: '2018-06-23T13:14:28.613Z',
1355
+ // updatedAt: '2018-06-23T13:14:30.19Z',
1356
+ // closedAt: '2018-06-23T13:14:30.19Z'
1357
+ // }
1358
+ //
1359
+ // Stop createOrder, fetchOpenOrders, fetchClosedOrders, fetchOrder, cancelOrder
1360
+ //
1361
+ // {
1362
+ // "id": "9791fe52-a3e5-4ac3-ae03-e327b2993571",
1363
+ // "marketSymbol": "BTC-USDT",
1364
+ // "operand": "LTE",
1365
+ // "triggerPrice": "0.1",
1366
+ // "orderToCreate": {
1367
+ // "marketSymbol": "BTC-USDT",
1368
+ // "direction": "BUY",
1369
+ // "type": "LIMIT",
1370
+ // "quantity": "0.0002",
1371
+ // "limit": "30000",
1372
+ // "timeInForce": "GOOD_TIL_CANCELLED"
1373
+ // },
1374
+ // "status": "OPEN",
1375
+ // "createdAt": "2022-04-19T21:02:14.17Z",
1376
+ // "updatedAt": "2022-04-19T21:02:14.17Z",
1377
+ // "closedAt": "2022-04-20T03:47:24.69Z"
1378
+ // }
1379
+ //
1380
+ const marketSymbol = this.safeString (order, 'marketSymbol');
1381
+ market = this.safeMarket (marketSymbol, market, '-');
1382
+ const symbol = market['symbol'];
1383
+ const feeCurrency = market['quote'];
1384
+ const createdAt = this.safeString (order, 'createdAt');
1385
+ const updatedAt = this.safeString (order, 'updatedAt');
1386
+ const closedAt = this.safeString (order, 'closedAt');
1387
+ const clientOrderId = this.safeString (order, 'clientOrderId');
1388
+ let lastTradeTimestamp = undefined;
1389
+ if (closedAt !== undefined) {
1390
+ lastTradeTimestamp = this.parse8601 (closedAt);
1391
+ } else if (updatedAt) {
1392
+ lastTradeTimestamp = this.parse8601 (updatedAt);
1393
+ }
1394
+ const timestamp = this.parse8601 (createdAt);
1395
+ let direction = this.safeStringLower (order, 'direction');
1396
+ if (direction === undefined) {
1397
+ let conditionalOrder = this.safeValue (order, 'orderToCreate');
1398
+ if (conditionalOrder === undefined) {
1399
+ conditionalOrder = this.safeValue (order, 'orderToCancel');
1400
+ }
1401
+ direction = this.safeStringLower (conditionalOrder, 'direction');
1402
+ }
1403
+ let type = this.safeStringLower (order, 'type');
1404
+ if (type === undefined) {
1405
+ let conditionalOrder = this.safeValue (order, 'orderToCreate');
1406
+ if (conditionalOrder === undefined) {
1407
+ conditionalOrder = this.safeValue (order, 'orderToCancel');
1408
+ }
1409
+ type = this.safeStringLower (conditionalOrder, 'type');
1410
+ }
1411
+ let quantity = this.safeString (order, 'quantity');
1412
+ if (quantity === undefined) {
1413
+ let conditionalOrder = this.safeValue (order, 'orderToCreate');
1414
+ if (conditionalOrder === undefined) {
1415
+ conditionalOrder = this.safeValue (order, 'orderToCancel');
1416
+ }
1417
+ quantity = this.safeString (conditionalOrder, 'quantity');
1418
+ }
1419
+ let limit = this.safeString (order, 'limit');
1420
+ if (limit === undefined) {
1421
+ let conditionalOrder = this.safeValue (order, 'orderToCreate');
1422
+ if (conditionalOrder === undefined) {
1423
+ conditionalOrder = this.safeValue (order, 'orderToCancel');
1424
+ }
1425
+ limit = this.safeString (conditionalOrder, 'limit');
1426
+ }
1427
+ let timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce'));
1428
+ if (timeInForce === undefined) {
1429
+ let conditionalOrder = this.safeValue (order, 'orderToCreate');
1430
+ if (conditionalOrder === undefined) {
1431
+ conditionalOrder = this.safeValue (order, 'orderToCancel');
1432
+ }
1433
+ timeInForce = this.parseTimeInForce (this.safeString (conditionalOrder, 'timeInForce'));
1434
+ }
1435
+ const fillQuantity = this.safeString (order, 'fillQuantity');
1436
+ const commission = this.safeNumber (order, 'commission');
1437
+ const proceeds = this.safeString (order, 'proceeds');
1438
+ const status = this.safeStringLower (order, 'status');
1439
+ const postOnly = (timeInForce === 'PO');
1440
+ return this.safeOrder ({
1441
+ 'id': this.safeString (order, 'id'),
1442
+ 'clientOrderId': clientOrderId,
1443
+ 'timestamp': timestamp,
1444
+ 'datetime': this.iso8601 (timestamp),
1445
+ 'lastTradeTimestamp': lastTradeTimestamp,
1446
+ 'symbol': symbol,
1447
+ 'type': type,
1448
+ 'timeInForce': timeInForce,
1449
+ 'postOnly': postOnly,
1450
+ 'side': direction,
1451
+ 'price': limit,
1452
+ 'stopPrice': this.safeString (order, 'triggerPrice'),
1453
+ 'cost': proceeds,
1454
+ 'average': undefined,
1455
+ 'amount': quantity,
1456
+ 'filled': fillQuantity,
1457
+ 'remaining': undefined,
1458
+ 'status': status,
1459
+ 'fee': {
1460
+ 'cost': commission,
1461
+ 'currency': feeCurrency,
1462
+ },
1463
+ 'info': order,
1464
+ 'trades': undefined,
1465
+ }, market);
1466
+ }
1467
+
1468
+ parseOrders (orders, market = undefined, since = undefined, limit = undefined, params = {}) {
1469
+ if (this.options['fetchClosedOrdersFilterBySince']) {
1470
+ return super.parseOrders (orders, market, since, limit, params);
1471
+ } else {
1472
+ return super.parseOrders (orders, market, undefined, limit, params);
1473
+ }
1474
+ }
1475
+
1476
+ parseOrderStatus (status) {
1477
+ const statuses = {
1478
+ 'CLOSED': 'closed',
1479
+ 'OPEN': 'open',
1480
+ 'CANCELLED': 'canceled',
1481
+ 'CANCELED': 'canceled',
1482
+ };
1483
+ return this.safeString (statuses, status, status);
1484
+ }
1485
+
1486
+ async fetchOrder (id, symbol = undefined, params = {}) {
1487
+ await this.loadMarkets ();
1488
+ const stop = this.safeValue (params, 'stop');
1489
+ let market = undefined;
1490
+ if (symbol !== undefined) {
1491
+ market = this.market (symbol);
1492
+ }
1493
+ let response = undefined;
1494
+ let method = undefined;
1495
+ try {
1496
+ const request = {};
1497
+ if (stop) {
1498
+ method = 'privateGetConditionalOrdersConditionalOrderId';
1499
+ request['conditionalOrderId'] = id;
1500
+ } else {
1501
+ method = 'privateGetOrdersOrderId';
1502
+ request['orderId'] = id;
1503
+ }
1504
+ const query = this.omit (params, 'stop');
1505
+ response = await this[method] (this.extend (request, query));
1506
+ } catch (e) {
1507
+ if (this.last_json_response) {
1508
+ const message = this.safeString (this.last_json_response, 'message');
1509
+ if (message === 'UUID_INVALID') {
1510
+ throw new OrderNotFound (this.id + ' fetchOrder() error: ' + this.last_http_response);
1511
+ }
1512
+ }
1513
+ throw e;
1514
+ }
1515
+ return this.parseOrder (response, market);
1516
+ }
1517
+
1518
+ orderToTrade (order) {
1519
+ // this entire method should be moved to the base class
1520
+ const timestamp = this.safeInteger2 (order, 'lastTradeTimestamp', 'timestamp');
1521
+ return {
1522
+ 'id': this.safeString (order, 'id'),
1523
+ 'side': this.safeString (order, 'side'),
1524
+ 'order': this.safeString (order, 'id'),
1525
+ 'type': this.safeString (order, 'type'),
1526
+ 'price': this.safeNumber (order, 'average'),
1527
+ 'amount': this.safeNumber (order, 'filled'),
1528
+ 'cost': this.safeNumber (order, 'cost'),
1529
+ 'symbol': this.safeString (order, 'symbol'),
1530
+ 'timestamp': timestamp,
1531
+ 'datetime': this.iso8601 (timestamp),
1532
+ 'fee': this.safeValue (order, 'fee'),
1533
+ 'info': order,
1534
+ 'takerOrMaker': undefined,
1535
+ };
1536
+ }
1537
+
1538
+ ordersToTrades (orders) {
1539
+ // this entire method should be moved to the base class
1540
+ const result = [];
1541
+ for (let i = 0; i < orders.length; i++) {
1542
+ result.push (this.orderToTrade (orders[i]));
1543
+ }
1544
+ return result;
1545
+ }
1546
+
1547
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1548
+ await this.loadMarkets ();
1549
+ const request = {};
1550
+ if (limit !== undefined) {
1551
+ request['pageSize'] = limit;
1552
+ }
1553
+ if (since !== undefined) {
1554
+ request['startDate'] = this.ymdhms (since, 'T') + 'Z';
1555
+ }
1556
+ let market = undefined;
1557
+ if (symbol !== undefined) {
1558
+ market = this.market (symbol);
1559
+ symbol = market['symbol'];
1560
+ // because of this line we will have to rethink the entire v3
1561
+ // in other words, markets define all the rest of the API
1562
+ // and v3 market ids are reversed in comparison to v1
1563
+ // v3 has to be a completely separate implementation
1564
+ // otherwise we will have to shuffle symbols and currencies everywhere
1565
+ // which is prone to errors, as was shown here
1566
+ // https://github.com/ccxt/ccxt/pull/5219#issuecomment-499646209
1567
+ request['marketSymbol'] = market['base'] + '-' + market['quote'];
1568
+ }
1569
+ const response = await this.privateGetOrdersClosed (this.extend (request, params));
1570
+ const orders = this.parseOrders (response, market);
1571
+ const trades = this.ordersToTrades (orders);
1572
+ return this.filterBySymbolSinceLimit (trades, symbol, since, limit);
1573
+ }
1574
+
1575
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1576
+ await this.loadMarkets ();
1577
+ const stop = this.safeValue (params, 'stop');
1578
+ const request = {};
1579
+ if (limit !== undefined) {
1580
+ request['pageSize'] = limit;
1581
+ }
1582
+ if (since !== undefined) {
1583
+ request['startDate'] = this.ymdhms (since, 'T') + 'Z';
1584
+ }
1585
+ let market = undefined;
1586
+ if (symbol !== undefined) {
1587
+ market = this.market (symbol);
1588
+ // because of this line we will have to rethink the entire v3
1589
+ // in other words, markets define all the rest of the API
1590
+ // and v3 market ids are reversed in comparison to v1
1591
+ // v3 has to be a completely separate implementation
1592
+ // otherwise we will have to shuffle symbols and currencies everywhere
1593
+ // which is prone to errors, as was shown here
1594
+ // https://github.com/ccxt/ccxt/pull/5219#issuecomment-499646209
1595
+ request['marketSymbol'] = market['base'] + '-' + market['quote'];
1596
+ }
1597
+ let method = 'privateGetOrdersClosed';
1598
+ if (stop) {
1599
+ method = 'privateGetConditionalOrdersClosed';
1600
+ }
1601
+ const query = this.omit (params, 'stop');
1602
+ const response = await this[method] (this.extend (request, query));
1603
+ //
1604
+ // Spot
1605
+ //
1606
+ // [
1607
+ // {
1608
+ // "id": "df6cf5ee-fc27-4b61-991a-cc94b6459ac9",
1609
+ // "marketSymbol": "BTC-USDT",
1610
+ // "direction": "BUY",
1611
+ // "type": "LIMIT",
1612
+ // "quantity": "0.00023277",
1613
+ // "limit": "30000.00000000",
1614
+ // "timeInForce": "GOOD_TIL_CANCELLED",
1615
+ // "fillQuantity": "0.00000000",
1616
+ // "commission": "0.00000000",
1617
+ // "proceeds": "0.00000000",
1618
+ // "status": "OPEN",
1619
+ // "createdAt": "2022-04-20T02:33:53.16Z",
1620
+ // "updatedAt": "2022-04-20T02:33:53.16Z"
1621
+ // }
1622
+ // ]
1623
+ //
1624
+ // Stop
1625
+ //
1626
+ // [
1627
+ // {
1628
+ // "id": "f64f7c4f-295c-408b-9cbc-601981abf100",
1629
+ // "marketSymbol": "BTC-USDT",
1630
+ // "operand": "LTE",
1631
+ // "triggerPrice": "0.10000000",
1632
+ // "orderToCreate": {
1633
+ // "marketSymbol": "BTC-USDT",
1634
+ // "direction": "BUY",
1635
+ // "type": "LIMIT",
1636
+ // "quantity": "0.00020000",
1637
+ // "limit": "30000.00000000",
1638
+ // "timeInForce": "GOOD_TIL_CANCELLED"
1639
+ // },
1640
+ // "status": "OPEN",
1641
+ // "createdAt": "2022-04-20T02:38:12.26Z",
1642
+ // "updatedAt": "2022-04-20T02:38:12.26Z"
1643
+ // }
1644
+ // ]
1645
+ //
1646
+ return this.parseOrders (response, market, since, limit);
1647
+ }
1648
+
1649
+ async createDepositAddress (code, params = {}) {
1650
+ await this.loadMarkets ();
1651
+ const currency = this.currency (code);
1652
+ const request = {
1653
+ 'currencySymbol': currency['id'],
1654
+ };
1655
+ const response = await this.privatePostAddresses (this.extend (request, params));
1656
+ //
1657
+ // {
1658
+ // "status":"PROVISIONED",
1659
+ // "currencySymbol":"XRP",
1660
+ // "cryptoAddress":"rPVMhWBsfF9iMXYj3aAzJVkPDTFNSyWdKy",
1661
+ // "cryptoAddressTag":"392034158"
1662
+ // }
1663
+ //
1664
+ let address = this.safeString (response, 'cryptoAddress');
1665
+ const message = this.safeString (response, 'status');
1666
+ if (!address || message === 'REQUESTED') {
1667
+ throw new AddressPending (this.id + ' the address for ' + code + ' is being generated (pending, not ready yet, retry again later)');
1668
+ }
1669
+ let tag = this.safeString (response, 'cryptoAddressTag');
1670
+ if ((tag === undefined) && (currency['type'] in this.options['tag'])) {
1671
+ tag = address;
1672
+ address = currency['address'];
1673
+ }
1674
+ this.checkAddress (address);
1675
+ return {
1676
+ 'currency': code,
1677
+ 'address': address,
1678
+ 'tag': tag,
1679
+ 'info': response,
1680
+ };
1681
+ }
1682
+
1683
+ async fetchDepositAddress (code, params = {}) {
1684
+ await this.loadMarkets ();
1685
+ const currency = this.currency (code);
1686
+ const request = {
1687
+ 'currencySymbol': currency['id'],
1688
+ };
1689
+ const response = await this.privateGetAddressesCurrencySymbol (this.extend (request, params));
1690
+ //
1691
+ // {
1692
+ // "status":"PROVISIONED",
1693
+ // "currencySymbol":"XRP",
1694
+ // "cryptoAddress":"rPVMhWBsfF9iMXYj3aAzJVkPDTFNSyWdKy",
1695
+ // "cryptoAddressTag":"392034158"
1696
+ // }
1697
+ //
1698
+ let address = this.safeString (response, 'cryptoAddress');
1699
+ const message = this.safeString (response, 'status');
1700
+ if (!address || message === 'REQUESTED') {
1701
+ throw new AddressPending (this.id + ' the address for ' + code + ' is being generated (pending, not ready yet, retry again later)');
1702
+ }
1703
+ let tag = this.safeString (response, 'cryptoAddressTag');
1704
+ if ((tag === undefined) && (currency['type'] in this.options['tag'])) {
1705
+ tag = address;
1706
+ address = currency['address'];
1707
+ }
1708
+ this.checkAddress (address);
1709
+ return {
1710
+ 'currency': code,
1711
+ 'address': address,
1712
+ 'tag': tag,
1713
+ 'network': undefined,
1714
+ 'info': response,
1715
+ };
1716
+ }
1717
+
1718
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1719
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1720
+ this.checkAddress (address);
1721
+ await this.loadMarkets ();
1722
+ const currency = this.currency (code);
1723
+ const request = {
1724
+ 'currencySymbol': currency['id'],
1725
+ 'quantity': amount,
1726
+ 'cryptoAddress': address,
1727
+ };
1728
+ if (tag !== undefined) {
1729
+ request['cryptoAddressTag'] = tag;
1730
+ }
1731
+ const response = await this.privatePostWithdrawals (this.extend (request, params));
1732
+ //
1733
+ // {
1734
+ // "currencySymbol": "string",
1735
+ // "quantity": "number (double)",
1736
+ // "cryptoAddress": "string",
1737
+ // "cryptoAddressTag": "string",
1738
+ // "fundsTransferMethodId": "string (uuid)",
1739
+ // "clientWithdrawalId": "string (uuid)"
1740
+ // }
1741
+ //
1742
+ return this.parseTransaction (response, currency);
1743
+ }
1744
+
1745
+ sign (path, api = 'v3', method = 'GET', params = {}, headers = undefined, body = undefined) {
1746
+ let url = this.implodeParams (this.urls['api'][api], {
1747
+ 'hostname': this.hostname,
1748
+ }) + '/';
1749
+ if (api === 'private') {
1750
+ url += this.version + '/';
1751
+ this.checkRequiredCredentials ();
1752
+ url += this.implodeParams (path, params);
1753
+ params = this.omit (params, this.extractParams (path));
1754
+ let hashString = '';
1755
+ if (method === 'POST') {
1756
+ body = this.json (params);
1757
+ hashString = body;
1758
+ } else {
1759
+ if (Object.keys (params).length) {
1760
+ url += '?' + this.rawencode (params);
1761
+ }
1762
+ }
1763
+ const contentHash = this.hash (this.encode (hashString), 'sha512', 'hex');
1764
+ const timestamp = this.milliseconds ().toString ();
1765
+ let auth = timestamp + url + method + contentHash;
1766
+ const subaccountId = this.safeValue (this.options, 'subaccountId');
1767
+ if (subaccountId !== undefined) {
1768
+ auth += subaccountId;
1769
+ }
1770
+ const signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha512');
1771
+ headers = {
1772
+ 'Api-Key': this.apiKey,
1773
+ 'Api-Timestamp': timestamp,
1774
+ 'Api-Content-Hash': contentHash,
1775
+ 'Api-Signature': signature,
1776
+ };
1777
+ if (subaccountId !== undefined) {
1778
+ headers['Api-Subaccount-Id'] = subaccountId;
1779
+ }
1780
+ if (method === 'POST') {
1781
+ headers['Content-Type'] = 'application/json';
1782
+ }
1783
+ } else {
1784
+ if (api === 'public') {
1785
+ url += this.version + '/';
1786
+ }
1787
+ url += this.implodeParams (path, params);
1788
+ params = this.omit (params, this.extractParams (path));
1789
+ if (Object.keys (params).length) {
1790
+ url += '?' + this.urlencode (params);
1791
+ }
1792
+ }
1793
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1794
+ }
1795
+
1796
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1797
+ if (response === undefined) {
1798
+ return; // fallback to default error handler
1799
+ }
1800
+ //
1801
+ // { success: false, message: "message" }
1802
+ //
1803
+ if (body[0] === '{') {
1804
+ const feedback = this.id + ' ' + body;
1805
+ let success = this.safeValue (response, 'success');
1806
+ if (success === undefined) {
1807
+ const code = this.safeString (response, 'code');
1808
+ if ((code === 'NOT_FOUND') && (url.indexOf ('addresses') >= 0)) {
1809
+ throw new InvalidAddress (feedback);
1810
+ }
1811
+ if (code !== undefined) {
1812
+ this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback);
1813
+ this.throwBroadlyMatchedException (this.exceptions['broad'], code, feedback);
1814
+ }
1815
+ // throw new ExchangeError (this.id + ' malformed response ' + this.json (response));
1816
+ return;
1817
+ }
1818
+ if (typeof success === 'string') {
1819
+ // bleutrade uses string instead of boolean
1820
+ success = (success === 'true');
1821
+ }
1822
+ if (!success) {
1823
+ const message = this.safeString (response, 'message');
1824
+ if (message === 'APIKEY_INVALID') {
1825
+ if (this.options['hasAlreadyAuthenticatedSuccessfully']) {
1826
+ throw new DDoSProtection (feedback);
1827
+ } else {
1828
+ throw new AuthenticationError (feedback);
1829
+ }
1830
+ }
1831
+ // https://github.com/ccxt/ccxt/issues/4932
1832
+ // the following two lines are now redundant, see line 171 in describe()
1833
+ //
1834
+ // if (message === 'DUST_TRADE_DISALLOWED_MIN_VALUE_50K_SAT')
1835
+ // throw new InvalidOrder (this.id + ' order cost should be over 50k satoshi ' + this.json (response));
1836
+ //
1837
+ if (message === 'INVALID_ORDER') {
1838
+ // Bittrex will return an ambiguous INVALID_ORDER message
1839
+ // upon canceling already-canceled and closed orders
1840
+ // therefore this special case for cancelOrder
1841
+ // let url = 'https://bittrex.com/api/v1.1/market/cancel?apikey=API_KEY&uuid=ORDER_UUID'
1842
+ const cancel = 'cancel';
1843
+ const indexOfCancel = url.indexOf (cancel);
1844
+ if (indexOfCancel >= 0) {
1845
+ const urlParts = url.split ('?');
1846
+ const numParts = urlParts.length;
1847
+ if (numParts > 1) {
1848
+ const query = urlParts[1];
1849
+ const params = query.split ('&');
1850
+ const numParams = params.length;
1851
+ let orderId = undefined;
1852
+ for (let i = 0; i < numParams; i++) {
1853
+ const param = params[i];
1854
+ const keyValue = param.split ('=');
1855
+ if (keyValue[0] === 'uuid') {
1856
+ orderId = keyValue[1];
1857
+ break;
1858
+ }
1859
+ }
1860
+ if (orderId !== undefined) {
1861
+ throw new OrderNotFound (this.id + ' cancelOrder ' + orderId + ' ' + this.json (response));
1862
+ } else {
1863
+ throw new OrderNotFound (this.id + ' cancelOrder ' + this.json (response));
1864
+ }
1865
+ }
1866
+ }
1867
+ }
1868
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
1869
+ if (message !== undefined) {
1870
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
1871
+ }
1872
+ throw new ExchangeError (feedback);
1873
+ }
1874
+ }
1875
+ }
1876
+ };