ccxt 4.3.65 → 4.3.67

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 (48) hide show
  1. package/README.md +4 -3
  2. package/dist/ccxt.browser.min.js +2 -2
  3. package/dist/cjs/ccxt.js +1 -1
  4. package/dist/cjs/src/base/Exchange.js +2 -2
  5. package/dist/cjs/src/bingx.js +151 -19
  6. package/dist/cjs/src/bithumb.js +61 -17
  7. package/dist/cjs/src/hyperliquid.js +63 -7
  8. package/dist/cjs/src/independentreserve.js +0 -1
  9. package/dist/cjs/src/kraken.js +27 -0
  10. package/dist/cjs/src/pro/hyperliquid.js +103 -1
  11. package/dist/cjs/src/pro/okx.js +22 -9
  12. package/js/ccxt.d.ts +1 -1
  13. package/js/ccxt.js +1 -1
  14. package/js/src/abstract/bingx.d.ts +7 -0
  15. package/js/src/base/Exchange.d.ts +14 -13
  16. package/js/src/base/Exchange.js +2 -2
  17. package/js/src/bingx.js +151 -19
  18. package/js/src/bithumb.js +61 -17
  19. package/js/src/hyperliquid.d.ts +3 -1
  20. package/js/src/hyperliquid.js +63 -7
  21. package/js/src/independentreserve.js +1 -1
  22. package/js/src/kraken.d.ts +7 -0
  23. package/js/src/kraken.js +27 -0
  24. package/js/src/pro/bitget.d.ts +1 -1
  25. package/js/src/pro/bybit.d.ts +1 -1
  26. package/js/src/pro/coinone.d.ts +1 -1
  27. package/js/src/pro/currencycom.d.ts +1 -1
  28. package/js/src/pro/hollaex.d.ts +1 -1
  29. package/js/src/pro/hyperliquid.d.ts +5 -2
  30. package/js/src/pro/hyperliquid.js +103 -1
  31. package/js/src/pro/kucoin.d.ts +1 -1
  32. package/js/src/pro/kucoinfutures.d.ts +1 -1
  33. package/js/src/pro/mexc.d.ts +1 -1
  34. package/js/src/pro/okcoin.d.ts +1 -1
  35. package/js/src/pro/okx.d.ts +2 -2
  36. package/js/src/pro/okx.js +23 -10
  37. package/js/src/pro/oxfun.d.ts +1 -1
  38. package/js/src/pro/p2b.d.ts +1 -1
  39. package/js/src/pro/poloniex.d.ts +1 -1
  40. package/js/src/pro/whitebit.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/dist/cjs/src/abstract/bittrex.js +0 -9
  43. package/dist/cjs/src/bittrex.js +0 -2308
  44. package/dist/cjs/src/pro/bittrex.js +0 -959
  45. package/js/src/bittrex.d.ts +0 -97
  46. package/js/src/bittrex.js +0 -2309
  47. package/js/src/pro/bittrex.d.ts +0 -69
  48. package/js/src/pro/bittrex.js +0 -960
