ccxt 4.5.63 → 4.5.64

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 (124) hide show
  1. package/README.md +6 -8
  2. package/dist/ccxt.browser.min.js +4 -4
  3. package/dist/cjs/ccxt.js +6 -12
  4. package/dist/cjs/src/aster.js +2 -2
  5. package/dist/cjs/src/base/Exchange.js +34 -3
  6. package/dist/cjs/src/bitget.js +5 -3
  7. package/dist/cjs/src/bitmex.js +1 -1
  8. package/dist/cjs/src/bitstamp.js +2 -1
  9. package/dist/cjs/src/bitvavo.js +1 -0
  10. package/dist/cjs/src/btcbox.js +1 -1
  11. package/dist/cjs/src/bullish.js +1 -1
  12. package/dist/cjs/src/bybiteu.js +3 -0
  13. package/dist/cjs/src/coinbase.js +3 -2
  14. package/dist/cjs/src/coinbaseinternational.js +1 -1
  15. package/dist/cjs/src/delta.js +23 -1
  16. package/dist/cjs/src/derive.js +1 -1
  17. package/dist/cjs/src/digifinex.js +12 -0
  18. package/dist/cjs/src/dydx.js +2 -2
  19. package/dist/cjs/src/extended.js +1 -1
  20. package/dist/cjs/src/gateeu.js +1 -0
  21. package/dist/cjs/src/grvt.js +1 -1
  22. package/dist/cjs/src/hashkey.js +127 -6
  23. package/dist/cjs/src/hibachi.js +20 -10
  24. package/dist/cjs/src/hyperliquid.js +1 -1
  25. package/dist/cjs/src/kraken.js +2 -0
  26. package/dist/cjs/src/kucoin.js +1 -1
  27. package/dist/cjs/src/kucoineu.js +3 -0
  28. package/dist/cjs/src/lighter.js +6 -4
  29. package/dist/cjs/src/mudrex.js +1328 -0
  30. package/dist/cjs/src/myokx.js +3 -0
  31. package/dist/cjs/src/okxus.js +1 -5
  32. package/dist/cjs/src/onetrading.js +1 -0
  33. package/dist/cjs/src/pacifica.js +1 -1
  34. package/dist/cjs/src/poloniex.js +1 -1
  35. package/dist/cjs/src/pro/bingx.js +4 -2
  36. package/dist/cjs/src/pro/bitget.js +9 -7
  37. package/dist/cjs/src/pro/grvt.js +1 -1
  38. package/dist/cjs/src/pro/hashkey.js +1 -1
  39. package/dist/cjs/src/pro/kraken.js +1 -1
  40. package/dist/cjs/src/pro/mudrex.js +226 -0
  41. package/dist/cjs/src/pro/okxus.js +1 -1
  42. package/js/ccxt.d.ts +8 -14
  43. package/js/ccxt.js +6 -10
  44. package/js/src/abstract/binance.d.ts +3 -0
  45. package/js/src/abstract/binancecoinm.d.ts +3 -0
  46. package/js/src/abstract/binanceus.d.ts +3 -0
  47. package/js/src/abstract/binanceusdm.d.ts +3 -0
  48. package/js/src/abstract/bybit.d.ts +39 -0
  49. package/js/src/abstract/bybiteu.d.ts +39 -0
  50. package/js/src/abstract/coincheck.d.ts +3 -0
  51. package/js/src/abstract/coinsph.d.ts +8 -1
  52. package/js/src/abstract/kucoineu.js +0 -6
  53. package/js/src/abstract/mudrex.d.ts +33 -0
  54. package/js/src/aster.js +2 -2
  55. package/js/src/base/Exchange.d.ts +10 -1
  56. package/js/src/base/Exchange.js +34 -3
  57. package/js/src/bitget.js +5 -3
  58. package/js/src/bitmex.js +1 -1
  59. package/js/src/bitstamp.js +2 -1
  60. package/js/src/bitvavo.js +1 -0
  61. package/js/src/btcbox.js +1 -1
  62. package/js/src/bullish.js +1 -1
  63. package/js/src/bybiteu.js +3 -0
  64. package/js/src/coinbase.js +3 -2
  65. package/js/src/coinbaseinternational.js +1 -1
  66. package/js/src/delta.d.ts +12 -0
  67. package/js/src/delta.js +23 -1
  68. package/js/src/derive.js +1 -1
  69. package/js/src/digifinex.d.ts +12 -0
  70. package/js/src/digifinex.js +12 -0
  71. package/js/src/dydx.d.ts +2 -2
  72. package/js/src/dydx.js +2 -2
  73. package/js/src/extended.js +1 -1
  74. package/js/src/gateeu.js +1 -0
  75. package/js/src/grvt.d.ts +1 -1
  76. package/js/src/grvt.js +1 -1
  77. package/js/src/hashkey.d.ts +40 -3
  78. package/js/src/hashkey.js +127 -6
  79. package/js/src/hibachi.d.ts +9 -5
  80. package/js/src/hibachi.js +20 -10
  81. package/js/src/hyperliquid.js +1 -1
  82. package/js/src/kraken.js +2 -0
  83. package/js/src/kucoin.js +1 -1
  84. package/js/src/kucoineu.js +3 -0
  85. package/js/src/lighter.js +6 -4
  86. package/js/src/mudrex.d.ts +310 -0
  87. package/js/src/mudrex.js +1321 -0
  88. package/js/src/myokx.js +3 -0
  89. package/js/src/okxus.js +1 -5
  90. package/js/src/onetrading.js +1 -0
  91. package/js/src/pacifica.js +1 -1
  92. package/js/src/poloniex.js +1 -1
  93. package/js/src/pro/bingx.js +4 -2
  94. package/js/src/pro/bitget.js +9 -7
  95. package/js/src/pro/grvt.d.ts +1 -1
  96. package/js/src/pro/grvt.js +1 -1
  97. package/js/src/pro/hashkey.d.ts +1 -1
  98. package/js/src/pro/hashkey.js +1 -1
  99. package/js/src/pro/kraken.js +1 -1
  100. package/js/src/pro/mudrex.d.ts +23 -0
  101. package/js/src/pro/mudrex.js +219 -0
  102. package/js/src/pro/okxus.js +1 -1
  103. package/package.json +3 -3
  104. package/dist/cjs/src/abstract/coinmetro.js +0 -11
  105. package/dist/cjs/src/abstract/novadax.js +0 -11
  106. package/dist/cjs/src/ascendex.js +0 -3780
  107. package/dist/cjs/src/coinmetro.js +0 -2030
  108. package/dist/cjs/src/novadax.js +0 -1678
  109. package/dist/cjs/src/pro/ascendex.js +0 -1013
  110. package/js/src/abstract/ascendex.d.ts +0 -80
  111. package/js/src/abstract/coinmetro.d.ts +0 -37
  112. package/js/src/abstract/coinmetro.js +0 -5
  113. package/js/src/abstract/novadax.d.ts +0 -32
  114. package/js/src/abstract/novadax.js +0 -5
  115. package/js/src/ascendex.d.ts +0 -436
  116. package/js/src/ascendex.js +0 -3773
  117. package/js/src/coinmetro.d.ts +0 -245
  118. package/js/src/coinmetro.js +0 -2023
  119. package/js/src/novadax.d.ts +0 -279
  120. package/js/src/novadax.js +0 -1671
  121. package/js/src/pro/ascendex.d.ts +0 -99
  122. package/js/src/pro/ascendex.js +0 -1006
  123. /package/dist/cjs/src/abstract/{ascendex.js → mudrex.js} +0 -0
  124. /package/js/src/abstract/{ascendex.js → mudrex.js} +0 -0
