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