@@ -1,2308 +0,0 @@
1
- 'use strict';
2
-
3
- var bittrex$1 = require('./abstract/bittrex.js');
4
- var errors = require('./base/errors.js');
5
- var number = require('./base/functions/number.js');
6
- var sha512 = require('./static_dependencies/noble-hashes/sha512.js');
7
-
8
- // ---------------------------------------------------------------------------
9
- // ---------------------------------------------------------------------------
10
- /**
11
- * @class bittrex
12
- * @augments Exchange
13
- */
14
- class bittrex extends bittrex$1 {
15
- describe() {
16
- return this.deepExtend(super.describe(), {
17
- 'id': 'bittrex',
18
- 'name': 'Bittrex',
19
- 'countries': ['US'],
20
- 'version': 'v3',
21
- 'rateLimit': 1500,
22
- 'certified': false,
23
- 'pro': true,
24
- // new metainfo interface
25
- 'has': {
26
- 'CORS': undefined,
27
- 'spot': true,
28
- 'margin': false,
29
- 'swap': false,
30
- 'future': false,
31
- 'option': false,
32
- 'addMargin': false,
33
- 'cancelAllOrders': true,
34
- 'cancelOrder': true,
35
- 'closeAllPositions': false,
36
- 'closePosition': false,
37
- 'createDepositAddress': true,
38
- 'createMarketOrder': true,
39
- 'createOrder': true,
40
- 'createReduceOnlyOrder': false,
41
- 'createStopLimitOrder': true,
42
- 'createStopMarketOrder': true,
43
- 'createStopOrder': true,
44
- 'fetchBalance': true,
45
- 'fetchBidsAsks': true,
46
- 'fetchBorrowRateHistories': false,
47
- 'fetchBorrowRateHistory': false,
48
- 'fetchClosedOrders': true,
49
- 'fetchCrossBorrowRate': false,
50
- 'fetchCrossBorrowRates': false,
51
- 'fetchCurrencies': true,
52
- 'fetchDeposit': true,
53
- 'fetchDepositAddress': true,
54
- 'fetchDeposits': true,
55
- 'fetchDepositWithdrawFee': 'emulated',
56
- 'fetchDepositWithdrawFees': true,
57
- 'fetchFundingHistory': false,
58
- 'fetchFundingRate': false,
59
- 'fetchFundingRateHistory': false,
60
- 'fetchFundingRates': false,
61
- 'fetchIndexOHLCV': false,
62
- 'fetchIsolatedBorrowRate': false,
63
- 'fetchIsolatedBorrowRates': false,
64
- 'fetchLeverage': false,
65
- 'fetchLeverageTiers': false,
66
- 'fetchMarginMode': false,
67
- 'fetchMarkets': true,
68
- 'fetchMarkOHLCV': false,
69
- 'fetchMyTrades': true,
70
- 'fetchOHLCV': true,
71
- 'fetchOpenInterestHistory': false,
72
- 'fetchOpenOrders': true,
73
- 'fetchOrder': true,
74
- 'fetchOrderBook': true,
75
- 'fetchOrderTrades': true,
76
- 'fetchPosition': false,
77
- 'fetchPositionMode': false,
78
- 'fetchPositions': false,
79
- 'fetchPositionsRisk': false,
80
- 'fetchPremiumIndexOHLCV': false,
81
- 'fetchTicker': true,
82
- 'fetchTickers': true,
83
- 'fetchTime': true,
84
- 'fetchTrades': true,
85
- 'fetchTradingFee': true,
86
- 'fetchTradingFees': true,
87
- 'fetchTransactionFees': undefined,
88
- 'fetchTransactions': false,
89
- 'fetchWithdrawal': true,
90
- 'fetchWithdrawals': true,
91
- 'reduceMargin': false,
92
- 'setLeverage': false,
93
- 'setMarginMode': false,
94
- 'setPositionMode': false,
95
- 'withdraw': true,
96
- },
97
- 'timeframes': {
98
- '1m': 'MINUTE_1',
99
- '5m': 'MINUTE_5',
100
- '1h': 'HOUR_1',
101
- '1d': 'DAY_1',
102
- },
103
- 'hostname': 'bittrex.com',
104
- 'urls': {
105
- 'logo': 'https://user-images.githubusercontent.com/51840849/87153921-edf53180-c2c0-11ea-96b9-f2a9a95a455b.jpg',
106
- 'api': {
107
- 'public': 'https://api.bittrex.com',
108
- 'private': 'https://api.bittrex.com',
109
- },
110
- 'www': 'https://bittrex.com',
111
- 'doc': [
112
- 'https://bittrex.github.io/api/v3',
113
- ],
114
- 'fees': [
115
- 'https://bittrex.zendesk.com/hc/en-us/articles/115003684371-BITTREX-SERVICE-FEES-AND-WITHDRAWAL-LIMITATIONS',
116
- 'https://bittrex.zendesk.com/hc/en-us/articles/115000199651-What-fees-does-Bittrex-charge-',
117
- ],
118
- 'referral': 'https://bittrex.com/Account/Register?referralCode=1ZE-G0G-M3B',
119
- },
120
- 'api': {
121
- 'public': {
122
- 'get': [
123
- 'ping',
124
- 'currencies',
125
- 'currencies/{symbol}',
126
- 'markets',
127
- 'markets/tickers',
128
- 'markets/summaries',
129
- 'markets/{marketSymbol}',
130
- 'markets/{marketSymbol}/summary',
131
- 'markets/{marketSymbol}/orderbook',
132
- 'markets/{marketSymbol}/trades',
133
- 'markets/{marketSymbol}/ticker',
134
- 'markets/{marketSymbol}/candles/{candleInterval}/recent',
135
- 'markets/{marketSymbol}/candles/{candleInterval}/historical/{year}/{month}/{day}',
136
- 'markets/{marketSymbol}/candles/{candleInterval}/historical/{year}/{month}',
137
- 'markets/{marketSymbol}/candles/{candleInterval}/historical/{year}',
138
- ],
139
- },
140
- 'private': {
141
- 'get': [
142
- 'account',
143
- 'account/fees/fiat',
144
- 'account/fees/fiat/{currencySymbol}',
145
- 'account/fees/trading',
146
- 'account/fees/trading/{marketSymbol}',
147
- 'account/volume',
148
- 'account/permissions/markets',
149
- 'account/permissions/markets/{marketSymbol}',
150
- 'account/permissions/currencies',
151
- 'account/permissions/currencies/{currencySymbol}',
152
- 'addresses',
153
- 'addresses/{currencySymbol}',
154
- 'balances',
155
- 'balances/{currencySymbol}',
156
- 'deposits/open',
157
- 'deposits/closed',
158
- 'deposits/ByTxId/{txId}',
159
- 'deposits/{depositId}',
160
- 'executions',
161
- 'executions/last-id',
162
- 'executions/{executionId}',
163
- 'orders/closed',
164
- 'orders/open',
165
- 'orders/{orderId}',
166
- 'orders/{orderId}/executions',
167
- 'ping',
168
- 'subaccounts/{subaccountId}',
169
- 'subaccounts',
170
- 'subaccounts/withdrawals/open',
171
- 'subaccounts/withdrawals/closed',
172
- 'subaccounts/deposits/open',
173
- 'subaccounts/deposits/closed',
174
- 'withdrawals/open',
175
- 'withdrawals/closed',
176
- 'withdrawals/ByTxId/{txId}',
177
- 'withdrawals/{withdrawalId}',
178
- 'withdrawals/allowed-addresses',
179
- 'conditional-orders/{conditionalOrderId}',
180
- 'conditional-orders/closed',
181
- 'conditional-orders/open',
182
- 'transfers/sent',
183
- 'transfers/received',
184
- 'transfers/{transferId}',
185
- 'funds-transfer-methods/{fundsTransferMethodId}',
186
- ],
187
- 'post': [
188
- 'addresses',
189
- 'orders',
190
- 'subaccounts',
191
- 'withdrawals',
192
- 'conditional-orders',
193
- 'transfers',
194
- 'batch',
195
- ],
196
- 'delete': [
197
- 'orders/open',
198
- 'orders/{orderId}',
199
- 'withdrawals/{withdrawalId}',
200
- 'conditional-orders/{conditionalOrderId}',
201
- ],
202
- },
203
- },
204
- 'fees': {
205
- 'trading': {
206
- 'tierBased': true,
207
- 'percentage': true,
208
- 'maker': this.parseNumber('0.0075'),
209
- 'taker': this.parseNumber('0.0075'),
210
- },
211
- 'funding': {
212
- 'tierBased': false,
213
- 'percentage': false,
214
- },
215
- },
216
- 'precisionMode': number.TICK_SIZE,
217
- 'exceptions': {
218
- 'exact': {
219
- 'BAD_REQUEST': errors.BadRequest,
220
- 'STARTDATE_OUT_OF_RANGE': errors.BadRequest,
221
- // 'Call to Cancel was throttled. Try again in 60 seconds.': DDoSProtection,
222
- // 'Call to GetBalances was throttled. Try again in 60 seconds.': DDoSProtection,
223
- 'APISIGN_NOT_PROVIDED': errors.AuthenticationError,
224
- 'APIKEY_INVALID': errors.AuthenticationError,
225
- 'INVALID_SIGNATURE': errors.AuthenticationError,
226
- 'INVALID_CURRENCY': errors.ExchangeError,
227
- 'INVALID_PERMISSION': errors.AuthenticationError,
228
- 'INSUFFICIENT_FUNDS': errors.InsufficientFunds,
229
- 'INVALID_CEILING_MARKET_BUY': errors.InvalidOrder,
230
- 'INVALID_FIAT_ACCOUNT': errors.InvalidOrder,
231
- 'INVALID_ORDER_TYPE': errors.InvalidOrder,
232
- 'QUANTITY_NOT_PROVIDED': errors.InvalidOrder,
233
- 'MIN_TRADE_REQUIREMENT_NOT_MET': errors.InvalidOrder,
234
- 'NOT_FOUND': errors.OrderNotFound,
235
- 'ORDER_NOT_OPEN': errors.OrderNotFound,
236
- 'INVALID_ORDER': errors.InvalidOrder,
237
- 'UUID_INVALID': errors.OrderNotFound,
238
- 'RATE_NOT_PROVIDED': errors.InvalidOrder,
239
- 'INVALID_MARKET': errors.BadSymbol,
240
- 'WHITELIST_VIOLATION_IP': errors.PermissionDenied,
241
- 'DUST_TRADE_DISALLOWED_MIN_VALUE': errors.InvalidOrder,
242
- 'RESTRICTED_MARKET': errors.BadSymbol,
243
- 'We are down for scheduled maintenance, but we\u2019ll be back up shortly.': errors.OnMaintenance, // {"success":false,"message":"We are down for scheduled maintenance, but we\u2019ll be back up shortly.","result":null,"explanation":null}
244
- },
245
- 'broad': {
246
- 'throttled': errors.DDoSProtection,
247
- 'problem': errors.ExchangeNotAvailable,
248
- },
249
- },
250
- 'options': {
251
- 'fetchTicker': {
252
- 'method': 'publicGetMarketsMarketSymbolTicker', // publicGetMarketsMarketSymbolSummary
253
- },
254
- 'fetchTickers': {
255
- 'method': 'publicGetMarketsTickers', // publicGetMarketsSummaries
256
- },
257
- 'fetchDeposits': {
258
- 'status': 'ok',
259
- },
260
- 'fetchWithdrawals': {
261
- 'status': 'ok',
262
- },
263
- 'parseOrderStatus': false,
264
- 'hasAlreadyAuthenticatedSuccessfully': false,
265
- 'subaccountId': undefined,
266
- // see the implementation of fetchClosedOrdersV3 below
267
- // 'fetchClosedOrdersMethod': 'fetch_closed_orders_v3',
268
- 'fetchClosedOrdersFilterBySince': true,
269
- // 'createOrderMethod': 'create_order_v1',
270
- },
271
- 'commonCurrencies': {
272
- 'BIFI': 'Bifrost Finance',
273
- 'BTR': 'BTRIPS',
274
- 'GMT': 'GMT Token',
275
- 'MEME': 'Memetic',
276
- 'MER': 'Mercury',
277
- 'PROS': 'Pros.Finance',
278
- 'REPV2': 'REP',
279
- 'TON': 'Tokamak Network',
280
- },
281
- });
282
- }
283
- feeToPrecision(symbol, fee) {
284
- return this.decimalToPrecision(fee, number.TRUNCATE, this.markets[symbol]['precision']['price'], this.precisionMode);
285
- }
286
- async fetchMarkets(params = {}) {
287
- /**
288
- * @method
289
- * @name bittrex#fetchMarkets
290
- * @description retrieves data on all markets for bittrex
291
- * @param {object} [params] extra parameters specific to the exchange API endpoint
292
- * @returns {object[]} an array of objects representing market data
293
- */
294
- const response = await this.publicGetMarkets(params);
295
- //
296
- // [
297
- // {
298
- // "symbol":"LTC-BTC",
299
- // "baseCurrencySymbol":"LTC",
300
- // "quoteCurrencySymbol":"BTC",
301
- // "minTradeSize":"0.01686767",
302
- // "precision":8,
303
- // "status":"ONLINE", // "OFFLINE"
304
- // "createdAt":"2014-02-13T00:00:00Z"
305
- // },
306
- // {
307
- // "symbol":"VDX-USDT",
308
- // "baseCurrencySymbol":"VDX",
309
- // "quoteCurrencySymbol":"USDT",
310
- // "minTradeSize":"300.00000000",
311
- // "precision":8,
312
- // "status":"ONLINE", // "OFFLINE"
313
- // "createdAt":"2019-05-23T00:41:21.843Z",
314
- // "notice":"USDT has swapped to an ERC20-based token as of August 5, 2019."
315
- // }
316
- // ]
317
- //
318
- return this.parseMarkets(response);
319
- }
320
- parseMarket(market) {
321
- const baseId = this.safeString(market, 'baseCurrencySymbol');
322
- const quoteId = this.safeString(market, 'quoteCurrencySymbol');
323
- const base = this.safeCurrencyCode(baseId);
324
- const quote = this.safeCurrencyCode(quoteId);
325
- const status = this.safeString(market, 'status');
326
- return {
327
- 'id': this.safeString(market, 'symbol'),
328
- 'symbol': base + '/' + quote,
329
- 'base': base,
330
- 'quote': quote,
331
- 'settle': undefined,
332
- 'baseId': baseId,
333
- 'quoteId': quoteId,
334
- 'settleId': undefined,
335
- 'type': 'spot',
336
- 'spot': true,
337
- 'margin': false,
338
- 'swap': false,
339
- 'future': false,
340
- 'option': false,
341
- 'active': (status === 'ONLINE'),
342
- 'contract': false,
343
- 'linear': undefined,
344
- 'inverse': undefined,
345
- 'contractSize': undefined,
346
- 'expiry': undefined,
347
- 'expiryDatetime': undefined,
348
- 'strike': undefined,
349
- 'optionType': undefined,
350
- 'precision': {
351
- 'amount': this.parseNumber('1e-8'),
352
- 'price': this.parseNumber(this.parsePrecision(this.safeString(market, 'precision'))),
353
- },
354
- 'limits': {
355
- 'leverage': {
356
- 'min': undefined,
357
- 'max': undefined,
358
- },
359
- 'amount': {
360
- 'min': this.safeNumber(market, 'minTradeSize'),
361
- 'max': undefined,
362
- },
363
- 'price': {
364
- 'min': undefined,
365
- 'max': undefined,
366
- },
367
- 'cost': {
368
- 'min': undefined,
369
- 'max': undefined,
370
- },
371
- },
372
- 'created': this.parse8601(this.safeString(market, 'createdAt')),
373
- 'info': market,
374
- };
375
- }
376
- parseBalance(response) {
377
- const result = { 'info': response };
378
- const indexed = this.indexBy(response, 'currencySymbol');
379
- const currencyIds = Object.keys(indexed);
380
- for (let i = 0; i < currencyIds.length; i++) {
381
- const currencyId = currencyIds[i];
382
- const code = this.safeCurrencyCode(currencyId);
383
- const account = this.account();
384
- const balance = indexed[currencyId];
385
- account['free'] = this.safeString(balance, 'available');
386
- account['total'] = this.safeString(balance, 'total');
387
- result[code] = account;
388
- }
389
- return this.safeBalance(result);
390
- }
391
- async fetchBalance(params = {}) {
392
- /**
393
- * @method
394
- * @name bittrex#fetchBalance
395
- * @description query for balance and get the amount of funds available for trading or funds locked in orders
396
- * @param {object} [params] extra parameters specific to the exchange API endpoint
397
- * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
398
- */
399
- await this.loadMarkets();
400
- const response = await this.privateGetBalances(params);
401
- return this.parseBalance(response);
402
- }
403
- async fetchOrderBook(symbol, limit = undefined, params = {}) {
404
- /**
405
- * @method
406
- * @name bittrex#fetchOrderBook
407
- * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
408
- * @param {string} symbol unified symbol of the market to fetch the order book for
409
- * @param {int} [limit] the maximum amount of order book entries to return
410
- * @param {object} [params] extra parameters specific to the exchange API endpoint
411
- * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
412
- */
413
- await this.loadMarkets();
414
- const market = this.market(symbol);
415
- const request = {
416
- 'marketSymbol': market['id'],
417
- };
418
- if (limit !== undefined) {
419
- if ((limit !== 1) && (limit !== 25) && (limit !== 500)) {
420
- throw new errors.BadRequest(this.id + ' fetchOrderBook() limit argument must be undefined, 1, 25 or 500, default is 25');
421
- }
422
- request['depth'] = limit;
423
- }
424
- const response = await this.publicGetMarketsMarketSymbolOrderbook(this.extend(request, params));
425
- //
426
- // {
427
- // "bid":[
428
- // {"quantity":"0.01250000","rate":"10718.56200003"},
429
- // {"quantity":"0.10000000","rate":"10718.56200002"},
430
- // {"quantity":"0.39648292","rate":"10718.56200001"},
431
- // ],
432
- // "ask":[
433
- // {"quantity":"0.05100000","rate":"10724.30099631"},
434
- // {"quantity":"0.10000000","rate":"10724.30099632"},
435
- // {"quantity":"0.26000000","rate":"10724.30099634"},
436
- // ]
437
- // }
438
- //
439
- const sequence = this.safeInteger(this.last_response_headers, 'Sequence');
440
- const orderbook = this.parseOrderBook(response, market['symbol'], undefined, 'bid', 'ask', 'rate', 'quantity');
441
- orderbook['nonce'] = sequence;
442
- return orderbook;
443
- }
444
- async fetchCurrencies(params = {}) {
445
- /**
446
- * @method
447
- * @name bittrex#fetchCurrencies
448
- * @description fetches all available currencies on an exchange
449
- * @param {object} [params] extra parameters specific to the exchange API endpoint
450
- * @returns {object} an associative dictionary of currencies
451
- */
452
- const response = await this.publicGetCurrencies(params);
453
- //
454
- // [
455
- // {
456
- // "symbol":"1ST",
457
- // "name":"Firstblood",
458
- // "coinType":"ETH_CONTRACT",
459
- // "status":"ONLINE",
460
- // "minConfirmations":36,
461
- // "notice":"",
462
- // "txFee":"4.50000000",
463
- // "logoUrl":"https://bittrexblobstorage.blob.core.windows.net/public/5685a7be-1edf-4ba0-a313-b5309bb204f8.png",
464
- // "prohibitedIn":[],
465
- // "baseAddress":"0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98",
466
- // "associatedTermsOfService":[]
467
- // }
468
- // ]
469
- //
470
- const result = {};
471
- for (let i = 0; i < response.length; i++) {
472
- const currency = response[i];
473
- const id = this.safeString(currency, 'symbol');
474
- const code = this.safeCurrencyCode(id);
475
- const precision = this.parseNumber('1e-8'); // default precision, seems exchange has same amount-precision across all pairs in UI too. todo: fix "magic constants"
476
- const fee = this.safeNumber(currency, 'txFee'); // todo: redesign
477
- const isActive = this.safeString(currency, 'status');
478
- const coinType = this.safeString(currency, 'coinType');
479
- let type = undefined;
480
- if (coinType === 'FIAT') {
481
- type = 'fiat';
482
- }
483
- else if (coinType === 'Award') {
484
- // these are exchange credits
485
- type = 'other';
486
- }
487
- else {
488
- // all others are cryptos
489
- type = 'crypto';
490
- }
491
- result[code] = {
492
- 'id': id,
493
- 'code': code,
494
- 'info': currency,
495
- 'type': type,
496
- 'name': this.safeString(currency, 'name'),
497
- 'active': (isActive === 'ONLINE'),
498
- 'deposit': undefined,
499
- 'withdraw': undefined,
500
- 'fee': fee,
501
- 'precision': precision,
502
- 'limits': {
503
- 'amount': {
504
- 'min': precision,
505
- 'max': undefined,
506
- },
507
- 'withdraw': {
508
- 'min': fee,
509
- 'max': undefined,
510
- },
511
- },
512
- 'networks': {},
513
- };
514
- }
515
- return result;
516
- }
517
- parseTicker(ticker, market = undefined) {
518
- //
519
- // ticker
520
- //
521
- // {
522
- // "symbol":"ETH-BTC",
523
- // "lastTradeRate":"0.03284496",
524
- // "bidRate":"0.03284523",
525
- // "askRate":"0.03286857"
526
- // }
527
- //
528
- // summary
529
- //
530
- // {
531
- // "symbol":"ETH-BTC",
532
- // "high":"0.03369528",
533
- // "low":"0.03282442",
534
- // "volume":"4307.83794556",
535
- // "quoteVolume":"143.08608869",
536
- // "percentChange":"0.79",
537
- // "updatedAt":"2020-09-29T07:36:57.823Z"
538
- // }
539
- //
540
- const timestamp = this.parse8601(this.safeString(ticker, 'updatedAt'));
541
- const marketId = this.safeString(ticker, 'symbol');
542
- market = this.safeMarket(marketId, market, '-');
543
- const symbol = market['symbol'];
544
- const percentage = this.safeString(ticker, 'percentChange');
545
- const last = this.safeString(ticker, 'lastTradeRate');
546
- return this.safeTicker({
547
- 'symbol': symbol,
548
- 'timestamp': timestamp,
549
- 'datetime': this.iso8601(timestamp),
550
- 'high': this.safeString(ticker, 'high'),
551
- 'low': this.safeString(ticker, 'low'),
552
- 'bid': this.safeString(ticker, 'bidRate'),
553
- 'bidVolume': undefined,
554
- 'ask': this.safeString(ticker, 'askRate'),
555
- 'askVolume': undefined,
556
- 'vwap': undefined,
557
- 'open': undefined,
558
- 'close': last,
559
- 'last': last,
560
- 'previousClose': undefined,
561
- 'change': undefined,
562
- 'percentage': percentage,
563
- 'average': undefined,
564
- 'baseVolume': this.safeString(ticker, 'volume'),
565
- 'quoteVolume': this.safeString(ticker, 'quoteVolume'),
566
- 'info': ticker,
567
- }, market);
568
- }
569
- async fetchTickers(symbols = undefined, params = {}) {
570
- /**
571
- * @method
572
- * @name bittrex#fetchTickers
573
- * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
574
- * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
575
- * @param {object} [params] extra parameters specific to the exchange API endpoint
576
- * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
577
- */
578
- await this.loadMarkets();
579
- symbols = this.marketSymbols(symbols);
580
- const options = this.safeValue(this.options, 'fetchTickers', {});
581
- const defaultMethod = this.safeString(options, 'method', 'publicGetMarketsTickers');
582
- const method = this.safeString(params, 'method', defaultMethod);
583
- params = this.omit(params, 'method');
584
- const response = await this[method](params);
585
- //
586
- // publicGetMarketsTickers
587
- //
588
- // [
589
- // {
590
- // "symbol":"4ART-BTC",
591
- // "lastTradeRate":"0.00000210",
592
- // "bidRate":"0.00000210",
593
- // "askRate":"0.00000215"
594
- // }
595
- // ]
596
- //
597
- // publicGetMarketsSummaries
598
- //
599
- // [
600
- // {
601
- // "symbol":"4ART-BTC",
602
- // "high":"0.00000206",
603
- // "low":"0.00000196",
604
- // "volume":"14871.32000233",
605
- // "quoteVolume":"0.02932756",
606
- // "percentChange":"1.48",
607
- // "updatedAt":"2020-09-29T07:34:32.757Z"
608
- // }
609
- // ]
610
- //
611
- const tickers = [];
612
- for (let i = 0; i < response.length; i++) {
613
- const ticker = this.parseTicker(response[i]);
614
- tickers.push(ticker);
615
- }
616
- return this.filterByArrayTickers(tickers, 'symbol', symbols);
617
- }
618
- async fetchTicker(symbol, params = {}) {
619
- /**
620
- * @method
621
- * @name bittrex#fetchTicker
622
- * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
623
- * @param {string} symbol unified symbol of the market to fetch the ticker for
624
- * @param {object} [params] extra parameters specific to the exchange API endpoint
625
- * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
626
- */
627
- await this.loadMarkets();
628
- const market = this.market(symbol);
629
- const request = {
630
- 'marketSymbol': market['id'],
631
- };
632
- const options = this.safeValue(this.options, 'fetchTicker', {});
633
- const defaultMethod = this.safeString(options, 'method', 'publicGetMarketsMarketSymbolTicker');
634
- const method = this.safeString(params, 'method', defaultMethod);
635
- params = this.omit(params, 'method');
636
- const response = await this[method](this.extend(request, params));
637
- //
638
- // publicGetMarketsMarketSymbolTicker
639
- //
640
- // {
641
- // "symbol":"ETH-BTC",
642
- // "lastTradeRate":"0.03284496",
643
- // "bidRate":"0.03284523",
644
- // "askRate":"0.03286857"
645
- // }
646
- //
647
- //
648
- // publicGetMarketsMarketSymbolSummary
649
- //
650
- // {
651
- // "symbol":"ETH-BTC",
652
- // "high":"0.03369528",
653
- // "low":"0.03282442",
654
- // "volume":"4307.83794556",
655
- // "quoteVolume":"143.08608869",
656
- // "percentChange":"0.79",
657
- // "updatedAt":"2020-09-29T07:36:57.823Z"
658
- // }
659
- //
660
- return this.parseTicker(response, market);
661
- }
662
- async fetchBidsAsks(symbols = undefined, params = {}) {
663
- /**
664
- * @method
665
- * @name bittrex#fetchBidsAsks
666
- * @description fetches the bid and ask price and volume for multiple markets
667
- * @param {string[]|undefined} symbols unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
668
- * @param {object} [params] extra parameters specific to the exchange API endpoint
669
- * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
670
- */
671
- await this.loadMarkets();
672
- const response = await this.publicGetMarketsTickers(params);
673
- //
674
- // [
675
- // {
676
- // "symbol":"ETH-BTC",
677
- // "lastTradeRate":"0.03284496",
678
- // "bidRate":"0.03284523",
679
- // "askRate":"0.03286857"
680
- // }
681
- // ]
682
- //
683
- return this.parseTickers(response, symbols);
684
- }
685
- parseTrade(trade, market = undefined) {
686
- //
687
- // public fetchTrades
688
- //
689
- // {
690
- // "id": "8a614d4e-e455-45b0-9aac-502b0aeb433f",
691
- // "executedAt": "2021-11-25T14:54:44.65Z",
692
- // "quantity": "30.00000000",
693
- // "rate": "1.72923112",
694
- // "takerSide": "SELL"
695
- // }
696
- //
697
- // private fetchOrderTrades
698
- // {
699
- // "id": "8a614d4e-e455-45b0-9aac-502b0aeb433f",
700
- // "marketSymbol": "ADA-USDT",
701
- // "executedAt": "2021-11-25T14:54:44.65Z",
702
- // "quantity": "30.00000000",
703
- // "rate": "1.72923112",
704
- // "orderId": "6f7abf18-6901-4659-a48c-db0e88440ea4",
705
- // "commission": "0.38907700",
706
- // "isTaker": true
707
- // }
708
- //
709
- // private fetchMyTrades
710
- // {
711
- // "id":"7e6488c9-294f-4137-b0f2-9f86578186fe",
712
- // "marketSymbol":"DOGE-USDT",
713
- // "executedAt":"2022-08-12T21:27:37.92Z",
714
- // "quantity":"100.00000000",
715
- // "rate":"0.071584100000",
716
- // "orderId":"2d53f11a-fb22-4820-b04d-80e5f48e6005",
717
- // "commission":"0.05368807",
718
- // "isTaker":true,
719
- // "direction":"BUY"
720
- // }
721
- //
722
- const timestamp = this.parse8601(this.safeString(trade, 'executedAt'));
723
- const id = this.safeString(trade, 'id');
724
- const order = this.safeString(trade, 'orderId');
725
- const marketId = this.safeString(trade, 'marketSymbol');
726
- market = this.safeMarket(marketId, market, '-');
727
- const priceString = this.safeString(trade, 'rate');
728
- const amountString = this.safeString(trade, 'quantity');
729
- let takerOrMaker = undefined;
730
- let side = this.safeStringLower2(trade, 'takerSide', 'direction');
731
- const isTaker = this.safeValue(trade, 'isTaker');
732
- if (isTaker !== undefined) {
733
- takerOrMaker = isTaker ? 'taker' : 'maker';
734
- if (!isTaker) { // as noted in PR #15655 this API provides confusing value - when it's 'maker' trade, then side value should reversed
735
- if (side === 'buy') {
736
- side = 'sell';
737
- }
738
- else if (side === 'sell') {
739
- side = 'buy';
740
- }
741
- }
742
- }
743
- let fee = undefined;
744
- const feeCostString = this.safeString(trade, 'commission');
745
- if (feeCostString !== undefined) {
746
- fee = {
747
- 'cost': feeCostString,
748
- 'currency': market['quote'],
749
- };
750
- }
751
- return this.safeTrade({
752
- 'info': trade,
753
- 'timestamp': timestamp,
754
- 'datetime': this.iso8601(timestamp),
755
- 'symbol': market['symbol'],
756
- 'id': id,
757
- 'order': order,
758
- 'takerOrMaker': takerOrMaker,
759
- 'type': undefined,
760
- 'side': side,
761
- 'price': priceString,
762
- 'amount': amountString,
763
- 'cost': undefined,
764
- 'fee': fee,
765
- }, market);
766
- }
767
- async fetchTime(params = {}) {
768
- /**
769
- * @method
770
- * @name bittrex#fetchTime
771
- * @description fetches the current integer timestamp in milliseconds from the exchange server
772
- * @param {object} [params] extra parameters specific to the exchange API endpoint
773
- * @returns {int} the current integer timestamp in milliseconds from the exchange server
774
- */
775
- const response = await this.publicGetPing(params);
776
- //
777
- // {
778
- // "serverTime": 1594596023162
779
- // }
780
- //
781
- return this.safeInteger(response, 'serverTime');
782
- }
783
- async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
784
- /**
785
- * @method
786
- * @name bittrex#fetchTrades
787
- * @description get the list of most recent trades for a particular symbol
788
- * @param {string} symbol unified symbol of the market to fetch trades for
789
- * @param {int} [since] timestamp in ms of the earliest trade to fetch
790
- * @param {int} [limit] the maximum amount of trades to fetch
791
- * @param {object} [params] extra parameters specific to the exchange API endpoint
792
- * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
793
- */
794
- await this.loadMarkets();
795
- const market = this.market(symbol);
796
- const request = {
797
- 'marketSymbol': market['id'],
798
- };
799
- const response = await this.publicGetMarketsMarketSymbolTrades(this.extend(request, params));
800
- //
801
- // [
802
- // {
803
- // "id":"9c5589db-42fb-436c-b105-5e2edcb95673",
804
- // "executedAt":"2020-10-03T11:48:43.38Z",
805
- // "quantity":"0.17939626",
806
- // "rate":"0.03297952",
807
- // "takerSide":"BUY"
808
- // }
809
- // ]
810
- //
811
- return this.parseTrades(response, market, since, limit);
812
- }
813
- async fetchTradingFee(symbol, params = {}) {
814
- /**
815
- * @method
816
- * @name bittrex#fetchTradingFee
817
- * @description fetch the trading fees for a market
818
- * @param {string} symbol unified market symbol
819
- * @param {object} [params] extra parameters specific to the exchange API endpoint
820
- * @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
821
- */
822
- await this.loadMarkets();
823
- const market = this.market(symbol);
824
- const request = {
825
- 'marketSymbol': market['id'],
826
- };
827
- const response = await this.privateGetAccountFeesTradingMarketSymbol(this.extend(request, params));
828
- //
829
- // {
830
- // "marketSymbol":"1INCH-ETH",
831
- // "makerRate":"0.00750000",
832
- // "takerRate":"0.00750000"
833
- // }
834
- //
835
- return this.parseTradingFee(response, market);
836
- }
837
- async fetchTradingFees(params = {}) {
838
- /**
839
- * @method
840
- * @name bittrex#fetchTradingFees
841
- * @description fetch the trading fees for multiple markets
842
- * @param {object} [params] extra parameters specific to the exchange API endpoint
843
- * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
844
- */
845
- await this.loadMarkets();
846
- const response = await this.privateGetAccountFeesTrading(params);
847
- //
848
- // [
849
- // {"marketSymbol":"1ECO-BTC","makerRate":"0.00750000","takerRate":"0.00750000"},
850
- // {"marketSymbol":"1ECO-USDT","makerRate":"0.00750000","takerRate":"0.00750000"},
851
- // {"marketSymbol":"1INCH-BTC","makerRate":"0.00750000","takerRate":"0.00750000"},
852
- // {"marketSymbol":"1INCH-ETH","makerRate":"0.00750000","takerRate":"0.00750000"},
853
- // {"marketSymbol":"1INCH-USD","makerRate":"0.00750000","takerRate":"0.00750000"},
854
- // ]
855
- //
856
- return this.parseTradingFees(response);
857
- }
858
- parseTradingFee(fee, market = undefined) {
859
- const marketId = this.safeString(fee, 'marketSymbol');
860
- const maker = this.safeNumber(fee, 'makerRate');
861
- const taker = this.safeNumber(fee, 'takerRate');
862
- return {
863
- 'info': fee,
864
- 'symbol': this.safeSymbol(marketId, market),
865
- 'maker': maker,
866
- 'taker': taker,
867
- };
868
- }
869
- parseTradingFees(fees) {
870
- const result = {
871
- 'info': fees,
872
- };
873
- for (let i = 0; i < fees.length; i++) {
874
- const fee = this.parseTradingFee(fees[i]);
875
- const symbol = fee['symbol'];
876
- result[symbol] = fee;
877
- }
878
- return result;
879
- }
880
- parseOHLCV(ohlcv, market = undefined) {
881
- //
882
- // {
883
- // "startsAt":"2020-06-12T02:35:00Z",
884
- // "open":"0.02493753",
885
- // "high":"0.02493753",
886
- // "low":"0.02493753",
887
- // "close":"0.02493753",
888
- // "volume":"0.09590123",
889
- // "quoteVolume":"0.00239153"
890
- // }
891
- //
892
- return [
893
- this.parse8601(this.safeString(ohlcv, 'startsAt')),
894
- this.safeNumber(ohlcv, 'open'),
895
- this.safeNumber(ohlcv, 'high'),
896
- this.safeNumber(ohlcv, 'low'),
897
- this.safeNumber(ohlcv, 'close'),
898
- this.safeNumber(ohlcv, 'volume'),
899
- ];
900
- }
901
- async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
902
- /**
903
- * @method
904
- * @name bittrex#fetchOHLCV
905
- * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
906
- * @param {string} symbol unified symbol of the market to fetch OHLCV data for
907
- * @param {string} timeframe the length of time each candle represents
908
- * @param {int} [since] timestamp in ms of the earliest candle to fetch
909
- * @param {int} [limit] the maximum amount of candles to fetch
910
- * @param {object} [params] extra parameters specific to the exchange API endpoint
911
- * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
912
- * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
913
- */
914
- let paginate = false;
915
- [paginate, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'paginate', false);
916
- if (paginate) {
917
- return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1440);
918
- }
919
- await this.loadMarkets();
920
- const market = this.market(symbol);
921
- const reverseId = market['baseId'] + '-' + market['quoteId'];
922
- const request = {
923
- 'candleInterval': this.safeString(this.timeframes, timeframe, timeframe),
924
- 'marketSymbol': reverseId,
925
- };
926
- let method = 'publicGetMarketsMarketSymbolCandlesCandleIntervalRecent';
927
- if (since !== undefined) {
928
- const now = this.milliseconds();
929
- const difference = Math.abs(now - since);
930
- const sinceDate = this.yyyymmdd(since);
931
- const parts = sinceDate.split('-');
932
- const sinceYear = this.safeInteger(parts, 0);
933
- const sinceMonth = this.safeInteger(parts, 1);
934
- const sinceDay = this.safeInteger(parts, 2);
935
- if (timeframe === '1d') {
936
- // if the since argument is beyond one year into the past
937
- if (difference > 31622400000) {
938
- method = 'publicGetMarketsMarketSymbolCandlesCandleIntervalHistoricalYear';
939
- request['year'] = sinceYear;
940
- }
941
- // request['year'] = year;
942
- }
943
- else if (timeframe === '1h') {
944
- // if the since argument is beyond 31 days into the past
945
- if (difference > 2678400000) {
946
- method = 'publicGetMarketsMarketSymbolCandlesCandleIntervalHistoricalYearMonth';
947
- request['year'] = sinceYear;
948
- request['month'] = sinceMonth;
949
- }
950
- }
951
- else {
952
- // if the since argument is beyond 1 day into the past
953
- if (difference > 86400000) {
954
- method = 'publicGetMarketsMarketSymbolCandlesCandleIntervalHistoricalYearMonthDay';
955
- request['year'] = sinceYear;
956
- request['month'] = sinceMonth;
957
- request['day'] = sinceDay;
958
- }
959
- }
960
- }
961
- const response = await this[method](this.extend(request, params));
962
- //
963
- // [
964
- // {"startsAt":"2020-06-12T02:35:00Z","open":"0.02493753","high":"0.02493753","low":"0.02493753","close":"0.02493753","volume":"0.09590123","quoteVolume":"0.00239153"},
965
- // {"startsAt":"2020-06-12T02:40:00Z","open":"0.02491874","high":"0.02491874","low":"0.02490970","close":"0.02490970","volume":"0.04515695","quoteVolume":"0.00112505"},
966
- // {"startsAt":"2020-06-12T02:45:00Z","open":"0.02490753","high":"0.02493143","low":"0.02490753","close":"0.02493143","volume":"0.17769640","quoteVolume":"0.00442663"}
967
- // ]
968
- //
969
- return this.parseOHLCVs(response, market, timeframe, since, limit);
970
- }
971
- async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
972
- /**
973
- * @method
974
- * @name bittrex#fetchOpenOrders
975
- * @description fetch all unfilled currently open orders
976
- * @param {string} symbol unified market symbol
977
- * @param {int} [since] the earliest time in ms to fetch open orders for
978
- * @param {int} [limit] the maximum number of open orders structures to retrieve
979
- * @param {object} [params] extra parameters specific to the exchange API endpoint
980
- * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
981
- */
982
- await this.loadMarkets();
983
- const request = {};
984
- let market = undefined;
985
- const stop = this.safeValue(params, 'stop');
986
- if (symbol !== undefined) {
987
- market = this.market(symbol);
988
- request['marketSymbol'] = market['id'];
989
- }
990
- let method = 'privateGetOrdersOpen';
991
- if (stop) {
992
- method = 'privateGetConditionalOrdersOpen';
993
- }
994
- const query = this.omit(params, 'stop');
995
- const response = await this[method](this.extend(request, query));
996
- //
997
- // Spot
998
- //
999
- // [
1000
- // {
1001
- // "id": "df6cf5ee-fc27-4b61-991a-cc94b6459ac9",
1002
- // "marketSymbol": "BTC-USDT",
1003
- // "direction": "BUY",
1004
- // "type": "LIMIT",
1005
- // "quantity": "0.00023277",
1006
- // "limit": "30000.00000000",
1007
- // "timeInForce": "GOOD_TIL_CANCELLED",
1008
- // "fillQuantity": "0.00000000",
1009
- // "commission": "0.00000000",
1010
- // "proceeds": "0.00000000",
1011
- // "status": "OPEN",
1012
- // "createdAt": "2022-04-20T02:33:53.16Z",
1013
- // "updatedAt": "2022-04-20T02:33:53.16Z"
1014
- // }
1015
- // ]
1016
- //
1017
- // Stop
1018
- //
1019
- // [
1020
- // {
1021
- // "id": "f64f7c4f-295c-408b-9cbc-601981abf100",
1022
- // "marketSymbol": "BTC-USDT",
1023
- // "operand": "LTE",
1024
- // "triggerPrice": "0.10000000",
1025
- // "orderToCreate": {
1026
- // "marketSymbol": "BTC-USDT",
1027
- // "direction": "BUY",
1028
- // "type": "LIMIT",
1029
- // "quantity": "0.00020000",
1030
- // "limit": "30000.00000000",
1031
- // "timeInForce": "GOOD_TIL_CANCELLED"
1032
- // },
1033
- // "status": "OPEN",
1034
- // "createdAt": "2022-04-20T02:38:12.26Z",
1035
- // "updatedAt": "2022-04-20T02:38:12.26Z"
1036
- // }
1037
- // ]
1038
- //
1039
- return this.parseOrders(response, market, since, limit);
1040
- }
1041
- async fetchOrderTrades(id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1042
- /**
1043
- * @method
1044
- * @name bittrex#fetchOrderTrades
1045
- * @description fetch all the trades made from a single order
1046
- * @param {string} id order id
1047
- * @param {string} symbol unified market symbol
1048
- * @param {int} [since] the earliest time in ms to fetch trades for
1049
- * @param {int} [limit] the maximum number of trades to retrieve
1050
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1051
- * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1052
- */
1053
- await this.loadMarkets();
1054
- const request = {
1055
- 'orderId': id,
1056
- };
1057
- const response = await this.privateGetOrdersOrderIdExecutions(this.extend(request, params));
1058
- let market = undefined;
1059
- if (symbol !== undefined) {
1060
- market = this.market(symbol);
1061
- }
1062
- return this.parseTrades(response, market, since, limit);
1063
- }
1064
- async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1065
- /**
1066
- * @method
1067
- * @name bittrex#createOrder
1068
- * @description create a trade order
1069
- * @param {string} symbol unified symbol of the market to create an order in
1070
- * @param {string} type 'market' or 'limit'
1071
- * @param {string} side 'buy' or 'sell'
1072
- * @param {float} amount how much of currency you want to trade in units of base currency
1073
- * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1074
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1075
- * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1076
- */
1077
- // A ceiling order is a market or limit order that allows you to specify
1078
- // the amount of quote currency you want to spend (or receive, if selling)
1079
- // instead of the quantity of the market currency (e.g. buy $100 USD of BTC
1080
- // at the current market BTC price)
1081
- await this.loadMarkets();
1082
- const market = this.market(symbol);
1083
- let uppercaseType = undefined;
1084
- if (type !== undefined) {
1085
- uppercaseType = type.toUpperCase();
1086
- }
1087
- const reverseId = market['baseId'] + '-' + market['quoteId'];
1088
- const stop = this.safeValue(params, 'stop');
1089
- const stopPrice = this.safeNumber2(params, 'triggerPrice', 'stopPrice');
1090
- const request = {
1091
- 'marketSymbol': reverseId, // SPOT and STOP
1092
- // 'direction': side.toUpperCase (), // SPOT, STOP 'orderToCreate'
1093
- // 'type': uppercaseType, // SPOT: LIMIT, MARKET, CEILING_LIMIT, CEILING_MARKET
1094
- // 'quantity': this.amountToPrecision (symbol, amount), // SPOT, required for limit orders, excluded for ceiling orders
1095
- // 'ceiling': this.priceToPrecision (symbol, price), // SPOT, required for ceiling orders, excluded for non-ceiling orders
1096
- // 'limit': this.priceToPrecision (symbol, price), // SPOT, required for limit orders, excluded for market orders
1097
- // 'timeInForce': 'GOOD_TIL_CANCELLED', // SPOT, IMMEDIATE_OR_CANCEL, FILL_OR_KILL, POST_ONLY_GOOD_TIL_CANCELLED
1098
- // 'useAwards': false, // SPOT, optional
1099
- // 'operand': 'LTE', // STOP, price above (GTE) or below (LTE) which the conditional order will trigger. either this or trailingStopPercent must be specified.
1100
- // 'triggerPrice': this.priceToPrecision (symbol, stopPrice), // STOP
1101
- // 'trailingStopPercent': this.priceToPrecision (symbol, stopPrice), // STOP, either this or triggerPrice must be set
1102
- // 'orderToCreate': {direction:side,type:uppercaseType}, // STOP, The spot order to be triggered
1103
- // 'orderToCancel': {id:'f03d5e98-b5ac-48fb-8647-dd4db828a297',type:uppercaseType}, // STOP, The spot order to be canceled
1104
- // 'clineConditionalOrderId': 'f03d5e98-b5ac-48fb-8647-dd4db828a297', // STOP
1105
- };
1106
- let method = 'privatePostOrders';
1107
- if (stop || stopPrice) {
1108
- method = 'privatePostConditionalOrders';
1109
- const operand = this.safeString(params, 'operand');
1110
- if (operand === undefined) {
1111
- throw new errors.ArgumentsRequired(this.id + ' createOrder() requires an operand parameter');
1112
- }
1113
- const trailingStopPercent = this.safeNumber(params, 'trailingStopPercent');
1114
- const orderToCreate = this.safeValue(params, 'orderToCreate');
1115
- const orderToCancel = this.safeValue(params, 'orderToCancel');
1116
- if (stopPrice === undefined) {
1117
- request['trailingStopPercent'] = this.priceToPrecision(symbol, trailingStopPercent);
1118
- }
1119
- if (orderToCreate) {
1120
- const isCeilingLimit = (uppercaseType === 'CEILING_LIMIT');
1121
- const isCeilingMarket = (uppercaseType === 'CEILING_MARKET');
1122
- const isCeilingOrder = isCeilingLimit || isCeilingMarket;
1123
- let ceiling = undefined;
1124
- let limit = undefined;
1125
- let timeInForce = undefined;
1126
- if (isCeilingOrder) {
1127
- let cost = undefined;
1128
- if (isCeilingLimit) {
1129
- limit = this.priceToPrecision(symbol, price);
1130
- cost = this.safeNumber2(params, 'ceiling', 'cost', amount);
1131
- }
1132
- else if (isCeilingMarket) {
1133
- cost = this.safeNumber2(params, 'ceiling', 'cost');
1134
- if (cost === undefined) {
1135
- if (price === undefined) {
1136
- cost = amount;
1137
- }
1138
- else {
1139
- cost = amount * price;
1140
- }
1141
- }
1142
- }
1143
- ceiling = this.costToPrecision(symbol, cost);
1144
- timeInForce = 'IMMEDIATE_OR_CANCEL';
1145
- }
1146
- else {
1147
- if (uppercaseType === 'LIMIT') {
1148
- limit = this.priceToPrecision(symbol, price);
1149
- timeInForce = 'GOOD_TIL_CANCELLED';
1150
- }
1151
- else {
1152
- timeInForce = 'IMMEDIATE_OR_CANCEL';
1153
- }
1154
- }
1155
- request['orderToCreate'] = {
1156
- 'marketSymbol': reverseId,
1157
- 'direction': side.toUpperCase(),
1158
- 'type': uppercaseType,
1159
- 'quantity': this.amountToPrecision(symbol, amount),
1160
- 'ceiling': ceiling,
1161
- 'limit': limit,
1162
- 'timeInForce': timeInForce,
1163
- 'clientOrderId': this.safeString(params, 'clientOrderId'),
1164
- 'useAwards': this.safeValue(params, 'useAwards'),
1165
- };
1166
- }
1167
- if (orderToCancel) {
1168
- request['orderToCancel'] = orderToCancel;
1169
- }
1170
- request['triggerPrice'] = this.priceToPrecision(symbol, stopPrice);
1171
- request['operand'] = operand;
1172
- }
1173
- else {
1174
- if (side !== undefined) {
1175
- request['direction'] = side.toUpperCase();
1176
- }
1177
- request['type'] = uppercaseType;
1178
- const isCeilingLimit = (uppercaseType === 'CEILING_LIMIT');
1179
- const isCeilingMarket = (uppercaseType === 'CEILING_MARKET');
1180
- const isCeilingOrder = isCeilingLimit || isCeilingMarket;
1181
- if (isCeilingOrder) {
1182
- let cost = undefined;
1183
- if (isCeilingLimit) {
1184
- request['limit'] = this.priceToPrecision(symbol, price);
1185
- cost = this.safeNumber2(params, 'ceiling', 'cost', amount);
1186
- }
1187
- else if (isCeilingMarket) {
1188
- cost = this.safeNumber2(params, 'ceiling', 'cost');
1189
- if (cost === undefined) {
1190
- if (price === undefined) {
1191
- cost = amount;
1192
- }
1193
- else {
1194
- cost = amount * price;
1195
- }
1196
- }
1197
- }
1198
- request['ceiling'] = this.costToPrecision(symbol, cost);
1199
- // bittrex only accepts IMMEDIATE_OR_CANCEL or FILL_OR_KILL for ceiling orders
1200
- request['timeInForce'] = 'IMMEDIATE_OR_CANCEL';
1201
- }
1202
- else {
1203
- request['quantity'] = this.amountToPrecision(symbol, amount);
1204
- if (uppercaseType === 'LIMIT') {
1205
- request['limit'] = this.priceToPrecision(symbol, price);
1206
- request['timeInForce'] = 'GOOD_TIL_CANCELLED';
1207
- }
1208
- else {
1209
- // bittrex does not allow GOOD_TIL_CANCELLED for market orders
1210
- request['timeInForce'] = 'IMMEDIATE_OR_CANCEL';
1211
- }
1212
- }
1213
- }
1214
- const query = this.omit(params, ['stop', 'stopPrice', 'ceiling', 'cost', 'operand', 'trailingStopPercent', 'orderToCreate', 'orderToCancel']);
1215
- const response = await this[method](this.extend(request, query));
1216
- //
1217
- // Spot
1218
- //
1219
- // {
1220
- // "id": "f03d5e98-b5ac-48fb-8647-dd4db828a297",
1221
- // "marketSymbol": "BTC-USDT",
1222
- // "direction": "SELL",
1223
- // "type": "LIMIT",
1224
- // "quantity": "0.01",
1225
- // "limit": "6000",
1226
- // "timeInForce": "GOOD_TIL_CANCELLED",
1227
- // "fillQuantity": "0.00000000",
1228
- // "commission": "0.00000000",
1229
- // "proceeds": "0.00000000",
1230
- // "status": "OPEN",
1231
- // "createdAt": "2020-03-18T02:37:33.42Z",
1232
- // "updatedAt": "2020-03-18T02:37:33.42Z"
1233
- // }
1234
- //
1235
- // Stop
1236
- //
1237
- // {
1238
- // "id": "9791fe52-a3e5-4ac3-ae03-e327b2993571",
1239
- // "marketSymbol": "BTC-USDT",
1240
- // "operand": "LTE",
1241
- // "triggerPrice": "0.1",
1242
- // "orderToCreate": {
1243
- // "marketSymbol": "BTC-USDT",
1244
- // "direction": "BUY",
1245
- // "type": "LIMIT",
1246
- // "quantity": "0.0002",
1247
- // "limit": "30000",
1248
- // "timeInForce": "GOOD_TIL_CANCELLED"
1249
- // },
1250
- // "status": "OPEN",
1251
- // "createdAt": "2022-04-19T21:02:14.17Z",
1252
- // "updatedAt": "2022-04-19T21:02:14.17Z"
1253
- // }
1254
- //
1255
- return this.parseOrder(response, market);
1256
- }
1257
- async cancelOrder(id, symbol = undefined, params = {}) {
1258
- /**
1259
- * @method
1260
- * @name bittrex#cancelOrder
1261
- * @description cancels an open order
1262
- * @param {string} id order id
1263
- * @param {string} symbol unified symbol of the market the order was made in
1264
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1265
- * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1266
- */
1267
- await this.loadMarkets();
1268
- const stop = this.safeValue(params, 'stop');
1269
- let request = {};
1270
- let method = undefined;
1271
- let market = undefined;
1272
- if (symbol !== undefined) {
1273
- market = this.market(symbol);
1274
- }
1275
- if (stop) {
1276
- method = 'privateDeleteConditionalOrdersConditionalOrderId';
1277
- request = {
1278
- 'conditionalOrderId': id,
1279
- };
1280
- }
1281
- else {
1282
- method = 'privateDeleteOrdersOrderId';
1283
- request = {
1284
- 'orderId': id,
1285
- };
1286
- }
1287
- const query = this.omit(params, 'stop');
1288
- const response = await this[method](this.extend(request, query));
1289
- //
1290
- // Spot
1291
- //
1292
- // [
1293
- // {
1294
- // "id": "df6cf5ee-fc27-4b61-991a-cc94b6459ac9",
1295
- // "marketSymbol": "BTC-USDT",
1296
- // "direction": "BUY",
1297
- // "type": "LIMIT",
1298
- // "quantity": "0.00023277",
1299
- // "limit": "30000.00000000",
1300
- // "timeInForce": "GOOD_TIL_CANCELLED",
1301
- // "fillQuantity": "0.00000000",
1302
- // "commission": "0.00000000",
1303
- // "proceeds": "0.00000000",
1304
- // "status": "CANCELLED",
1305
- // "createdAt": "2022-04-20T02:33:53.16Z",
1306
- // "updatedAt": "2022-04-20T02:33:53.16Z"
1307
- // }
1308
- // ]
1309
- //
1310
- // Stop
1311
- //
1312
- // [
1313
- // {
1314
- // "id": "f64f7c4f-295c-408b-9cbc-601981abf100",
1315
- // "marketSymbol": "BTC-USDT",
1316
- // "operand": "LTE",
1317
- // "triggerPrice": "0.10000000",
1318
- // "orderToCreate": {
1319
- // "marketSymbol": "BTC-USDT",
1320
- // "direction": "BUY",
1321
- // "type": "LIMIT",
1322
- // "quantity": "0.00020000",
1323
- // "limit": "30000.00000000",
1324
- // "timeInForce": "GOOD_TIL_CANCELLED"
1325
- // },
1326
- // "status": "CANCELLED",
1327
- // "createdAt": "2022-04-20T02:38:12.26Z",
1328
- // "updatedAt": "2022-04-20T02:38:12.26Z"
1329
- // "closedAt": "2022-04-20T03:47:24.69Z"
1330
- // }
1331
- // ]
1332
- //
1333
- return this.extend(this.parseOrder(response, market), {
1334
- 'id': id,
1335
- 'info': response,
1336
- 'status': 'canceled',
1337
- });
1338
- }
1339
- async cancelAllOrders(symbol = undefined, params = {}) {
1340
- /**
1341
- * @method
1342
- * @name bittrex#cancelAllOrders
1343
- * @description cancel all open orders
1344
- * @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
1345
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1346
- * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1347
- */
1348
- await this.loadMarkets();
1349
- const request = {};
1350
- let market = undefined;
1351
- if (symbol !== undefined) {
1352
- market = this.market(symbol);
1353
- request['marketSymbol'] = market['id'];
1354
- }
1355
- const response = await this.privateDeleteOrdersOpen(this.extend(request, params));
1356
- //
1357
- // [
1358
- // {
1359
- // "id":"66582be0-5337-4d8c-b212-c356dd525801",
1360
- // "statusCode":"SUCCESS",
1361
- // "result":{
1362
- // "id":"66582be0-5337-4d8c-b212-c356dd525801",
1363
- // "marketSymbol":"BTC-USDT",
1364
- // "direction":"BUY",
1365
- // "type":"LIMIT",
1366
- // "quantity":"0.01000000",
1367
- // "limit":"3000.00000000",
1368
- // "timeInForce":"GOOD_TIL_CANCELLED",
1369
- // "fillQuantity":"0.00000000",
1370
- // "commission":"0.00000000",
1371
- // "proceeds":"0.00000000",
1372
- // "status":"CLOSED",
1373
- // "createdAt":"2020-10-06T12:31:53.39Z",
1374
- // "updatedAt":"2020-10-06T12:54:28.8Z",
1375
- // "closedAt":"2020-10-06T12:54:28.8Z"
1376
- // }
1377
- // }
1378
- // ]
1379
- //
1380
- const orders = [];
1381
- for (let i = 0; i < response.length; i++) {
1382
- const result = this.safeValue(response[i], 'result', {});
1383
- orders.push(result);
1384
- }
1385
- return this.parseOrders(orders, market);
1386
- }
1387
- async fetchDeposit(id, code = undefined, params = {}) {
1388
- /**
1389
- * @method
1390
- * @name bittrex#fetchDeposit
1391
- * @description fetch data on a currency deposit via the deposit id
1392
- * @param {string} id deposit id
1393
- * @param {string} code filter by currency code
1394
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1395
- * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1396
- */
1397
- await this.loadMarkets();
1398
- const request = {
1399
- 'txId': id,
1400
- };
1401
- let currency = undefined;
1402
- if (code !== undefined) {
1403
- currency = this.currency(code);
1404
- }
1405
- const response = await this.privateGetDepositsByTxIdTxId(this.extend(request, params));
1406
- const transactions = this.parseTransactions(response, currency, undefined, undefined);
1407
- return this.safeValue(transactions, 0);
1408
- }
1409
- async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
1410
- /**
1411
- * @method
1412
- * @name bittrex#fetchDeposits
1413
- * @description fetch all deposits made to an account
1414
- * @param {string} code unified currency code
1415
- * @param {int} [since] the earliest time in ms to fetch deposits for
1416
- * @param {int} [limit] the maximum number of deposits structures to retrieve
1417
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1418
- * @param {int} [params.endDate] Filters out result after this timestamp. Uses ISO-8602 format.
1419
- * @param {string} [params.nextPageToken] The unique identifier of the item that the resulting query result should start after, in the sort order of the given endpoint. Used for traversing a paginated set in the forward direction.
1420
- * @param {string} [params.previousPageToken] The unique identifier of the item that the resulting query result should end before, in the sort order of the given endpoint. Used for traversing a paginated set in the reverse direction.
1421
- * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1422
- */
1423
- await this.loadMarkets();
1424
- // https://support.bittrex.com/hc/en-us/articles/115003723911
1425
- const request = {};
1426
- let currency = undefined;
1427
- if (code !== undefined) {
1428
- currency = this.currency(code);
1429
- request['currencySymbol'] = currency['id'];
1430
- }
1431
- if (since !== undefined) {
1432
- const startDate = this.parseToInt(since / 1000) * 1000;
1433
- request['startDate'] = this.iso8601(startDate);
1434
- }
1435
- if (limit !== undefined) {
1436
- request['pageSize'] = limit;
1437
- }
1438
- let method = undefined;
1439
- const options = this.safeValue(this.options, 'fetchDeposits', {});
1440
- const defaultStatus = this.safeString(options, 'status', 'ok');
1441
- const status = this.safeString(params, 'status', defaultStatus);
1442
- if (status === 'pending') {
1443
- method = 'privateGetDepositsOpen';
1444
- }
1445
- else {
1446
- method = 'privateGetDepositsClosed';
1447
- }
1448
- params = this.omit(params, 'status');
1449
- const response = await this[method](this.extend(request, params));
1450
- // we cannot filter by `since` timestamp, as it isn't set by Bittrex
1451
- // see https://github.com/ccxt/ccxt/issues/4067
1452
- // return this.parseTransactions (response, currency, since, limit);
1453
- return this.parseTransactions(response, currency, undefined, limit);
1454
- }
1455
- async fetchPendingDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
1456
- /**
1457
- * @method
1458
- * @name bittrex#fetchPendingDeposits
1459
- * @description fetch all pending deposits made from an account
1460
- * @param {string} code unified currency code
1461
- * @param {int} [since] the earliest time in ms to fetch withdrawals for
1462
- * @param {int} [limit] the maximum number of withdrawals structures to retrieve
1463
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1464
- * @param {int} [params.endDate] Filters out result after this timestamp. Uses ISO-8602 format.
1465
- * @param {string} [params.nextPageToken] The unique identifier of the item that the resulting query result should start after, in the sort order of the given endpoint. Used for traversing a paginated set in the forward direction.
1466
- * @param {string} [params.previousPageToken] The unique identifier of the item that the resulting query result should end before, in the sort order of the given endpoint. Used for traversing a paginated set in the reverse direction.
1467
- * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1468
- */
1469
- await this.loadMarkets();
1470
- return this.fetchDeposits(code, since, limit, this.extend(params, { 'status': 'pending' }));
1471
- }
1472
- async fetchWithdrawal(id, code = undefined, params = {}) {
1473
- /**
1474
- * @method
1475
- * @name bittrex#fetchWithdrawal
1476
- * @description fetch data on a currency withdrawal via the withdrawal id
1477
- * @param {string} id withdrawal id
1478
- * @param {string} code filter by currency code
1479
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1480
- * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1481
- */
1482
- await this.loadMarkets();
1483
- const request = {
1484
- 'txId': id,
1485
- };
1486
- let currency = undefined;
1487
- if (code !== undefined) {
1488
- currency = this.currency(code);
1489
- }
1490
- const response = await this.privateGetWithdrawalsByTxIdTxId(this.extend(request, params));
1491
- const transactions = this.parseTransactions(response, currency, undefined, undefined);
1492
- return this.safeValue(transactions, 0);
1493
- }
1494
- async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
1495
- /**
1496
- * @method
1497
- * @name bittrex#fetchWithdrawals
1498
- * @description fetch all withdrawals made from an account
1499
- * @param {string} code unified currency code
1500
- * @param {int} [since] the earliest time in ms to fetch withdrawals for
1501
- * @param {int} [limit] the maximum number of withdrawals structures to retrieve
1502
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1503
- * @param {int} [params.endDate] Filters out result after this timestamp. Uses ISO-8602 format.
1504
- * @param {string} [params.nextPageToken] The unique identifier of the item that the resulting query result should start after, in the sort order of the given endpoint. Used for traversing a paginated set in the forward direction.
1505
- * @param {string} [params.previousPageToken] The unique identifier of the item that the resulting query result should end before, in the sort order of the given endpoint. Used for traversing a paginated set in the reverse direction.
1506
- * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1507
- */
1508
- await this.loadMarkets();
1509
- // https://support.bittrex.com/hc/en-us/articles/115003723911
1510
- const request = {};
1511
- let currency = undefined;
1512
- if (code !== undefined) {
1513
- currency = this.currency(code);
1514
- request['currencySymbol'] = currency['id'];
1515
- }
1516
- if (since !== undefined) {
1517
- const startDate = this.parseToInt(since / 1000) * 1000;
1518
- request['startDate'] = this.iso8601(startDate);
1519
- }
1520
- if (limit !== undefined) {
1521
- request['pageSize'] = limit;
1522
- }
1523
- let method = undefined;
1524
- const options = this.safeValue(this.options, 'fetchWithdrawals', {});
1525
- const defaultStatus = this.safeString(options, 'status', 'ok');
1526
- const status = this.safeString(params, 'status', defaultStatus);
1527
- if (status === 'pending') {
1528
- method = 'privateGetWithdrawalsOpen';
1529
- }
1530
- else {
1531
- method = 'privateGetWithdrawalsClosed';
1532
- }
1533
- params = this.omit(params, 'status');
1534
- const response = await this[method](this.extend(request, params));
1535
- return this.parseTransactions(response, currency, since, limit);
1536
- }
1537
- async fetchPendingWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
1538
- /**
1539
- * @method
1540
- * @name bittrex#fetchPendingWithdrawals
1541
- * @description fetch all pending withdrawals made from an account
1542
- * @param {string} code unified currency code
1543
- * @param {int} [since] the earliest time in ms to fetch withdrawals for
1544
- * @param {int} [limit] the maximum number of withdrawals structures to retrieve
1545
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1546
- * @param {int} [params.endDate] Filters out result after this timestamp. Uses ISO-8602 format.
1547
- * @param {string} [params.nextPageToken] The unique identifier of the item that the resulting query result should start after, in the sort order of the given endpoint. Used for traversing a paginated set in the forward direction.
1548
- * @param {string} [params.previousPageToken] The unique identifier of the item that the resulting query result should end before, in the sort order of the given endpoint. Used for traversing a paginated set in the reverse direction.
1549
- * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1550
- */
1551
- await this.loadMarkets();
1552
- return this.fetchWithdrawals(code, since, limit, this.extend(params, { 'status': 'pending' }));
1553
- }
1554
- parseTransaction(transaction, currency = undefined) {
1555
- //
1556
- // fetchDeposits
1557
- //
1558
- // {
1559
- // "id": "77f2e4f0-a33d-4285-9140-ed5b20533a17",
1560
- // "currencySymbol": "ETH",
1561
- // "quantity": "0.36487773",
1562
- // "cryptoAddress": "0xeee7cff0f587706acdddfc1ff65968936fcf621e",
1563
- // "txId": "0x059fd3279452a245b308a944a0ee341ff9d17652a8a1bc663e6006282128c782",
1564
- // "confirmations": 44,
1565
- // "updatedAt": "2017-12-28T13:57:42.753Z",
1566
- // "completedAt": "2017-12-28T13:57:42.753Z",
1567
- // "status": "COMPLETED",
1568
- // "source": "BLOCKCHAIN"
1569
- // }
1570
- //
1571
- // fetchWithdrawals
1572
- //
1573
- // {
1574
- // "id":"d20d556c-59ac-4480-95d8-268f8d4adedb",
1575
- // "currencySymbol":"OMG",
1576
- // "quantity":"2.67000000",
1577
- // "cryptoAddress":"0xa7daa9acdb41c0c476966ee23d388d6f2a1448cd",
1578
- // "cryptoAddressTag":"",
1579
- // "txCost":"0.10000000",
1580
- // "txId":"0xb54b8c5fb889aa9f9154e013cc5dd67b3048a3e0ae58ba845868225cda154bf5",
1581
- // "status":"COMPLETED",
1582
- // "createdAt":"2017-12-16T20:46:22.5Z",
1583
- // "completedAt":"2017-12-16T20:48:03.887Z",
1584
- // "target":"BLOCKCHAIN"
1585
- // }
1586
- //
1587
- // withdraw
1588
- //
1589
- // {
1590
- // "currencySymbol": "string",
1591
- // "quantity": "number (double)",
1592
- // "cryptoAddress": "string",
1593
- // "cryptoAddressTag": "string",
1594
- // "fundsTransferMethodId": "string (uuid)",
1595
- // "clientWithdrawalId": "string (uuid)"
1596
- // }
1597
- //
1598
- const id = this.safeString2(transaction, 'id', 'clientWithdrawalId');
1599
- const amount = this.safeNumber(transaction, 'quantity');
1600
- const address = this.safeString(transaction, 'cryptoAddress');
1601
- let addressTo = undefined;
1602
- let addressFrom = undefined;
1603
- const isDeposit = this.safeString(transaction, 'source') === 'BLOCKCHAIN';
1604
- if (isDeposit) {
1605
- addressFrom = address;
1606
- }
1607
- else {
1608
- addressTo = address;
1609
- }
1610
- const txid = this.safeString(transaction, 'txId');
1611
- const updated = this.parse8601(this.safeString(transaction, 'updatedAt'));
1612
- const opened = this.parse8601(this.safeString(transaction, 'createdAt'));
1613
- const timestamp = opened ? opened : updated;
1614
- const type = (opened === undefined) ? 'deposit' : 'withdrawal';
1615
- const currencyId = this.safeString(transaction, 'currencySymbol');
1616
- const code = this.safeCurrencyCode(currencyId, currency);
1617
- let status = 'pending';
1618
- if (type === 'deposit') {
1619
- //
1620
- // deposits numConfirmations never reach the minConfirmations number
1621
- // we set all of them to 'ok', otherwise they'd all be 'pending'
1622
- //
1623
- // const numConfirmations = this.safeInteger (transaction, 'Confirmations', 0);
1624
- // const minConfirmations = this.safeInteger (currency['info'], 'MinConfirmation');
1625
- // if (numConfirmations >= minConfirmations) {
1626
- // status = 'ok';
1627
- // }
1628
- //
1629
- status = 'ok';
1630
- }
1631
- else {
1632
- const responseStatus = this.safeString(transaction, 'status');
1633
- if (responseStatus === 'ERROR_INVALID_ADDRESS') {
1634
- status = 'failed';
1635
- }
1636
- else if (responseStatus === 'CANCELLED') {
1637
- status = 'canceled';
1638
- }
1639
- else if (responseStatus === 'PENDING') {
1640
- status = 'pending';
1641
- }
1642
- else if (responseStatus === 'COMPLETED') {
1643
- status = 'ok';
1644
- }
1645
- else if (responseStatus === 'AUTHORIZED' && (txid !== undefined)) {
1646
- status = 'ok';
1647
- }
1648
- }
1649
- let feeCost = this.safeNumber(transaction, 'txCost');
1650
- if (feeCost === undefined) {
1651
- if (type === 'deposit') {
1652
- // according to https://support.bittrex.com/hc/en-us/articles/115000199651-What-fees-does-Bittrex-charge-
1653
- feeCost = 0;
1654
- }
1655
- }
1656
- return {
1657
- 'info': transaction,
1658
- 'id': id,
1659
- 'currency': code,
1660
- 'amount': amount,
1661
- 'network': undefined,
1662
- 'address': address,
1663
- 'addressTo': addressTo,
1664
- 'addressFrom': addressFrom,
1665
- 'tag': undefined,
1666
- 'tagTo': undefined,
1667
- 'tagFrom': undefined,
1668
- 'status': status,
1669
- 'type': type,
1670
- 'updated': updated,
1671
- 'txid': txid,
1672
- 'timestamp': timestamp,
1673
- 'datetime': this.iso8601(timestamp),
1674
- 'comment': undefined,
1675
- 'internal': undefined,
1676
- 'fee': {
1677
- 'currency': code,
1678
- 'cost': feeCost,
1679
- },
1680
- };
1681
- }
1682
- parseTimeInForce(timeInForce) {
1683
- const timeInForces = {
1684
- 'GOOD_TIL_CANCELLED': 'GTC',
1685
- 'IMMEDIATE_OR_CANCEL': 'IOC',
1686
- 'FILL_OR_KILL': 'FOK',
1687
- 'POST_ONLY_GOOD_TIL_CANCELLED': 'PO',
1688
- };
1689
- return this.safeString(timeInForces, timeInForce, timeInForce);
1690
- }
1691
- parseOrder(order, market = undefined) {
1692
- //
1693
- // Spot createOrder, fetchOpenOrders, fetchClosedOrders, fetchOrder, cancelOrder
1694
- //
1695
- // {
1696
- // "id": "1be35109-b763-44ce-b6ea-05b6b0735c0c",
1697
- // "marketSymbol": "LTC-ETH",
1698
- // "direction": "BUY",
1699
- // "type": "LIMIT",
1700
- // "quantity": "0.50000000",
1701
- // "limit": "0.17846699",
1702
- // "timeInForce": "GOOD_TIL_CANCELLED",
1703
- // "clientOrderId": "ff156d39-fe01-44ca-8f21-b0afa19ef228",
1704
- // "fillQuantity": "0.50000000",
1705
- // "commission": "0.00022286",
1706
- // "proceeds": "0.08914915",
1707
- // "status": "CLOSED",
1708
- // "createdAt": "2018-06-23T13:14:28.613Z",
1709
- // "updatedAt": "2018-06-23T13:14:30.19Z",
1710
- // "closedAt": "2018-06-23T13:14:30.19Z"
1711
- // }
1712
- //
1713
- // Stop createOrder, fetchOpenOrders, fetchClosedOrders, fetchOrder, cancelOrder
1714
- //
1715
- // {
1716
- // "id": "9791fe52-a3e5-4ac3-ae03-e327b2993571",
1717
- // "marketSymbol": "BTC-USDT",
1718
- // "operand": "LTE",
1719
- // "triggerPrice": "0.1",
1720
- // "orderToCreate": {
1721
- // "marketSymbol": "BTC-USDT",
1722
- // "direction": "BUY",
1723
- // "type": "LIMIT",
1724
- // "quantity": "0.0002",
1725
- // "limit": "30000",
1726
- // "timeInForce": "GOOD_TIL_CANCELLED"
1727
- // },
1728
- // "status": "OPEN",
1729
- // "createdAt": "2022-04-19T21:02:14.17Z",
1730
- // "updatedAt": "2022-04-19T21:02:14.17Z",
1731
- // "closedAt": "2022-04-20T03:47:24.69Z"
1732
- // }
1733
- //
1734
- const marketSymbol = this.safeString(order, 'marketSymbol');
1735
- market = this.safeMarket(marketSymbol, market, '-');
1736
- const symbol = market['symbol'];
1737
- const feeCurrency = market['quote'];
1738
- const createdAt = this.safeString(order, 'createdAt');
1739
- const updatedAt = this.safeString(order, 'updatedAt');
1740
- const closedAt = this.safeString(order, 'closedAt');
1741
- const clientOrderId = this.safeString(order, 'clientOrderId');
1742
- let lastTradeTimestamp = undefined;
1743
- if (closedAt !== undefined) {
1744
- lastTradeTimestamp = this.parse8601(closedAt);
1745
- }
1746
- else if (updatedAt) {
1747
- lastTradeTimestamp = this.parse8601(updatedAt);
1748
- }
1749
- const timestamp = this.parse8601(createdAt);
1750
- let direction = this.safeStringLower(order, 'direction');
1751
- if (direction === undefined) {
1752
- let conditionalOrder = this.safeValue(order, 'orderToCreate');
1753
- if (conditionalOrder === undefined) {
1754
- conditionalOrder = this.safeValue(order, 'orderToCancel');
1755
- }
1756
- direction = this.safeStringLower(conditionalOrder, 'direction');
1757
- }
1758
- let type = this.safeStringLower(order, 'type');
1759
- if (type === undefined) {
1760
- let conditionalOrder = this.safeValue(order, 'orderToCreate');
1761
- if (conditionalOrder === undefined) {
1762
- conditionalOrder = this.safeValue(order, 'orderToCancel');
1763
- }
1764
- type = this.safeStringLower(conditionalOrder, 'type');
1765
- }
1766
- let quantity = this.safeString(order, 'quantity');
1767
- if (quantity === undefined) {
1768
- let conditionalOrder = this.safeValue(order, 'orderToCreate');
1769
- if (conditionalOrder === undefined) {
1770
- conditionalOrder = this.safeValue(order, 'orderToCancel');
1771
- }
1772
- quantity = this.safeString(conditionalOrder, 'quantity');
1773
- }
1774
- let limit = this.safeString(order, 'limit');
1775
- if (limit === undefined) {
1776
- let conditionalOrder = this.safeValue(order, 'orderToCreate');
1777
- if (conditionalOrder === undefined) {
1778
- conditionalOrder = this.safeValue(order, 'orderToCancel');
1779
- }
1780
- limit = this.safeString(conditionalOrder, 'limit');
1781
- }
1782
- let timeInForce = this.parseTimeInForce(this.safeString(order, 'timeInForce'));
1783
- if (timeInForce === undefined) {
1784
- let conditionalOrder = this.safeValue(order, 'orderToCreate');
1785
- if (conditionalOrder === undefined) {
1786
- conditionalOrder = this.safeValue(order, 'orderToCancel');
1787
- }
1788
- timeInForce = this.parseTimeInForce(this.safeString(conditionalOrder, 'timeInForce'));
1789
- }
1790
- const fillQuantity = this.safeString(order, 'fillQuantity');
1791
- const commission = this.safeNumber(order, 'commission');
1792
- const proceeds = this.safeString(order, 'proceeds');
1793
- const status = this.safeStringLower(order, 'status');
1794
- const postOnly = (timeInForce === 'PO');
1795
- return this.safeOrder({
1796
- 'id': this.safeString(order, 'id'),
1797
- 'clientOrderId': clientOrderId,
1798
- 'timestamp': timestamp,
1799
- 'datetime': this.iso8601(timestamp),
1800
- 'lastTradeTimestamp': lastTradeTimestamp,
1801
- 'symbol': symbol,
1802
- 'type': type,
1803
- 'timeInForce': timeInForce,
1804
- 'postOnly': postOnly,
1805
- 'side': direction,
1806
- 'price': limit,
1807
- 'stopPrice': this.safeString(order, 'triggerPrice'),
1808
- 'triggerPrice': this.safeString(order, 'triggerPrice'),
1809
- 'cost': proceeds,
1810
- 'average': undefined,
1811
- 'amount': quantity,
1812
- 'filled': fillQuantity,
1813
- 'remaining': undefined,
1814
- 'status': status,
1815
- 'fee': {
1816
- 'cost': commission,
1817
- 'currency': feeCurrency,
1818
- },
1819
- 'info': order,
1820
- 'trades': undefined,
1821
- }, market);
1822
- }
1823
- parseOrders(orders, market = undefined, since = undefined, limit = undefined, params = {}) {
1824
- if (this.options['fetchClosedOrdersFilterBySince']) {
1825
- return super.parseOrders(orders, market, since, limit, params);
1826
- }
1827
- else {
1828
- return super.parseOrders(orders, market, undefined, limit, params);
1829
- }
1830
- }
1831
- parseOrderStatus(status) {
1832
- const statuses = {
1833
- 'CLOSED': 'closed',
1834
- 'OPEN': 'open',
1835
- 'CANCELLED': 'canceled',
1836
- 'CANCELED': 'canceled',
1837
- };
1838
- return this.safeString(statuses, status, status);
1839
- }
1840
- async fetchOrder(id, symbol = undefined, params = {}) {
1841
- /**
1842
- * @method
1843
- * @name bittrex#fetchOrder
1844
- * @description fetches information on an order made by the user
1845
- * @param {string} symbol unified symbol of the market the order was made in
1846
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1847
- * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1848
- */
1849
- await this.loadMarkets();
1850
- const stop = this.safeValue(params, 'stop');
1851
- let market = undefined;
1852
- if (symbol !== undefined) {
1853
- market = this.market(symbol);
1854
- }
1855
- let response = undefined;
1856
- let method = undefined;
1857
- try {
1858
- const request = {};
1859
- if (stop) {
1860
- method = 'privateGetConditionalOrdersConditionalOrderId';
1861
- request['conditionalOrderId'] = id;
1862
- }
1863
- else {
1864
- method = 'privateGetOrdersOrderId';
1865
- request['orderId'] = id;
1866
- }
1867
- const query = this.omit(params, 'stop');
1868
- response = await this[method](this.extend(request, query));
1869
- }
1870
- catch (e) {
1871
- if (this.last_json_response) {
1872
- const message = this.safeString(this.last_json_response, 'message');
1873
- if (message === 'UUID_INVALID') {
1874
- throw new errors.OrderNotFound(this.id + ' fetchOrder() error: ' + this.last_http_response);
1875
- }
1876
- }
1877
- throw e;
1878
- }
1879
- return this.parseOrder(response, market);
1880
- }
1881
- async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1882
- /**
1883
- * @method
1884
- * @name bittrex#fetchMyTrades
1885
- * @description fetch all trades made by the user
1886
- * @param {string} symbol unified market symbol
1887
- * @param {int} [since] the earliest time in ms to fetch trades for
1888
- * @param {int} [limit] the maximum number of trades structures to retrieve
1889
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1890
- * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1891
- */
1892
- await this.loadMarkets();
1893
- const request = {};
1894
- if (limit !== undefined) {
1895
- request['pageSize'] = limit;
1896
- }
1897
- if (since !== undefined) {
1898
- request['startDate'] = this.ymdhms(since, 'T') + 'Z';
1899
- }
1900
- let market = undefined;
1901
- if (symbol !== undefined) {
1902
- market = this.market(symbol);
1903
- request['marketSymbol'] = market['id'];
1904
- }
1905
- const response = await this.privateGetExecutions(this.extend(request, params));
1906
- return this.parseTrades(response, market, since, limit);
1907
- }
1908
- async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1909
- /**
1910
- * @method
1911
- * @name bittrex#fetchClosedOrders
1912
- * @description fetches information on multiple closed orders made by the user
1913
- * @param {string} symbol unified market symbol of the market orders were made in
1914
- * @param {int} [since] the earliest time in ms to fetch orders for
1915
- * @param {int} [limit] the maximum number of orde structures to retrieve
1916
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1917
- * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1918
- */
1919
- await this.loadMarkets();
1920
- const stop = this.safeValue(params, 'stop');
1921
- const request = {};
1922
- if (limit !== undefined) {
1923
- request['pageSize'] = limit;
1924
- }
1925
- if (since !== undefined) {
1926
- request['startDate'] = this.ymdhms(since, 'T') + 'Z';
1927
- }
1928
- let market = undefined;
1929
- if (symbol !== undefined) {
1930
- market = this.market(symbol);
1931
- // because of this line we will have to rethink the entire v3
1932
- // in other words, markets define all the rest of the API
1933
- // and v3 market ids are reversed in comparison to v1
1934
- // v3 has to be a completely separate implementation
1935
- // otherwise we will have to shuffle symbols and currencies everywhere
1936
- // which is prone to errors, as was shown here
1937
- // https://github.com/ccxt/ccxt/pull/5219#issuecomment-499646209
1938
- request['marketSymbol'] = market['base'] + '-' + market['quote'];
1939
- }
1940
- let method = 'privateGetOrdersClosed';
1941
- if (stop) {
1942
- method = 'privateGetConditionalOrdersClosed';
1943
- }
1944
- const query = this.omit(params, 'stop');
1945
- const response = await this[method](this.extend(request, query));
1946
- //
1947
- // Spot
1948
- //
1949
- // [
1950
- // {
1951
- // "id": "df6cf5ee-fc27-4b61-991a-cc94b6459ac9",
1952
- // "marketSymbol": "BTC-USDT",
1953
- // "direction": "BUY",
1954
- // "type": "LIMIT",
1955
- // "quantity": "0.00023277",
1956
- // "limit": "30000.00000000",
1957
- // "timeInForce": "GOOD_TIL_CANCELLED",
1958
- // "fillQuantity": "0.00000000",
1959
- // "commission": "0.00000000",
1960
- // "proceeds": "0.00000000",
1961
- // "status": "OPEN",
1962
- // "createdAt": "2022-04-20T02:33:53.16Z",
1963
- // "updatedAt": "2022-04-20T02:33:53.16Z"
1964
- // }
1965
- // ]
1966
- //
1967
- // Stop
1968
- //
1969
- // [
1970
- // {
1971
- // "id": "f64f7c4f-295c-408b-9cbc-601981abf100",
1972
- // "marketSymbol": "BTC-USDT",
1973
- // "operand": "LTE",
1974
- // "triggerPrice": "0.10000000",
1975
- // "orderToCreate": {
1976
- // "marketSymbol": "BTC-USDT",
1977
- // "direction": "BUY",
1978
- // "type": "LIMIT",
1979
- // "quantity": "0.00020000",
1980
- // "limit": "30000.00000000",
1981
- // "timeInForce": "GOOD_TIL_CANCELLED"
1982
- // },
1983
- // "status": "OPEN",
1984
- // "createdAt": "2022-04-20T02:38:12.26Z",
1985
- // "updatedAt": "2022-04-20T02:38:12.26Z"
1986
- // }
1987
- // ]
1988
- //
1989
- return this.parseOrders(response, market, since, limit);
1990
- }
1991
- async createDepositAddress(code, params = {}) {
1992
- /**
1993
- * @method
1994
- * @name bittrex#createDepositAddress
1995
- * @description create a currency deposit address
1996
- * @param {string} code unified currency code of the currency for the deposit address
1997
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1998
- * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
1999
- */
2000
- await this.loadMarkets();
2001
- const currency = this.currency(code);
2002
- const request = {
2003
- 'currencySymbol': currency['id'],
2004
- };
2005
- const response = await this.privatePostAddresses(this.extend(request, params));
2006
- //
2007
- // {
2008
- // "status":"PROVISIONED",
2009
- // "currencySymbol":"XRP",
2010
- // "cryptoAddress":"rPVMhWBsfF9iMXYj3aAzJVkPDTFNSyWdKy",
2011
- // "cryptoAddressTag":"392034158"
2012
- // }
2013
- //
2014
- const address = this.safeString(response, 'cryptoAddress');
2015
- const message = this.safeString(response, 'status');
2016
- if (!address || message === 'REQUESTED') {
2017
- throw new errors.AddressPending(this.id + ' the address for ' + code + ' is being generated (pending, not ready yet, retry again later)');
2018
- }
2019
- this.checkAddress(address);
2020
- return {
2021
- 'currency': code,
2022
- 'address': address,
2023
- 'tag': this.safeString(response, 'cryptoAddressTag'),
2024
- 'network': undefined,
2025
- 'info': response,
2026
- };
2027
- }
2028
- async fetchDepositAddress(code, params = {}) {
2029
- /**
2030
- * @method
2031
- * @name bittrex#fetchDepositAddress
2032
- * @description fetch the deposit address for a currency associated with this account
2033
- * @param {string} code unified currency code
2034
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2035
- * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
2036
- */
2037
- await this.loadMarkets();
2038
- const currency = this.currency(code);
2039
- const request = {
2040
- 'currencySymbol': currency['id'],
2041
- };
2042
- const response = await this.privateGetAddressesCurrencySymbol(this.extend(request, params));
2043
- //
2044
- // {
2045
- // "status":"PROVISIONED",
2046
- // "currencySymbol":"XRP",
2047
- // "cryptoAddress":"rPVMhWBsfF9iMXYj3aAzJVkPDTFNSyWdKy",
2048
- // "cryptoAddressTag":"392034158"
2049
- // }
2050
- //
2051
- const address = this.safeString(response, 'cryptoAddress');
2052
- const message = this.safeString(response, 'status');
2053
- if (!address || message === 'REQUESTED') {
2054
- throw new errors.AddressPending(this.id + ' the address for ' + code + ' is being generated (pending, not ready yet, retry again later)');
2055
- }
2056
- this.checkAddress(address);
2057
- return {
2058
- 'currency': code,
2059
- 'address': address,
2060
- 'tag': this.safeString(response, 'cryptoAddressTag'),
2061
- 'network': undefined,
2062
- 'info': response,
2063
- };
2064
- }
2065
- parseDepositWithdrawFee(fee, currency = undefined) {
2066
- //
2067
- // {
2068
- // "symbol": "APXP",
2069
- // "name": "APEX Protocol",
2070
- // "coinType": "ETH_CONTRACT",
2071
- // "status": "ONLINE",
2072
- // "minConfirmations": 36,
2073
- // "notice": "",
2074
- // "txFee": "4702.00000000",
2075
- // "logoUrl": "https://bittrex.com/content/dynamic/currencies/logos/6cbff899-0ba6-4284-931b-5306a0a2333a.png",
2076
- // "prohibitedIn": [
2077
- // "US"
2078
- // ],
2079
- // "baseAddress": "0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98",
2080
- // "associatedTermsOfService": [
2081
- // ],
2082
- // "tags": [
2083
- // ]
2084
- // }
2085
- //
2086
- return {
2087
- 'info': fee,
2088
- 'withdraw': {
2089
- 'fee': this.safeNumber(fee, 'txFee'),
2090
- 'percentage': false,
2091
- },
2092
- 'deposit': {
2093
- 'fee': undefined,
2094
- 'percentage': undefined,
2095
- },
2096
- 'networks': {},
2097
- };
2098
- }
2099
- async fetchDepositWithdrawFees(codes = undefined, params = {}) {
2100
- /**
2101
- * @method
2102
- * @name bittrex#fetchDepositWithdrawFees
2103
- * @description fetch deposit and withdraw fees
2104
- * @param {string[]|undefined} codes list of unified currency codes
2105
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2106
- * @returns {object} a list of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure}
2107
- */
2108
- await this.loadMarkets();
2109
- const response = await this.publicGetCurrencies(params);
2110
- //
2111
- // [
2112
- // {
2113
- // "symbol": "APXP",
2114
- // "name": "APEX Protocol",
2115
- // "coinType": "ETH_CONTRACT",
2116
- // "status": "ONLINE",
2117
- // "minConfirmations": 36,
2118
- // "notice": "",
2119
- // "txFee": "4702.00000000",
2120
- // "logoUrl": "https://bittrex.com/content/dynamic/currencies/logos/6cbff899-0ba6-4284-931b-5306a0a2333a.png",
2121
- // "prohibitedIn": [
2122
- // "US"
2123
- // ],
2124
- // "baseAddress": "0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98",
2125
- // "associatedTermsOfService": [
2126
- // ],
2127
- // "tags": [
2128
- // ]
2129
- // },
2130
- // ]
2131
- //
2132
- return this.parseDepositWithdrawFees(response, codes, 'symbol');
2133
- }
2134
- async withdraw(code, amount, address, tag = undefined, params = {}) {
2135
- /**
2136
- * @method
2137
- * @name bittrex#withdraw
2138
- * @description make a withdrawal
2139
- * @param {string} code unified currency code
2140
- * @param {float} amount the amount to withdraw
2141
- * @param {string} address the address to withdraw to
2142
- * @param {string} tag
2143
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2144
- * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2145
- */
2146
- [tag, params] = this.handleWithdrawTagAndParams(tag, params);
2147
- this.checkAddress(address);
2148
- await this.loadMarkets();
2149
- const currency = this.currency(code);
2150
- const request = {
2151
- 'currencySymbol': currency['id'],
2152
- 'quantity': amount,
2153
- 'cryptoAddress': address,
2154
- };
2155
- if (tag !== undefined) {
2156
- request['cryptoAddressTag'] = tag;
2157
- }
2158
- const response = await this.privatePostWithdrawals(this.extend(request, params));
2159
- //
2160
- // {
2161
- // "currencySymbol": "string",
2162
- // "quantity": "number (double)",
2163
- // "cryptoAddress": "string",
2164
- // "cryptoAddressTag": "string",
2165
- // "fundsTransferMethodId": "string (uuid)",
2166
- // "clientWithdrawalId": "string (uuid)"
2167
- // }
2168
- //
2169
- return this.parseTransaction(response, currency);
2170
- }
2171
- sign(path, api = 'v3', method = 'GET', params = {}, headers = undefined, body = undefined) {
2172
- let url = this.implodeParams(this.urls['api'][api], {
2173
- 'hostname': this.hostname,
2174
- }) + '/';
2175
- if (api === 'private') {
2176
- url += this.version + '/';
2177
- this.checkRequiredCredentials();
2178
- url += this.implodeParams(path, params);
2179
- params = this.omit(params, this.extractParams(path));
2180
- let hashString = '';
2181
- if (method === 'POST') {
2182
- body = this.json(params);
2183
- hashString = body;
2184
- }
2185
- else {
2186
- if (Object.keys(params).length) {
2187
- url += '?' + this.rawencode(params);
2188
- }
2189
- }
2190
- const contentHash = this.hash(this.encode(hashString), sha512.sha512, 'hex');
2191
- const timestamp = this.milliseconds().toString();
2192
- let auth = timestamp + url + method + contentHash;
2193
- const subaccountId = this.safeValue(this.options, 'subaccountId');
2194
- if (subaccountId !== undefined) {
2195
- auth += subaccountId;
2196
- }
2197
- const signature = this.hmac(this.encode(auth), this.encode(this.secret), sha512.sha512);
2198
- headers = {
2199
- 'Api-Key': this.apiKey,
2200
- 'Api-Timestamp': timestamp,
2201
- 'Api-Content-Hash': contentHash,
2202
- 'Api-Signature': signature,
2203
- };
2204
- if (subaccountId !== undefined) {
2205
- headers['Api-Subaccount-Id'] = subaccountId;
2206
- }
2207
- if (method === 'POST') {
2208
- headers['Content-Type'] = 'application/json';
2209
- }
2210
- }
2211
- else {
2212
- if (api === 'public') {
2213
- url += this.version + '/';
2214
- }
2215
- url += this.implodeParams(path, params);
2216
- params = this.omit(params, this.extractParams(path));
2217
- if (Object.keys(params).length) {
2218
- url += '?' + this.urlencode(params);
2219
- }
2220
- }
2221
- return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2222
- }
2223
- handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2224
- if (response === undefined) {
2225
- return undefined; // fallback to default error handler
2226
- }
2227
- //
2228
- // { success: false, message: "message" }
2229
- //
2230
- if (body[0] === '{') {
2231
- const feedback = this.id + ' ' + body;
2232
- let success = this.safeValue(response, 'success');
2233
- if (success === undefined) {
2234
- const codeInner = this.safeString(response, 'code');
2235
- if ((codeInner === 'NOT_FOUND') && (url.indexOf('addresses') >= 0)) {
2236
- throw new errors.InvalidAddress(feedback);
2237
- }
2238
- if (codeInner !== undefined) {
2239
- this.throwExactlyMatchedException(this.exceptions['exact'], codeInner, feedback);
2240
- this.throwBroadlyMatchedException(this.exceptions['broad'], codeInner, feedback);
2241
- }
2242
- // throw new ExchangeError (this.id + ' malformed response ' + this.json (response));
2243
- return undefined;
2244
- }
2245
- if (typeof success === 'string') {
2246
- // bleutrade uses string instead of boolean
2247
- success = (success === 'true');
2248
- }
2249
- if (!success) {
2250
- const message = this.safeString(response, 'message');
2251
- if (message === 'APIKEY_INVALID') {
2252
- if (this.options['hasAlreadyAuthenticatedSuccessfully']) {
2253
- throw new errors.DDoSProtection(feedback);
2254
- }
2255
- else {
2256
- throw new errors.AuthenticationError(feedback);
2257
- }
2258
- }
2259
- // https://github.com/ccxt/ccxt/issues/4932
2260
- // the following two lines are now redundant, see line 171 in describe()
2261
- //
2262
- // if (message === 'DUST_TRADE_DISALLOWED_MIN_VALUE_50K_SAT')
2263
- // throw new InvalidOrder (this.id + ' order cost should be over 50k satoshi ' + this.json (response));
2264
- //
2265
- if (message === 'INVALID_ORDER') {
2266
- // Bittrex will return an ambiguous INVALID_ORDER message
2267
- // upon canceling already-canceled and closed orders
2268
- // therefore this special case for cancelOrder
2269
- // let url = 'https://bittrex.com/api/v1.1/market/cancel?apikey=API_KEY&uuid=ORDER_UUID'
2270
- const cancel = 'cancel';
2271
- const indexOfCancel = url.indexOf(cancel);
2272
- if (indexOfCancel >= 0) {
2273
- const urlParts = url.split('?');
2274
- const numParts = urlParts.length;
2275
- if (numParts > 1) {
2276
- const query = urlParts[1];
2277
- const params = query.split('&');
2278
- const numParams = params.length;
2279
- let orderId = undefined;
2280
- for (let i = 0; i < numParams; i++) {
2281
- const param = params[i];
2282
- const keyValue = param.split('=');
2283
- if (keyValue[0] === 'uuid') {
2284
- orderId = keyValue[1];
2285
- break;
2286
- }
2287
- }
2288
- if (orderId !== undefined) {
2289
- throw new errors.OrderNotFound(this.id + ' cancelOrder ' + orderId + ' ' + this.json(response));
2290
- }
2291
- else {
2292
- throw new errors.OrderNotFound(this.id + ' cancelOrder ' + this.json(response));
2293
- }
2294
- }
2295
- }
2296
- }
2297
- this.throwExactlyMatchedException(this.exceptions['exact'], message, feedback);
2298
- if (message !== undefined) {
2299
- this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
2300
- }
2301
- throw new errors.ExchangeError(feedback);
2302
- }
2303
- }
2304
- return undefined;
2305
- }
2306
- }
2307
-
2308
- module.exports = bittrex;