@@ -1,3773 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- import { sha256 } from '@noble/hashes/sha2.js';
3
- import Exchange from './abstract/ascendex.js';
4
- import { ArgumentsRequired, AuthenticationError, ExchangeError, AccountSuspended, InsufficientFunds, InvalidOrder, BadSymbol, PermissionDenied, BadRequest, NotSupported } from './base/errors.js';
5
- import { Precise } from './base/Precise.js';
6
- import { TICK_SIZE } from './base/functions/number.js';
7
- // ---------------------------------------------------------------------------
8
- /**
9
- * @class ascendex
10
- * @augments Exchange
11
- */
12
- export default class ascendex extends Exchange {
13
- describe() {
14
- return this.deepExtend(super.describe(), {
15
- 'id': 'ascendex',
16
- 'name': 'AscendEX',
17
- 'countries': ['SG'], // Singapore
18
- // 8 requests per minute = 0.13333 per second => rateLimit = 750
19
- // testing 400 works
20
- 'rateLimit': 400,
21
- 'certified': false,
22
- 'pro': true,
23
- // new metainfo interface
24
- 'has': {
25
- 'CORS': undefined,
26
- 'spot': true,
27
- 'margin': true,
28
- 'swap': true,
29
- 'future': false,
30
- 'option': false,
31
- 'addMargin': true,
32
- 'cancelAllOrders': true,
33
- 'cancelOrder': true,
34
- 'createOrder': true,
35
- 'createOrders': true,
36
- 'createPostOnlyOrder': true,
37
- 'createReduceOnlyOrder': true,
38
- 'createStopLimitOrder': true,
39
- 'createStopMarketOrder': true,
40
- 'createStopOrder': true,
41
- 'fetchAccounts': true,
42
- 'fetchAllGreeks': false,
43
- 'fetchBalance': true,
44
- 'fetchBorrowRate': false,
45
- 'fetchBorrowRateHistory': false,
46
- 'fetchBorrowRates': false,
47
- 'fetchClosedOrders': true,
48
- 'fetchCrossBorrowRate': false,
49
- 'fetchCrossBorrowRates': false,
50
- 'fetchCurrencies': true,
51
- 'fetchDepositAddress': true,
52
- 'fetchDepositAddresses': false,
53
- 'fetchDepositAddressesByNetwork': false,
54
- 'fetchDeposits': true,
55
- 'fetchDepositsWithdrawals': true,
56
- 'fetchDepositWithdrawFee': 'emulated',
57
- 'fetchDepositWithdrawFees': true,
58
- 'fetchFundingHistory': true,
59
- 'fetchFundingRate': 'emulated',
60
- 'fetchFundingRateHistory': false,
61
- 'fetchFundingRates': true,
62
- 'fetchGreeks': false,
63
- 'fetchIndexOHLCV': false,
64
- 'fetchIsolatedBorrowRate': false,
65
- 'fetchIsolatedBorrowRates': false,
66
- 'fetchLeverage': 'emulated',
67
- 'fetchLeverages': true,
68
- 'fetchLeverageTiers': true,
69
- 'fetchMarginMode': 'emulated',
70
- 'fetchMarginModes': true,
71
- 'fetchMarketLeverageTiers': 'emulated',
72
- 'fetchMarkets': true,
73
- 'fetchMarkOHLCV': false,
74
- 'fetchMySettlementHistory': false,
75
- 'fetchOHLCV': true,
76
- 'fetchOpenInterest': 'emulated',
77
- 'fetchOpenInterestHistory': false,
78
- 'fetchOpenInterests': true,
79
- 'fetchOpenOrders': true,
80
- 'fetchOption': false,
81
- 'fetchOptionChain': false,
82
- 'fetchOrder': true,
83
- 'fetchOrderBook': true,
84
- 'fetchOrders': false,
85
- 'fetchPosition': false,
86
- 'fetchPositionMode': false,
87
- 'fetchPositions': true,
88
- 'fetchPositionsRisk': false,
89
- 'fetchPremiumIndexOHLCV': false,
90
- 'fetchSettlementHistory': false,
91
- 'fetchTicker': true,
92
- 'fetchTickers': true,
93
- 'fetchTime': true,
94
- 'fetchTrades': true,
95
- 'fetchTradingFee': false,
96
- 'fetchTradingFees': true,
97
- 'fetchTransactionFee': false,
98
- 'fetchTransactionFees': false,
99
- 'fetchTransactions': 'emulated',
100
- 'fetchTransfer': false,
101
- 'fetchTransfers': false,
102
- 'fetchVolatilityHistory': false,
103
- 'fetchWithdrawal': false,
104
- 'fetchWithdrawals': true,
105
- 'reduceMargin': true,
106
- 'sandbox': true,
107
- 'setLeverage': true,
108
- 'setMarginMode': true,
109
- 'setPositionMode': false,
110
- 'transfer': true,
111
- },
112
- 'timeframes': {
113
- '1m': '1',
114
- '5m': '5',
115
- '15m': '15',
116
- '30m': '30',
117
- '1h': '60',
118
- '2h': '120',
119
- '4h': '240',
120
- '6h': '360',
121
- '12h': '720',
122
- '1d': '1d',
123
- '1w': '1w',
124
- '1M': '1m',
125
- },
126
- 'version': 'v2',
127
- 'urls': {
128
- 'logo': 'https://github.com/user-attachments/assets/55bab6b9-d4ca-42a8-a0e6-fac81ae557f1',
129
- 'api': {
130
- 'rest': 'https://ascendex.com',
131
- },
132
- 'test': {
133
- 'rest': 'https://api-test.ascendex-sandbox.com',
134
- },
135
- 'www': 'https://ascendex.com',
136
- 'doc': [
137
- 'https://ascendex.github.io/ascendex-pro-api/#ascendex-pro-api-documentation',
138
- ],
139
- 'fees': 'https://ascendex.com/en/feerate/transactionfee-traderate',
140
- 'referral': {
141
- 'url': 'https://ascendex.com/en-us/register?inviteCode=EL6BXBQM',
142
- 'discount': 0.25,
143
- },
144
- },
145
- 'api': {
146
- 'v1': {
147
- 'public': {
148
- 'get': {
149
- 'assets': 1,
150
- 'products': 1,
151
- 'ticker': 1,
152
- 'barhist/info': 1,
153
- 'barhist': 1,
154
- 'depth': 1,
155
- 'trades': 1,
156
- 'cash/assets': 1, // not documented
157
- 'cash/products': 1, // not documented
158
- 'margin/assets': 1, // not documented
159
- 'margin/products': 1, // not documented
160
- 'futures/collateral': 1,
161
- 'futures/contracts': 1,
162
- 'futures/ref-px': 1,
163
- 'futures/market-data': 1,
164
- 'futures/funding-rates': 1,
165
- 'risk-limit-info': 1,
166
- 'exchange-info': 1,
167
- },
168
- },
169
- 'private': {
170
- 'get': {
171
- 'info': 1,
172
- 'wallet/transactions': 1,
173
- 'wallet/deposit/address': 1,
174
- 'data/balance/snapshot': 1,
175
- 'data/balance/history': 1,
176
- },
177
- 'accountCategory': {
178
- 'get': {
179
- 'balance': 1,
180
- 'order/open': 1,
181
- 'order/status': 1,
182
- 'order/hist/current': 1,
183
- 'risk': 1,
184
- },
185
- 'post': {
186
- 'order': 1,
187
- 'order/batch': 1,
188
- },
189
- 'delete': {
190
- 'order': 1,
191
- 'order/all': 1,
192
- 'order/batch': 1,
193
- },
194
- },
195
- 'accountGroup': {
196
- 'get': {
197
- 'cash/balance': 1,
198
- 'margin/balance': 1,
199
- 'margin/risk': 1,
200
- 'futures/collateral-balance': 1,
201
- 'futures/position': 1,
202
- 'futures/risk': 1,
203
- 'futures/funding-payments': 1,
204
- 'order/hist': 1,
205
- 'spot/fee': 1,
206
- },
207
- 'post': {
208
- 'transfer': 1,
209
- 'futures/transfer/deposit': 1,
210
- 'futures/transfer/withdraw': 1,
211
- },
212
- },
213
- },
214
- },
215
- 'v2': {
216
- 'public': {
217
- 'get': {
218
- 'assets': 1,
219
- 'futures/contract': 1,
220
- 'futures/collateral': 1,
221
- 'futures/pricing-data': 1,
222
- 'futures/ticker': 1,
223
- 'risk-limit-info': 1,
224
- },
225
- },
226
- 'private': {
227
- 'data': {
228
- 'get': {
229
- 'order/hist': 1,
230
- },
231
- },
232
- 'get': {
233
- 'account/info': 1,
234
- },
235
- 'accountGroup': {
236
- 'get': {
237
- 'order/hist': 1,
238
- 'futures/position': 1,
239
- 'futures/free-margin': 1,
240
- 'futures/order/hist/current': 1,
241
- 'futures/funding-payments': 1,
242
- 'futures/order/open': 1,
243
- 'futures/order/status': 1,
244
- },
245
- 'post': {
246
- 'futures/isolated-position-margin': 1,
247
- 'futures/margin-type': 1,
248
- 'futures/leverage': 1,
249
- 'futures/transfer/deposit': 1,
250
- 'futures/transfer/withdraw': 1,
251
- 'futures/order': 1,
252
- 'futures/order/batch': 1,
253
- 'futures/order/open': 1,
254
- 'subuser/subuser-transfer': 1,
255
- 'subuser/subuser-transfer-hist': 1,
256
- },
257
- 'delete': {
258
- 'futures/order': 1,
259
- 'futures/order/batch': 1,
260
- 'futures/order/all': 1,
261
- },
262
- },
263
- },
264
- },
265
- },
266
- 'fees': {
267
- 'trading': {
268
- 'feeSide': 'get',
269
- 'tierBased': true,
270
- 'percentage': true,
271
- 'taker': this.parseNumber('0.002'),
272
- 'maker': this.parseNumber('0.002'),
273
- },
274
- },
275
- 'precisionMode': TICK_SIZE,
276
- 'options': {
277
- 'account-category': 'cash', // 'cash', 'margin', 'futures' // obsolete
278
- 'account-group': undefined,
279
- 'fetchClosedOrders': {
280
- 'method': 'v2PrivateDataGetOrderHist', // 'v1PrivateAccountCategoryGetOrderHistCurrent'
281
- },
282
- 'defaultType': 'spot', // 'spot', 'margin', 'swap'
283
- 'accountsByType': {
284
- 'spot': 'cash',
285
- 'swap': 'futures',
286
- 'margin': 'margin',
287
- },
288
- 'transfer': {
289
- 'fillResponseFromRequest': true,
290
- },
291
- 'networks': {
292
- 'BSC': 'BEP20 ' + '(BSC)',
293
- 'ARB': 'arbitrum',
294
- 'SOL': 'Solana',
295
- 'AVAX': 'avalanche C chain',
296
- 'OMNI': 'Omni',
297
- // 'TRC': 'TRC20',
298
- 'TRC20': 'TRC20',
299
- 'ERC20': 'ERC20',
300
- 'GO20': 'GO20',
301
- 'BEP2': 'BEP2',
302
- 'BTC': 'Bitcoin',
303
- 'BCH': 'Bitcoin ABC',
304
- 'LTC': 'Litecoin',
305
- 'MATIC': 'Matic Network',
306
- 'AKT': 'Akash',
307
- },
308
- },
309
- 'features': {
310
- 'default': {
311
- 'sandbox': true,
312
- 'createOrder': {
313
- 'marginMode': true,
314
- 'triggerPrice': true,
315
- 'triggerPriceType': undefined,
316
- 'triggerDirection': false,
317
- 'stopLossPrice': false, // todo with triggerprice
318
- 'takeProfitPrice': false, // todo with triggerprice
319
- 'attachedStopLossTakeProfit': undefined,
320
- 'timeInForce': {
321
- 'IOC': true,
322
- 'FOK': true,
323
- 'PO': true,
324
- 'GTD': false,
325
- },
326
- 'hedged': false,
327
- 'trailing': false,
328
- 'leverage': false,
329
- 'marketBuyRequiresPrice': false,
330
- 'marketBuyByCost': false,
331
- 'selfTradePrevention': false,
332
- 'iceberg': false,
333
- },
334
- 'createOrders': {
335
- 'max': 10,
336
- },
337
- 'fetchMyTrades': undefined,
338
- 'fetchOrder': {
339
- 'marginMode': false,
340
- 'trigger': false,
341
- 'trailing': false,
342
- 'marketType': true,
343
- 'symbolRequired': false,
344
- },
345
- 'fetchOpenOrders': {
346
- 'marginMode': false,
347
- 'limit': undefined,
348
- 'trigger': false,
349
- 'trailing': false,
350
- 'marketType': true,
351
- 'symbolRequired': false,
352
- },
353
- 'fetchOrders': undefined,
354
- 'fetchClosedOrders': undefined,
355
- 'fetchOHLCV': {
356
- 'limit': 500,
357
- },
358
- },
359
- 'spot': {
360
- 'extends': 'default',
361
- 'fetchClosedOrders': {
362
- 'marginMode': false,
363
- 'limit': 1000,
364
- 'daysBack': 100000,
365
- 'daysBackCanceled': 1,
366
- 'untilDays': 100000,
367
- 'trigger': false,
368
- 'trailing': false,
369
- 'symbolRequired': false,
370
- },
371
- },
372
- 'forDerivatives': {
373
- 'extends': 'default',
374
- 'createOrder': {
375
- // todo: implementation
376
- 'attachedStopLossTakeProfit': {
377
- 'triggerPriceType': {
378
- 'last': true,
379
- 'mark': false,
380
- 'index': false,
381
- },
382
- 'price': false,
383
- },
384
- },
385
- 'fetchClosedOrders': {
386
- 'marginMode': false,
387
- 'limit': 1000,
388
- 'daysBack': undefined,
389
- 'daysBackCanceled': undefined,
390
- 'untilDays': undefined,
391
- 'trigger': false,
392
- 'trailing': false,
393
- 'symbolRequired': false,
394
- },
395
- },
396
- 'swap': {
397
- 'linear': {
398
- 'extends': 'forDerivatives',
399
- },
400
- 'inverse': undefined,
401
- },
402
- 'future': {
403
- 'linear': undefined,
404
- 'inverse': undefined,
405
- },
406
- },
407
- 'exceptions': {
408
- 'exact': {
409
- // not documented
410
- '1900': BadRequest, // {"code":1900,"message":"Invalid Http Request Input"}
411
- '2100': AuthenticationError, // {"code":2100,"message":"ApiKeyFailure"}
412
- '5002': BadSymbol, // {"code":5002,"message":"Invalid Symbol"}
413
- '6001': BadSymbol, // {"code":6001,"message":"Trading is disabled on symbol."}
414
- '6010': InsufficientFunds, // {'code': 6010, 'message': 'Not enough balance.'}
415
- '60060': InvalidOrder, // { 'code': 60060, 'message': 'The order is already filled or canceled.' }
416
- '600503': InvalidOrder, // {"code":600503,"message":"Notional is too small."}
417
- // documented
418
- '100001': BadRequest, // INVALID_HTTP_INPUT Http request is invalid
419
- '100002': BadRequest, // DATA_NOT_AVAILABLE Some required data is missing
420
- '100003': BadRequest, // KEY_CONFLICT The same key exists already
421
- '100004': BadRequest, // INVALID_REQUEST_DATA The HTTP request contains invalid field or argument
422
- '100005': BadRequest, // INVALID_WS_REQUEST_DATA Websocket request contains invalid field or argument
423
- '100006': BadRequest, // INVALID_ARGUMENT The arugment is invalid
424
- '100007': BadRequest, // ENCRYPTION_ERROR Something wrong with data encryption
425
- '100008': BadSymbol, // SYMBOL_ERROR Symbol does not exist or not valid for the request
426
- '100009': AuthenticationError, // AUTHORIZATION_NEEDED Authorization is require for the API access or request
427
- '100010': BadRequest, // INVALID_OPERATION The action is invalid or not allowed for the account
428
- '100011': BadRequest, // INVALID_TIMESTAMP Not a valid timestamp
429
- '100012': BadRequest, // INVALID_STR_FORMAT String format does not
430
- '100013': BadRequest, // INVALID_NUM_FORMAT Invalid number input
431
- '100101': ExchangeError, // UNKNOWN_ERROR Some unknown error
432
- '150001': BadRequest, // INVALID_JSON_FORMAT Require a valid json object
433
- '200001': AuthenticationError, // AUTHENTICATION_FAILED Authorization failed
434
- '200002': ExchangeError, // TOO_MANY_ATTEMPTS Tried and failed too many times
435
- '200003': ExchangeError, // ACCOUNT_NOT_FOUND Account not exist
436
- '200004': ExchangeError, // ACCOUNT_NOT_SETUP Account not setup properly
437
- '200005': ExchangeError, // ACCOUNT_ALREADY_EXIST Account already exist
438
- '200006': ExchangeError, // ACCOUNT_ERROR Some error related with error
439
- '200007': ExchangeError, // CODE_NOT_FOUND
440
- '200008': ExchangeError, // CODE_EXPIRED Code expired
441
- '200009': ExchangeError, // CODE_MISMATCH Code does not match
442
- '200010': AuthenticationError, // PASSWORD_ERROR Wrong assword
443
- '200011': ExchangeError, // CODE_GEN_FAILED Do not generate required code promptly
444
- '200012': ExchangeError, // FAKE_COKE_VERIFY
445
- '200013': ExchangeError, // SECURITY_ALERT Provide security alert message
446
- '200014': PermissionDenied, // RESTRICTED_ACCOUNT Account is restricted for certain activity, such as trading, or withdraw.
447
- '200015': PermissionDenied, // PERMISSION_DENIED No enough permission for the operation
448
- '300001': InvalidOrder, // INVALID_PRICE Order price is invalid
449
- '300002': InvalidOrder, // INVALID_QTY Order size is invalid
450
- '300003': InvalidOrder, // INVALID_SIDE Order side is invalid
451
- '300004': InvalidOrder, // INVALID_NOTIONAL Notional is too small or too large
452
- '300005': InvalidOrder, // INVALID_TYPE Order typs is invalid
453
- '300006': InvalidOrder, // INVALID_ORDER_ID Order id is invalid
454
- '300007': InvalidOrder, // INVALID_TIME_IN_FORCE Time In Force in order request is invalid
455
- '300008': InvalidOrder, // INVALID_ORDER_PARAMETER Some order parameter is invalid
456
- '300009': InvalidOrder, // TRADING_VIOLATION Trading violation on account or asset
457
- '300011': InsufficientFunds, // INVALID_BALANCE No enough account or asset balance for the trading
458
- '300012': BadSymbol, // INVALID_PRODUCT Not a valid product supported by exchange
459
- '300013': InvalidOrder, // INVALID_BATCH_ORDER Some or all orders are invalid in batch order request
460
- '300014': InvalidOrder, // {"code":300014,"message":"Order price doesn't conform to the required tick size: 0.1","reason":"TICK_SIZE_VIOLATION"}
461
- '300020': InvalidOrder, // TRADING_RESTRICTED There is some trading restriction on account or asset
462
- '300021': AccountSuspended, // {"code":300021,"message":"Trading disabled for this account.","reason":"TRADING_DISABLED"}
463
- '300031': InvalidOrder, // NO_MARKET_PRICE No market price for market type order trading
464
- '310001': InsufficientFunds, // INVALID_MARGIN_BALANCE No enough margin balance
465
- '310002': InvalidOrder, // INVALID_MARGIN_ACCOUNT Not a valid account for margin trading
466
- '310003': InvalidOrder, // MARGIN_TOO_RISKY Leverage is too high
467
- '310004': BadSymbol, // INVALID_MARGIN_ASSET This asset does not support margin trading
468
- '310005': InvalidOrder, // INVALID_REFERENCE_PRICE There is no valid reference price
469
- '510001': ExchangeError, // SERVER_ERROR Something wrong with server.
470
- '900001': ExchangeError, // HUMAN_CHALLENGE Human change do not pass
471
- },
472
- 'broad': {},
473
- },
474
- 'commonCurrencies': {
475
- 'XBT': 'XBT', // this is not BTC ! just another token
476
- 'BOND': 'BONDED',
477
- 'BTCBEAR': 'BEAR',
478
- 'BTCBULL': 'BULL',
479
- 'BYN': 'BeyondFi',
480
- 'PLN': 'Pollen',
481
- },
482
- });
483
- }
484
- getAccount(params = {}) {
485
- // get current or provided bitmax sub-account
486
- const account = this.safeValue(params, 'account', this.options['account']);
487
- const lowercaseAccount = account.toLowerCase();
488
- return this.capitalize(lowercaseAccount);
489
- }
490
- /**
491
- * @method
492
- * @name ascendex#fetchCurrencies
493
- * @description fetches all available currencies on an exchange
494
- * @param {object} [params] extra parameters specific to the exchange API endpoint
495
- * @returns {object} an associative dictionary of currencies
496
- */
497
- async fetchCurrencies(params = {}) {
498
- const response = await this.v2PublicGetAssets(params);
499
- //
500
- // {
501
- // "code": "0",
502
- // "data": [
503
- // {
504
- // "assetCode": "USDT",
505
- // "assetName": "Tether",
506
- // "precisionScale": 9,
507
- // "nativeScale": 4,
508
- // "blockChain": [
509
- // {
510
- // "chainName": "Solana",
511
- // "withdrawFee": "2.0",
512
- // "allowDeposit": true,
513
- // "allowWithdraw": true,
514
- // "minDepositAmt": "0.01",
515
- // "minWithdrawal": "4.0",
516
- // "numConfirmations": 1
517
- // },
518
- // ...
519
- // ]
520
- // },
521
- // ]
522
- // }
523
- //
524
- const data = this.safeList(response, 'data', []);
525
- return this.parseCurrencies(data);
526
- }
527
- parseCurrency(rawCurrency) {
528
- const id = this.safeString(rawCurrency, 'assetCode');
529
- const code = this.safeCurrencyCode(id);
530
- const chains = this.safeList(rawCurrency, 'blockChain', []);
531
- const precision = this.parseNumber(this.parsePrecision(this.safeString(rawCurrency, 'nativeScale')));
532
- const networks = {};
533
- for (let j = 0; j < chains.length; j++) {
534
- const networkEtnry = chains[j];
535
- const networkId = this.safeString(networkEtnry, 'chainName');
536
- const networkCode = this.networkCodeToId(networkId, code);
537
- networks[networkCode] = {
538
- 'fee': this.safeNumber(networkEtnry, 'withdrawFee'),
539
- 'active': undefined,
540
- 'withdraw': this.safeBool(networkEtnry, 'allowWithdraw'),
541
- 'deposit': this.safeBool(networkEtnry, 'allowDeposit'),
542
- 'precision': precision,
543
- 'limits': {
544
- 'amount': {
545
- 'min': undefined,
546
- 'max': undefined,
547
- },
548
- 'withdraw': {
549
- 'min': this.safeNumber(networkEtnry, 'minWithdrawal'),
550
- 'max': undefined,
551
- },
552
- 'deposit': {
553
- 'min': this.safeNumber(networkEtnry, 'minDepositAmt'),
554
- 'max': undefined,
555
- },
556
- },
557
- };
558
- }
559
- // todo type: if (chainsLength === 0 && (assetName.endsWith (' Staking') || assetName.indexOf (' Reward ') >= 0 || assetName.indexOf ('Slot Auction') >= 0 || assetName.indexOf (' Freeze Asset') >= 0))
560
- return this.safeCurrencyStructure({
561
- 'id': id,
562
- 'code': code,
563
- 'info': rawCurrency,
564
- 'type': undefined,
565
- 'margin': undefined,
566
- 'name': this.safeString(rawCurrency, 'assetName'),
567
- 'active': undefined,
568
- 'deposit': undefined,
569
- 'withdraw': undefined,
570
- 'fee': undefined,
571
- 'precision': precision,
572
- 'limits': {
573
- 'amount': {
574
- 'min': undefined,
575
- 'max': undefined,
576
- },
577
- 'withdraw': {
578
- 'min': this.safeNumber(rawCurrency, 'minWithdrawalAmt'),
579
- 'max': undefined,
580
- },
581
- },
582
- 'networks': networks,
583
- });
584
- }
585
- /**
586
- * @method
587
- * @name ascendex#fetchMarkets
588
- * @description retrieves data on all markets for ascendex
589
- * @param {object} [params] extra parameters specific to the exchange API endpoint
590
- * @returns {object[]} an array of objects representing market data
591
- */
592
- async fetchMarkets(params = {}) {
593
- const spotPromise = this.fetchSpotMarkets(params);
594
- const contractPromise = this.fetchContractMarkets(params);
595
- const [spotMarkets, contractMarkets] = await Promise.all([spotPromise, contractPromise]);
596
- return this.arrayConcat(spotMarkets, contractMarkets);
597
- }
598
- async fetchSpotMarkets(params = {}) {
599
- const productsPromise = this.v1PublicGetProducts(params);
600
- //
601
- // {
602
- // "code": 0,
603
- // "data": [
604
- // {
605
- // "symbol": "LBA/BTC",
606
- // "baseAsset": "LBA",
607
- // "quoteAsset": "BTC",
608
- // "status": "Normal",
609
- // "minNotional": "0.000625",
610
- // "maxNotional": "6.25",
611
- // "marginTradable": false,
612
- // "commissionType": "Quote",
613
- // "commissionReserveRate": "0.001",
614
- // "tickSize": "0.000000001",
615
- // "lotSize": "1"
616
- // },
617
- // ]
618
- // }
619
- //
620
- const cashPromise = this.v1PublicGetCashProducts(params);
621
- //
622
- // {
623
- // "code": 0,
624
- // "data": [
625
- // {
626
- // "symbol": "QTUM/BTC",
627
- // "displayName": "QTUM/BTC",
628
- // "domain": "BTC",
629
- // "tradingStartTime": 1569506400000,
630
- // "collapseDecimals": "0.0001,0.000001,0.00000001",
631
- // "minQty": "0.000000001",
632
- // "maxQty": "1000000000",
633
- // "minNotional": "0.000625",
634
- // "maxNotional": "12.5",
635
- // "statusCode": "Normal",
636
- // "statusMessage": "",
637
- // "tickSize": "0.00000001",
638
- // "useTick": false,
639
- // "lotSize": "0.1",
640
- // "useLot": false,
641
- // "commissionType": "Quote",
642
- // "commissionReserveRate": "0.001",
643
- // "qtyScale": 1,
644
- // "priceScale": 8,
645
- // "notionalScale": 4
646
- // }
647
- // ]
648
- // }
649
- //
650
- const [products, cash] = await Promise.all([productsPromise, cashPromise]);
651
- const productsData = this.safeList(products, 'data', []);
652
- const productsById = this.indexBy(productsData, 'symbol');
653
- const cashData = this.safeList(cash, 'data', []);
654
- const cashAndPerpetualsById = this.indexBy(cashData, 'symbol');
655
- const dataById = this.deepExtend(productsById, cashAndPerpetualsById);
656
- const ids = Object.keys(dataById);
657
- const result = [];
658
- for (let i = 0; i < ids.length; i++) {
659
- const id = ids[i];
660
- if (id.indexOf('-PERP') >= 0) {
661
- continue; // skip perpetuals, as separate endpoint returns them
662
- }
663
- const market = dataById[id];
664
- const status = this.safeString(market, 'status');
665
- const domain = this.safeString(market, 'domain');
666
- let active = false;
667
- if (((status === 'Normal') || (status === 'InternalTrading')) && (domain !== 'LeveragedETF')) {
668
- active = true;
669
- }
670
- const minQty = this.safeNumber(market, 'minQty');
671
- const maxQty = this.safeNumber(market, 'maxQty');
672
- const minPrice = this.safeNumber(market, 'tickSize');
673
- const maxPrice = undefined;
674
- const underlying = this.safeString2(market, 'underlying', 'symbol');
675
- const parts = underlying.split('/');
676
- const baseId = this.safeString(parts, 0);
677
- const quoteId = this.safeString(parts, 1);
678
- const base = this.safeCurrencyCode(baseId);
679
- const quote = this.safeCurrencyCode(quoteId);
680
- const fee = this.safeNumber(market, 'commissionReserveRate');
681
- const marginTradable = this.safeBool(market, 'marginTradable', false);
682
- result.push({
683
- 'id': id,
684
- 'symbol': base + '/' + quote,
685
- 'base': base,
686
- 'baseId': baseId,
687
- 'quote': quote,
688
- 'quoteId': quoteId,
689
- 'settle': undefined,
690
- 'settleId': undefined,
691
- 'type': 'spot',
692
- 'spot': true,
693
- 'margin': marginTradable,
694
- 'swap': false,
695
- 'future': false,
696
- 'option': false,
697
- 'active': active,
698
- 'contract': false,
699
- 'linear': undefined,
700
- 'inverse': undefined,
701
- 'taker': fee,
702
- 'maker': fee,
703
- 'contractSize': undefined,
704
- 'expiry': undefined,
705
- 'expiryDatetime': undefined,
706
- 'strike': undefined,
707
- 'optionType': undefined,
708
- 'precision': {
709
- 'amount': this.safeNumber(market, 'lotSize'),
710
- 'price': this.safeNumber(market, 'tickSize'),
711
- },
712
- 'limits': {
713
- 'leverage': {
714
- 'min': undefined,
715
- 'max': undefined,
716
- },
717
- 'amount': {
718
- 'min': minQty,
719
- 'max': maxQty,
720
- },
721
- 'price': {
722
- 'min': minPrice,
723
- 'max': maxPrice,
724
- },
725
- 'cost': {
726
- 'min': this.safeNumber(market, 'minNotional'),
727
- 'max': this.safeNumber(market, 'maxNotional'),
728
- },
729
- },
730
- 'created': this.safeInteger(market, 'tradingStartTime'),
731
- 'info': market,
732
- });
733
- }
734
- return result;
735
- }
736
- async fetchContractMarkets(params = {}) {
737
- const contracts = await this.v2PublicGetFuturesContract(params);
738
- //
739
- // {
740
- // "code": 0,
741
- // "data": [
742
- // {
743
- // "symbol": "BTC-PERP",
744
- // "status": "Normal",
745
- // "displayName": "BTCUSDT",
746
- // "settlementAsset": "USDT",
747
- // "underlying": "BTC/USDT",
748
- // "tradingStartTime": 1579701600000,
749
- // "priceFilter": {
750
- // "minPrice": "0.1",
751
- // "maxPrice": "1000000",
752
- // "tickSize": "0.1"
753
- // },
754
- // "lotSizeFilter": {
755
- // "minQty": "0.0001",
756
- // "maxQty": "1000000000",
757
- // "lotSize": "0.0001"
758
- // },
759
- // "commissionType": "Quote",
760
- // "commissionReserveRate": "0.001",
761
- // "marketOrderPriceMarkup": "0.03",
762
- // "marginRequirements": [
763
- // {
764
- // "positionNotionalLowerBound": "0",
765
- // "positionNotionalUpperBound": "50000",
766
- // "initialMarginRate": "0.01",
767
- // "maintenanceMarginRate": "0.006"
768
- // },
769
- // ...
770
- // ]
771
- // }
772
- // ]
773
- // }
774
- //
775
- const data = this.safeList(contracts, 'data', []);
776
- const result = [];
777
- for (let i = 0; i < data.length; i++) {
778
- const market = data[i];
779
- const id = this.safeString(market, 'symbol');
780
- const underlying = this.safeString(market, 'underlying');
781
- const parts = underlying.split('/');
782
- const baseId = this.safeString(parts, 0);
783
- const base = this.safeCurrencyCode(baseId);
784
- const quoteId = this.safeString(parts, 1);
785
- const quote = this.safeCurrencyCode(quoteId);
786
- const settleId = this.safeString(market, 'settlementAsset');
787
- const settle = this.safeCurrencyCode(settleId);
788
- const linear = settle === quote;
789
- const inverse = settle === base;
790
- const symbol = base + '/' + quote + ':' + settle;
791
- const priceFilter = this.safeDict(market, 'priceFilter');
792
- const lotSizeFilter = this.safeDict(market, 'lotSizeFilter');
793
- const fee = this.safeNumber(market, 'commissionReserveRate');
794
- result.push({
795
- 'id': id,
796
- 'symbol': symbol,
797
- 'base': base,
798
- 'quote': quote,
799
- 'settle': settle,
800
- 'baseId': baseId,
801
- 'quoteId': quoteId,
802
- 'settleId': settleId,
803
- 'type': 'swap',
804
- 'spot': false,
805
- 'margin': undefined,
806
- 'swap': true,
807
- 'future': false,
808
- 'option': false,
809
- 'active': this.safeString(market, 'status') === 'Normal',
810
- 'contract': true,
811
- 'linear': linear,
812
- 'inverse': inverse,
813
- 'taker': fee,
814
- 'maker': fee,
815
- 'contractSize': this.parseNumber('1'),
816
- 'expiry': undefined,
817
- 'expiryDatetime': undefined,
818
- 'strike': undefined,
819
- 'optionType': undefined,
820
- 'precision': {
821
- 'amount': this.safeNumber(lotSizeFilter, 'lotSize'),
822
- 'price': this.safeNumber(priceFilter, 'tickSize'),
823
- },
824
- 'limits': {
825
- 'leverage': {
826
- 'min': undefined,
827
- 'max': undefined,
828
- },
829
- 'amount': {
830
- 'min': this.safeNumber(lotSizeFilter, 'minQty'),
831
- 'max': this.safeNumber(lotSizeFilter, 'maxQty'),
832
- },
833
- 'price': {
834
- 'min': this.safeNumber(priceFilter, 'minPrice'),
835
- 'max': this.safeNumber(priceFilter, 'maxPrice'),
836
- },
837
- 'cost': {
838
- 'min': this.safeNumber(market, 'minNotional'),
839
- 'max': this.safeNumber(market, 'maxNotional'),
840
- },
841
- },
842
- 'created': this.safeInteger(market, 'tradingStartTime'),
843
- 'info': market,
844
- });
845
- }
846
- return result;
847
- }
848
- /**
849
- * @method
850
- * @name ascendex#fetchTime
851
- * @description fetches the current integer timestamp in milliseconds from the ascendex server
852
- * @param {object} [params] extra parameters specific to the exchange API endpoint
853
- * @returns {int} the current integer timestamp in milliseconds from the ascendex server
854
- */
855
- async fetchTime(params = {}) {
856
- const request = {
857
- 'requestTime': this.milliseconds(),
858
- };
859
- const response = await this.v1PublicGetExchangeInfo(this.extend(request, params));
860
- //
861
- // {
862
- // "code": 0,
863
- // "data": {
864
- // "requestTimeEcho": 1656560463601,
865
- // "requestReceiveAt": 1656560464331,
866
- // "latency": 730
867
- // }
868
- // }
869
- //
870
- const data = this.safeDict(response, 'data', {});
871
- return this.safeInteger(data, 'requestReceiveAt');
872
- }
873
- /**
874
- * @method
875
- * @name ascendex#fetchAccounts
876
- * @description fetch all the accounts associated with a profile
877
- * @param {object} [params] extra parameters specific to the exchange API endpoint
878
- * @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/?id=account-structure} indexed by the account type
879
- */
880
- async fetchAccounts(params = {}) {
881
- let accountGroup = this.safeString(this.options, 'account-group');
882
- let response = undefined;
883
- if (accountGroup === undefined) {
884
- response = await this.v1PrivateGetInfo(params);
885
- //
886
- // {
887
- // "code":0,
888
- // "data":{
889
- // "email":"igor.kroitor@gmail.com",
890
- // "accountGroup":8,
891
- // "viewPermission":true,
892
- // "tradePermission":true,
893
- // "transferPermission":true,
894
- // "cashAccount":["cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda"],
895
- // "marginAccount":["martXoh1v1N3EMQC5FDtSj5VHso8aI2Z"],
896
- // "futuresAccount":["futc9r7UmFJAyBY2rE3beA2JFxav2XFF"],
897
- // "userUID":"U6491137460"
898
- // }
899
- // }
900
- //
901
- const data = this.safeDict(response, 'data', {});
902
- accountGroup = this.safeString(data, 'accountGroup');
903
- this.options['account-group'] = accountGroup;
904
- }
905
- const finalResponse = response; // java req
906
- const finalAccountGroup = accountGroup;
907
- return [
908
- {
909
- 'id': finalAccountGroup,
910
- 'type': undefined,
911
- 'code': undefined,
912
- 'info': finalResponse,
913
- },
914
- ];
915
- }
916
- parseBalance(response) {
917
- const result = {
918
- 'info': response,
919
- 'timestamp': undefined,
920
- 'datetime': undefined,
921
- };
922
- const balances = this.safeList(response, 'data', []);
923
- for (let i = 0; i < balances.length; i++) {
924
- const balance = balances[i];
925
- const code = this.safeCurrencyCode(this.safeString(balance, 'asset'));
926
- const account = this.account();
927
- account['free'] = this.safeString(balance, 'availableBalance');
928
- account['total'] = this.safeString(balance, 'totalBalance');
929
- result[code] = account;
930
- }
931
- return this.safeBalance(result);
932
- }
933
- parseMarginBalance(response) {
934
- const result = {
935
- 'info': response,
936
- 'timestamp': undefined,
937
- 'datetime': undefined,
938
- };
939
- const balances = this.safeList(response, 'data', []);
940
- for (let i = 0; i < balances.length; i++) {
941
- const balance = balances[i];
942
- const code = this.safeCurrencyCode(this.safeString(balance, 'asset'));
943
- const account = this.account();
944
- account['free'] = this.safeString(balance, 'availableBalance');
945
- account['total'] = this.safeString(balance, 'totalBalance');
946
- const debt = this.safeString(balance, 'borrowed');
947
- const interest = this.safeString(balance, 'interest');
948
- account['debt'] = Precise.stringAdd(debt, interest);
949
- result[code] = account;
950
- }
951
- return this.safeBalance(result);
952
- }
953
- parseSwapBalance(response) {
954
- const result = {
955
- 'info': response,
956
- 'timestamp': undefined,
957
- 'datetime': undefined,
958
- };
959
- const data = this.safeDict(response, 'data', {});
960
- const collaterals = this.safeList(data, 'collaterals', []);
961
- for (let i = 0; i < collaterals.length; i++) {
962
- const balance = collaterals[i];
963
- const code = this.safeCurrencyCode(this.safeString(balance, 'asset'));
964
- const account = this.account();
965
- account['total'] = this.safeString(balance, 'balance');
966
- result[code] = account;
967
- }
968
- return this.safeBalance(result);
969
- }
970
- /**
971
- * @method
972
- * @name ascendex#fetchBalance
973
- * @description query for balance and get the amount of funds available for trading or funds locked in orders
974
- * @see https://ascendex.github.io/ascendex-pro-api/#cash-account-balance
975
- * @see https://ascendex.github.io/ascendex-pro-api/#margin-account-balance
976
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#position
977
- * @param {object} [params] extra parameters specific to the exchange API endpoint
978
- * @param {string} [params.type] wallet type, 'spot', 'margin', or 'swap'
979
- * @param {string} [params.marginMode] 'cross' or undefined, for spot margin trading, value of 'isolated' is invalid
980
- * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
981
- */
982
- async fetchBalance(params = {}) {
983
- await this.loadMarkets();
984
- await this.loadAccounts();
985
- let marketType = undefined;
986
- let marginMode = undefined;
987
- [marketType, params] = this.handleMarketTypeAndParams('fetchBalance', undefined, params);
988
- [marginMode, params] = this.handleMarginModeAndParams('fetchBalance', params);
989
- const isMargin = this.safeBool(params, 'margin', false);
990
- const isCross = marginMode === 'cross';
991
- marketType = (isMargin || isCross) ? 'margin' : marketType;
992
- params = this.omit(params, 'margin');
993
- const accountsByType = this.safeDict(this.options, 'accountsByType', {});
994
- const accountCategory = this.safeString(accountsByType, marketType, 'cash');
995
- const account = this.safeDict(this.accounts, 0, {});
996
- const accountGroup = this.safeString(account, 'id');
997
- const request = {
998
- 'account-group': accountGroup,
999
- };
1000
- if ((marginMode === 'isolated') && (marketType !== 'swap')) {
1001
- throw new BadRequest(this.id + ' does not supported isolated margin trading');
1002
- }
1003
- if ((accountCategory === 'cash') || (accountCategory === 'margin')) {
1004
- request['account-category'] = accountCategory;
1005
- }
1006
- let response = undefined;
1007
- if ((marketType === 'spot') || (marketType === 'margin')) {
1008
- response = await this.v1PrivateAccountCategoryGetBalance(this.extend(request, params));
1009
- }
1010
- else if (marketType === 'swap') {
1011
- response = await this.v2PrivateAccountGroupGetFuturesPosition(this.extend(request, params));
1012
- }
1013
- else {
1014
- throw new NotSupported(this.id + ' fetchBalance() is not currently supported for ' + marketType + ' markets');
1015
- }
1016
- //
1017
- // cash
1018
- //
1019
- // {
1020
- // "code": 0,
1021
- // "data": [
1022
- // {
1023
- // "asset": "BCHSV",
1024
- // "totalBalance": "64.298000048",
1025
- // "availableBalance": "64.298000048",
1026
- // },
1027
- // ]
1028
- // }
1029
- //
1030
- // margin
1031
- //
1032
- // {
1033
- // "code": 0,
1034
- // "data": [
1035
- // {
1036
- // "asset": "BCHSV",
1037
- // "totalBalance": "64.298000048",
1038
- // "availableBalance": "64.298000048",
1039
- // "borrowed": "0",
1040
- // "interest": "0",
1041
- // },
1042
- // ]
1043
- // }
1044
- //
1045
- // swap
1046
- //
1047
- // {
1048
- // "code": 0,
1049
- // "data": {
1050
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1051
- // "ac": "FUTURES",
1052
- // "collaterals": [
1053
- // {"asset":"ADA","balance":"0.355803","referencePrice":"1.05095","discountFactor":"0.9"},
1054
- // {"asset":"USDT","balance":"0.000014519","referencePrice":"1","discountFactor":"1"}
1055
- // ],
1056
- // }j
1057
- // }
1058
- //
1059
- if (marketType === 'swap') {
1060
- return this.parseSwapBalance(response);
1061
- }
1062
- else if (marketType === 'margin') {
1063
- return this.parseMarginBalance(response);
1064
- }
1065
- else {
1066
- return this.parseBalance(response);
1067
- }
1068
- }
1069
- /**
1070
- * @method
1071
- * @name ascendex#fetchOrderBook
1072
- * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1073
- * @param {string} symbol unified symbol of the market to fetch the order book for
1074
- * @param {int} [limit] the maximum amount of order book entries to return
1075
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1076
- * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/?id=order-book-structure}
1077
- */
1078
- async fetchOrderBook(symbol, limit = undefined, params = {}) {
1079
- await this.loadMarkets();
1080
- const market = this.market(symbol);
1081
- const request = {
1082
- 'symbol': market['id'],
1083
- };
1084
- const response = await this.v1PublicGetDepth(this.extend(request, params));
1085
- //
1086
- // {
1087
- // "code":0,
1088
- // "data":{
1089
- // "m":"depth-snapshot",
1090
- // "symbol":"BTC-PERP",
1091
- // "data":{
1092
- // "ts":1590223998202,
1093
- // "seqnum":115444921,
1094
- // "asks":[
1095
- // ["9207.5","18.2383"],
1096
- // ["9207.75","18.8235"],
1097
- // ["9208","10.7873"],
1098
- // ],
1099
- // "bids":[
1100
- // ["9207.25","0.4009"],
1101
- // ["9207","0.003"],
1102
- // ["9206.5","0.003"],
1103
- // ]
1104
- // }
1105
- // }
1106
- // }
1107
- //
1108
- const data = this.safeDict(response, 'data', {});
1109
- const orderbook = this.safeDict(data, 'data', {});
1110
- const timestamp = this.safeInteger(orderbook, 'ts');
1111
- const result = this.parseOrderBook(orderbook, symbol, timestamp);
1112
- result['nonce'] = this.safeInteger(orderbook, 'seqnum');
1113
- return result;
1114
- }
1115
- parseTicker(ticker, market = undefined) {
1116
- //
1117
- // {
1118
- // "symbol":"QTUM/BTC",
1119
- // "open":"0.00016537",
1120
- // "close":"0.00019077",
1121
- // "high":"0.000192",
1122
- // "low":"0.00016537",
1123
- // "volume":"846.6",
1124
- // "ask":["0.00018698","26.2"],
1125
- // "bid":["0.00018408","503.7"],
1126
- // "type":"spot"
1127
- // }
1128
- //
1129
- const timestamp = undefined;
1130
- const marketId = this.safeString(ticker, 'symbol');
1131
- const type = this.safeString(ticker, 'type');
1132
- const delimiter = (type === 'spot') ? '/' : undefined;
1133
- const symbol = this.safeSymbol(marketId, market, delimiter);
1134
- const close = this.safeString(ticker, 'close');
1135
- const bid = this.safeList(ticker, 'bid', []);
1136
- const ask = this.safeList(ticker, 'ask', []);
1137
- const open = this.safeString(ticker, 'open');
1138
- return this.safeTicker({
1139
- 'symbol': symbol,
1140
- 'timestamp': timestamp,
1141
- 'datetime': undefined,
1142
- 'high': this.safeString(ticker, 'high'),
1143
- 'low': this.safeString(ticker, 'low'),
1144
- 'bid': this.safeString(bid, 0),
1145
- 'bidVolume': this.safeString(bid, 1),
1146
- 'ask': this.safeString(ask, 0),
1147
- 'askVolume': this.safeString(ask, 1),
1148
- 'vwap': undefined,
1149
- 'open': open,
1150
- 'close': close,
1151
- 'last': close,
1152
- 'previousClose': undefined, // previous day close
1153
- 'change': undefined,
1154
- 'percentage': undefined,
1155
- 'average': undefined,
1156
- 'baseVolume': this.safeString(ticker, 'volume'),
1157
- 'quoteVolume': undefined,
1158
- 'info': ticker,
1159
- }, market);
1160
- }
1161
- /**
1162
- * @method
1163
- * @name ascendex#fetchTicker
1164
- * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1165
- * @param {string} symbol unified symbol of the market to fetch the ticker for
1166
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1167
- * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
1168
- */
1169
- async fetchTicker(symbol, params = {}) {
1170
- await this.loadMarkets();
1171
- const market = this.market(symbol);
1172
- const request = {
1173
- 'symbol': market['id'],
1174
- };
1175
- const response = await this.v1PublicGetTicker(this.extend(request, params));
1176
- //
1177
- // {
1178
- // "code":0,
1179
- // "data":{
1180
- // "symbol":"BTC-PERP", // or "BTC/USDT"
1181
- // "open":"9073",
1182
- // "close":"9185.75",
1183
- // "high":"9185.75",
1184
- // "low":"9185.75",
1185
- // "volume":"576.8334",
1186
- // "ask":["9185.75","15.5863"],
1187
- // "bid":["9185.5","0.003"],
1188
- // "type":"derivatives", // or "spot"
1189
- // }
1190
- // }
1191
- //
1192
- const data = this.safeDict(response, 'data', {});
1193
- return this.parseTicker(data, market);
1194
- }
1195
- /**
1196
- * @method
1197
- * @name ascendex#fetchTickers
1198
- * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1199
- * @see https://ascendex.github.io/ascendex-pro-api/#ticker
1200
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#ticker
1201
- * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1202
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1203
- * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/?id=ticker-structure}
1204
- */
1205
- async fetchTickers(symbols = undefined, params = {}) {
1206
- await this.loadMarkets();
1207
- const request = {};
1208
- let market = undefined;
1209
- if (symbols !== undefined) {
1210
- const symbol = this.safeString(symbols, 0);
1211
- market = this.market(symbol);
1212
- const marketIds = this.marketIds(symbols);
1213
- request['symbol'] = marketIds.join(',');
1214
- }
1215
- let type = undefined;
1216
- [type, params] = this.handleMarketTypeAndParams('fetchTickers', market, params);
1217
- let response = undefined;
1218
- if (type === 'spot') {
1219
- response = await this.v1PublicGetTicker(this.extend(request, params));
1220
- }
1221
- else {
1222
- response = await this.v2PublicGetFuturesTicker(this.extend(request, params));
1223
- }
1224
- //
1225
- // {
1226
- // "code":0,
1227
- // "data": {
1228
- // "symbol":"QTUM/BTC",
1229
- // "open":"0.00016537",
1230
- // "close":"0.00019077",
1231
- // "high":"0.000192",
1232
- // "low":"0.00016537",
1233
- // "volume":"846.6",
1234
- // "ask":["0.00018698","26.2"],
1235
- // "bid":["0.00018408","503.7"],
1236
- // "type":"spot"
1237
- // }
1238
- // }
1239
- //
1240
- const data = this.safeList(response, 'data', []);
1241
- if (!Array.isArray(data)) {
1242
- return this.parseTickers([data], symbols);
1243
- }
1244
- return this.parseTickers(data, symbols);
1245
- }
1246
- parseOHLCV(ohlcv, market = undefined) {
1247
- //
1248
- // {
1249
- // "m":"bar",
1250
- // "s":"BTC/USDT",
1251
- // "data":{
1252
- // "i":"1",
1253
- // "ts":1590228000000,
1254
- // "o":"9139.59",
1255
- // "c":"9131.94",
1256
- // "h":"9139.99",
1257
- // "l":"9121.71",
1258
- // "v":"25.20648"
1259
- // }
1260
- // }
1261
- //
1262
- const data = this.safeDict(ohlcv, 'data', {});
1263
- return [
1264
- this.safeInteger(data, 'ts'),
1265
- this.safeNumber(data, 'o'),
1266
- this.safeNumber(data, 'h'),
1267
- this.safeNumber(data, 'l'),
1268
- this.safeNumber(data, 'c'),
1269
- this.safeNumber(data, 'v'),
1270
- ];
1271
- }
1272
- /**
1273
- * @method
1274
- * @name ascendex#fetchOHLCV
1275
- * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1276
- * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1277
- * @param {string} timeframe the length of time each candle represents
1278
- * @param {int} [since] timestamp in ms of the earliest candle to fetch
1279
- * @param {int} [limit] the maximum amount of candles to fetch
1280
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1281
- * @param {int} [params.until] timestamp in ms of the latest candle to fetch
1282
- * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1283
- */
1284
- async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1285
- await this.loadMarkets();
1286
- const market = this.market(symbol);
1287
- const request = {
1288
- 'symbol': market['id'],
1289
- 'interval': this.safeString(this.timeframes, timeframe, timeframe),
1290
- };
1291
- // if since and limit are not specified
1292
- // the exchange will return just 1 last candle by default
1293
- const duration = this.parseTimeframe(timeframe);
1294
- const options = this.safeDict(this.options, 'fetchOHLCV', {});
1295
- const defaultLimit = this.safeInteger(options, 'limit', 500);
1296
- const until = this.safeInteger(params, 'until');
1297
- if (since !== undefined) {
1298
- request['from'] = since;
1299
- if (limit === undefined) {
1300
- limit = defaultLimit;
1301
- }
1302
- else {
1303
- limit = Math.min(limit, defaultLimit);
1304
- }
1305
- const toWithLimit = this.sum(since, limit * duration * 1000, 1);
1306
- if (until !== undefined) {
1307
- request['to'] = Math.min(toWithLimit, until + 1);
1308
- }
1309
- else {
1310
- request['to'] = toWithLimit;
1311
- }
1312
- }
1313
- else if (until !== undefined) {
1314
- request['to'] = until + 1;
1315
- if (limit === undefined) {
1316
- limit = defaultLimit;
1317
- }
1318
- else {
1319
- limit = Math.min(limit, defaultLimit);
1320
- }
1321
- request['from'] = until - (limit * duration * 1000);
1322
- }
1323
- else if (limit !== undefined) {
1324
- request['n'] = limit; // max 500
1325
- }
1326
- params = this.omit(params, 'until');
1327
- const response = await this.v1PublicGetBarhist(this.extend(request, params));
1328
- //
1329
- // {
1330
- // "code":0,
1331
- // "data":[
1332
- // {
1333
- // "m":"bar",
1334
- // "s":"BTC/USDT",
1335
- // "data":{
1336
- // "i":"1",
1337
- // "ts":1590228000000,
1338
- // "o":"9139.59",
1339
- // "c":"9131.94",
1340
- // "h":"9139.99",
1341
- // "l":"9121.71",
1342
- // "v":"25.20648"
1343
- // }
1344
- // }
1345
- // ]
1346
- // }
1347
- //
1348
- const data = this.safeList(response, 'data', []);
1349
- return this.parseOHLCVs(data, market, timeframe, since, limit);
1350
- }
1351
- parseTrade(trade, market = undefined) {
1352
- //
1353
- // public fetchTrades
1354
- //
1355
- // {
1356
- // "p":"9128.5", // price
1357
- // "q":"0.0030", // quantity
1358
- // "ts":1590229002385, // timestamp
1359
- // "bm":false, // if true, the buyer is the market maker, we only use this field to "define the side" of a public trade
1360
- // "seqnum":180143985289898554
1361
- // }
1362
- //
1363
- const timestamp = this.safeInteger(trade, 'ts');
1364
- const priceString = this.safeString2(trade, 'price', 'p');
1365
- const amountString = this.safeString(trade, 'q');
1366
- const buyerIsMaker = this.safeBool(trade, 'bm', false);
1367
- const side = buyerIsMaker ? 'sell' : 'buy';
1368
- market = this.safeMarket(undefined, market);
1369
- return this.safeTrade({
1370
- 'info': trade,
1371
- 'timestamp': timestamp,
1372
- 'datetime': this.iso8601(timestamp),
1373
- 'symbol': market['symbol'],
1374
- 'id': undefined,
1375
- 'order': undefined,
1376
- 'type': undefined,
1377
- 'takerOrMaker': undefined,
1378
- 'side': side,
1379
- 'price': priceString,
1380
- 'amount': amountString,
1381
- 'cost': undefined,
1382
- 'fee': undefined,
1383
- }, market);
1384
- }
1385
- /**
1386
- * @method
1387
- * @name ascendex#fetchTrades
1388
- * @description get the list of most recent trades for a particular symbol
1389
- * @see https://ascendex.github.io/ascendex-pro-api/#market-trades
1390
- * @param {string} symbol unified symbol of the market to fetch trades for
1391
- * @param {int} [since] timestamp in ms of the earliest trade to fetch
1392
- * @param {int} [limit] the maximum amount of trades to fetch
1393
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1394
- * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
1395
- */
1396
- async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
1397
- await this.loadMarkets();
1398
- const market = this.market(symbol);
1399
- const request = {
1400
- 'symbol': market['id'],
1401
- };
1402
- if (limit !== undefined) {
1403
- request['n'] = limit; // max 100
1404
- }
1405
- const response = await this.v1PublicGetTrades(this.extend(request, params));
1406
- //
1407
- // {
1408
- // "code":0,
1409
- // "data":{
1410
- // "m":"trades",
1411
- // "symbol":"BTC-PERP",
1412
- // "data":[
1413
- // {"p":"9128.5","q":"0.0030","ts":1590229002385,"bm":false,"seqnum":180143985289898554},
1414
- // {"p":"9129","q":"0.0030","ts":1590229002642,"bm":false,"seqnum":180143985289898587},
1415
- // {"p":"9129.5","q":"0.0030","ts":1590229021306,"bm":false,"seqnum":180143985289899043}
1416
- // ]
1417
- // }
1418
- // }
1419
- //
1420
- const records = this.safeDict(response, 'data', {});
1421
- const trades = this.safeList(records, 'data', []);
1422
- return this.parseTrades(trades, market, since, limit);
1423
- }
1424
- parseOrderStatus(status) {
1425
- const statuses = {
1426
- 'PendingNew': 'open',
1427
- 'New': 'open',
1428
- 'PartiallyFilled': 'open',
1429
- 'Filled': 'closed',
1430
- 'Canceled': 'canceled',
1431
- 'Rejected': 'rejected',
1432
- };
1433
- return this.safeString(statuses, status, status);
1434
- }
1435
- parseOrder(order, market = undefined) {
1436
- //
1437
- // createOrder
1438
- //
1439
- // {
1440
- // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa",
1441
- // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830",
1442
- // "orderType": "Market",
1443
- // "symbol": "BTC/USDT",
1444
- // "timestamp": 1573576916201
1445
- // }
1446
- //
1447
- // & linear (fetchClosedOrders)
1448
- //
1449
- // {
1450
- // "ac": "FUTURES",
1451
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1452
- // "time": 1640819389454,
1453
- // "orderId": "a17e0874ecbdU0711043490bbtcpDU5X",
1454
- // "seqNum": -1,
1455
- // "orderType": "Limit",
1456
- // "execInst": "NULL_VAL", // NULL_VAL, ReduceOnly , ...
1457
- // "side": "Buy",
1458
- // "symbol": "BTC-PERP",
1459
- // "price": "30000",
1460
- // "orderQty": "0.002",
1461
- // "stopPrice": "0",
1462
- // "stopBy": "ref-px",
1463
- // "status": "Ack",
1464
- // "lastExecTime": 1640819389454,
1465
- // "lastQty": "0",
1466
- // "lastPx": "0",
1467
- // "avgFilledPx": "0",
1468
- // "cumFilledQty": "0",
1469
- // "fee": "0",
1470
- // "cumFee": "0",
1471
- // "feeAsset": "",
1472
- // "errorCode": "",
1473
- // "posStopLossPrice": "0",
1474
- // "posStopLossTrigger": "market",
1475
- // "posTakeProfitPrice": "0",
1476
- // "posTakeProfitTrigger": "market",
1477
- // "liquidityInd": "n"
1478
- // }
1479
- //
1480
- // fetchOrder, fetchOpenOrders, fetchClosedOrders
1481
- //
1482
- // {
1483
- // "symbol": "BTC/USDT",
1484
- // "price": "8131.22",
1485
- // "orderQty": "0.00082",
1486
- // "orderType": "Market",
1487
- // "avgPx": "7392.02",
1488
- // "cumFee": "0.005152238",
1489
- // "cumFilledQty": "0.00082",
1490
- // "errorCode": "",
1491
- // "feeAsset": "USDT",
1492
- // "lastExecTime": 1575953151764,
1493
- // "orderId": "a16eee20b6750866943712zWEDdAjt3",
1494
- // "seqNum": 2623469,
1495
- // "side": "Buy",
1496
- // "status": "Filled",
1497
- // "stopPrice": "",
1498
- // "execInst": "NULL_VAL" // "Post" (for postOnly orders), "reduceOnly" (for reduceOnly orders)
1499
- // }
1500
- //
1501
- // {
1502
- // "orderId": "a173ad938fc3U22666567717788c3b66", // orderId
1503
- // "seqNum": 18777366360, // sequence number
1504
- // "accountId": "cshwSjbpPjSwHmxPdz2CPQVU9mnbzPpt", // accountId
1505
- // "symbol": "BTC/USDT", // symbol
1506
- // "orderType": "Limit", // order type (Limit/Market/StopMarket/StopLimit)
1507
- // "side": "Sell", // order side (Buy/Sell)
1508
- // "price": "11346.77", // order price
1509
- // "stopPrice": "0", // stop price (0 by default)
1510
- // "orderQty": "0.01", // order quantity (in base asset)
1511
- // "status": "Canceled", // order status (Filled/Canceled/Rejected)
1512
- // "createTime": 1596344995793, // order creation time
1513
- // "lastExecTime": 1596344996053, // last execution time
1514
- // "avgFillPrice": "11346.77", // average filled price
1515
- // "fillQty": "0.01", // filled quantity (in base asset)
1516
- // "fee": "-0.004992579", // cummulative fee. if negative, this value is the commission charged; if possitive, this value is the rebate received.
1517
- // "feeAsset": "USDT" // fee asset
1518
- // }
1519
- //
1520
- // {
1521
- // "ac": "FUTURES",
1522
- // "accountId": "testabcdefg",
1523
- // "avgPx": "0",
1524
- // "cumFee": "0",
1525
- // "cumQty": "0",
1526
- // "errorCode": "NULL_VAL",
1527
- // "execInst": "NULL_VAL",
1528
- // "feeAsset": "USDT",
1529
- // "lastExecTime": 1584072844085,
1530
- // "orderId": "r170d21956dd5450276356bbtcpKa74",
1531
- // "orderQty": "1.1499",
1532
- // "orderType": "Limit",
1533
- // "price": "4000",
1534
- // "sendingTime": 1584072841033,
1535
- // "seqNum": 24105338,
1536
- // "side": "Buy",
1537
- // "status": "Canceled",
1538
- // "stopPrice": "",
1539
- // "symbol": "BTC-PERP"
1540
- // },
1541
- //
1542
- const status = this.parseOrderStatus(this.safeString(order, 'status'));
1543
- const marketId = this.safeString(order, 'symbol');
1544
- const symbol = this.safeSymbol(marketId, market, '/');
1545
- let timestamp = this.safeIntegerN(order, ['timestamp', 'sendingTime', 'time']);
1546
- const lastTradeTimestamp = this.safeInteger(order, 'lastExecTime');
1547
- if (timestamp === undefined) {
1548
- timestamp = lastTradeTimestamp;
1549
- }
1550
- const price = this.safeString(order, 'price');
1551
- const amount = this.safeString(order, 'orderQty');
1552
- const average = this.safeString2(order, 'avgPx', 'avgFilledPx');
1553
- const filled = this.safeStringN(order, ['cumFilledQty', 'cumQty', 'fillQty']);
1554
- const id = this.safeString(order, 'orderId');
1555
- let clientOrderId = this.safeString(order, 'id');
1556
- if (clientOrderId !== undefined) {
1557
- if (clientOrderId.length < 1) {
1558
- clientOrderId = undefined;
1559
- }
1560
- }
1561
- const rawTypeLower = this.safeStringLower(order, 'orderType');
1562
- let type = rawTypeLower;
1563
- if (rawTypeLower !== undefined) {
1564
- if (rawTypeLower === 'stoplimit') {
1565
- type = 'limit';
1566
- }
1567
- if (rawTypeLower === 'stopmarket') {
1568
- type = 'market';
1569
- }
1570
- }
1571
- const side = this.safeStringLower(order, 'side');
1572
- const feeCost = this.safeNumber2(order, 'cumFee', 'fee');
1573
- let fee = undefined;
1574
- if (feeCost !== undefined) {
1575
- const feeCurrencyId = this.safeString(order, 'feeAsset');
1576
- const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
1577
- fee = {
1578
- 'cost': feeCost,
1579
- 'currency': feeCurrencyCode,
1580
- };
1581
- }
1582
- const triggerPrice = this.omitZero(this.safeString(order, 'stopPrice'));
1583
- let reduceOnly = undefined;
1584
- const execInst = this.safeStringLower(order, 'execInst');
1585
- if (execInst === 'reduceonly') {
1586
- reduceOnly = true;
1587
- }
1588
- let postOnly = undefined;
1589
- if (execInst === 'post') {
1590
- postOnly = true;
1591
- }
1592
- return this.safeOrder({
1593
- 'info': order,
1594
- 'id': id,
1595
- 'clientOrderId': clientOrderId,
1596
- 'timestamp': timestamp,
1597
- 'datetime': this.iso8601(timestamp),
1598
- 'lastTradeTimestamp': lastTradeTimestamp,
1599
- 'symbol': symbol,
1600
- 'type': type,
1601
- 'timeInForce': undefined,
1602
- 'postOnly': postOnly,
1603
- 'reduceOnly': reduceOnly,
1604
- 'side': side,
1605
- 'price': price,
1606
- 'triggerPrice': triggerPrice,
1607
- 'amount': amount,
1608
- 'cost': undefined,
1609
- 'average': average,
1610
- 'filled': filled,
1611
- 'remaining': undefined,
1612
- 'status': status,
1613
- 'fee': fee,
1614
- 'trades': undefined,
1615
- }, market);
1616
- }
1617
- /**
1618
- * @method
1619
- * @name ascendex#fetchTradingFees
1620
- * @description fetch the trading fees for multiple markets
1621
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1622
- * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/?id=fee-structure} indexed by market symbols
1623
- */
1624
- async fetchTradingFees(params = {}) {
1625
- await this.loadMarkets();
1626
- await this.loadAccounts();
1627
- const account = this.safeDict(this.accounts, 0, {});
1628
- const accountGroup = this.safeString(account, 'id');
1629
- const request = {
1630
- 'account-group': accountGroup,
1631
- };
1632
- const response = await this.v1PrivateAccountGroupGetSpotFee(this.extend(request, params));
1633
- //
1634
- // {
1635
- // "code": "0",
1636
- // "data": {
1637
- // "domain": "spot",
1638
- // "userUID": "U1479576457",
1639
- // "vipLevel": "0",
1640
- // "fees": [
1641
- // { symbol: 'HT/USDT', fee: { taker: '0.001', maker: "0.001" } },
1642
- // { symbol: 'LAMB/BTC', fee: { taker: '0.002', maker: "0.002" } },
1643
- // { symbol: 'STOS/USDT', fee: { taker: '0.002', maker: "0.002" } },
1644
- // ...
1645
- // ]
1646
- // }
1647
- // }
1648
- //
1649
- const data = this.safeDict(response, 'data', {});
1650
- const fees = this.safeList(data, 'fees', []);
1651
- const result = {};
1652
- for (let i = 0; i < fees.length; i++) {
1653
- const fee = fees[i];
1654
- const marketId = this.safeString(fee, 'symbol');
1655
- const symbol = this.safeSymbol(marketId, undefined, '/');
1656
- const takerMaker = this.safeDict(fee, 'fee', {});
1657
- result[symbol] = {
1658
- 'info': fee,
1659
- 'symbol': symbol,
1660
- 'maker': this.safeNumber(takerMaker, 'maker'),
1661
- 'taker': this.safeNumber(takerMaker, 'taker'),
1662
- 'percentage': undefined,
1663
- 'tierBased': undefined,
1664
- };
1665
- }
1666
- return result;
1667
- }
1668
- createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1669
- /**
1670
- * @method
1671
- * @ignore
1672
- * @name ascendex#createOrderRequest
1673
- * @description helper function to build request
1674
- * @param {string} symbol unified symbol of the market to create an order in
1675
- * @param {string} type 'market' or 'limit'
1676
- * @param {string} side 'buy' or 'sell'
1677
- * @param {float} amount how much you want to trade in units of the base currency
1678
- * @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1679
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1680
- * @param {string} [params.timeInForce] "GTC", "IOC", "FOK", or "PO"
1681
- * @param {bool} [params.postOnly] true or false
1682
- * @param {float} [params.triggerPrice] the price at which a trigger order is triggered at
1683
- * @returns {object} request to be sent to the exchange
1684
- */
1685
- const market = this.market(symbol);
1686
- let marginMode = undefined;
1687
- let marketType = undefined;
1688
- [marginMode, params] = this.handleMarginModeAndParams('createOrderRequest', params);
1689
- [marketType, params] = this.handleMarketTypeAndParams('createOrderRequest', market, params);
1690
- const accountsByType = this.safeDict(this.options, 'accountsByType', {});
1691
- let accountCategory = this.safeString(accountsByType, marketType, 'cash');
1692
- if (marginMode !== undefined) {
1693
- accountCategory = 'margin';
1694
- }
1695
- const account = this.safeDict(this.accounts, 0, {});
1696
- const accountGroup = this.safeString(account, 'id');
1697
- const clientOrderId = this.safeString2(params, 'clientOrderId', 'id');
1698
- const request = {
1699
- 'account-group': accountGroup,
1700
- 'account-category': accountCategory,
1701
- 'symbol': market['id'],
1702
- 'time': this.milliseconds(),
1703
- 'orderQty': this.amountToPrecision(symbol, amount),
1704
- 'orderType': type, // limit, market, stop_market, stop_limit
1705
- 'side': side, // buy or sell,
1706
- // 'execInst': // Post for postOnly, ReduceOnly for reduceOnly
1707
- // 'respInst': 'ACK', // ACK, 'ACCEPT, DONE
1708
- };
1709
- const isMarketOrder = ((type === 'market') || (type === 'stop_market'));
1710
- const isLimitOrder = ((type === 'limit') || (type === 'stop_limit'));
1711
- const timeInForce = this.safeString(params, 'timeInForce');
1712
- const postOnly = this.isPostOnly(isMarketOrder, false, params);
1713
- const reduceOnly = this.safeBool(params, 'reduceOnly', false);
1714
- const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
1715
- if (isLimitOrder) {
1716
- request['orderPrice'] = this.priceToPrecision(symbol, price);
1717
- }
1718
- if (timeInForce === 'IOC') {
1719
- request['timeInForce'] = 'IOC';
1720
- }
1721
- if (timeInForce === 'FOK') {
1722
- request['timeInForce'] = 'FOK';
1723
- }
1724
- if (postOnly) {
1725
- request['postOnly'] = true;
1726
- }
1727
- if (triggerPrice !== undefined) {
1728
- request['stopPrice'] = this.priceToPrecision(symbol, triggerPrice);
1729
- if (isLimitOrder) {
1730
- request['orderType'] = 'stop_limit';
1731
- }
1732
- else if (isMarketOrder) {
1733
- request['orderType'] = 'stop_market';
1734
- }
1735
- }
1736
- if (clientOrderId !== undefined) {
1737
- request['id'] = clientOrderId;
1738
- }
1739
- if (market['spot']) {
1740
- if (accountCategory !== undefined) {
1741
- request['category'] = accountCategory;
1742
- }
1743
- }
1744
- else {
1745
- request['account-category'] = accountCategory;
1746
- if (reduceOnly) {
1747
- request['execInst'] = 'ReduceOnly';
1748
- }
1749
- if (postOnly) {
1750
- request['execInst'] = 'Post';
1751
- }
1752
- }
1753
- params = this.omit(params, ['reduceOnly', 'triggerPrice']);
1754
- return this.extend(request, params);
1755
- }
1756
- /**
1757
- * @method
1758
- * @name ascendex#createOrder
1759
- * @description create a trade order on the exchange
1760
- * @see https://ascendex.github.io/ascendex-pro-api/#place-order
1761
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#new-order
1762
- * @param {string} symbol unified CCXT market symbol
1763
- * @param {string} type "limit" or "market"
1764
- * @param {string} side "buy" or "sell"
1765
- * @param {float} amount the amount of currency to trade
1766
- * @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1767
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1768
- * @param {string} [params.timeInForce] "GTC", "IOC", "FOK", or "PO"
1769
- * @param {bool} [params.postOnly] true or false
1770
- * @param {float} [params.triggerPrice] the price at which a trigger order is triggered at
1771
- * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice that the attached take profit order will be triggered (perpetual swap markets only)
1772
- * @param {float} [params.takeProfit.triggerPrice] *swap only* take profit trigger price
1773
- * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice that the attached stop loss order will be triggered (perpetual swap markets only)
1774
- * @param {float} [params.stopLoss.triggerPrice] *swap only* stop loss trigger price
1775
- * @returns [An order structure]{@link https://docs.ccxt.com/?id=order-structure}
1776
- */
1777
- async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1778
- await this.loadMarkets();
1779
- await this.loadAccounts();
1780
- const market = this.market(symbol);
1781
- const request = this.createOrderRequest(symbol, type, side, amount, price, params);
1782
- let response = undefined;
1783
- if (market['swap']) {
1784
- response = await this.v2PrivateAccountGroupPostFuturesOrder(request);
1785
- }
1786
- else {
1787
- response = await this.v1PrivateAccountCategoryPostOrder(request);
1788
- }
1789
- //
1790
- // spot
1791
- //
1792
- // {
1793
- // "code":0,
1794
- // "data": {
1795
- // "accountId":"cshwT8RKojkT1HoaA5UdeimR2SrmHG2I",
1796
- // "ac":"CASH",
1797
- // "action":"place-order",
1798
- // "status":"Ack",
1799
- // "info": {
1800
- // "symbol":"TRX/USDT",
1801
- // "orderType":"StopLimit",
1802
- // "timestamp":1654290662172,
1803
- // "id":"",
1804
- // "orderId":"a1812b6840ddU8191168955av0k6Eyhj"
1805
- // }
1806
- // }
1807
- // }
1808
- //
1809
- // swap
1810
- //
1811
- // {
1812
- // "code":0,
1813
- // "data": {
1814
- // "meta": {
1815
- // "id":"",
1816
- // "action":"place-order",
1817
- // "respInst":"ACK"
1818
- // },
1819
- // "order": {
1820
- // "ac":"FUTURES",
1821
- // "accountId":"futwT8RKojkT1HoaA5UdeimR2SrmHG2I",
1822
- // "time":1654290969965,
1823
- // "orderId":"a1812b6cf322U8191168955oJamfTh7b",
1824
- // "seqNum":-1,
1825
- // "orderType":"StopLimit",
1826
- // "execInst":"NULL_VAL",
1827
- // "side":"Buy",
1828
- // "symbol":"TRX-PERP",
1829
- // "price":"0.083",
1830
- // "orderQty":"1",
1831
- // "stopPrice":"0.082",
1832
- // "stopBy":"ref-px",
1833
- // "status":"Ack",
1834
- // "lastExecTime":1654290969965,
1835
- // "lastQty":"0",
1836
- // "lastPx":"0",
1837
- // "avgFilledPx":"0",
1838
- // "cumFilledQty":"0",
1839
- // "fee":"0",
1840
- // "cumFee":"0",
1841
- // "feeAsset":"",
1842
- // "errorCode":"",
1843
- // "posStopLossPrice":"0",
1844
- // "posStopLossTrigger":"market",
1845
- // "posTakeProfitPrice":"0",
1846
- // "posTakeProfitTrigger":"market",
1847
- // "liquidityInd":"n"
1848
- // }
1849
- // }
1850
- // }
1851
- //
1852
- const data = this.safeDict(response, 'data', {});
1853
- const order = this.safeDict2(data, 'order', 'info', {});
1854
- return this.parseOrder(order, market);
1855
- }
1856
- /**
1857
- * @method
1858
- * @name ascendex#createOrders
1859
- * @description create a list of trade orders
1860
- * @see https://ascendex.github.io/ascendex-pro-api/#place-batch-orders
1861
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#place-batch-orders
1862
- * @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1863
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1864
- * @param {string} [params.timeInForce] "GTC", "IOC", "FOK", or "PO"
1865
- * @param {bool} [params.postOnly] true or false
1866
- * @param {float} [params.triggerPrice] the price at which a trigger order is triggered at
1867
- * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
1868
- */
1869
- async createOrders(orders, params = {}) {
1870
- await this.loadMarkets();
1871
- await this.loadAccounts();
1872
- const ordersRequests = [];
1873
- let symbol = undefined;
1874
- let marginMode = undefined;
1875
- for (let i = 0; i < orders.length; i++) {
1876
- const rawOrder = orders[i];
1877
- const marketId = this.safeString(rawOrder, 'symbol');
1878
- if (symbol === undefined) {
1879
- symbol = marketId;
1880
- }
1881
- else {
1882
- if (symbol !== marketId) {
1883
- throw new BadRequest(this.id + ' createOrders() requires all orders to have the same symbol');
1884
- }
1885
- }
1886
- const type = this.safeString(rawOrder, 'type');
1887
- const side = this.safeString(rawOrder, 'side');
1888
- const amount = this.safeNumber(rawOrder, 'amount');
1889
- const price = this.safeNumber(rawOrder, 'price');
1890
- const orderParams = this.safeDict(rawOrder, 'params', {});
1891
- const marginResult = this.handleMarginModeAndParams('createOrders', orderParams);
1892
- const currentMarginMode = marginResult[0];
1893
- if (currentMarginMode !== undefined) {
1894
- if (marginMode === undefined) {
1895
- marginMode = currentMarginMode;
1896
- }
1897
- else {
1898
- if (marginMode !== currentMarginMode) {
1899
- throw new BadRequest(this.id + ' createOrders() requires all orders to have the same margin mode (isolated or cross)');
1900
- }
1901
- }
1902
- }
1903
- const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
1904
- ordersRequests.push(orderRequest);
1905
- }
1906
- const market = this.market(symbol);
1907
- const accountsByType = this.safeDict(this.options, 'accountsByType', {});
1908
- let accountCategory = this.safeString(accountsByType, market['type'], 'cash');
1909
- if (marginMode !== undefined) {
1910
- accountCategory = 'margin';
1911
- }
1912
- const account = this.safeDict(this.accounts, 0, {});
1913
- const accountGroup = this.safeString(account, 'id');
1914
- const request = {};
1915
- let response = undefined;
1916
- if (market['swap']) {
1917
- throw new NotSupported(this.id + ' createOrders() is not currently supported for swap markets on ascendex');
1918
- // request['account-group'] = accountGroup;
1919
- // request['category'] = accountCategory;
1920
- // request['orders'] = ordersRequests;
1921
- // response = await this.v2PrivateAccountGroupPostFuturesOrderBatch (request);
1922
- }
1923
- else {
1924
- request['account-group'] = accountGroup;
1925
- request['account-category'] = accountCategory;
1926
- request['orders'] = ordersRequests;
1927
- response = await this.v1PrivateAccountCategoryPostOrderBatch(request);
1928
- }
1929
- //
1930
- // spot
1931
- //
1932
- // {
1933
- // "code": 0,
1934
- // "data": {
1935
- // "accountId": "cshdAKBO43TKIh2kJtq7FVVb42KIePyS",
1936
- // "ac": "CASH",
1937
- // "action": "batch-place-order",
1938
- // "status": "Ack",
1939
- // "info": [
1940
- // {
1941
- // "symbol": "BTC/USDT",
1942
- // "orderType": "Limit",
1943
- // "timestamp": 1699326589344,
1944
- // "id": "",
1945
- // "orderId": "a18ba7c1f6efU0711043490p3HvjjN5x"
1946
- // }
1947
- // ]
1948
- // }
1949
- // }
1950
- //
1951
- const data = this.safeDict(response, 'data', {});
1952
- const info = this.safeList(data, 'info', []);
1953
- return this.parseOrders(info, market);
1954
- }
1955
- /**
1956
- * @method
1957
- * @name ascendex#fetchOrder
1958
- * @description fetches information on an order made by the user
1959
- * @see https://ascendex.github.io/ascendex-pro-api/#query-order
1960
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#query-order-by-id
1961
- * @param {string} id the order id
1962
- * @param {string} symbol unified symbol of the market the order was made in
1963
- * @param {object} [params] extra parameters specific to the exchange API endpoint
1964
- * @returns {object} An [order structure]{@link https://docs.ccxt.com/?id=order-structure}
1965
- */
1966
- async fetchOrder(id, symbol = undefined, params = {}) {
1967
- await this.loadMarkets();
1968
- await this.loadAccounts();
1969
- let market = undefined;
1970
- if (symbol !== undefined) {
1971
- market = this.market(symbol);
1972
- }
1973
- const [type, query] = this.handleMarketTypeAndParams('fetchOrder', market, params);
1974
- const accountsByType = this.safeDict(this.options, 'accountsByType', {});
1975
- const accountCategory = this.safeString(accountsByType, type, 'cash');
1976
- const account = this.safeDict(this.accounts, 0, {});
1977
- const accountGroup = this.safeString(account, 'id');
1978
- const request = {
1979
- 'account-group': accountGroup,
1980
- 'account-category': accountCategory,
1981
- 'orderId': id,
1982
- };
1983
- let response = undefined;
1984
- if ((type === 'spot') || (type === 'margin')) {
1985
- response = await this.v1PrivateAccountCategoryGetOrderStatus(this.extend(request, query));
1986
- }
1987
- else if (type === 'swap') {
1988
- request['account-category'] = accountCategory;
1989
- response = await this.v2PrivateAccountGroupGetFuturesOrderStatus(this.extend(request, query));
1990
- }
1991
- else {
1992
- throw new NotSupported(this.id + ' fetchOrder() is not currently supported for ' + type + ' markets');
1993
- }
1994
- //
1995
- // AccountCategoryGetOrderStatus
1996
- //
1997
- // {
1998
- // "code": 0,
1999
- // "accountCategory": "CASH",
2000
- // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
2001
- // "data": [
2002
- // {
2003
- // "symbol": "BTC/USDT",
2004
- // "price": "8131.22",
2005
- // "orderQty": "0.00082",
2006
- // "orderType": "Market",
2007
- // "avgPx": "7392.02",
2008
- // "cumFee": "0.005152238",
2009
- // "cumFilledQty": "0.00082",
2010
- // "errorCode": "",
2011
- // "feeAsset": "USDT",
2012
- // "lastExecTime": 1575953151764,
2013
- // "orderId": "a16eee20b6750866943712zWEDdAjt3",
2014
- // "seqNum": 2623469,
2015
- // "side": "Buy",
2016
- // "status": "Filled",
2017
- // "stopPrice": "",
2018
- // "execInst": "NULL_VAL"
2019
- // }
2020
- // ]
2021
- // }
2022
- //
2023
- // AccountGroupGetFuturesOrderStatus
2024
- //
2025
- // {
2026
- // "code": 0,
2027
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2028
- // "ac": "FUTURES",
2029
- // "data": {
2030
- // "ac": "FUTURES",
2031
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2032
- // "time": 1640247020217,
2033
- // "orderId": "r17de65747aeU0711043490bbtcp0cmt",
2034
- // "seqNum": 28796162908,
2035
- // "orderType": "Limit",
2036
- // "execInst": "NULL_VAL",
2037
- // "side": "Buy",
2038
- // "symbol": "BTC-PERP",
2039
- // "price": "30000",
2040
- // "orderQty": "0.0021",
2041
- // "stopPrice": "0",
2042
- // "stopBy": "market",
2043
- // "status": "New",
2044
- // "lastExecTime": 1640247020232,
2045
- // "lastQty": "0",
2046
- // "lastPx": "0",
2047
- // "avgFilledPx": "0",
2048
- // "cumFilledQty": "0",
2049
- // "fee": "0",
2050
- // "cumFee": "0",
2051
- // "feeAsset": "USDT",
2052
- // "errorCode": "",
2053
- // "posStopLossPrice": "0",
2054
- // "posStopLossTrigger": "market",
2055
- // "posTakeProfitPrice": "0",
2056
- // "posTakeProfitTrigger": "market",
2057
- // "liquidityInd": "n"
2058
- // }
2059
- // }
2060
- //
2061
- const data = this.safeDict(response, 'data', {});
2062
- return this.parseOrder(data, market);
2063
- }
2064
- /**
2065
- * @method
2066
- * @name ascendex#fetchOpenOrders
2067
- * @description fetch all unfilled currently open orders
2068
- * @see https://ascendex.github.io/ascendex-pro-api/#list-open-orders
2069
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#list-open-orders
2070
- * @param {string} symbol unified market symbol
2071
- * @param {int} [since] the earliest time in ms to fetch open orders for
2072
- * @param {int} [limit] the maximum number of open orders structures to retrieve
2073
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2074
- * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
2075
- */
2076
- async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2077
- await this.loadMarkets();
2078
- await this.loadAccounts();
2079
- let market = undefined;
2080
- if (symbol !== undefined) {
2081
- market = this.market(symbol);
2082
- symbol = market['symbol'];
2083
- }
2084
- const account = this.safeDict(this.accounts, 0, {});
2085
- const accountGroup = this.safeString(account, 'id');
2086
- const [type, query] = this.handleMarketTypeAndParams('fetchOpenOrders', market, params);
2087
- const accountsByType = this.safeDict(this.options, 'accountsByType', {});
2088
- const accountCategory = this.safeString(accountsByType, type, 'cash');
2089
- const request = {
2090
- 'account-group': accountGroup,
2091
- 'account-category': accountCategory,
2092
- };
2093
- let response = undefined;
2094
- if ((type === 'spot') || (type === 'margin')) {
2095
- response = await this.v1PrivateAccountCategoryGetOrderOpen(this.extend(request, query));
2096
- }
2097
- else if (type === 'swap') {
2098
- request['account-category'] = accountCategory;
2099
- response = await this.v2PrivateAccountGroupGetFuturesOrderOpen(this.extend(request, query));
2100
- }
2101
- else {
2102
- throw new NotSupported(this.id + ' fetchOpenOrders() is not currently supported for ' + type + ' markets');
2103
- }
2104
- //
2105
- // AccountCategoryGetOrderOpen
2106
- //
2107
- // {
2108
- // "ac": "CASH",
2109
- // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
2110
- // "code": 0,
2111
- // "data": [
2112
- // {
2113
- // "avgPx": "0", // Average filled price of the order
2114
- // "cumFee": "0", // cumulative fee paid for this order
2115
- // "cumFilledQty": "0", // cumulative filled quantity
2116
- // "errorCode": "", // error code; could be empty
2117
- // "feeAsset": "USDT", // fee asset
2118
- // "lastExecTime": 1576019723550, // The last execution time of the order
2119
- // "orderId": "s16ef21882ea0866943712034f36d83", // server provided orderId
2120
- // "orderQty": "0.0083", // order quantity
2121
- // "orderType": "Limit", // order type
2122
- // "price": "7105", // order price
2123
- // "seqNum": 8193258, // sequence number
2124
- // "side": "Buy", // order side
2125
- // "status": "New", // order status on matching engine
2126
- // "stopPrice": "", // only available for stop market and stop limit orders; otherwise empty
2127
- // "symbol": "BTC/USDT",
2128
- // "execInst": "NULL_VAL" // execution instruction
2129
- // },
2130
- // ]
2131
- // }
2132
- //
2133
- // AccountGroupGetFuturesOrderOpen
2134
- //
2135
- // {
2136
- // "code": 0,
2137
- // "data": [
2138
- // {
2139
- // "ac": "FUTURES",
2140
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2141
- // "time": 1640247020217,
2142
- // "orderId": "r17de65747aeU0711043490bbtcp0cmt",
2143
- // "seqNum": 28796162908,
2144
- // "orderType": "Limit",
2145
- // "execInst": "NULL_VAL",
2146
- // "side": "Buy",
2147
- // "symbol": "BTC-PERP",
2148
- // "price": "30000",
2149
- // "orderQty": "0.0021",
2150
- // "stopPrice": "0",
2151
- // "stopBy": "market",
2152
- // "status": "New",
2153
- // "lastExecTime": 1640247020232,
2154
- // "lastQty": "0",
2155
- // "lastPx": "0",
2156
- // "avgFilledPx": "0",
2157
- // "cumFilledQty": "0",
2158
- // "fee": "0",
2159
- // "cumFee": "0",
2160
- // "feeAsset": "USDT",
2161
- // "errorCode": "",
2162
- // "posStopLossPrice": "0",
2163
- // "posStopLossTrigger": "market",
2164
- // "posTakeProfitPrice": "0",
2165
- // "posTakeProfitTrigger": "market",
2166
- // "liquidityInd": "n"
2167
- // }
2168
- // ]
2169
- // }
2170
- //
2171
- const data = this.safeList(response, 'data', []);
2172
- if (accountCategory === 'futures') {
2173
- return this.parseOrders(data, market, since, limit);
2174
- }
2175
- // a workaround for https://github.com/ccxt/ccxt/issues/7187
2176
- const orders = [];
2177
- for (let i = 0; i < data.length; i++) {
2178
- const order = this.parseOrder(data[i], market);
2179
- orders.push(order);
2180
- }
2181
- return this.filterBySymbolSinceLimit(orders, symbol, since, limit);
2182
- }
2183
- /**
2184
- * @method
2185
- * @name ascendex#fetchClosedOrders
2186
- * @description fetches information on multiple closed orders made by the user
2187
- * @see https://ascendex.github.io/ascendex-pro-api/#list-history-orders-v2
2188
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#list-current-history-orders
2189
- * @param {string} symbol unified market symbol of the market orders were made in
2190
- * @param {int} [since] the earliest time in ms to fetch orders for
2191
- * @param {int} [limit] the maximum number of order structures to retrieve
2192
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2193
- * @param {int} [params.until] the latest time in ms to fetch orders for
2194
- * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
2195
- */
2196
- async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2197
- await this.loadMarkets();
2198
- await this.loadAccounts();
2199
- const account = this.safeDict(this.accounts, 0, {});
2200
- const accountGroup = this.safeString(account, 'id');
2201
- const request = {
2202
- // 'category': accountCategory,
2203
- // 'symbol': market['id'],
2204
- // 'orderType': 'market', // optional, string
2205
- // 'side': 'buy', // or 'sell', optional, case insensitive.
2206
- // 'status': 'Filled', // "Filled", "Canceled", or "Rejected"
2207
- // 'startTime': exchange.milliseconds (),
2208
- // 'endTime': exchange.milliseconds (),
2209
- // 'page': 1,
2210
- // 'pageSize': 100,
2211
- };
2212
- let market = undefined;
2213
- if (symbol !== undefined) {
2214
- market = this.market(symbol);
2215
- request['symbol'] = market['id'];
2216
- }
2217
- const [type, query] = this.handleMarketTypeAndParams('fetchClosedOrders', market, params);
2218
- const options = this.safeDict(this.options, 'fetchClosedOrders', {});
2219
- const defaultMethod = this.safeString(options, 'method', 'v2PrivateDataGetOrderHist');
2220
- const method = this.getSupportedMapping(type, {
2221
- 'spot': defaultMethod,
2222
- 'margin': defaultMethod,
2223
- 'swap': 'v2PrivateAccountGroupGetFuturesOrderHistCurrent',
2224
- });
2225
- if (since !== undefined) {
2226
- request['startTime'] = since;
2227
- }
2228
- const until = this.safeString(params, 'until');
2229
- if (until !== undefined) {
2230
- request['endTime'] = until;
2231
- }
2232
- const accountsByType = this.safeDict(this.options, 'accountsByType', {});
2233
- const accountCategory = this.safeString(accountsByType, type, 'cash'); // margin, futures
2234
- let response = undefined;
2235
- if (method === 'v1PrivateAccountCategoryGetOrderHistCurrent') {
2236
- request['account-group'] = accountGroup;
2237
- request['account-category'] = accountCategory;
2238
- if (limit !== undefined) {
2239
- request['limit'] = limit;
2240
- }
2241
- response = await this.v1PrivateAccountCategoryGetOrderHistCurrent(this.extend(request, query));
2242
- }
2243
- else if (method === 'v2PrivateDataGetOrderHist') {
2244
- request['account'] = accountCategory;
2245
- if (limit !== undefined) {
2246
- request['limit'] = limit;
2247
- }
2248
- response = await this.v2PrivateDataGetOrderHist(this.extend(request, query));
2249
- }
2250
- else if (method === 'v2PrivateAccountGroupGetFuturesOrderHistCurrent') {
2251
- request['account-group'] = accountGroup;
2252
- request['account-category'] = accountCategory;
2253
- if (limit !== undefined) {
2254
- request['pageSize'] = limit;
2255
- }
2256
- response = await this.v2PrivateAccountGroupGetFuturesOrderHistCurrent(this.extend(request, query));
2257
- }
2258
- else {
2259
- throw new NotSupported(this.id + ' fetchClosedOrders() is not currently supported for ' + type + ' markets');
2260
- }
2261
- //
2262
- // accountCategoryGetOrderHistCurrent
2263
- //
2264
- // {
2265
- // "code":0,
2266
- // "accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda",
2267
- // "ac":"CASH",
2268
- // "data":[
2269
- // {
2270
- // "seqNum":15561826728,
2271
- // "orderId":"a17294d305c0U6491137460bethu7kw9",
2272
- // "symbol":"ETH/USDT",
2273
- // "orderType":"Limit",
2274
- // "lastExecTime":1591635618200,
2275
- // "price":"200",
2276
- // "orderQty":"0.1",
2277
- // "side":"Buy",
2278
- // "status":"Canceled",
2279
- // "avgPx":"0",
2280
- // "cumFilledQty":"0",
2281
- // "stopPrice":"",
2282
- // "errorCode":"",
2283
- // "cumFee":"0",
2284
- // "feeAsset":"USDT",
2285
- // "execInst":"NULL_VAL"
2286
- // }
2287
- // ]
2288
- // }
2289
- //
2290
- // {
2291
- // "code": 0,
2292
- // "data": [
2293
- // {
2294
- // "orderId" : "a173ad938fc3U22666567717788c3b66", // orderId
2295
- // "seqNum" : 18777366360, // sequence number
2296
- // "accountId" : "cshwSjbpPjSwHmxPdz2CPQVU9mnbzPpt", // accountId
2297
- // "symbol" : "BTC/USDT", // symbol
2298
- // "orderType" : "Limit", // order type (Limit/Market/StopMarket/StopLimit)
2299
- // "side" : "Sell", // order side (Buy/Sell)
2300
- // "price" : "11346.77", // order price
2301
- // "stopPrice" : "0", // stop price (0 by default)
2302
- // "orderQty" : "0.01", // order quantity (in base asset)
2303
- // "status" : "Canceled", // order status (Filled/Canceled/Rejected)
2304
- // "createTime" : 1596344995793, // order creation time
2305
- // "lastExecTime": 1596344996053, // last execution time
2306
- // "avgFillPrice": "11346.77", // average filled price
2307
- // "fillQty" : "0.01", // filled quantity (in base asset)
2308
- // "fee" : "-0.004992579", // cummulative fee. if negative, this value is the commission charged; if possitive, this value is the rebate received.
2309
- // "feeAsset" : "USDT" // fee asset
2310
- // }
2311
- // ]
2312
- // }
2313
- //
2314
- // accountGroupGetFuturesOrderHistCurrent
2315
- //
2316
- // {
2317
- // "code": 0,
2318
- // "data": [
2319
- // {
2320
- // "ac": "FUTURES",
2321
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2322
- // "time": 1640245777002,
2323
- // "orderId": "r17de6444fa6U0711043490bbtcpJ2lI",
2324
- // "seqNum": 28796124902,
2325
- // "orderType": "Limit",
2326
- // "execInst": "NULL_VAL",
2327
- // "side": "Buy",
2328
- // "symbol": "BTC-PERP",
2329
- // "price": "30000",
2330
- // "orderQty": "0.0021",
2331
- // "stopPrice": "0",
2332
- // "stopBy": "market",
2333
- // "status": "Canceled",
2334
- // "lastExecTime": 1640246574886,
2335
- // "lastQty": "0",
2336
- // "lastPx": "0",
2337
- // "avgFilledPx": "0",
2338
- // "cumFilledQty": "0",
2339
- // "fee": "0",
2340
- // "cumFee": "0",
2341
- // "feeAsset": "USDT",
2342
- // "errorCode": "",
2343
- // "posStopLossPrice": "0",
2344
- // "posStopLossTrigger": "market",
2345
- // "posTakeProfitPrice": "0",
2346
- // "posTakeProfitTrigger": "market",
2347
- // "liquidityInd": "n"
2348
- // }
2349
- // ]
2350
- // }
2351
- //
2352
- let data = this.safeList(response, 'data', []);
2353
- if (!Array.isArray(data)) {
2354
- data = this.safeList(data, 'data', []);
2355
- }
2356
- return this.parseOrders(data, market, since, limit);
2357
- }
2358
- /**
2359
- * @method
2360
- * @name ascendex#cancelOrder
2361
- * @description cancels an open order
2362
- * @see https://ascendex.github.io/ascendex-pro-api/#cancel-order
2363
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#cancel-order
2364
- * @param {string} id order id
2365
- * @param {string} symbol unified symbol of the market the order was made in
2366
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2367
- * @returns {object} An [order structure]{@link https://docs.ccxt.com/?id=order-structure}
2368
- */
2369
- async cancelOrder(id, symbol = undefined, params = {}) {
2370
- if (symbol === undefined) {
2371
- throw new ArgumentsRequired(this.id + ' cancelOrder() requires a symbol argument');
2372
- }
2373
- await this.loadMarkets();
2374
- await this.loadAccounts();
2375
- const market = this.market(symbol);
2376
- const [type, query] = this.handleMarketTypeAndParams('cancelOrder', market, params);
2377
- const accountsByType = this.safeDict(this.options, 'accountsByType', {});
2378
- const accountCategory = this.safeString(accountsByType, type, 'cash');
2379
- const account = this.safeDict(this.accounts, 0, {});
2380
- const accountGroup = this.safeString(account, 'id');
2381
- const request = {
2382
- 'account-group': accountGroup,
2383
- 'account-category': accountCategory,
2384
- 'symbol': market['id'],
2385
- 'time': this.milliseconds(),
2386
- 'id': 'foobar',
2387
- };
2388
- const clientOrderId = this.safeString2(params, 'clientOrderId', 'id');
2389
- if (clientOrderId === undefined) {
2390
- request['orderId'] = id;
2391
- }
2392
- else {
2393
- request['id'] = clientOrderId;
2394
- params = this.omit(params, ['clientOrderId', 'id']);
2395
- }
2396
- let response = undefined;
2397
- if ((type === 'spot') || (type === 'margin')) {
2398
- response = await this.v1PrivateAccountCategoryDeleteOrder(this.extend(request, query));
2399
- }
2400
- else if (type === 'swap') {
2401
- request['account-category'] = accountCategory;
2402
- response = await this.v2PrivateAccountGroupDeleteFuturesOrder(this.extend(request, query));
2403
- }
2404
- else {
2405
- throw new NotSupported(this.id + ' cancelOrder() is not currently supported for ' + type + ' markets');
2406
- }
2407
- //
2408
- // AccountCategoryDeleteOrder
2409
- //
2410
- // {
2411
- // "code": 0,
2412
- // "data": {
2413
- // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
2414
- // "ac": "CASH",
2415
- // "action": "cancel-order",
2416
- // "status": "Ack",
2417
- // "info": {
2418
- // "id": "wv8QGquoeamhssvQBeHOHGQCGlcBjj23",
2419
- // "orderId": "16e6198afb4s8bXHbAwwoqDo2ebc19dc",
2420
- // "orderType": "", // could be empty
2421
- // "symbol": "ETH/USDT",
2422
- // "timestamp": 1573594877822
2423
- // }
2424
- // }
2425
- // }
2426
- //
2427
- // AccountGroupDeleteFuturesOrder
2428
- //
2429
- // {
2430
- // "code": 0,
2431
- // "data": {
2432
- // "meta": {
2433
- // "id": "foobar",
2434
- // "action": "cancel-order",
2435
- // "respInst": "ACK"
2436
- // },
2437
- // "order": {
2438
- // "ac": "FUTURES",
2439
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2440
- // "time": 1640244480476,
2441
- // "orderId": "r17de63086f4U0711043490bbtcpPUF4",
2442
- // "seqNum": 28795959269,
2443
- // "orderType": "Limit",
2444
- // "execInst": "NULL_VAL",
2445
- // "side": "Buy",
2446
- // "symbol": "BTC-PERP",
2447
- // "price": "30000",
2448
- // "orderQty": "0.0021",
2449
- // "stopPrice": "0",
2450
- // "stopBy": "market",
2451
- // "status": "New",
2452
- // "lastExecTime": 1640244480491,
2453
- // "lastQty": "0",
2454
- // "lastPx": "0",
2455
- // "avgFilledPx": "0",
2456
- // "cumFilledQty": "0",
2457
- // "fee": "0",
2458
- // "cumFee": "0",
2459
- // "feeAsset": "BTCPC",
2460
- // "errorCode": "",
2461
- // "posStopLossPrice": "0",
2462
- // "posStopLossTrigger": "market",
2463
- // "posTakeProfitPrice": "0",
2464
- // "posTakeProfitTrigger": "market",
2465
- // "liquidityInd": "n"
2466
- // }
2467
- // }
2468
- // }
2469
- //
2470
- const data = this.safeDict(response, 'data', {});
2471
- const order = this.safeDict2(data, 'order', 'info', {});
2472
- return this.parseOrder(order, market);
2473
- }
2474
- /**
2475
- * @method
2476
- * @name ascendex#cancelAllOrders
2477
- * @description cancel all open orders
2478
- * @see https://ascendex.github.io/ascendex-pro-api/#cancel-all-orders
2479
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#cancel-all-open-orders
2480
- * @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
2481
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2482
- * @returns {object[]} a list with a single [order structure]{@link https://docs.ccxt.com/?id=order-structure} with the response assigned to the info property
2483
- */
2484
- async cancelAllOrders(symbol = undefined, params = {}) {
2485
- await this.loadMarkets();
2486
- await this.loadAccounts();
2487
- let market = undefined;
2488
- if (symbol !== undefined) {
2489
- market = this.market(symbol);
2490
- }
2491
- const [type, query] = this.handleMarketTypeAndParams('cancelAllOrders', market, params);
2492
- const accountsByType = this.safeDict(this.options, 'accountsByType', {});
2493
- const accountCategory = this.safeString(accountsByType, type, 'cash');
2494
- const account = this.safeDict(this.accounts, 0, {});
2495
- const accountGroup = this.safeString(account, 'id');
2496
- const request = {
2497
- 'account-group': accountGroup,
2498
- 'account-category': accountCategory,
2499
- 'time': this.milliseconds(),
2500
- };
2501
- if (symbol !== undefined) {
2502
- request['symbol'] = this.safeString(market, 'id');
2503
- }
2504
- let response = undefined;
2505
- if ((type === 'spot') || (type === 'margin')) {
2506
- response = await this.v1PrivateAccountCategoryDeleteOrderAll(this.extend(request, query));
2507
- }
2508
- else if (type === 'swap') {
2509
- request['account-category'] = accountCategory;
2510
- response = await this.v2PrivateAccountGroupDeleteFuturesOrderAll(this.extend(request, query));
2511
- }
2512
- else {
2513
- throw new NotSupported(this.id + ' cancelAllOrders() is not currently supported for ' + type + ' markets');
2514
- }
2515
- //
2516
- // AccountCategoryDeleteOrderAll
2517
- //
2518
- // {
2519
- // "code": 0,
2520
- // "data": {
2521
- // "ac": "CASH",
2522
- // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
2523
- // "action": "cancel-all",
2524
- // "info": {
2525
- // "id": "2bmYvi7lyTrneMzpcJcf2D7Pe9V1P9wy",
2526
- // "orderId": "",
2527
- // "orderType": "NULL_VAL",
2528
- // "symbol": "",
2529
- // "timestamp": 1574118495462
2530
- // },
2531
- // "status": "Ack"
2532
- // }
2533
- // }
2534
- //
2535
- // AccountGroupDeleteFuturesOrderAll
2536
- //
2537
- // {
2538
- // "code": 0,
2539
- // "data": {
2540
- // "ac": "FUTURES",
2541
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2542
- // "action": "cancel-all",
2543
- // "info": {
2544
- // "symbol":"BTC-PERP"
2545
- // }
2546
- // }
2547
- // }
2548
- //
2549
- return [this.safeOrder({
2550
- 'info': response,
2551
- })];
2552
- }
2553
- parseDepositAddress(depositAddress, currency = undefined) {
2554
- //
2555
- // {
2556
- // "address": "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722",
2557
- // "destTag": "",
2558
- // "tagType": "",
2559
- // "tagId": "",
2560
- // "chainName": "ERC20",
2561
- // "numConfirmations": 20,
2562
- // "withdrawalFee": 1,
2563
- // "nativeScale": 4,
2564
- // "tips": []
2565
- // }
2566
- //
2567
- const address = this.safeString(depositAddress, 'address');
2568
- const tagId = this.safeString(depositAddress, 'tagId');
2569
- const tag = this.safeString(depositAddress, tagId);
2570
- this.checkAddress(address);
2571
- const code = (currency === undefined) ? undefined : currency['code'];
2572
- const chainName = this.safeString(depositAddress, 'blockchain');
2573
- const network = this.networkIdToCode(chainName, code);
2574
- return {
2575
- 'info': depositAddress,
2576
- 'currency': code,
2577
- 'network': network,
2578
- 'address': address,
2579
- 'tag': tag,
2580
- };
2581
- }
2582
- /**
2583
- * @method
2584
- * @name ascendex#fetchDepositAddress
2585
- * @description fetch the deposit address for a currency associated with this account
2586
- * @see https://ascendex.github.io/ascendex-pro-api/#query-deposit-addresses
2587
- * @param {string} code unified currency code
2588
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2589
- * @param {string} [params.network] unified network code for deposit chain
2590
- * @returns {object} an [address structure]{@link https://docs.ccxt.com/?id=address-structure}
2591
- */
2592
- async fetchDepositAddress(code, params = {}) {
2593
- await this.loadMarkets();
2594
- const currency = this.currency(code);
2595
- const networkCode = this.safeString2(params, 'network', 'chainName');
2596
- const networkId = this.networkCodeToId(networkCode, currency['code']);
2597
- params = this.omit(params, ['chainName']);
2598
- const request = {
2599
- 'asset': currency['id'],
2600
- 'blockchain': networkId,
2601
- };
2602
- const response = await this.v1PrivateGetWalletDepositAddress(this.extend(request, params));
2603
- //
2604
- // {
2605
- // "code":0,
2606
- // "data":{
2607
- // "asset":"USDT",
2608
- // "assetName":"Tether",
2609
- // "address":[
2610
- // {
2611
- // "address":"1N22odLHXnLPCjC8kwBJPTayarr9RtPod6",
2612
- // "destTag":"",
2613
- // "tagType":"",
2614
- // "tagId":"",
2615
- // "chainName":"Omni",
2616
- // "numConfirmations":3,
2617
- // "withdrawalFee":4.7,
2618
- // "nativeScale":4,
2619
- // "tips":[]
2620
- // },
2621
- // {
2622
- // "address":"0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722",
2623
- // "destTag":"",
2624
- // "tagType":"",
2625
- // "tagId":"",
2626
- // "chainName":"ERC20",
2627
- // "numConfirmations":20,
2628
- // "withdrawalFee":1.0,
2629
- // "nativeScale":4,
2630
- // "tips":[]
2631
- // }
2632
- // ]
2633
- // }
2634
- // }
2635
- //
2636
- const data = this.safeDict(response, 'data', {});
2637
- const addresses = this.safeList(data, 'address', []);
2638
- const numAddresses = addresses.length;
2639
- let address = undefined;
2640
- if (numAddresses > 1) {
2641
- const addressesByChainName = this.indexBy(addresses, 'chainName');
2642
- if (networkId === undefined) {
2643
- const chainNames = Object.keys(addressesByChainName);
2644
- const chains = chainNames.join(', ');
2645
- throw new ArgumentsRequired(this.id + ' fetchDepositAddress() returned more than one address, a chainName parameter is required, one of ' + chains);
2646
- }
2647
- address = this.safeDict(addressesByChainName, networkId, {});
2648
- }
2649
- else {
2650
- // first address
2651
- address = this.safeDict(addresses, 0, {});
2652
- }
2653
- const result = this.parseDepositAddress(address, currency);
2654
- return this.extend(result, {
2655
- 'info': response,
2656
- });
2657
- }
2658
- /**
2659
- * @method
2660
- * @name ascendex#fetchDeposits
2661
- * @description fetch all deposits made to an account
2662
- * @param {string} code unified currency code
2663
- * @param {int} [since] the earliest time in ms to fetch deposits for
2664
- * @param {int} [limit] the maximum number of deposits structures to retrieve
2665
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2666
- * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/?id=transaction-structure}
2667
- */
2668
- async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
2669
- const request = {
2670
- 'txType': 'deposit',
2671
- };
2672
- return await this.fetchTransactions(code, since, limit, this.extend(request, params));
2673
- }
2674
- /**
2675
- * @method
2676
- * @name ascendex#fetchWithdrawals
2677
- * @description fetch all withdrawals made from an account
2678
- * @param {string} code unified currency code
2679
- * @param {int} [since] the earliest time in ms to fetch withdrawals for
2680
- * @param {int} [limit] the maximum number of withdrawals structures to retrieve
2681
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2682
- * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/?id=transaction-structure}
2683
- */
2684
- async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2685
- const request = {
2686
- 'txType': 'withdrawal',
2687
- };
2688
- return await this.fetchTransactions(code, since, limit, this.extend(request, params));
2689
- }
2690
- /**
2691
- * @method
2692
- * @name ascendex#fetchDepositsWithdrawals
2693
- * @description fetch history of deposits and withdrawals
2694
- * @param {string} [code] unified currency code for the currency of the deposit/withdrawals, default is undefined
2695
- * @param {int} [since] timestamp in ms of the earliest deposit/withdrawal, default is undefined
2696
- * @param {int} [limit] max number of deposit/withdrawals to return, default is undefined
2697
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2698
- * @returns {object} a list of [transaction structure]{@link https://docs.ccxt.com/?id=transaction-structure}
2699
- */
2700
- async fetchDepositsWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2701
- await this.loadMarkets();
2702
- const request = {
2703
- // 'asset': currency['id'],
2704
- // 'page': 1,
2705
- // 'pageSize': 20,
2706
- // 'startTs': this.milliseconds (),
2707
- // 'endTs': this.milliseconds (),
2708
- // 'txType': undefned, // deposit, withdrawal
2709
- };
2710
- let currency = undefined;
2711
- if (code !== undefined) {
2712
- currency = this.currency(code);
2713
- request['asset'] = currency['id'];
2714
- }
2715
- if (since !== undefined) {
2716
- request['startTs'] = since;
2717
- }
2718
- if (limit !== undefined) {
2719
- request['pageSize'] = limit;
2720
- }
2721
- const response = await this.v1PrivateGetWalletTransactions(this.extend(request, params));
2722
- //
2723
- // {
2724
- // "code": 0,
2725
- // "data": {
2726
- // "data": [
2727
- // {
2728
- // "requestId": "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB",
2729
- // "time": 1591606166000,
2730
- // "asset": "USDT",
2731
- // "transactionType": "deposit",
2732
- // "amount": "25",
2733
- // "commission": "0",
2734
- // "networkTransactionId": "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce",
2735
- // "status": "pending",
2736
- // "numConfirmed": 8,
2737
- // "numConfirmations": 20,
2738
- // "destAddress": { address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722" }
2739
- // }
2740
- // ],
2741
- // "page": 1,
2742
- // "pageSize": 20,
2743
- // "hasNext": false
2744
- // }
2745
- // }
2746
- //
2747
- const data = this.safeDict(response, 'data', {});
2748
- const transactions = this.safeList(data, 'data', []);
2749
- return this.parseTransactions(transactions, currency, since, limit);
2750
- }
2751
- parseTransactionStatus(status) {
2752
- const statuses = {
2753
- 'reviewing': 'pending',
2754
- 'pending': 'pending',
2755
- 'confirmed': 'ok',
2756
- 'rejected': 'rejected',
2757
- };
2758
- return this.safeString(statuses, status, status);
2759
- }
2760
- parseTransaction(transaction, currency = undefined) {
2761
- //
2762
- // {
2763
- // "requestId": "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB",
2764
- // "time": 1591606166000,
2765
- // "asset": "USDT",
2766
- // "transactionType": "deposit",
2767
- // "amount": "25",
2768
- // "commission": "0",
2769
- // "networkTransactionId": "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce",
2770
- // "status": "pending",
2771
- // "numConfirmed": 8,
2772
- // "numConfirmations": 20,
2773
- // "destAddress": {
2774
- // "address": "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722",
2775
- // "destTag": "..." // for currencies that have it
2776
- // }
2777
- // }
2778
- //
2779
- const destAddress = this.safeDict(transaction, 'destAddress', {});
2780
- const address = this.safeString(destAddress, 'address');
2781
- const tag = this.safeString(destAddress, 'destTag');
2782
- const timestamp = this.safeInteger(transaction, 'time');
2783
- const currencyId = this.safeString(transaction, 'asset');
2784
- let amountString = this.safeString(transaction, 'amount');
2785
- const feeCostString = this.safeString(transaction, 'commission');
2786
- amountString = Precise.stringSub(amountString, feeCostString);
2787
- const code = this.safeCurrencyCode(currencyId, currency);
2788
- return {
2789
- 'info': transaction,
2790
- 'id': this.safeString(transaction, 'requestId'),
2791
- 'txid': this.safeString(transaction, 'networkTransactionId'),
2792
- 'type': this.safeString(transaction, 'transactionType'),
2793
- 'currency': code,
2794
- 'network': undefined,
2795
- 'amount': this.parseNumber(amountString),
2796
- 'status': this.parseTransactionStatus(this.safeString(transaction, 'status')),
2797
- 'timestamp': timestamp,
2798
- 'datetime': this.iso8601(timestamp),
2799
- 'address': address,
2800
- 'addressFrom': undefined,
2801
- 'addressTo': address,
2802
- 'tag': tag,
2803
- 'tagFrom': undefined,
2804
- 'tagTo': tag,
2805
- 'updated': undefined,
2806
- 'comment': undefined,
2807
- 'fee': {
2808
- 'currency': code,
2809
- 'cost': this.parseNumber(feeCostString),
2810
- 'rate': undefined,
2811
- },
2812
- 'internal': false,
2813
- };
2814
- }
2815
- /**
2816
- * @method
2817
- * @name ascendex#fetchPositions
2818
- * @description fetch all open positions
2819
- * @param {string[]|undefined} symbols list of unified market symbols
2820
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2821
- * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/?id=position-structure}
2822
- */
2823
- async fetchPositions(symbols = undefined, params = {}) {
2824
- await this.loadMarkets();
2825
- await this.loadAccounts();
2826
- const account = this.safeDict(this.accounts, 0, {});
2827
- const accountGroup = this.safeString(account, 'id');
2828
- const request = {
2829
- 'account-group': accountGroup,
2830
- };
2831
- const response = await this.v2PrivateAccountGroupGetFuturesPosition(this.extend(request, params));
2832
- //
2833
- // {
2834
- // "code": 0,
2835
- // "data": {
2836
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
2837
- // "ac": "FUTURES",
2838
- // "collaterals": [
2839
- // {
2840
- // "asset": "USDT",
2841
- // "balance": "44.570287262",
2842
- // "referencePrice": "1",
2843
- // "discountFactor": "1"
2844
- // }
2845
- // ],
2846
- // "contracts": [
2847
- // {
2848
- // "symbol": "BTC-PERP",
2849
- // "side": "LONG",
2850
- // "position": "0.0001",
2851
- // "referenceCost": "-3.12277254",
2852
- // "unrealizedPnl": "-0.001700233",
2853
- // "realizedPnl": "0",
2854
- // "avgOpenPrice": "31209",
2855
- // "marginType": "isolated",
2856
- // "isolatedMargin": "1.654972977",
2857
- // "leverage": "2",
2858
- // "takeProfitPrice": "0",
2859
- // "takeProfitTrigger": "market",
2860
- // "stopLossPrice": "0",
2861
- // "stopLossTrigger": "market",
2862
- // "buyOpenOrderNotional": "0",
2863
- // "sellOpenOrderNotional": "0",
2864
- // "markPrice": "31210.723063672",
2865
- // "indexPrice": "31223.148857925"
2866
- // },
2867
- // ]
2868
- // }
2869
- // }
2870
- //
2871
- const data = this.safeDict(response, 'data', {});
2872
- const position = this.safeList(data, 'contracts', []);
2873
- const result = [];
2874
- for (let i = 0; i < position.length; i++) {
2875
- result.push(this.parsePosition(position[i]));
2876
- }
2877
- symbols = this.marketSymbols(symbols);
2878
- return this.filterByArrayPositions(result, 'symbol', symbols, false);
2879
- }
2880
- parsePosition(position, market = undefined) {
2881
- //
2882
- // {
2883
- // "symbol": "BTC-PERP",
2884
- // "side": "LONG",
2885
- // "position": "0.0001",
2886
- // "referenceCost": "-3.12277254",
2887
- // "unrealizedPnl": "-0.001700233",
2888
- // "realizedPnl": "0",
2889
- // "avgOpenPrice": "31209",
2890
- // "marginType": "isolated",
2891
- // "isolatedMargin": "1.654972977",
2892
- // "leverage": "2",
2893
- // "takeProfitPrice": "0",
2894
- // "takeProfitTrigger": "market",
2895
- // "stopLossPrice": "0",
2896
- // "stopLossTrigger": "market",
2897
- // "buyOpenOrderNotional": "0",
2898
- // "sellOpenOrderNotional": "0",
2899
- // "markPrice": "31210.723063672",
2900
- // "indexPrice": "31223.148857925"
2901
- // },
2902
- //
2903
- const marketId = this.safeString(position, 'symbol');
2904
- market = this.safeMarket(marketId, market);
2905
- let notional = this.safeString(position, 'buyOpenOrderNotional');
2906
- if (Precise.stringEq(notional, '0')) {
2907
- notional = this.safeString(position, 'sellOpenOrderNotional');
2908
- }
2909
- const marginType = this.safeString(position, 'marginType');
2910
- const marginMode = (marginType === 'crossed') ? 'cross' : 'isolated';
2911
- let collateral = undefined;
2912
- if (marginMode === 'isolated') {
2913
- collateral = this.safeString(position, 'isolatedMargin');
2914
- }
2915
- return this.safePosition({
2916
- 'info': position,
2917
- 'id': undefined,
2918
- 'symbol': market['symbol'],
2919
- 'notional': this.parseNumber(notional),
2920
- 'marginMode': marginMode,
2921
- 'liquidationPrice': undefined,
2922
- 'entryPrice': this.safeNumber(position, 'avgOpenPrice'),
2923
- 'unrealizedPnl': this.safeNumber(position, 'unrealizedPnl'),
2924
- 'percentage': undefined,
2925
- 'contracts': this.safeNumber(position, 'position'),
2926
- 'contractSize': this.safeNumber(market, 'contractSize'),
2927
- 'markPrice': this.safeNumber(position, 'markPrice'),
2928
- 'lastPrice': undefined,
2929
- 'side': this.safeStringLower(position, 'side'),
2930
- 'hedged': undefined,
2931
- 'timestamp': undefined,
2932
- 'datetime': undefined,
2933
- 'lastUpdateTimestamp': undefined,
2934
- 'maintenanceMargin': undefined,
2935
- 'maintenanceMarginPercentage': undefined,
2936
- 'collateral': collateral,
2937
- 'initialMargin': undefined,
2938
- 'initialMarginPercentage': undefined,
2939
- 'leverage': this.safeInteger(position, 'leverage'),
2940
- 'marginRatio': undefined,
2941
- 'stopLossPrice': this.safeNumber(position, 'stopLossPrice'),
2942
- 'takeProfitPrice': this.safeNumber(position, 'takeProfitPrice'),
2943
- });
2944
- }
2945
- parseFundingRate(contract, market = undefined) {
2946
- //
2947
- // {
2948
- // "time": 1640061364830,
2949
- // "symbol": "EOS-PERP",
2950
- // "markPrice": "3.353854865",
2951
- // "indexPrice": "3.3542",
2952
- // "openInterest": "14242",
2953
- // "fundingRate": "-0.000073026",
2954
- // "nextFundingTime": 1640073600000
2955
- // }
2956
- //
2957
- const marketId = this.safeString(contract, 'symbol');
2958
- const symbol = this.safeSymbol(marketId, market);
2959
- const currentTime = this.safeInteger(contract, 'time');
2960
- const nextFundingRate = this.safeNumber(contract, 'fundingRate');
2961
- const nextFundingRateTimestamp = this.safeInteger(contract, 'nextFundingTime');
2962
- return {
2963
- 'info': contract,
2964
- 'symbol': symbol,
2965
- 'markPrice': this.safeNumber(contract, 'markPrice'),
2966
- 'indexPrice': this.safeNumber(contract, 'indexPrice'),
2967
- 'interestRate': this.parseNumber('0'),
2968
- 'estimatedSettlePrice': undefined,
2969
- 'timestamp': currentTime,
2970
- 'datetime': this.iso8601(currentTime),
2971
- 'previousFundingRate': undefined,
2972
- 'nextFundingRate': undefined,
2973
- 'previousFundingTimestamp': undefined,
2974
- 'nextFundingTimestamp': undefined,
2975
- 'previousFundingDatetime': undefined,
2976
- 'nextFundingDatetime': undefined,
2977
- 'fundingRate': nextFundingRate,
2978
- 'fundingTimestamp': nextFundingRateTimestamp,
2979
- 'fundingDatetime': this.iso8601(nextFundingRateTimestamp),
2980
- 'interval': undefined,
2981
- };
2982
- }
2983
- /**
2984
- * @method
2985
- * @name ascendex#fetchFundingRates
2986
- * @description fetch the funding rate for multiple markets
2987
- * @param {string[]|undefined} symbols list of unified market symbols
2988
- * @param {object} [params] extra parameters specific to the exchange API endpoint
2989
- * @returns {object[]} a list of [funding rates structures]{@link https://docs.ccxt.com/?id=funding-rates-structure}, indexe by market symbols
2990
- */
2991
- async fetchFundingRates(symbols = undefined, params = {}) {
2992
- await this.loadMarkets();
2993
- symbols = this.marketSymbols(symbols);
2994
- const response = await this.v2PublicGetFuturesPricingData(params);
2995
- //
2996
- // {
2997
- // "code": 0,
2998
- // "data": {
2999
- // "contracts": [
3000
- // {
3001
- // "time": 1640061364830,
3002
- // "symbol": "EOS-PERP",
3003
- // "markPrice": "3.353854865",
3004
- // "indexPrice": "3.3542",
3005
- // "openInterest": "14242",
3006
- // "fundingRate": "-0.000073026",
3007
- // "nextFundingTime": 1640073600000
3008
- // },
3009
- // ],
3010
- // "collaterals": [
3011
- // {
3012
- // "asset": "USDTR",
3013
- // "referencePrice": "1"
3014
- // },
3015
- // ]
3016
- // }
3017
- // }
3018
- //
3019
- const data = this.safeDict(response, 'data', {});
3020
- const contracts = this.safeList(data, 'contracts', []);
3021
- return this.parseFundingRates(contracts, symbols);
3022
- }
3023
- async modifyMarginHelper(symbol, amount, type, params = {}) {
3024
- await this.loadMarkets();
3025
- await this.loadAccounts();
3026
- const market = this.market(symbol);
3027
- const account = this.safeDict(this.accounts, 0, {});
3028
- const accountGroup = this.safeString(account, 'id');
3029
- amount = this.amountToPrecision(symbol, amount);
3030
- const request = {
3031
- 'account-group': accountGroup,
3032
- 'symbol': market['id'],
3033
- 'amount': amount, // positive value for adding margin, negative for reducing
3034
- };
3035
- const response = await this.v2PrivateAccountGroupPostFuturesIsolatedPositionMargin(this.extend(request, params));
3036
- //
3037
- // Can only change margin for perpetual futures isolated margin positions
3038
- //
3039
- // {
3040
- // "code": 0
3041
- // }
3042
- //
3043
- if (type === 'reduce') {
3044
- amount = Precise.stringAbs(amount);
3045
- }
3046
- const parsedAmount = this.parseNumber(amount);
3047
- return this.extend(this.parseMarginModification(response, market), {
3048
- 'amount': parsedAmount,
3049
- 'type': type,
3050
- });
3051
- }
3052
- parseMarginModification(data, market = undefined) {
3053
- //
3054
- // addMargin/reduceMargin
3055
- //
3056
- // {
3057
- // "code": 0
3058
- // }
3059
- //
3060
- const errorCode = this.safeString(data, 'code');
3061
- const status = (errorCode === '0') ? 'ok' : 'failed';
3062
- return {
3063
- 'info': data,
3064
- 'symbol': this.safeString(market, 'symbol'),
3065
- 'type': undefined,
3066
- 'marginMode': 'isolated',
3067
- 'amount': undefined,
3068
- 'total': undefined,
3069
- 'code': this.safeString(market, 'quote'),
3070
- 'status': status,
3071
- 'timestamp': undefined,
3072
- 'datetime': undefined,
3073
- };
3074
- }
3075
- /**
3076
- * @method
3077
- * @name ascendex#reduceMargin
3078
- * @description remove margin from a position
3079
- * @param {string} symbol unified market symbol
3080
- * @param {float} amount the amount of margin to remove
3081
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3082
- * @returns {object} a [margin structure]{@link https://docs.ccxt.com/?id=margin-structure}
3083
- */
3084
- async reduceMargin(symbol, amount, params = {}) {
3085
- return await this.modifyMarginHelper(symbol, -amount, 'reduce', params);
3086
- }
3087
- /**
3088
- * @method
3089
- * @name ascendex#addMargin
3090
- * @description add margin
3091
- * @param {string} symbol unified market symbol
3092
- * @param {float} amount amount of margin to add
3093
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3094
- * @returns {object} a [margin structure]{@link https://docs.ccxt.com/?id=margin-structure}
3095
- */
3096
- async addMargin(symbol, amount, params = {}) {
3097
- return await this.modifyMarginHelper(symbol, amount, 'add', params);
3098
- }
3099
- /**
3100
- * @method
3101
- * @name ascendex#setLeverage
3102
- * @description set the level of leverage for a market
3103
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#change-contract-leverage
3104
- * @param {float} leverage the rate of leverage
3105
- * @param {string} symbol unified market symbol
3106
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3107
- * @returns {object} response from the exchange
3108
- */
3109
- async setLeverage(leverage, symbol = undefined, params = {}) {
3110
- if (symbol === undefined) {
3111
- throw new ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
3112
- }
3113
- if ((leverage < 1) || (leverage > 100)) {
3114
- throw new BadRequest(this.id + ' leverage should be between 1 and 100');
3115
- }
3116
- await this.loadMarkets();
3117
- await this.loadAccounts();
3118
- const market = this.market(symbol);
3119
- if (!market['swap']) {
3120
- throw new BadSymbol(this.id + ' setLeverage() supports swap contracts only');
3121
- }
3122
- const account = this.safeDict(this.accounts, 0, {});
3123
- const accountGroup = this.safeString(account, 'id');
3124
- const request = {
3125
- 'account-group': accountGroup,
3126
- 'symbol': market['id'],
3127
- 'leverage': leverage,
3128
- };
3129
- return await this.v2PrivateAccountGroupPostFuturesLeverage(this.extend(request, params));
3130
- }
3131
- /**
3132
- * @method
3133
- * @name ascendex#setMarginMode
3134
- * @description set margin mode to 'cross' or 'isolated'
3135
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#change-margin-type
3136
- * @param {string} marginMode 'cross' or 'isolated'
3137
- * @param {string} symbol unified market symbol
3138
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3139
- * @returns {object} response from the exchange
3140
- */
3141
- async setMarginMode(marginMode, symbol = undefined, params = {}) {
3142
- if (symbol === undefined) {
3143
- throw new ArgumentsRequired(this.id + ' setMarginMode() requires a symbol argument');
3144
- }
3145
- marginMode = marginMode.toLowerCase();
3146
- if (marginMode === 'cross') {
3147
- marginMode = 'crossed';
3148
- }
3149
- if (marginMode !== 'isolated' && marginMode !== 'crossed') {
3150
- throw new BadRequest(this.id + ' setMarginMode() marginMode argument should be isolated or cross');
3151
- }
3152
- await this.loadMarkets();
3153
- await this.loadAccounts();
3154
- const market = this.market(symbol);
3155
- const account = this.safeDict(this.accounts, 0, {});
3156
- const accountGroup = this.safeString(account, 'id');
3157
- const request = {
3158
- 'account-group': accountGroup,
3159
- 'symbol': market['id'],
3160
- 'marginType': marginMode,
3161
- };
3162
- if (!market['swap']) {
3163
- throw new BadSymbol(this.id + ' setMarginMode() supports swap contracts only');
3164
- }
3165
- return await this.v2PrivateAccountGroupPostFuturesMarginType(this.extend(request, params));
3166
- }
3167
- /**
3168
- * @method
3169
- * @name ascendex#fetchLeverageTiers
3170
- * @description retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
3171
- * @param {string[]|undefined} symbols list of unified market symbols
3172
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3173
- * @returns {object} a dictionary of [leverage tiers structures]{@link https://docs.ccxt.com/?id=leverage-tiers-structure}, indexed by market symbols
3174
- */
3175
- async fetchLeverageTiers(symbols = undefined, params = {}) {
3176
- await this.loadMarkets();
3177
- const response = await this.v2PublicGetFuturesContract(params);
3178
- //
3179
- // {
3180
- // "code":0,
3181
- // "data":[
3182
- // {
3183
- // "symbol":"BTC-PERP",
3184
- // "status":"Normal",
3185
- // "displayName":"BTCUSDT",
3186
- // "settlementAsset":"USDT",
3187
- // "underlying":"BTC/USDT",
3188
- // "tradingStartTime":1579701600000,
3189
- // "priceFilter":{"minPrice":"1","maxPrice":"1000000","tickSize":"1"},
3190
- // "lotSizeFilter":{"minQty":"0.0001","maxQty":"1000000000","lotSize":"0.0001"},
3191
- // "commissionType":"Quote",
3192
- // "commissionReserveRate":"0.001",
3193
- // "marketOrderPriceMarkup":"0.03",
3194
- // "marginRequirements":[
3195
- // {"positionNotionalLowerBound":"0","positionNotionalUpperBound":"50000","initialMarginRate":"0.01","maintenanceMarginRate":"0.006"},
3196
- // {"positionNotionalLowerBound":"50000","positionNotionalUpperBound":"200000","initialMarginRate":"0.02","maintenanceMarginRate":"0.012"},
3197
- // {"positionNotionalLowerBound":"200000","positionNotionalUpperBound":"2000000","initialMarginRate":"0.04","maintenanceMarginRate":"0.024"},
3198
- // {"positionNotionalLowerBound":"2000000","positionNotionalUpperBound":"20000000","initialMarginRate":"0.1","maintenanceMarginRate":"0.06"},
3199
- // {"positionNotionalLowerBound":"20000000","positionNotionalUpperBound":"40000000","initialMarginRate":"0.2","maintenanceMarginRate":"0.12"},
3200
- // {"positionNotionalLowerBound":"40000000","positionNotionalUpperBound":"1000000000","initialMarginRate":"0.333333","maintenanceMarginRate":"0.2"}
3201
- // ]
3202
- // }
3203
- // ]
3204
- // }
3205
- //
3206
- const data = this.safeList(response, 'data', []);
3207
- symbols = this.marketSymbols(symbols);
3208
- return this.parseLeverageTiers(data, symbols, 'symbol');
3209
- }
3210
- parseMarketLeverageTiers(info, market = undefined) {
3211
- /**
3212
- * @param {object} info Exchange market response for 1 market
3213
- * @param {object} market CCXT market
3214
- */
3215
- //
3216
- // {
3217
- // "symbol":"BTC-PERP",
3218
- // "status":"Normal",
3219
- // "displayName":"BTCUSDT",
3220
- // "settlementAsset":"USDT",
3221
- // "underlying":"BTC/USDT",
3222
- // "tradingStartTime":1579701600000,
3223
- // "priceFilter":{"minPrice":"1","maxPrice":"1000000","tickSize":"1"},
3224
- // "lotSizeFilter":{"minQty":"0.0001","maxQty":"1000000000","lotSize":"0.0001"},
3225
- // "commissionType":"Quote",
3226
- // "commissionReserveRate":"0.001",
3227
- // "marketOrderPriceMarkup":"0.03",
3228
- // "marginRequirements":[
3229
- // {"positionNotionalLowerBound":"0","positionNotionalUpperBound":"50000","initialMarginRate":"0.01","maintenanceMarginRate":"0.006"},
3230
- // {"positionNotionalLowerBound":"50000","positionNotionalUpperBound":"200000","initialMarginRate":"0.02","maintenanceMarginRate":"0.012"},
3231
- // {"positionNotionalLowerBound":"200000","positionNotionalUpperBound":"2000000","initialMarginRate":"0.04","maintenanceMarginRate":"0.024"},
3232
- // {"positionNotionalLowerBound":"2000000","positionNotionalUpperBound":"20000000","initialMarginRate":"0.1","maintenanceMarginRate":"0.06"},
3233
- // {"positionNotionalLowerBound":"20000000","positionNotionalUpperBound":"40000000","initialMarginRate":"0.2","maintenanceMarginRate":"0.12"},
3234
- // {"positionNotionalLowerBound":"40000000","positionNotionalUpperBound":"1000000000","initialMarginRate":"0.333333","maintenanceMarginRate":"0.2"}
3235
- // ]
3236
- // }
3237
- //
3238
- const marginRequirements = this.safeList(info, 'marginRequirements', []);
3239
- const marketId = this.safeString(info, 'symbol');
3240
- market = this.safeMarket(marketId, market);
3241
- const tiers = [];
3242
- for (let i = 0; i < marginRequirements.length; i++) {
3243
- const tier = marginRequirements[i];
3244
- const initialMarginRate = this.safeString(tier, 'initialMarginRate');
3245
- tiers.push({
3246
- 'tier': this.sum(i, 1),
3247
- 'symbol': this.safeSymbol(marketId, market, undefined, 'contract'),
3248
- 'currency': market['quote'],
3249
- 'minNotional': this.safeNumber(tier, 'positionNotionalLowerBound'),
3250
- 'maxNotional': this.safeNumber(tier, 'positionNotionalUpperBound'),
3251
- 'maintenanceMarginRate': this.safeNumber(tier, 'maintenanceMarginRate'),
3252
- 'maxLeverage': this.parseNumber(Precise.stringDiv('1', initialMarginRate)),
3253
- 'info': tier,
3254
- });
3255
- }
3256
- return tiers;
3257
- }
3258
- parseDepositWithdrawFee(fee, currency = undefined) {
3259
- //
3260
- // {
3261
- // "assetCode": "USDT",
3262
- // "assetName": "Tether",
3263
- // "precisionScale": 9,
3264
- // "nativeScale": 4,
3265
- // "blockChain": [
3266
- // {
3267
- // "chainName": "Omni",
3268
- // "withdrawFee": "30.0",
3269
- // "allowDeposit": true,
3270
- // "allowWithdraw": true,
3271
- // "minDepositAmt": "0.0",
3272
- // "minWithdrawal": "50.0",
3273
- // "numConfirmations": 3
3274
- // },
3275
- // ]
3276
- // }
3277
- //
3278
- const blockChains = this.safeList(fee, 'blockChain', []);
3279
- const blockChainsLength = blockChains.length;
3280
- const result = {
3281
- 'info': fee,
3282
- 'withdraw': {
3283
- 'fee': undefined,
3284
- 'percentage': undefined,
3285
- },
3286
- 'deposit': {
3287
- 'fee': undefined,
3288
- 'percentage': undefined,
3289
- },
3290
- 'networks': {},
3291
- };
3292
- for (let i = 0; i < blockChainsLength; i++) {
3293
- const blockChain = blockChains[i];
3294
- const networkId = this.safeString(blockChain, 'chainName');
3295
- const currencyCode = this.safeString(currency, 'code');
3296
- const networkCode = this.networkIdToCode(networkId, currencyCode);
3297
- result['networks'][networkCode] = {
3298
- 'deposit': { 'fee': undefined, 'percentage': undefined },
3299
- 'withdraw': { 'fee': this.safeNumber(blockChain, 'withdrawFee'), 'percentage': false },
3300
- };
3301
- if (blockChainsLength === 1) {
3302
- result['withdraw']['fee'] = this.safeNumber(blockChain, 'withdrawFee');
3303
- result['withdraw']['percentage'] = false;
3304
- }
3305
- }
3306
- return result;
3307
- }
3308
- /**
3309
- * @method
3310
- * @name ascendex#fetchDepositWithdrawFees
3311
- * @description fetch deposit and withdraw fees
3312
- * @see https://ascendex.github.io/ascendex-pro-api/#list-all-assets
3313
- * @param {string[]|undefined} codes list of unified currency codes
3314
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3315
- * @returns {object} a list of [fee structures]{@link https://docs.ccxt.com/?id=fee-structure}
3316
- */
3317
- async fetchDepositWithdrawFees(codes = undefined, params = {}) {
3318
- await this.loadMarkets();
3319
- const response = await this.v2PublicGetAssets(params);
3320
- const data = this.safeList(response, 'data');
3321
- return this.parseDepositWithdrawFees(data, codes, 'assetCode');
3322
- }
3323
- /**
3324
- * @method
3325
- * @name ascendex#transfer
3326
- * @description transfer currency internally between wallets on the same account
3327
- * @param {string} code unified currency codeåå
3328
- * @param {float} amount amount to transfer
3329
- * @param {string} fromAccount account to transfer from
3330
- * @param {string} toAccount account to transfer to
3331
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3332
- * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/?id=transfer-structure}
3333
- */
3334
- async transfer(code, amount, fromAccount, toAccount, params = {}) {
3335
- await this.loadMarkets();
3336
- await this.loadAccounts();
3337
- const account = this.safeDict(this.accounts, 0, {});
3338
- const accountGroup = this.safeString(account, 'id');
3339
- const currency = this.currency(code);
3340
- const accountsByType = this.safeDict(this.options, 'accountsByType', {});
3341
- const fromId = this.safeString(accountsByType, fromAccount, fromAccount);
3342
- const toId = this.safeString(accountsByType, toAccount, toAccount);
3343
- if (fromId !== 'cash' && toId !== 'cash') {
3344
- throw new ExchangeError(this.id + ' transfer() only supports direct balance transfer between spot and swap, spot and margin');
3345
- }
3346
- const request = {
3347
- 'account-group': accountGroup,
3348
- 'amount': this.currencyToPrecision(code, amount),
3349
- 'asset': currency['id'],
3350
- 'fromAccount': fromId,
3351
- 'toAccount': toId,
3352
- };
3353
- const response = await this.v1PrivateAccountGroupPostTransfer(this.extend(request, params));
3354
- //
3355
- // { "code": "0" }
3356
- //
3357
- const transferOptions = this.safeDict(this.options, 'transfer', {});
3358
- const fillResponseFromRequest = this.safeBool(transferOptions, 'fillResponseFromRequest', true);
3359
- const transfer = this.parseTransfer(response, currency);
3360
- if (fillResponseFromRequest) {
3361
- transfer['fromAccount'] = fromAccount;
3362
- transfer['toAccount'] = toAccount;
3363
- transfer['amount'] = amount;
3364
- transfer['currency'] = code;
3365
- }
3366
- return transfer;
3367
- }
3368
- parseTransfer(transfer, currency = undefined) {
3369
- //
3370
- // { "code": "0" }
3371
- //
3372
- const status = this.safeString(transfer, 'code');
3373
- const currencyCode = this.safeCurrencyCode(undefined, currency);
3374
- return {
3375
- 'info': transfer,
3376
- 'id': undefined,
3377
- 'timestamp': undefined,
3378
- 'datetime': undefined,
3379
- 'currency': currencyCode,
3380
- 'amount': undefined,
3381
- 'fromAccount': undefined,
3382
- 'toAccount': undefined,
3383
- 'status': this.parseTransferStatus(status),
3384
- };
3385
- }
3386
- parseTransferStatus(status) {
3387
- if (status === '0') {
3388
- return 'ok';
3389
- }
3390
- return 'failed';
3391
- }
3392
- /**
3393
- * @method
3394
- * @name ascendex#fetchFundingHistory
3395
- * @description fetch the history of funding payments paid and received on this account
3396
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#funding-payment-history
3397
- * @param {string} [symbol] unified market symbol
3398
- * @param {int} [since] the earliest time in ms to fetch funding history for
3399
- * @param {int} [limit] the maximum number of funding history structures to retrieve
3400
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3401
- * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3402
- * @returns {object} a [funding history structure]{@link https://docs.ccxt.com/?id=funding-history-structure}
3403
- */
3404
- async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3405
- await this.loadMarkets();
3406
- await this.loadAccounts();
3407
- let paginate = false;
3408
- [paginate, params] = this.handleOptionAndParams(params, 'fetchFundingHistory', 'paginate');
3409
- if (paginate) {
3410
- return await this.fetchPaginatedCallIncremental('fetchFundingHistory', symbol, since, limit, params, 'page', 25);
3411
- }
3412
- const account = this.safeDict(this.accounts, 0, {});
3413
- const accountGroup = this.safeString(account, 'id');
3414
- const request = {
3415
- 'account-group': accountGroup,
3416
- };
3417
- let market = undefined;
3418
- if (symbol !== undefined) {
3419
- market = this.market(symbol);
3420
- request['symbol'] = market['id'];
3421
- }
3422
- if (limit !== undefined) {
3423
- request['pageSize'] = limit;
3424
- }
3425
- const response = await this.v2PrivateAccountGroupGetFuturesFundingPayments(this.extend(request, params));
3426
- //
3427
- // {
3428
- // "code": 0,
3429
- // "data": {
3430
- // "data": [
3431
- // {
3432
- // "timestamp": 1640476800000,
3433
- // "symbol": "BTC-PERP",
3434
- // "paymentInUSDT": "-0.013991178",
3435
- // "fundingRate": "0.000173497"
3436
- // },
3437
- // ],
3438
- // "page": 1,
3439
- // "pageSize": 3,
3440
- // "hasNext": true
3441
- // }
3442
- // }
3443
- //
3444
- const data = this.safeDict(response, 'data', {});
3445
- const rows = this.safeList(data, 'data', []);
3446
- return this.parseIncomes(rows, market, since, limit);
3447
- }
3448
- parseIncome(income, market = undefined) {
3449
- //
3450
- // {
3451
- // "timestamp": 1640476800000,
3452
- // "symbol": "BTC-PERP",
3453
- // "paymentInUSDT": "-0.013991178",
3454
- // "fundingRate": "0.000173497"
3455
- // }
3456
- //
3457
- const marketId = this.safeString(income, 'symbol');
3458
- const timestamp = this.safeInteger(income, 'timestamp');
3459
- return {
3460
- 'info': income,
3461
- 'symbol': this.safeSymbol(marketId, market, '-', 'swap'),
3462
- 'code': 'USDT',
3463
- 'timestamp': timestamp,
3464
- 'datetime': this.iso8601(timestamp),
3465
- 'id': undefined,
3466
- 'amount': this.safeNumber(income, 'paymentInUSDT'),
3467
- };
3468
- }
3469
- /**
3470
- * @method
3471
- * @name ascendex#fetchMarginModes
3472
- * @description fetches the set margin mode of the user
3473
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#position
3474
- * @param {string[]} [symbols] a list of unified market symbols
3475
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3476
- * @returns {object} a list of [margin mode structures]{@link https://docs.ccxt.com/?id=margin-mode-structure}
3477
- */
3478
- async fetchMarginModes(symbols = undefined, params = {}) {
3479
- await this.loadMarkets();
3480
- await this.loadAccounts();
3481
- const account = this.safeDict(this.accounts, 0, {});
3482
- const accountGroup = this.safeString(account, 'id');
3483
- const request = {
3484
- 'account-group': accountGroup,
3485
- };
3486
- const response = await this.v2PrivateAccountGroupGetFuturesPosition(this.extend(request, params));
3487
- //
3488
- // {
3489
- // "code": 0,
3490
- // "data": {
3491
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
3492
- // "ac": "FUTURES",
3493
- // "collaterals": [
3494
- // {
3495
- // "asset": "USDT",
3496
- // "balance": "44.570287262",
3497
- // "referencePrice": "1",
3498
- // "discountFactor": "1"
3499
- // }
3500
- // ],
3501
- // "contracts": [
3502
- // {
3503
- // "symbol": "BTC-PERP",
3504
- // "side": "LONG",
3505
- // "position": "0.0001",
3506
- // "referenceCost": "-3.12277254",
3507
- // "unrealizedPnl": "-0.001700233",
3508
- // "realizedPnl": "0",
3509
- // "avgOpenPrice": "31209",
3510
- // "marginType": "isolated",
3511
- // "isolatedMargin": "1.654972977",
3512
- // "leverage": "2",
3513
- // "takeProfitPrice": "0",
3514
- // "takeProfitTrigger": "market",
3515
- // "stopLossPrice": "0",
3516
- // "stopLossTrigger": "market",
3517
- // "buyOpenOrderNotional": "0",
3518
- // "sellOpenOrderNotional": "0",
3519
- // "markPrice": "31210.723063672",
3520
- // "indexPrice": "31223.148857925"
3521
- // },
3522
- // ]
3523
- // }
3524
- // }
3525
- //
3526
- const data = this.safeDict(response, 'data', {});
3527
- const marginModes = this.safeList(data, 'contracts', []);
3528
- return this.parseMarginModes(marginModes, symbols, 'symbol');
3529
- }
3530
- parseMarginMode(marginMode, market = undefined) {
3531
- const marketId = this.safeString(marginMode, 'symbol');
3532
- const marginType = this.safeString(marginMode, 'marginType');
3533
- const margin = (marginType === 'crossed') ? 'cross' : 'isolated';
3534
- return {
3535
- 'info': marginMode,
3536
- 'symbol': this.safeSymbol(marketId, market),
3537
- 'marginMode': margin,
3538
- };
3539
- }
3540
- /**
3541
- * @method
3542
- * @name ascendex#fetchLeverages
3543
- * @description fetch the set leverage for all contract markets
3544
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#position
3545
- * @param {string[]} [symbols] a list of unified market symbols
3546
- * @param {object} [params] extra parameters specific to the exchange API endpoint
3547
- * @returns {object} a list of [leverage structures]{@link https://docs.ccxt.com/?id=leverage-structure}
3548
- */
3549
- async fetchLeverages(symbols = undefined, params = {}) {
3550
- await this.loadMarkets();
3551
- await this.loadAccounts();
3552
- const account = this.safeDict(this.accounts, 0, {});
3553
- const accountGroup = this.safeString(account, 'id');
3554
- const request = {
3555
- 'account-group': accountGroup,
3556
- };
3557
- const response = await this.v2PrivateAccountGroupGetFuturesPosition(this.extend(request, params));
3558
- //
3559
- // {
3560
- // "code": 0,
3561
- // "data": {
3562
- // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
3563
- // "ac": "FUTURES",
3564
- // "collaterals": [
3565
- // {
3566
- // "asset": "USDT",
3567
- // "balance": "44.570287262",
3568
- // "referencePrice": "1",
3569
- // "discountFactor": "1"
3570
- // }
3571
- // ],
3572
- // "contracts": [
3573
- // {
3574
- // "symbol": "BTC-PERP",
3575
- // "side": "LONG",
3576
- // "position": "0.0001",
3577
- // "referenceCost": "-3.12277254",
3578
- // "unrealizedPnl": "-0.001700233",
3579
- // "realizedPnl": "0",
3580
- // "avgOpenPrice": "31209",
3581
- // "marginType": "isolated",
3582
- // "isolatedMargin": "1.654972977",
3583
- // "leverage": "2",
3584
- // "takeProfitPrice": "0",
3585
- // "takeProfitTrigger": "market",
3586
- // "stopLossPrice": "0",
3587
- // "stopLossTrigger": "market",
3588
- // "buyOpenOrderNotional": "0",
3589
- // "sellOpenOrderNotional": "0",
3590
- // "markPrice": "31210.723063672",
3591
- // "indexPrice": "31223.148857925"
3592
- // },
3593
- // ]
3594
- // }
3595
- // }
3596
- //
3597
- const data = this.safeDict(response, 'data', {});
3598
- const leverages = this.safeList(data, 'contracts', []);
3599
- return this.parseLeverages(leverages, symbols, 'symbol');
3600
- }
3601
- /**
3602
- * @method
3603
- * @name ascendex#fetchOpenInterests
3604
- * @description Retrieves the open interest for a list of symbols
3605
- * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#futures-pricing-data
3606
- * @param {string[]} [symbols] a list of unified CCXT market symbols
3607
- * @param {object} [params] exchange specific parameters
3608
- * @returns {object[]} a list of [open interest structures]{@link https://docs.ccxt.com/?id=open-interest-structure}
3609
- */
3610
- async fetchOpenInterests(symbols = undefined, params = {}) {
3611
- await this.loadMarkets();
3612
- const request = {};
3613
- const response = await this.v2PublicGetFuturesPricingData(this.extend(request, params));
3614
- //
3615
- // {
3616
- // code: '0',
3617
- // data: {
3618
- // contracts: [
3619
- // {
3620
- // time: '1772138885616',
3621
- // symbol: 'ZIL-PERP',
3622
- // markPrice: '0.004167783',
3623
- // indexPrice: '0.004168',
3624
- // lastPrice: '0.00416',
3625
- // openInterest: '7685003',
3626
- // fundingRate: '0.0003',
3627
- // nextFundingTime: '1772139600000'
3628
- // },
3629
- // ]
3630
- // collaterals: [
3631
- // { asset: 'TAO', referencePrice: '182.15' },
3632
- // ...
3633
- // ]
3634
- // }
3635
- // }
3636
- //
3637
- symbols = this.marketSymbols(symbols);
3638
- const data = this.safeDict(response, 'data', {});
3639
- const contracts = this.safeList(data, 'contracts', []);
3640
- return this.parseOpenInterests(contracts, symbols);
3641
- }
3642
- parseOpenInterest(interest, market = undefined) {
3643
- //
3644
- // fetchOpenInterests
3645
- //
3646
- // {
3647
- // time: '1772138885616',
3648
- // symbol: 'ZIL-PERP',
3649
- // markPrice: '0.004167783',
3650
- // indexPrice: '0.004168',
3651
- // lastPrice: '0.00416',
3652
- // openInterest: '7685003',
3653
- // fundingRate: '0.0003',
3654
- // nextFundingTime: '1772139600000'
3655
- // }
3656
- //
3657
- const marketId = this.safeString(interest, 'symbol');
3658
- const timestamp = this.safeInteger(interest, 'time');
3659
- const openInterest = this.safeNumber(interest, 'openInterest');
3660
- return this.safeOpenInterest({
3661
- 'info': interest,
3662
- 'symbol': this.safeSymbol(marketId, market, undefined, 'swap'),
3663
- 'baseVolume': openInterest, // deprecated
3664
- 'quoteVolume': undefined, // deprecated
3665
- 'openInterestAmount': openInterest,
3666
- 'openInterestValue': undefined,
3667
- 'timestamp': timestamp,
3668
- 'datetime': this.iso8601(timestamp),
3669
- }, market);
3670
- }
3671
- parseLeverage(leverage, market = undefined) {
3672
- const marketId = this.safeString(leverage, 'symbol');
3673
- const leverageValue = this.safeInteger(leverage, 'leverage');
3674
- const marginType = this.safeString(leverage, 'marginType');
3675
- const marginMode = (marginType === 'crossed') ? 'cross' : 'isolated';
3676
- return {
3677
- 'info': leverage,
3678
- 'symbol': this.safeSymbol(marketId, market),
3679
- 'marginMode': marginMode,
3680
- 'longLeverage': leverageValue,
3681
- 'shortLeverage': leverageValue,
3682
- };
3683
- }
3684
- sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
3685
- const version = api[0];
3686
- const access = api[1];
3687
- const type = this.safeString(api, 2);
3688
- let url = '';
3689
- const accountCategory = (type === 'accountCategory');
3690
- if (accountCategory || (type === 'accountGroup')) {
3691
- url += this.implodeParams('/{account-group}', params);
3692
- params = this.omit(params, 'account-group');
3693
- }
3694
- let request = this.implodeParams(path, params);
3695
- url += '/api/pro/';
3696
- if (version === 'v2') {
3697
- if (type === 'data') {
3698
- request = 'data/' + version + '/' + request;
3699
- }
3700
- else {
3701
- request = version + '/' + request;
3702
- }
3703
- }
3704
- else {
3705
- url += version + '/';
3706
- }
3707
- if (accountCategory) {
3708
- url += this.implodeParams('{account-category}/', params);
3709
- }
3710
- params = this.omit(params, 'account-category');
3711
- url += request;
3712
- if ((version === 'v1') && (request === 'cash/balance') || (request === 'margin/balance')) {
3713
- request = 'balance';
3714
- }
3715
- if ((version === 'v1') && (request === 'spot/fee')) {
3716
- request = 'fee';
3717
- }
3718
- if (request.indexOf('subuser') >= 0) {
3719
- const parts = request.split('/');
3720
- request = parts[2];
3721
- }
3722
- params = this.omit(params, this.extractParams(path));
3723
- if (access === 'public') {
3724
- if (Object.keys(params).length) {
3725
- url += '?' + this.urlencode(params);
3726
- }
3727
- }
3728
- else {
3729
- this.checkRequiredCredentials();
3730
- const timestamp = this.milliseconds().toString();
3731
- const payload = timestamp + '+' + request;
3732
- const hmac = this.hmac(this.encode(payload), this.encode(this.secret), sha256, 'base64');
3733
- headers = {
3734
- 'x-auth-key': this.apiKey,
3735
- 'x-auth-timestamp': timestamp,
3736
- 'x-auth-signature': hmac,
3737
- };
3738
- if (method === 'GET') {
3739
- if (Object.keys(params).length) {
3740
- url += '?' + this.urlencode(params);
3741
- }
3742
- }
3743
- else {
3744
- headers['Content-Type'] = 'application/json';
3745
- body = this.json(params);
3746
- }
3747
- }
3748
- url = this.urls['api']['rest'] + url;
3749
- return { 'url': url, 'method': method, 'body': body, 'headers': headers };
3750
- }
3751
- handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
3752
- if (response === undefined) {
3753
- return undefined; // fallback to default error handler
3754
- }
3755
- //
3756
- // {"code": 6010, "message": "Not enough balance."}
3757
- // {"code": 60060, "message": "The order is already filled or canceled."}
3758
- // {"code":2100,"message":"ApiKeyFailure"}
3759
- // {"code":300001,"message":"Price is too low from market price.","reason":"INVALID_PRICE","accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda","ac":"CASH","action":"place-order","status":"Err","info":{"symbol":"BTC/USDT"}}
3760
- //
3761
- const code = this.safeString(response, 'code');
3762
- const message = this.safeString(response, 'message');
3763
- const error = (code !== undefined) && (code !== '0');
3764
- if (error || (message !== undefined)) {
3765
- const feedback = this.id + ' ' + body;
3766
- this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
3767
- this.throwExactlyMatchedException(this.exceptions['exact'], message, feedback);
3768
- this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
3769
- throw new ExchangeError(feedback); // unknown message
3770
- }
3771
- return undefined;
3772
- }
3773
- }