ccxt 4.3.42 → 4.3.44

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 (52) hide show
  1. package/README.md +9 -7
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +4 -1
  4. package/dist/cjs/src/binance.js +169 -44
  5. package/dist/cjs/src/btcmarkets.js +31 -2
  6. package/dist/cjs/src/coinex.js +106 -107
  7. package/dist/cjs/src/lykke.js +10 -2
  8. package/dist/cjs/src/ndax.js +5 -1
  9. package/dist/cjs/src/phemex.js +5 -4
  10. package/dist/cjs/src/poloniexfutures.js +2 -2
  11. package/dist/cjs/src/pro/bitget.js +28 -21
  12. package/dist/cjs/src/pro/bitmex.js +9 -0
  13. package/dist/cjs/src/pro/bybit.js +1 -1
  14. package/dist/cjs/src/pro/mexc.js +1 -1
  15. package/dist/cjs/src/pro/woo.js +1 -1
  16. package/dist/cjs/src/tradeogre.js +11 -5
  17. package/dist/cjs/src/wavesexchange.js +2 -2
  18. package/dist/cjs/src/wazirx.js +38 -15
  19. package/dist/cjs/src/xt.js +134 -95
  20. package/dist/cjs/src/zonda.js +9 -1
  21. package/js/ccxt.d.ts +6 -3
  22. package/js/ccxt.js +4 -2
  23. package/js/src/abstract/coinex.d.ts +2 -1
  24. package/js/src/abstract/xt.d.ts +155 -0
  25. package/js/src/abstract/xt.js +11 -0
  26. package/js/src/binance.js +169 -44
  27. package/js/src/btcmarkets.d.ts +2 -2
  28. package/js/src/btcmarkets.js +31 -2
  29. package/js/src/coinex.js +106 -107
  30. package/js/src/lykke.d.ts +2 -2
  31. package/js/src/lykke.js +10 -2
  32. package/js/src/ndax.d.ts +1 -1
  33. package/js/src/ndax.js +5 -1
  34. package/js/src/phemex.js +6 -5
  35. package/js/src/poloniexfutures.js +2 -2
  36. package/js/src/pro/bitget.js +28 -21
  37. package/js/src/pro/bitmex.js +9 -0
  38. package/js/src/pro/bybit.js +1 -1
  39. package/js/src/pro/mexc.js +1 -1
  40. package/js/src/pro/woo.js +1 -1
  41. package/js/src/static_dependencies/jsencrypt/lib/jsbn/jsbn.d.ts +1 -1
  42. package/js/src/tradeogre.d.ts +1 -1
  43. package/js/src/tradeogre.js +12 -6
  44. package/js/src/wavesexchange.d.ts +1 -20
  45. package/js/src/wavesexchange.js +2 -2
  46. package/js/src/wazirx.d.ts +1 -1
  47. package/js/src/wazirx.js +38 -15
  48. package/js/src/xt.d.ts +161 -0
  49. package/js/src/xt.js +4761 -0
  50. package/js/src/zonda.d.ts +1 -1
  51. package/js/src/zonda.js +9 -1
  52. package/package.json +1 -1
package/js/src/xt.js ADDED
@@ -0,0 +1,4761 @@
1
+ // ----------------------------------------------------------------------------
2
+
3
+ // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+ // EDIT THE CORRESPONDENT .ts FILE INSTEAD
6
+
7
+ // ---------------------------------------------------------------------------
8
+ import Exchange from './abstract/xt.js';
9
+ import { Precise } from './base/Precise.js';
10
+ import { TICK_SIZE } from './base/functions/number.js';
11
+ import { ArgumentsRequired, AuthenticationError, BadRequest, BadSymbol, ExchangeError, InsufficientFunds, InvalidOrder, NetworkError, NotSupported, OnMaintenance, PermissionDenied, RateLimitExceeded, RequestTimeout } from './base/errors.js';
12
+ import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
13
+ // ---------------------------------------------------------------------------
14
+ export default class xt extends Exchange {
15
+ describe() {
16
+ return this.deepExtend(super.describe(), {
17
+ 'id': 'xt',
18
+ 'name': 'XT',
19
+ 'countries': ['SC'],
20
+ // spot api ratelimits are undefined, 10/s/ip, 50/s/ip, 100/s/ip or 200/s/ip
21
+ // futures 3 requests per second => 1000ms / (100 * 3.33) = 3.003 (get assets -> fetchMarkets & fetchCurrencies)
22
+ // futures 10 requests per second => 1000ms / (100 * 1) = 10 (all other)
23
+ // futures 1000 times per minute for each single IP -> Otherwise account locked for 10min
24
+ 'rateLimit': 100,
25
+ 'version': 'v4',
26
+ 'certified': true,
27
+ 'pro': false,
28
+ 'has': {
29
+ 'CORS': false,
30
+ 'spot': true,
31
+ 'margin': true,
32
+ 'swap': true,
33
+ 'future': true,
34
+ 'option': false,
35
+ 'addMargin': true,
36
+ 'borrowMargin': false,
37
+ 'cancelAllOrders': true,
38
+ 'cancelOrder': true,
39
+ 'cancelOrders': true,
40
+ 'createDepositAddress': false,
41
+ 'createMarketBuyOrderWithCost': true,
42
+ 'createMarketSellOrderWithCost': false,
43
+ 'createOrder': true,
44
+ 'createPostOnlyOrder': false,
45
+ 'createReduceOnlyOrder': true,
46
+ 'editOrder': false,
47
+ 'fetchAccounts': false,
48
+ 'fetchBalance': true,
49
+ 'fetchBidsAsks': true,
50
+ 'fetchBorrowInterest': false,
51
+ 'fetchBorrowRate': false,
52
+ 'fetchBorrowRateHistories': false,
53
+ 'fetchBorrowRateHistory': false,
54
+ 'fetchBorrowRatesPerSymbol': false,
55
+ 'fetchCanceledOrders': true,
56
+ 'fetchClosedOrders': true,
57
+ 'fetchCurrencies': true,
58
+ 'fetchDeposit': false,
59
+ 'fetchDepositAddress': true,
60
+ 'fetchDeposits': true,
61
+ 'fetchDepositWithdrawals': false,
62
+ 'fetchDepositWithdrawFee': false,
63
+ 'fetchDepositWithdrawFees': false,
64
+ 'fetchFundingHistory': true,
65
+ 'fetchFundingRate': true,
66
+ 'fetchFundingRateHistory': true,
67
+ 'fetchFundingRates': false,
68
+ 'fetchIndexOHLCV': false,
69
+ 'fetchL3OrderBook': false,
70
+ 'fetchLedger': true,
71
+ 'fetchLedgerEntry': false,
72
+ 'fetchLeverage': false,
73
+ 'fetchLeverageTiers': true,
74
+ 'fetchMarketLeverageTiers': true,
75
+ 'fetchMarkets': true,
76
+ 'fetchMarkOHLCV': false,
77
+ 'fetchMyTrades': true,
78
+ 'fetchOHLCV': true,
79
+ 'fetchOpenInterest': false,
80
+ 'fetchOpenInterestHistory': false,
81
+ 'fetchOpenOrders': true,
82
+ 'fetchOrder': true,
83
+ 'fetchOrderBook': true,
84
+ 'fetchOrderBooks': false,
85
+ 'fetchOrders': true,
86
+ 'fetchOrdersByStatus': true,
87
+ 'fetchOrderTrades': false,
88
+ 'fetchPosition': true,
89
+ 'fetchPositions': true,
90
+ 'fetchPremiumIndexOHLCV': false,
91
+ 'fetchSettlementHistory': false,
92
+ 'fetchStatus': false,
93
+ 'fetchTicker': true,
94
+ 'fetchTickers': true,
95
+ 'fetchTime': true,
96
+ 'fetchTrades': true,
97
+ 'fetchTradingFee': false,
98
+ 'fetchTradingFees': false,
99
+ 'fetchTradingLimits': false,
100
+ 'fetchTransactionFee': false,
101
+ 'fetchTransactionFees': false,
102
+ 'fetchTransactions': false,
103
+ 'fetchTransfer': false,
104
+ 'fetchTransfers': false,
105
+ 'fetchWithdrawal': false,
106
+ 'fetchWithdrawals': true,
107
+ 'fetchWithdrawalWhitelist': false,
108
+ 'reduceMargin': true,
109
+ 'repayMargin': false,
110
+ 'setLeverage': true,
111
+ 'setMargin': false,
112
+ 'setMarginMode': false,
113
+ 'setPositionMode': false,
114
+ 'signIn': false,
115
+ 'transfer': true,
116
+ 'withdraw': true,
117
+ },
118
+ 'precisionMode': TICK_SIZE,
119
+ 'urls': {
120
+ 'logo': 'https://user-images.githubusercontent.com/14319357/232636712-466df2fc-560a-4ca4-aab2-b1d954a58e24.jpg',
121
+ 'api': {
122
+ 'spot': 'https://sapi.xt.com',
123
+ 'linear': 'https://fapi.xt.com',
124
+ 'inverse': 'https://dapi.xt.com',
125
+ 'user': 'https://api.xt.com',
126
+ },
127
+ 'www': 'https://xt.com',
128
+ 'referral': 'https://www.xt.com/en/accounts/register?ref=9PTM9VW',
129
+ 'doc': [
130
+ 'https://doc.xt.com/',
131
+ 'https://github.com/xtpub/api-doc',
132
+ ],
133
+ 'fees': 'https://www.xt.com/en/rate',
134
+ },
135
+ 'api': {
136
+ 'public': {
137
+ 'spot': {
138
+ 'get': {
139
+ 'currencies': 1,
140
+ 'depth': 0.05,
141
+ 'kline': 0.1,
142
+ 'symbol': 1,
143
+ 'ticker': 1,
144
+ 'ticker/book': 1,
145
+ 'ticker/price': 1,
146
+ 'ticker/24h': 1,
147
+ 'time': 1,
148
+ 'trade/history': 0.1,
149
+ 'trade/recent': 0.1,
150
+ 'wallet/support/currency': 1,
151
+ },
152
+ },
153
+ 'linear': {
154
+ 'get': {
155
+ 'future/market/v1/public/contract/risk-balance': 1,
156
+ 'future/market/v1/public/contract/open-interest': 1,
157
+ 'future/market/v1/public/leverage/bracket/detail': 1,
158
+ 'future/market/v1/public/leverage/bracket/list': 1,
159
+ 'future/market/v1/public/q/agg-ticker': 1,
160
+ 'future/market/v1/public/q/agg-tickers': 1,
161
+ 'future/market/v1/public/q/deal': 1,
162
+ 'future/market/v1/public/q/depth': 1,
163
+ 'future/market/v1/public/q/funding-rate': 1,
164
+ 'future/market/v1/public/q/funding-rate-record': 1,
165
+ 'future/market/v1/public/q/index-price': 1,
166
+ 'future/market/v1/public/q/kline': 1,
167
+ 'future/market/v1/public/q/mark-price': 1,
168
+ 'future/market/v1/public/q/symbol-index-price': 1,
169
+ 'future/market/v1/public/q/symbol-mark-price': 1,
170
+ 'future/market/v1/public/q/ticker': 1,
171
+ 'future/market/v1/public/q/tickers': 1,
172
+ 'future/market/v1/public/symbol/coins': 3.33,
173
+ 'future/market/v1/public/symbol/detail': 3.33,
174
+ 'future/market/v1/public/symbol/list': 1,
175
+ },
176
+ },
177
+ 'inverse': {
178
+ 'get': {
179
+ 'future/market/v1/public/contract/risk-balance': 1,
180
+ 'future/market/v1/public/contract/open-interest': 1,
181
+ 'future/market/v1/public/leverage/bracket/detail': 1,
182
+ 'future/market/v1/public/leverage/bracket/list': 1,
183
+ 'future/market/v1/public/q/agg-ticker': 1,
184
+ 'future/market/v1/public/q/agg-tickers': 1,
185
+ 'future/market/v1/public/q/deal': 1,
186
+ 'future/market/v1/public/q/depth': 1,
187
+ 'future/market/v1/public/q/funding-rate': 1,
188
+ 'future/market/v1/public/q/funding-rate-record': 1,
189
+ 'future/market/v1/public/q/index-price': 1,
190
+ 'future/market/v1/public/q/kline': 1,
191
+ 'future/market/v1/public/q/mark-price': 1,
192
+ 'future/market/v1/public/q/symbol-index-price': 1,
193
+ 'future/market/v1/public/q/symbol-mark-price': 1,
194
+ 'future/market/v1/public/q/ticker': 1,
195
+ 'future/market/v1/public/q/tickers': 1,
196
+ 'future/market/v1/public/symbol/coins': 3.33,
197
+ 'future/market/v1/public/symbol/detail': 3.33,
198
+ 'future/market/v1/public/symbol/list': 1,
199
+ },
200
+ },
201
+ },
202
+ 'private': {
203
+ 'spot': {
204
+ 'get': {
205
+ 'balance': 1,
206
+ 'balances': 1,
207
+ 'batch-order': 1,
208
+ 'deposit/address': 1,
209
+ 'deposit/history': 1,
210
+ 'history-order': 1,
211
+ 'open-order': 1,
212
+ 'order': 1,
213
+ 'order/{orderId}': 1,
214
+ 'trade': 1,
215
+ 'withdraw/history': 1,
216
+ },
217
+ 'post': {
218
+ 'order': 0.2,
219
+ 'withdraw': 1,
220
+ 'balance/transfer': 1,
221
+ 'balance/account/transfer': 1,
222
+ },
223
+ 'delete': {
224
+ 'batch-order': 1,
225
+ 'open-order': 1,
226
+ 'order/{orderId}': 1,
227
+ },
228
+ },
229
+ 'linear': {
230
+ 'get': {
231
+ 'future/trade/v1/entrust/plan-detail': 1,
232
+ 'future/trade/v1/entrust/plan-list': 1,
233
+ 'future/trade/v1/entrust/plan-list-history': 1,
234
+ 'future/trade/v1/entrust/profit-detail': 1,
235
+ 'future/trade/v1/entrust/profit-list': 1,
236
+ 'future/trade/v1/order/detail': 1,
237
+ 'future/trade/v1/order/list': 1,
238
+ 'future/trade/v1/order/list-history': 1,
239
+ 'future/trade/v1/order/trade-list': 1,
240
+ 'future/user/v1/account/info': 1,
241
+ 'future/user/v1/balance/bills': 1,
242
+ 'future/user/v1/balance/detail': 1,
243
+ 'future/user/v1/balance/funding-rate-list': 1,
244
+ 'future/user/v1/balance/list': 1,
245
+ 'future/user/v1/position/adl': 1,
246
+ 'future/user/v1/position/list': 1,
247
+ 'future/user/v1/user/collection/list': 1,
248
+ 'future/user/v1/user/listen-key': 1,
249
+ },
250
+ 'post': {
251
+ 'future/trade/v1/entrust/cancel-all-plan': 1,
252
+ 'future/trade/v1/entrust/cancel-all-profit-stop': 1,
253
+ 'future/trade/v1/entrust/cancel-plan': 1,
254
+ 'future/trade/v1/entrust/cancel-profit-stop': 1,
255
+ 'future/trade/v1/entrust/create-plan': 1,
256
+ 'future/trade/v1/entrust/create-profit': 1,
257
+ 'future/trade/v1/entrust/update-profit-stop': 1,
258
+ 'future/trade/v1/order/cancel': 1,
259
+ 'future/trade/v1/order/cancel-all': 1,
260
+ 'future/trade/v1/order/create': 1,
261
+ 'future/trade/v1/order/create-batch': 1,
262
+ 'future/user/v1/account/open': 1,
263
+ 'future/user/v1/position/adjust-leverage': 1,
264
+ 'future/user/v1/position/auto-margin': 1,
265
+ 'future/user/v1/position/close-all': 1,
266
+ 'future/user/v1/position/margin': 1,
267
+ 'future/user/v1/user/collection/add': 1,
268
+ 'future/user/v1/user/collection/cancel': 1,
269
+ },
270
+ },
271
+ 'inverse': {
272
+ 'get': {
273
+ 'future/trade/v1/entrust/plan-detail': 1,
274
+ 'future/trade/v1/entrust/plan-list': 1,
275
+ 'future/trade/v1/entrust/plan-list-history': 1,
276
+ 'future/trade/v1/entrust/profit-detail': 1,
277
+ 'future/trade/v1/entrust/profit-list': 1,
278
+ 'future/trade/v1/order/detail': 1,
279
+ 'future/trade/v1/order/list': 1,
280
+ 'future/trade/v1/order/list-history': 1,
281
+ 'future/trade/v1/order/trade-list': 1,
282
+ 'future/user/v1/account/info': 1,
283
+ 'future/user/v1/balance/bills': 1,
284
+ 'future/user/v1/balance/detail': 1,
285
+ 'future/user/v1/balance/funding-rate-list': 1,
286
+ 'future/user/v1/balance/list': 1,
287
+ 'future/user/v1/position/adl': 1,
288
+ 'future/user/v1/position/list': 1,
289
+ 'future/user/v1/user/collection/list': 1,
290
+ 'future/user/v1/user/listen-key': 1,
291
+ },
292
+ 'post': {
293
+ 'future/trade/v1/entrust/cancel-all-plan': 1,
294
+ 'future/trade/v1/entrust/cancel-all-profit-stop': 1,
295
+ 'future/trade/v1/entrust/cancel-plan': 1,
296
+ 'future/trade/v1/entrust/cancel-profit-stop': 1,
297
+ 'future/trade/v1/entrust/create-plan': 1,
298
+ 'future/trade/v1/entrust/create-profit': 1,
299
+ 'future/trade/v1/entrust/update-profit-stop': 1,
300
+ 'future/trade/v1/order/cancel': 1,
301
+ 'future/trade/v1/order/cancel-all': 1,
302
+ 'future/trade/v1/order/create': 1,
303
+ 'future/trade/v1/order/create-batch': 1,
304
+ 'future/user/v1/account/open': 1,
305
+ 'future/user/v1/position/adjust-leverage': 1,
306
+ 'future/user/v1/position/auto-margin': 1,
307
+ 'future/user/v1/position/close-all': 1,
308
+ 'future/user/v1/position/margin': 1,
309
+ 'future/user/v1/user/collection/add': 1,
310
+ 'future/user/v1/user/collection/cancel': 1,
311
+ },
312
+ },
313
+ 'user': {
314
+ 'get': {
315
+ 'user/account': 1,
316
+ 'user/account/api-key': 1,
317
+ },
318
+ 'post': {
319
+ 'user/account': 1,
320
+ 'user/account/api-key': 1,
321
+ },
322
+ 'put': {
323
+ 'user/account/api-key': 1,
324
+ },
325
+ 'delete': {
326
+ 'user/account/{apikeyId}': 1,
327
+ },
328
+ },
329
+ },
330
+ },
331
+ 'fees': {
332
+ 'spot': {
333
+ 'tierBased': true,
334
+ 'percentage': true,
335
+ 'maker': this.parseNumber('0.002'),
336
+ 'taker': this.parseNumber('0.002'),
337
+ 'tiers': {
338
+ 'maker': [
339
+ [this.parseNumber('0'), this.parseNumber('0.002')],
340
+ [this.parseNumber('5000'), this.parseNumber('0.0018')],
341
+ [this.parseNumber('10000'), this.parseNumber('0.0016')],
342
+ [this.parseNumber('20000'), this.parseNumber('0.0014')],
343
+ [this.parseNumber('50000'), this.parseNumber('0.0012')],
344
+ [this.parseNumber('150000'), this.parseNumber('0.0010')],
345
+ [this.parseNumber('300000'), this.parseNumber('0.0008')],
346
+ [this.parseNumber('600000'), this.parseNumber('0.0007')],
347
+ [this.parseNumber('1200000'), this.parseNumber('0.0006')],
348
+ [this.parseNumber('2500000'), this.parseNumber('0.0005')],
349
+ [this.parseNumber('6000000'), this.parseNumber('0.0004')],
350
+ [this.parseNumber('15000000'), this.parseNumber('0.0003')],
351
+ [this.parseNumber('30000000'), this.parseNumber('0.0002')],
352
+ ],
353
+ 'taker': [
354
+ [this.parseNumber('0'), this.parseNumber('0.002')],
355
+ [this.parseNumber('5000'), this.parseNumber('0.0018')],
356
+ [this.parseNumber('10000'), this.parseNumber('0.0016')],
357
+ [this.parseNumber('20000'), this.parseNumber('0.0014')],
358
+ [this.parseNumber('50000'), this.parseNumber('0.0012')],
359
+ [this.parseNumber('150000'), this.parseNumber('0.0010')],
360
+ [this.parseNumber('300000'), this.parseNumber('0.0008')],
361
+ [this.parseNumber('600000'), this.parseNumber('0.0007')],
362
+ [this.parseNumber('1200000'), this.parseNumber('0.0006')],
363
+ [this.parseNumber('2500000'), this.parseNumber('0.0005')],
364
+ [this.parseNumber('6000000'), this.parseNumber('0.0004')],
365
+ [this.parseNumber('15000000'), this.parseNumber('0.0003')],
366
+ [this.parseNumber('30000000'), this.parseNumber('0.0002')],
367
+ ],
368
+ },
369
+ },
370
+ 'contract': {
371
+ 'tierBased': true,
372
+ 'percentage': true,
373
+ 'maker': this.parseNumber('0.0004'),
374
+ 'taker': this.parseNumber('0.0006'),
375
+ 'tiers': {
376
+ 'maker': [
377
+ [this.parseNumber('0'), this.parseNumber('0.0004')],
378
+ [this.parseNumber('200000'), this.parseNumber('0.00038')],
379
+ [this.parseNumber('1000000'), this.parseNumber('0.00036')],
380
+ [this.parseNumber('5000000'), this.parseNumber('0.00034')],
381
+ [this.parseNumber('10000000'), this.parseNumber('0.00032')],
382
+ [this.parseNumber('15000000'), this.parseNumber('0.00028')],
383
+ [this.parseNumber('30000000'), this.parseNumber('0.00024')],
384
+ [this.parseNumber('50000000'), this.parseNumber('0.0002')],
385
+ [this.parseNumber('100000000'), this.parseNumber('0.00016')],
386
+ [this.parseNumber('300000000'), this.parseNumber('0.00012')],
387
+ [this.parseNumber('500000000'), this.parseNumber('0.00008')],
388
+ ],
389
+ 'taker': [
390
+ [this.parseNumber('0'), this.parseNumber('0.0006')],
391
+ [this.parseNumber('200000'), this.parseNumber('0.000588')],
392
+ [this.parseNumber('1000000'), this.parseNumber('0.00057')],
393
+ [this.parseNumber('5000000'), this.parseNumber('0.00054')],
394
+ [this.parseNumber('10000000'), this.parseNumber('0.00051')],
395
+ [this.parseNumber('15000000'), this.parseNumber('0.00048')],
396
+ [this.parseNumber('30000000'), this.parseNumber('0.00045')],
397
+ [this.parseNumber('50000000'), this.parseNumber('0.00045')],
398
+ [this.parseNumber('100000000'), this.parseNumber('0.00036')],
399
+ [this.parseNumber('300000000'), this.parseNumber('0.00033')],
400
+ [this.parseNumber('500000000'), this.parseNumber('0.0003')],
401
+ ],
402
+ },
403
+ },
404
+ },
405
+ 'exceptions': {
406
+ 'exact': {
407
+ '400': NetworkError,
408
+ '404': ExchangeError,
409
+ '429': RateLimitExceeded,
410
+ '500': ExchangeError,
411
+ '502': ExchangeError,
412
+ '503': OnMaintenance,
413
+ 'AUTH_001': AuthenticationError,
414
+ 'AUTH_002': AuthenticationError,
415
+ 'AUTH_003': AuthenticationError,
416
+ 'AUTH_004': AuthenticationError,
417
+ 'AUTH_005': AuthenticationError,
418
+ 'AUTH_006': AuthenticationError,
419
+ 'AUTH_007': AuthenticationError,
420
+ 'AUTH_101': AuthenticationError,
421
+ 'AUTH_102': AuthenticationError,
422
+ 'AUTH_103': AuthenticationError,
423
+ 'AUTH_104': AuthenticationError,
424
+ 'AUTH_105': AuthenticationError,
425
+ 'AUTH_106': PermissionDenied,
426
+ 'SYMBOL_001': BadSymbol,
427
+ 'SYMBOL_002': BadSymbol,
428
+ 'SYMBOL_003': BadSymbol,
429
+ 'SYMBOL_004': BadSymbol,
430
+ 'SYMBOL_005': BadSymbol,
431
+ 'ORDER_001': InvalidOrder,
432
+ 'ORDER_002': InsufficientFunds,
433
+ 'ORDER_003': InvalidOrder,
434
+ 'ORDER_004': InvalidOrder,
435
+ 'ORDER_005': InvalidOrder,
436
+ 'ORDER_006': InvalidOrder,
437
+ 'ORDER_007': PermissionDenied,
438
+ 'ORDER_F0101': InvalidOrder,
439
+ 'ORDER_F0102': InvalidOrder,
440
+ 'ORDER_F0103': InvalidOrder,
441
+ 'ORDER_F0201': InvalidOrder,
442
+ 'ORDER_F0202': InvalidOrder,
443
+ 'ORDER_F0203': InvalidOrder,
444
+ 'ORDER_F0301': InvalidOrder,
445
+ 'ORDER_F0401': InvalidOrder,
446
+ 'ORDER_F0501': InvalidOrder,
447
+ 'ORDER_F0502': InvalidOrder,
448
+ 'ORDER_F0601': InvalidOrder,
449
+ 'COMMON_001': ExchangeError,
450
+ 'COMMON_002': ExchangeError,
451
+ 'COMMON_003': BadRequest,
452
+ 'CURRENCY_001': BadRequest,
453
+ 'DEPOSIT_001': BadRequest,
454
+ 'DEPOSIT_002': PermissionDenied,
455
+ 'DEPOSIT_003': BadRequest,
456
+ 'DEPOSIT_004': BadRequest,
457
+ 'DEPOSIT_005': BadRequest,
458
+ 'DEPOSIT_006': BadRequest,
459
+ 'DEPOSIT_007': BadRequest,
460
+ 'DEPOSIT_008': BadRequest,
461
+ 'WITHDRAW_001': BadRequest,
462
+ 'WITHDRAW_002': BadRequest,
463
+ 'WITHDRAW_003': PermissionDenied,
464
+ 'WITHDRAW_004': BadRequest,
465
+ 'WITHDRAW_005': BadRequest,
466
+ 'WITHDRAW_006': BadRequest,
467
+ 'WITHDRAW_008': PermissionDenied,
468
+ 'WITHDRAW_009': PermissionDenied,
469
+ 'WITHDRAW_010': BadRequest,
470
+ 'WITHDRAW_011': InsufficientFunds,
471
+ 'WITHDRAW_012': PermissionDenied,
472
+ 'WITHDRAW_013': PermissionDenied,
473
+ 'WITHDRAW_014': BadRequest,
474
+ 'WITHDRAW_015': BadRequest,
475
+ 'WITHDRAW_016': BadRequest,
476
+ 'WITHDRAW_017': BadRequest,
477
+ 'WITHDRAW_018': BadRequest,
478
+ 'WITHDRAW_019': BadRequest,
479
+ 'WITHDRAW_020': PermissionDenied,
480
+ 'WITHDRAW_021': PermissionDenied,
481
+ 'WITHDRAW_022': BadRequest,
482
+ 'WITHDRAW_023': BadRequest,
483
+ 'WITHDRAW_024': BadRequest,
484
+ 'WITHDRAW_025': BadRequest,
485
+ 'FUND_001': BadRequest,
486
+ 'FUND_002': InsufficientFunds,
487
+ 'FUND_003': BadRequest,
488
+ 'FUND_004': ExchangeError,
489
+ 'FUND_005': PermissionDenied,
490
+ 'FUND_014': BadRequest,
491
+ 'FUND_015': BadRequest,
492
+ 'FUND_016': BadRequest,
493
+ 'FUND_017': BadRequest,
494
+ 'FUND_018': BadRequest,
495
+ 'FUND_019': BadRequest,
496
+ 'FUND_020': BadRequest,
497
+ 'FUND_021': BadRequest,
498
+ 'FUND_022': BadRequest,
499
+ 'FUND_044': BadRequest,
500
+ 'TRANSFER_001': BadRequest,
501
+ 'TRANSFER_002': InsufficientFunds,
502
+ 'TRANSFER_003': BadRequest,
503
+ 'TRANSFER_004': PermissionDenied,
504
+ 'TRANSFER_005': PermissionDenied,
505
+ 'TRANSFER_006': PermissionDenied,
506
+ 'TRANSFER_007': RequestTimeout,
507
+ 'TRANSFER_008': BadRequest,
508
+ 'TRANSFER_009': BadRequest,
509
+ 'TRANSFER_010': PermissionDenied,
510
+ 'TRANSFER_011': PermissionDenied,
511
+ 'TRANSFER_012': PermissionDenied,
512
+ 'symbol_not_support_trading_via_api': BadSymbol,
513
+ 'open_order_min_nominal_value_limit': InvalidOrder, // {"returnCode":1,"msgInfo":"failure","error":{"code":"open_order_min_nominal_value_limit","msg":"Exceeds the minimum notional value of a single order"},"result":null}
514
+ },
515
+ 'broad': {
516
+ 'The symbol does not support trading via API': BadSymbol,
517
+ 'Exceeds the minimum notional value of a single order': InvalidOrder, // {"returnCode":1,"msgInfo":"failure","error":{"code":"open_order_min_nominal_value_limit","msg":"Exceeds the minimum notional value of a single order"},"result":null}
518
+ },
519
+ },
520
+ 'timeframes': {
521
+ '1m': '1m',
522
+ '5m': '5m',
523
+ '15m': '15m',
524
+ '30m': '30m',
525
+ '1h': '1h',
526
+ '2h': '2h',
527
+ '4h': '4h',
528
+ '6h': '6h',
529
+ '8h': '8h',
530
+ '1d': '1d',
531
+ '3d': '3d',
532
+ '1w': '1w',
533
+ '1M': '1M', // spot only
534
+ },
535
+ 'commonCurrencies': {},
536
+ 'options': {
537
+ 'adjustForTimeDifference': false,
538
+ 'timeDifference': 0,
539
+ 'accountsById': {
540
+ 'spot': 'SPOT',
541
+ 'leverage': 'LEVER',
542
+ 'finance': 'FINANCE',
543
+ 'swap': 'FUTURES_U',
544
+ 'future': 'FUTURES_U',
545
+ 'linear': 'FUTURES_U',
546
+ 'inverse': 'FUTURES_C',
547
+ },
548
+ 'networks': {
549
+ 'ERC20': 'Ethereum',
550
+ 'TRC20': 'Tron',
551
+ 'BEP20': 'BNB Smart Chain',
552
+ 'BEP2': 'BNB-BEP2',
553
+ 'ETH': 'Ethereum',
554
+ 'TRON': 'Tron',
555
+ 'BNB': 'BNB Smart Chain',
556
+ 'AVAX': 'AVAX C-Chain',
557
+ 'GAL': 'GAL(FT)',
558
+ 'ALEO': 'ALEO(IOU)',
559
+ 'BTC': 'Bitcoin',
560
+ 'XT': 'XT Smart Chain',
561
+ 'ETC': 'Ethereum Classic',
562
+ 'MATIC': 'Polygon',
563
+ 'LTC': 'Litecoin',
564
+ 'BTS': 'BitShares',
565
+ 'XRP': 'Ripple',
566
+ 'XLM': 'Stellar Network',
567
+ 'ADA': 'Cardano',
568
+ 'XWC': 'XWC-XWC',
569
+ 'DOGE': 'dogecoin',
570
+ 'DCR': 'Decred',
571
+ 'SC': 'Siacoin',
572
+ 'XTZ': 'Tezos',
573
+ 'ZEC': 'Zcash',
574
+ 'XMR': 'Monero',
575
+ 'LSK': 'Lisk',
576
+ 'ATOM': 'Cosmos',
577
+ 'ONT': 'Ontology',
578
+ 'ALGO': 'Algorand',
579
+ 'SOL': 'SOL-SOL',
580
+ 'DOT': 'Polkadot',
581
+ 'ZEN': 'Horizen',
582
+ 'FIL': 'Filecoin',
583
+ 'CHZ': 'chz',
584
+ 'ICP': 'Internet Computer',
585
+ 'KSM': 'Kusama',
586
+ 'LUNA': 'Terra',
587
+ 'THETA': 'Theta Token',
588
+ 'FTM': 'Fantom',
589
+ 'VET': 'VeChain',
590
+ 'NEAR': 'NEAR Protocol',
591
+ 'ONE': 'Harmony',
592
+ 'KLAY': 'Klaytn',
593
+ 'AR': 'Arweave',
594
+ 'CELT': 'OKT',
595
+ 'EGLD': 'Elrond eGold',
596
+ 'CRO': 'CRO-CRONOS',
597
+ 'BCH': 'Bitcoin Cash',
598
+ 'GLMR': 'Moonbeam',
599
+ 'LOOP': 'LOOP-LRC',
600
+ 'REI': 'REI Network',
601
+ 'ASTR': 'Astar Network',
602
+ 'OP': 'OPT',
603
+ 'MMT': 'MMT-MMT',
604
+ 'TBC': 'TBC-TBC',
605
+ 'OMAX': 'OMAX-OMAX CHAIN',
606
+ 'GMMT': 'GMMT chain',
607
+ 'ZIL': 'Zilliqa',
608
+ },
609
+ 'networksById': {
610
+ 'Ethereum': 'ERC20',
611
+ 'Tron': 'TRC20',
612
+ 'BNB Smart Chain': 'BEP20',
613
+ 'BNB-BEP2': 'BEP2',
614
+ 'Bitcoin': 'BTC',
615
+ 'XT Smart Chain': 'XT',
616
+ 'Ethereum Classic': 'ETC',
617
+ 'Polygon': 'MATIC',
618
+ 'Litecoin': 'LTC',
619
+ 'BitShares': 'BTS',
620
+ 'Ripple': 'XRP',
621
+ 'Stellar Network': 'XLM',
622
+ 'Cardano': 'ADA',
623
+ 'XWC-XWC': 'XWC',
624
+ 'dogecoin': 'DOGE',
625
+ 'Decred': 'DCR',
626
+ 'Siacoin': 'SC',
627
+ 'Tezos': 'XTZ',
628
+ 'Zcash': 'ZEC',
629
+ 'Monero': 'XMR',
630
+ 'Lisk': 'LSK',
631
+ 'Cosmos': 'ATOM',
632
+ 'Ontology': 'ONT',
633
+ 'Algorand': 'ALGO',
634
+ 'SOL-SOL': 'SOL',
635
+ 'Polkadot': 'DOT',
636
+ 'Horizen': 'ZEN',
637
+ 'Filecoin': 'FIL',
638
+ 'chz': 'CHZ',
639
+ 'Internet Computer': 'ICP',
640
+ 'Kusama': 'KSM',
641
+ 'Terra': 'LUNA',
642
+ 'Theta Token': 'THETA',
643
+ 'Fantom': 'FTM',
644
+ 'VeChain': 'VET',
645
+ 'AVAX C-Chain': 'AVAX',
646
+ 'NEAR Protocol': 'NEAR',
647
+ 'Harmony': 'ONE',
648
+ 'Klaytn': 'KLAY',
649
+ 'Arweave': 'AR',
650
+ 'OKT': 'CELT',
651
+ 'Elrond eGold': 'EGLD',
652
+ 'CRO-CRONOS': 'CRO',
653
+ 'Bitcoin Cash': 'BCH',
654
+ 'Moonbeam': 'GLMR',
655
+ 'LOOP-LRC': 'LOOP',
656
+ 'REI Network': 'REI',
657
+ 'Astar Network': 'ASTR',
658
+ 'GAL(FT)': 'GAL',
659
+ 'ALEO(IOU)': 'ALEO',
660
+ 'OPT': 'OP',
661
+ 'MMT-MMT': 'MMT',
662
+ 'TBC-TBC': 'TBC',
663
+ 'OMAX-OMAX CHAIN': 'OMAX',
664
+ 'GMMT chain': 'GMMT',
665
+ 'Zilliqa': 'ZIL',
666
+ },
667
+ 'createMarketBuyOrderRequiresPrice': true,
668
+ 'recvWindow': '5000', // in milliseconds, spot only
669
+ },
670
+ });
671
+ }
672
+ nonce() {
673
+ return this.milliseconds() - this.options['timeDifference'];
674
+ }
675
+ async fetchTime(params = {}) {
676
+ /**
677
+ * @method
678
+ * @name xt#fetchTime
679
+ * @description fetches the current integer timestamp in milliseconds from the xt server
680
+ * @see https://doc.xt.com/#market1serverInfo
681
+ * @param {object} params extra parameters specific to the xt api endpoint
682
+ * @returns {int} the current integer timestamp in milliseconds from the xt server
683
+ */
684
+ const response = await this.publicSpotGetTime(params);
685
+ //
686
+ // {
687
+ // "rc": 0,
688
+ // "mc": "SUCCESS",
689
+ // "ma": [],
690
+ // "result": {
691
+ // "serverTime": 1677823301643
692
+ // }
693
+ // }
694
+ //
695
+ const data = this.safeValue(response, 'result');
696
+ return this.safeInteger(data, 'serverTime');
697
+ }
698
+ async fetchCurrencies(params = {}) {
699
+ /**
700
+ * @method
701
+ * @name xt#fetchCurrencies
702
+ * @description fetches all available currencies on an exchange
703
+ * @see https://doc.xt.com/#deposit_withdrawalsupportedCurrenciesGet
704
+ * @param {object} params extra parameters specific to the xt api endpoint
705
+ * @returns {object} an associative dictionary of currencies
706
+ */
707
+ const promisesRaw = [this.publicSpotGetWalletSupportCurrency(params), this.publicSpotGetCurrencies(params)];
708
+ const [chainsResponse, currenciesResponse] = await Promise.all(promisesRaw);
709
+ //
710
+ // currencies
711
+ //
712
+ // {
713
+ // "time": "1686626116145",
714
+ // "version": "5dbbb2f2527c22b2b2e3b47187ef13d1",
715
+ // "currencies": [
716
+ // {
717
+ // "id": "2",
718
+ // "currency": "btc",
719
+ // "fullName": "Bitcoin",
720
+ // "logo": "https://a.static-global.com/1/currency/btc.png",
721
+ // "cmcLink": "https://coinmarketcap.com/currencies/bitcoin/",
722
+ // "weight": "99999",
723
+ // "maxPrecision": "10",
724
+ // "depositStatus": "1",
725
+ // "withdrawStatus": "1",
726
+ // "convertEnabled": "1",
727
+ // "transferEnabled": "1",
728
+ // "isChainExist": "1",
729
+ // "plates": [152]
730
+ // },
731
+ // ],
732
+ // }
733
+ //
734
+ //
735
+ // chains
736
+ //
737
+ // {
738
+ // "rc": 0,
739
+ // "mc": "SUCCESS",
740
+ // "ma": [],
741
+ // "result": [
742
+ // {
743
+ // "currency": "btc",
744
+ // "supportChains": [
745
+ // {
746
+ // "chain": "Bitcoin",
747
+ // "depositEnabled": true,
748
+ // "withdrawEnabled": true,
749
+ // "withdrawFeeAmount": 0.0009,
750
+ // "withdrawMinAmount": 0.0005,
751
+ // "depositFeeRate": 0
752
+ // },
753
+ // ]
754
+ // },
755
+ // ]
756
+ // }
757
+ //
758
+ // note: individual network's full data is available on per-currency endpoint: https://www.xt.com/sapi/v4/balance/public/currency/11
759
+ //
760
+ const chainsData = this.safeValue(chainsResponse, 'result', []);
761
+ const currenciesResult = this.safeValue(currenciesResponse, 'result', []);
762
+ const currenciesData = this.safeValue(currenciesResult, 'currencies', []);
763
+ const chainsDataIndexed = this.indexBy(chainsData, 'currency');
764
+ const result = {};
765
+ for (let i = 0; i < currenciesData.length; i++) {
766
+ const entry = currenciesData[i];
767
+ const currencyId = this.safeString(entry, 'currency');
768
+ const code = this.safeCurrencyCode(currencyId);
769
+ const minPrecision = this.parseNumber(this.parsePrecision(this.safeString(entry, 'maxPrecision')));
770
+ const networkEntry = this.safeValue(chainsDataIndexed, currencyId, {});
771
+ const rawNetworks = this.safeValue(networkEntry, 'supportChains', []);
772
+ const networks = {};
773
+ let minWithdrawString = undefined;
774
+ let minWithdrawFeeString = undefined;
775
+ let active = false;
776
+ let deposit = false;
777
+ let withdraw = false;
778
+ for (let j = 0; j < rawNetworks.length; j++) {
779
+ const rawNetwork = rawNetworks[j];
780
+ const networkId = this.safeString(rawNetwork, 'chain');
781
+ const network = this.networkIdToCode(networkId);
782
+ const depositEnabled = this.safeValue(rawNetwork, 'depositEnabled');
783
+ deposit = (depositEnabled) ? depositEnabled : deposit;
784
+ const withdrawEnabled = this.safeValue(rawNetwork, 'withdrawEnabled');
785
+ withdraw = (withdrawEnabled) ? withdrawEnabled : withdraw;
786
+ const networkActive = depositEnabled && withdrawEnabled;
787
+ active = (networkActive) ? networkActive : active;
788
+ const withdrawFeeString = this.safeString(rawNetwork, 'withdrawFeeAmount');
789
+ if (withdrawFeeString !== undefined) {
790
+ minWithdrawFeeString = (minWithdrawFeeString === undefined) ? withdrawFeeString : Precise.stringMin(withdrawFeeString, minWithdrawFeeString);
791
+ }
792
+ const minNetworkWithdrawString = this.safeString(rawNetwork, 'withdrawMinAmount');
793
+ if (minNetworkWithdrawString !== undefined) {
794
+ minWithdrawString = (minWithdrawString === undefined) ? minNetworkWithdrawString : Precise.stringMin(minNetworkWithdrawString, minWithdrawString);
795
+ }
796
+ networks[network] = {
797
+ 'info': rawNetwork,
798
+ 'id': networkId,
799
+ 'network': network,
800
+ 'name': undefined,
801
+ 'active': networkActive,
802
+ 'fee': this.parseNumber(withdrawFeeString),
803
+ 'precision': minPrecision,
804
+ 'deposit': depositEnabled,
805
+ 'withdraw': withdrawEnabled,
806
+ 'limits': {
807
+ 'amount': {
808
+ 'min': undefined,
809
+ 'max': undefined,
810
+ },
811
+ 'withdraw': {
812
+ 'min': this.parseNumber(minNetworkWithdrawString),
813
+ 'max': undefined,
814
+ },
815
+ 'deposit': {
816
+ 'min': undefined,
817
+ 'max': undefined,
818
+ },
819
+ },
820
+ };
821
+ }
822
+ result[code] = {
823
+ 'info': entry,
824
+ 'id': currencyId,
825
+ 'code': code,
826
+ 'name': this.safeString(entry, 'fullName'),
827
+ 'active': active,
828
+ 'fee': this.parseNumber(minWithdrawFeeString),
829
+ 'precision': undefined,
830
+ 'deposit': deposit,
831
+ 'withdraw': withdraw,
832
+ 'networks': networks,
833
+ 'limits': {
834
+ 'amount': {
835
+ 'min': undefined,
836
+ 'max': undefined,
837
+ },
838
+ 'withdraw': {
839
+ 'min': this.parseNumber(minWithdrawString),
840
+ 'max': undefined,
841
+ },
842
+ 'deposit': {
843
+ 'min': undefined,
844
+ 'max': undefined,
845
+ },
846
+ },
847
+ };
848
+ }
849
+ return result;
850
+ }
851
+ async fetchMarkets(params = {}) {
852
+ /**
853
+ * @method
854
+ * @name xt#fetchMarkets
855
+ * @description retrieves data on all markets for xt
856
+ * @see https://doc.xt.com/#market2symbol
857
+ * @see https://doc.xt.com/#futures_quotesgetSymbols
858
+ * @param {object} params extra parameters specific to the xt api endpoint
859
+ * @returns {object[]} an array of objects representing market data
860
+ */
861
+ if (this.options['adjustForTimeDifference']) {
862
+ await this.loadTimeDifference();
863
+ }
864
+ const promisesUnresolved = [
865
+ this.fetchSpotMarkets(params),
866
+ this.fetchSwapAndFutureMarkets(params),
867
+ ];
868
+ const promises = await Promise.all(promisesUnresolved);
869
+ const spotMarkets = promises[0];
870
+ const swapAndFutureMarkets = promises[1];
871
+ return this.arrayConcat(spotMarkets, swapAndFutureMarkets);
872
+ }
873
+ async fetchSpotMarkets(params = {}) {
874
+ const response = await this.publicSpotGetSymbol(params);
875
+ //
876
+ // {
877
+ // "rc": 0,
878
+ // "mc": "SUCCESS",
879
+ // "ma": [],
880
+ // "result": {
881
+ // "time": 1677881368812,
882
+ // "version": "abb101d1543e54bee40687b135411ba0",
883
+ // "symbols": [
884
+ // {
885
+ // "id": 640,
886
+ // "symbol": "xt_usdt",
887
+ // "state": "ONLINE",
888
+ // "stateTime": 1554048000000,
889
+ // "tradingEnabled": true,
890
+ // "openapiEnabled": true,
891
+ // "nextStateTime": null,
892
+ // "nextState": null,
893
+ // "depthMergePrecision": 5,
894
+ // "baseCurrency": "xt",
895
+ // "baseCurrencyPrecision": 8,
896
+ // "baseCurrencyId": 128,
897
+ // "quoteCurrency": "usdt",
898
+ // "quoteCurrencyPrecision": 8,
899
+ // "quoteCurrencyId": 11,
900
+ // "pricePrecision": 4,
901
+ // "quantityPrecision": 2,
902
+ // "orderTypes": ["LIMIT","MARKET"],
903
+ // "timeInForces": ["GTC","IOC"],
904
+ // "displayWeight": 10002,
905
+ // "displayLevel": "FULL",
906
+ // "plates": [],
907
+ // "filters":[
908
+ // {
909
+ // "filter": "QUOTE_QTY",
910
+ // "min": "1"
911
+ // },
912
+ // {
913
+ // "filter": "PROTECTION_LIMIT",
914
+ // "buyMaxDeviation": "0.8",
915
+ // "sellMaxDeviation": "4"
916
+ // },
917
+ // {
918
+ // "filter": "PROTECTION_MARKET",
919
+ // "maxDeviation": "0.02"
920
+ // }
921
+ // ]
922
+ // },
923
+ // ]
924
+ // }
925
+ // }
926
+ //
927
+ const data = this.safeValue(response, 'result', {});
928
+ const symbols = this.safeValue(data, 'symbols', []);
929
+ return this.parseMarkets(symbols);
930
+ }
931
+ async fetchSwapAndFutureMarkets(params = {}) {
932
+ const markets = await Promise.all([this.publicLinearGetFutureMarketV1PublicSymbolList(params), this.publicInverseGetFutureMarketV1PublicSymbolList(params)]);
933
+ //
934
+ // {
935
+ // "returnCode": 0,
936
+ // "msgInfo": "success",
937
+ // "error": null,
938
+ // "result": [
939
+ // {
940
+ // "id": 52,
941
+ // "symbolGroupId": 71,
942
+ // "symbol": "xt_usdt",
943
+ // "pair": "xt_usdt",
944
+ // "contractType": "PERPETUAL",
945
+ // "productType": "perpetual",
946
+ // "predictEventType": null,
947
+ // "underlyingType": "U_BASED",
948
+ // "contractSize": "1",
949
+ // "tradeSwitch": true,
950
+ // "isDisplay": true,
951
+ // "isOpenApi": false,
952
+ // "state": 0,
953
+ // "initLeverage": 20,
954
+ // "initPositionType": "CROSSED",
955
+ // "baseCoin": "xt",
956
+ // "quoteCoin": "usdt",
957
+ // "baseCoinPrecision": 8,
958
+ // "baseCoinDisplayPrecision": 4,
959
+ // "quoteCoinPrecision": 8,
960
+ // "quoteCoinDisplayPrecision": 4,
961
+ // "quantityPrecision": 0,
962
+ // "pricePrecision": 4,
963
+ // "supportOrderType": "LIMIT,MARKET",
964
+ // "supportTimeInForce": "GTC,FOK,IOC,GTX",
965
+ // "supportEntrustType": "TAKE_PROFIT,STOP,TAKE_PROFIT_MARKET,STOP_MARKET,TRAILING_STOP_MARKET",
966
+ // "supportPositionType": "CROSSED,ISOLATED",
967
+ // "minQty": "1",
968
+ // "minNotional": "5",
969
+ // "maxNotional": "20000000",
970
+ // "multiplierDown": "0.1",
971
+ // "multiplierUp": "0.1",
972
+ // "maxOpenOrders": 200,
973
+ // "maxEntrusts": 200,
974
+ // "makerFee": "0.0004",
975
+ // "takerFee": "0.0006",
976
+ // "liquidationFee": "0.01",
977
+ // "marketTakeBound": "0.1",
978
+ // "depthPrecisionMerge": 5,
979
+ // "labels": ["HOT"],
980
+ // "onboardDate": 1657101601000,
981
+ // "enName": "XTUSDT ",
982
+ // "cnName": "XTUSDT",
983
+ // "minStepPrice": "0.0001",
984
+ // "minPrice": null,
985
+ // "maxPrice": null,
986
+ // "deliveryDate": 1669879634000,
987
+ // "deliveryPrice": null,
988
+ // "deliveryCompletion": false,
989
+ // "cnDesc": null,
990
+ // "enDesc": null
991
+ // },
992
+ // ]
993
+ // }
994
+ //
995
+ const swapAndFutureMarkets = this.arrayConcat(this.safeValue(markets[0], 'result', []), this.safeValue(markets[1], 'result', []));
996
+ return this.parseMarkets(swapAndFutureMarkets);
997
+ }
998
+ parseMarkets(markets) {
999
+ const result = [];
1000
+ for (let i = 0; i < markets.length; i++) {
1001
+ result.push(this.parseMarket(markets[i]));
1002
+ }
1003
+ return result;
1004
+ }
1005
+ parseMarket(market) {
1006
+ //
1007
+ // spot
1008
+ //
1009
+ // {
1010
+ // "id": 640,
1011
+ // "symbol": "xt_usdt",
1012
+ // "state": "ONLINE",
1013
+ // "stateTime": 1554048000000,
1014
+ // "tradingEnabled": true,
1015
+ // "openapiEnabled": true,
1016
+ // "nextStateTime": null,
1017
+ // "nextState": null,
1018
+ // "depthMergePrecision": 5,
1019
+ // "baseCurrency": "xt",
1020
+ // "baseCurrencyPrecision": 8,
1021
+ // "baseCurrencyId": 128,
1022
+ // "quoteCurrency": "usdt",
1023
+ // "quoteCurrencyPrecision": 8,
1024
+ // "quoteCurrencyId": 11,
1025
+ // "pricePrecision": 4,
1026
+ // "quantityPrecision": 2,
1027
+ // "orderTypes": ["LIMIT","MARKET"],
1028
+ // "timeInForces": ["GTC","IOC"],
1029
+ // "displayWeight": 10002,
1030
+ // "displayLevel": "FULL",
1031
+ // "plates": [],
1032
+ // "filters":[
1033
+ // {
1034
+ // "filter": "QUOTE_QTY",
1035
+ // "min": "1"
1036
+ // },
1037
+ // {
1038
+ // "filter": "PRICE",
1039
+ // "min": null,
1040
+ // "max": null,
1041
+ // "tickSize": null
1042
+ // },
1043
+ // {
1044
+ // "filter": "QUANTITY",
1045
+ // "min": null,
1046
+ // "max": null,
1047
+ // "tickSize": null
1048
+ // },
1049
+ // {
1050
+ // "filter": "PROTECTION_LIMIT",
1051
+ // "buyMaxDeviation": "0.8",
1052
+ // "sellMaxDeviation": "4"
1053
+ // },
1054
+ // {
1055
+ // "filter": "PROTECTION_MARKET",
1056
+ // "maxDeviation": "0.02"
1057
+ // },
1058
+ // {
1059
+ // "filter": "PROTECTION_ONLINE",
1060
+ // "durationSeconds": "300",
1061
+ // "maxPriceMultiple": "5"
1062
+ // },
1063
+ // ]
1064
+ // }
1065
+ //
1066
+ // swap and future
1067
+ //
1068
+ // {
1069
+ // "id": 52,
1070
+ // "symbolGroupId": 71,
1071
+ // "symbol": "xt_usdt",
1072
+ // "pair": "xt_usdt",
1073
+ // "contractType": "PERPETUAL",
1074
+ // "productType": "perpetual",
1075
+ // "predictEventType": null,
1076
+ // "underlyingType": "U_BASED",
1077
+ // "contractSize": "1",
1078
+ // "tradeSwitch": true,
1079
+ // "isDisplay": true,
1080
+ // "isOpenApi": false,
1081
+ // "state": 0,
1082
+ // "initLeverage": 20,
1083
+ // "initPositionType": "CROSSED",
1084
+ // "baseCoin": "xt",
1085
+ // "quoteCoin": "usdt",
1086
+ // "baseCoinPrecision": 8,
1087
+ // "baseCoinDisplayPrecision": 4,
1088
+ // "quoteCoinPrecision": 8,
1089
+ // "quoteCoinDisplayPrecision": 4,
1090
+ // "quantityPrecision": 0,
1091
+ // "pricePrecision": 4,
1092
+ // "supportOrderType": "LIMIT,MARKET",
1093
+ // "supportTimeInForce": "GTC,FOK,IOC,GTX",
1094
+ // "supportEntrustType": "TAKE_PROFIT,STOP,TAKE_PROFIT_MARKET,STOP_MARKET,TRAILING_STOP_MARKET",
1095
+ // "supportPositionType": "CROSSED,ISOLATED",
1096
+ // "minQty": "1",
1097
+ // "minNotional": "5",
1098
+ // "maxNotional": "20000000",
1099
+ // "multiplierDown": "0.1",
1100
+ // "multiplierUp": "0.1",
1101
+ // "maxOpenOrders": 200,
1102
+ // "maxEntrusts": 200,
1103
+ // "makerFee": "0.0004",
1104
+ // "takerFee": "0.0006",
1105
+ // "liquidationFee": "0.01",
1106
+ // "marketTakeBound": "0.1",
1107
+ // "depthPrecisionMerge": 5,
1108
+ // "labels": ["HOT"],
1109
+ // "onboardDate": 1657101601000,
1110
+ // "enName": "XTUSDT ",
1111
+ // "cnName": "XTUSDT",
1112
+ // "minStepPrice": "0.0001",
1113
+ // "minPrice": null,
1114
+ // "maxPrice": null,
1115
+ // "deliveryDate": 1669879634000,
1116
+ // "deliveryPrice": null,
1117
+ // "deliveryCompletion": false,
1118
+ // "cnDesc": null,
1119
+ // "enDesc": null
1120
+ // }
1121
+ //
1122
+ const id = this.safeString(market, 'symbol');
1123
+ const baseId = this.safeString2(market, 'baseCurrency', 'baseCoin');
1124
+ const quoteId = this.safeString2(market, 'quoteCurrency', 'quoteCoin');
1125
+ const base = this.safeCurrencyCode(baseId);
1126
+ const quote = this.safeCurrencyCode(quoteId);
1127
+ const state = this.safeString(market, 'state');
1128
+ let symbol = base + '/' + quote;
1129
+ const filters = this.safeValue(market, 'filters', []);
1130
+ let minAmount = undefined;
1131
+ let maxAmount = undefined;
1132
+ let minCost = undefined;
1133
+ let maxCost = undefined;
1134
+ let minPrice = undefined;
1135
+ let maxPrice = undefined;
1136
+ for (let i = 0; i < filters.length; i++) {
1137
+ const entry = filters[i];
1138
+ const filter = this.safeString(entry, 'filter');
1139
+ if (filter === 'QUANTITY') {
1140
+ minAmount = this.safeNumber(entry, 'min');
1141
+ maxAmount = this.safeNumber(entry, 'max');
1142
+ }
1143
+ if (filter === 'QUOTE_QTY') {
1144
+ minCost = this.safeNumber(entry, 'min');
1145
+ }
1146
+ if (filter === 'PRICE') {
1147
+ minPrice = this.safeNumber(entry, 'min');
1148
+ maxPrice = this.safeNumber(entry, 'max');
1149
+ }
1150
+ }
1151
+ const underlyingType = this.safeString(market, 'underlyingType');
1152
+ let linear = undefined;
1153
+ let inverse = undefined;
1154
+ let settleId = undefined;
1155
+ let settle = undefined;
1156
+ let expiry = undefined;
1157
+ let future = false;
1158
+ let swap = false;
1159
+ let contract = false;
1160
+ let spot = true;
1161
+ let type = 'spot';
1162
+ if (underlyingType === 'U_BASED') {
1163
+ symbol = symbol + ':' + quote;
1164
+ settleId = baseId;
1165
+ settle = quote;
1166
+ linear = true;
1167
+ inverse = false;
1168
+ }
1169
+ else if (underlyingType === 'COIN_BASED') {
1170
+ symbol = symbol + ':' + base;
1171
+ settleId = baseId;
1172
+ settle = base;
1173
+ linear = false;
1174
+ inverse = true;
1175
+ }
1176
+ if (underlyingType !== undefined) {
1177
+ expiry = this.safeInteger(market, 'deliveryDate');
1178
+ const productType = this.safeString(market, 'productType');
1179
+ if (productType !== 'perpetual') {
1180
+ symbol = symbol + '-' + this.yymmdd(expiry);
1181
+ type = 'future';
1182
+ future = true;
1183
+ }
1184
+ else {
1185
+ type = 'swap';
1186
+ swap = true;
1187
+ }
1188
+ minAmount = this.safeNumber(market, 'minQty');
1189
+ minCost = this.safeNumber(market, 'minNotional');
1190
+ maxCost = this.safeNumber(market, 'maxNotional');
1191
+ minPrice = this.safeNumber(market, 'minPrice');
1192
+ maxPrice = this.safeNumber(market, 'maxPrice');
1193
+ contract = true;
1194
+ spot = false;
1195
+ }
1196
+ let isActive = false;
1197
+ if (contract) {
1198
+ isActive = this.safeValue(market, 'isOpenApi', false);
1199
+ }
1200
+ else {
1201
+ if ((state === 'ONLINE') && (this.safeValue(market, 'tradingEnabled')) && (this.safeValue(market, 'openapiEnabled'))) {
1202
+ isActive = true;
1203
+ }
1204
+ }
1205
+ return this.safeMarketStructure({
1206
+ 'id': id,
1207
+ 'symbol': symbol,
1208
+ 'base': base,
1209
+ 'quote': quote,
1210
+ 'settle': settle,
1211
+ 'baseId': baseId,
1212
+ 'quoteId': quoteId,
1213
+ 'settleId': settleId,
1214
+ 'type': type,
1215
+ 'spot': spot,
1216
+ 'margin': undefined,
1217
+ 'swap': swap,
1218
+ 'future': future,
1219
+ 'option': false,
1220
+ 'active': isActive,
1221
+ 'contract': contract,
1222
+ 'linear': linear,
1223
+ 'inverse': inverse,
1224
+ 'taker': this.safeNumber(market, 'takerFee'),
1225
+ 'maker': this.safeNumber(market, 'makerFee'),
1226
+ 'contractSize': this.safeNumber(market, 'contractSize'),
1227
+ 'expiry': expiry,
1228
+ 'expiryDatetime': this.iso8601(expiry),
1229
+ 'strike': undefined,
1230
+ 'optionType': undefined,
1231
+ 'precision': {
1232
+ 'price': this.parseNumber(this.parsePrecision(this.safeString(market, 'pricePrecision'))),
1233
+ 'amount': this.parseNumber(this.parsePrecision(this.safeString(market, 'quantityPrecision'))),
1234
+ 'base': this.parseNumber(this.parsePrecision(this.safeString(market, 'baseCoinPrecision'))),
1235
+ 'quote': this.parseNumber(this.parsePrecision(this.safeString(market, 'quoteCoinPrecision'))),
1236
+ },
1237
+ 'limits': {
1238
+ 'leverage': {
1239
+ 'min': this.parseNumber('1'),
1240
+ 'max': undefined,
1241
+ },
1242
+ 'amount': {
1243
+ 'min': minAmount,
1244
+ 'max': maxAmount,
1245
+ },
1246
+ 'price': {
1247
+ 'min': minPrice,
1248
+ 'max': maxPrice,
1249
+ },
1250
+ 'cost': {
1251
+ 'min': minCost,
1252
+ 'max': maxCost,
1253
+ },
1254
+ },
1255
+ 'info': market,
1256
+ });
1257
+ }
1258
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1259
+ /**
1260
+ * @method
1261
+ * @name xt#fetchOHLCV
1262
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1263
+ * @see https://doc.xt.com/#market4kline
1264
+ * @see https://doc.xt.com/#futures_quotesgetKLine
1265
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1266
+ * @param {string} timeframe the length of time each candle represents
1267
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
1268
+ * @param {int} [limit] the maximum amount of candles to fetch
1269
+ * @param {object} params extra parameters specific to the xt api endpoint
1270
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1271
+ */
1272
+ await this.loadMarkets();
1273
+ const market = this.market(symbol);
1274
+ const request = {
1275
+ 'symbol': market['id'],
1276
+ 'interval': this.safeString(this.timeframes, timeframe, timeframe),
1277
+ };
1278
+ if (since !== undefined) {
1279
+ request['startTime'] = since;
1280
+ }
1281
+ if (limit !== undefined) {
1282
+ request['limit'] = limit;
1283
+ }
1284
+ let response = undefined;
1285
+ if (market['linear']) {
1286
+ response = await this.publicLinearGetFutureMarketV1PublicQKline(this.extend(request, params));
1287
+ }
1288
+ else if (market['inverse']) {
1289
+ response = await this.publicInverseGetFutureMarketV1PublicQKline(this.extend(request, params));
1290
+ }
1291
+ else {
1292
+ response = await this.publicSpotGetKline(this.extend(request, params));
1293
+ }
1294
+ //
1295
+ // spot
1296
+ //
1297
+ // {
1298
+ // "rc": 0,
1299
+ // "mc": "SUCCESS",
1300
+ // "ma": [],
1301
+ // "result": [
1302
+ // {
1303
+ // "t": 1678167720000,
1304
+ // "o": "22467.85",
1305
+ // "c": "22465.87",
1306
+ // "h": "22468.86",
1307
+ // "l": "22465.21",
1308
+ // "q": "1.316656",
1309
+ // "v": "29582.73018498"
1310
+ // },
1311
+ // ]
1312
+ // }
1313
+ //
1314
+ // swap and future
1315
+ //
1316
+ // {
1317
+ // "returnCode": 0,
1318
+ // "msgInfo": "success",
1319
+ // "error": null,
1320
+ // "result": [
1321
+ // {
1322
+ // "s": "btc_usdt",
1323
+ // "p": "btc_usdt",
1324
+ // "t": 1678168020000,
1325
+ // "o": "22450.0",
1326
+ // "c": "22441.5",
1327
+ // "h": "22450.0",
1328
+ // "l": "22441.5",
1329
+ // "a": "312931",
1330
+ // "v": "702461.58895"
1331
+ // },
1332
+ // ]
1333
+ // }
1334
+ //
1335
+ const ohlcvs = this.safeValue(response, 'result', []);
1336
+ return this.parseOHLCVs(ohlcvs, market, timeframe, since, limit);
1337
+ }
1338
+ parseOHLCV(ohlcv, market = undefined) {
1339
+ //
1340
+ // spot
1341
+ //
1342
+ // {
1343
+ // "t": 1678167720000,
1344
+ // "o": "22467.85",
1345
+ // "c": "22465.87",
1346
+ // "h": "22468.86",
1347
+ // "l": "22465.21",
1348
+ // "q": "1.316656",
1349
+ // "v": "29582.73018498"
1350
+ // }
1351
+ //
1352
+ // swap and future
1353
+ //
1354
+ // {
1355
+ // "s": "btc_usdt",
1356
+ // "p": "btc_usdt",
1357
+ // "t": 1678168020000,
1358
+ // "o": "22450.0",
1359
+ // "c": "22441.5",
1360
+ // "h": "22450.0",
1361
+ // "l": "22441.5",
1362
+ // "a": "312931",
1363
+ // "v": "702461.58895"
1364
+ // }
1365
+ //
1366
+ const volumeIndex = (market['inverse']) ? 'v' : 'a';
1367
+ return [
1368
+ this.safeInteger(ohlcv, 't'),
1369
+ this.safeNumber(ohlcv, 'o'),
1370
+ this.safeNumber(ohlcv, 'h'),
1371
+ this.safeNumber(ohlcv, 'l'),
1372
+ this.safeNumber(ohlcv, 'c'),
1373
+ this.safeNumber2(ohlcv, volumeIndex, 'v'),
1374
+ ];
1375
+ }
1376
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
1377
+ /**
1378
+ * @method
1379
+ * @name xt#fetchOrderBook
1380
+ * @see https://doc.xt.com/#market3depth
1381
+ * @see https://doc.xt.com/#futures_quotesgetDepth
1382
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1383
+ * @param {string} symbol unified market symbol to fetch the order book for
1384
+ * @param {int} [limit] the maximum amount of order book entries to return
1385
+ * @param {object} params extra parameters specific to the xt api endpoint
1386
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-book-structure} indexed by market symbols
1387
+ */
1388
+ await this.loadMarkets();
1389
+ const market = this.market(symbol);
1390
+ const request = {
1391
+ 'symbol': market['id'],
1392
+ };
1393
+ let response = undefined;
1394
+ if (market['spot']) {
1395
+ if (limit !== undefined) {
1396
+ request['limit'] = Math.min(limit, 500);
1397
+ }
1398
+ response = await this.publicSpotGetDepth(this.extend(request, params));
1399
+ }
1400
+ else {
1401
+ if (limit !== undefined) {
1402
+ request['level'] = Math.min(limit, 50);
1403
+ }
1404
+ else {
1405
+ request['level'] = 50;
1406
+ }
1407
+ if (market['linear']) {
1408
+ response = await this.publicLinearGetFutureMarketV1PublicQDepth(this.extend(request, params));
1409
+ }
1410
+ else if (market['inverse']) {
1411
+ response = await this.publicInverseGetFutureMarketV1PublicQDepth(this.extend(request, params));
1412
+ }
1413
+ }
1414
+ //
1415
+ // spot
1416
+ //
1417
+ // {
1418
+ // "rc": 0,
1419
+ // "mc": "SUCCESS",
1420
+ // "ma": [],
1421
+ // "result": {
1422
+ // "timestamp": 1678169975184,
1423
+ // "lastUpdateId": 1675333221812,
1424
+ // "bids": [
1425
+ // ["22444.51", "0.129887"],
1426
+ // ["22444.49", "0.114245"],
1427
+ // ["22444.30", "0.225956"]
1428
+ // ],
1429
+ // "asks": [
1430
+ // ["22446.19", "0.095330"],
1431
+ // ["22446.24", "0.224413"],
1432
+ // ["22446.28", "0.329095"]
1433
+ // ]
1434
+ // }
1435
+ // }
1436
+ //
1437
+ // swap and future
1438
+ //
1439
+ // {
1440
+ // "returnCode": 0,
1441
+ // "msgInfo": "success",
1442
+ // "error": null,
1443
+ // "result": {
1444
+ // "t": 1678170311005,
1445
+ // "s": "btc_usdt",
1446
+ // "u": 471694545627,
1447
+ // "b": [
1448
+ // ["22426", "198623"],
1449
+ // ["22423.5", "80295"],
1450
+ // ["22423", "163580"]
1451
+ // ],
1452
+ // "a": [
1453
+ // ["22427", "3417"],
1454
+ // ["22428.5", "43532"],
1455
+ // ["22429", "119"]
1456
+ // ]
1457
+ // }
1458
+ // }
1459
+ //
1460
+ const orderBook = this.safeValue(response, 'result', {});
1461
+ const timestamp = this.safeInteger2(orderBook, 'timestamp', 't');
1462
+ if (market['spot']) {
1463
+ return this.parseOrderBook(orderBook, symbol, timestamp);
1464
+ }
1465
+ return this.parseOrderBook(orderBook, symbol, timestamp, 'b', 'a');
1466
+ }
1467
+ async fetchTicker(symbol, params = {}) {
1468
+ /**
1469
+ * @method
1470
+ * @name xt#fetchTicker
1471
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1472
+ * @see https://doc.xt.com/#market10ticker24h
1473
+ * @see https://doc.xt.com/#futures_quotesgetAggTicker
1474
+ * @param {string} symbol unified market symbol to fetch the ticker for
1475
+ * @param {object} params extra parameters specific to the xt api endpoint
1476
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure}
1477
+ */
1478
+ await this.loadMarkets();
1479
+ const market = this.market(symbol);
1480
+ const request = {
1481
+ 'symbol': market['id'],
1482
+ };
1483
+ let response = undefined;
1484
+ if (market['linear']) {
1485
+ response = await this.publicLinearGetFutureMarketV1PublicQAggTicker(this.extend(request, params));
1486
+ }
1487
+ else if (market['inverse']) {
1488
+ response = await this.publicInverseGetFutureMarketV1PublicQAggTicker(this.extend(request, params));
1489
+ }
1490
+ else {
1491
+ response = await this.publicSpotGetTicker24h(this.extend(request, params));
1492
+ }
1493
+ //
1494
+ // spot
1495
+ //
1496
+ // {
1497
+ // "rc": 0,
1498
+ // "mc": "SUCCESS",
1499
+ // "ma": [],
1500
+ // "result": [
1501
+ // {
1502
+ // "s": "btc_usdt",
1503
+ // "t": 1678172693931,
1504
+ // "cv": "34.00",
1505
+ // "cr": "0.0015",
1506
+ // "o": "22398.05",
1507
+ // "l": "22323.72",
1508
+ // "h": "22600.50",
1509
+ // "c": "22432.05",
1510
+ // "q": "7962.256931",
1511
+ // "v": "178675209.47416856"
1512
+ // }
1513
+ // ]
1514
+ // }
1515
+ //
1516
+ // swap and future
1517
+ //
1518
+ // {
1519
+ // "returnCode": 0,
1520
+ // "msgInfo": "success",
1521
+ // "error": null,
1522
+ // "result": {
1523
+ // "t": 1678172848572,
1524
+ // "s": "btc_usdt",
1525
+ // "c": "22415.5",
1526
+ // "h": "22590.0",
1527
+ // "l": "22310.0",
1528
+ // "a": "623654031",
1529
+ // "v": "1399166074.31675",
1530
+ // "o": "22381.5",
1531
+ // "r": "0.0015",
1532
+ // "i": "22424.5",
1533
+ // "m": "22416.5",
1534
+ // "bp": "22415",
1535
+ // "ap": "22415.5"
1536
+ // }
1537
+ // }
1538
+ //
1539
+ const ticker = this.safeValue(response, 'result');
1540
+ if (market['spot']) {
1541
+ return this.parseTicker(ticker[0], market);
1542
+ }
1543
+ return this.parseTicker(ticker, market);
1544
+ }
1545
+ async fetchTickers(symbols = undefined, params = {}) {
1546
+ /**
1547
+ * @method
1548
+ * @name xt#fetchTickers
1549
+ * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
1550
+ * @see https://doc.xt.com/#market10ticker24h
1551
+ * @see https://doc.xt.com/#futures_quotesgetAggTickers
1552
+ * @param {string} [symbols] unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1553
+ * @param {object} params extra parameters specific to the xt api endpoint
1554
+ * @returns {object} an array of [ticker structures]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure}
1555
+ */
1556
+ await this.loadMarkets();
1557
+ let market = undefined;
1558
+ if (symbols !== undefined) {
1559
+ symbols = this.marketSymbols(symbols);
1560
+ market = this.market(symbols[0]);
1561
+ }
1562
+ const request = {};
1563
+ let type = undefined;
1564
+ let subType = undefined;
1565
+ let response = undefined;
1566
+ [type, params] = this.handleMarketTypeAndParams('fetchTickers', market, params);
1567
+ [subType, params] = this.handleSubTypeAndParams('fetchTickers', market, params);
1568
+ if (subType === 'inverse') {
1569
+ response = await this.publicInverseGetFutureMarketV1PublicQAggTickers(this.extend(request, params));
1570
+ }
1571
+ else if ((subType === 'linear') || (type === 'swap') || (type === 'future')) {
1572
+ response = await this.publicLinearGetFutureMarketV1PublicQAggTickers(this.extend(request, params));
1573
+ }
1574
+ else {
1575
+ response = await this.publicSpotGetTicker24h(this.extend(request, params));
1576
+ }
1577
+ //
1578
+ // spot
1579
+ //
1580
+ // {
1581
+ // "rc": 0,
1582
+ // "mc": "SUCCESS",
1583
+ // "ma": [],
1584
+ // "result": [
1585
+ // {
1586
+ // "s": "btc_usdt",
1587
+ // "t": 1678172693931,
1588
+ // "cv": "34.00",
1589
+ // "cr": "0.0015",
1590
+ // "o": "22398.05",
1591
+ // "l": "22323.72",
1592
+ // "h": "22600.50",
1593
+ // "c": "22432.05",
1594
+ // "q": "7962.256931",
1595
+ // "v": "178675209.47416856"
1596
+ // }
1597
+ // ]
1598
+ // }
1599
+ //
1600
+ // swap and future
1601
+ //
1602
+ // {
1603
+ // "returnCode": 0,
1604
+ // "msgInfo": "success",
1605
+ // "error": null,
1606
+ // "result": [
1607
+ // {
1608
+ // "t": 1680738775108,
1609
+ // "s": "badger_usdt",
1610
+ // "c": "2.7176",
1611
+ // "h": "2.7917",
1612
+ // "l": "2.6818",
1613
+ // "a": "88332",
1614
+ // "v": "242286.3520",
1615
+ // "o": "2.7422",
1616
+ // "r": "-0.0089",
1617
+ // "i": "2.7155",
1618
+ // "m": "2.7161",
1619
+ // "bp": "2.7152",
1620
+ // "ap": "2.7176"
1621
+ // },
1622
+ // ]
1623
+ // }
1624
+ //
1625
+ const tickers = this.safeValue(response, 'result', []);
1626
+ const result = {};
1627
+ for (let i = 0; i < tickers.length; i++) {
1628
+ const ticker = this.parseTicker(tickers[i], market);
1629
+ const symbol = ticker['symbol'];
1630
+ result[symbol] = ticker;
1631
+ }
1632
+ return this.filterByArray(result, 'symbol', symbols);
1633
+ }
1634
+ async fetchBidsAsks(symbols = undefined, params = {}) {
1635
+ /**
1636
+ * @method
1637
+ * @name xt#fetchBidsAsks
1638
+ * @description fetches the bid and ask price and volume for multiple markets
1639
+ * @see https://doc.xt.com/#market9tickerBook
1640
+ * @param {string} [symbols] unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
1641
+ * @param {object} params extra parameters specific to the xt api endpoint
1642
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure}
1643
+ */
1644
+ await this.loadMarkets();
1645
+ symbols = this.marketSymbols(symbols);
1646
+ const request = {};
1647
+ let market = undefined;
1648
+ if (symbols !== undefined) {
1649
+ market = this.market(symbols[0]);
1650
+ }
1651
+ let subType = undefined;
1652
+ [subType, params] = this.handleSubTypeAndParams('fetchBidsAsks', market, params);
1653
+ if (subType !== undefined) {
1654
+ throw new NotSupported(this.id + ' fetchBidsAsks() is not available for swap and future markets, only spot markets are supported');
1655
+ }
1656
+ const response = await this.publicSpotGetTickerBook(this.extend(request, params));
1657
+ //
1658
+ // {
1659
+ // "rc": 0,
1660
+ // "mc": "SUCCESS",
1661
+ // "ma": [],
1662
+ // "result": [
1663
+ // {
1664
+ // "s": "kas_usdt",
1665
+ // "t": 1679539891853,
1666
+ // "ap": "0.016298",
1667
+ // "aq": "5119.09",
1668
+ // "bp": "0.016290",
1669
+ // "bq": "135.37"
1670
+ // },
1671
+ // ]
1672
+ // }
1673
+ //
1674
+ const tickers = this.safeValue(response, 'result', []);
1675
+ return this.parseTickers(tickers, symbols);
1676
+ }
1677
+ parseTicker(ticker, market = undefined) {
1678
+ //
1679
+ // spot: fetchTicker, fetchTickers
1680
+ //
1681
+ // {
1682
+ // "s": "btc_usdt",
1683
+ // "t": 1678172693931,
1684
+ // "cv": "34.00",
1685
+ // "cr": "0.0015",
1686
+ // "o": "22398.05",
1687
+ // "l": "22323.72",
1688
+ // "h": "22600.50",
1689
+ // "c": "22432.05",
1690
+ // "q": "7962.256931",
1691
+ // "v": "178675209.47416856"
1692
+ // }
1693
+ //
1694
+ // swap and future: fetchTicker, fetchTickers
1695
+ //
1696
+ // {
1697
+ // "t": 1678172848572,
1698
+ // "s": "btc_usdt",
1699
+ // "c": "22415.5",
1700
+ // "h": "22590.0",
1701
+ // "l": "22310.0",
1702
+ // "a": "623654031",
1703
+ // "v": "1399166074.31675",
1704
+ // "o": "22381.5",
1705
+ // "r": "0.0015",
1706
+ // "i": "22424.5",
1707
+ // "m": "22416.5",
1708
+ // "bp": "22415",
1709
+ // "ap": "22415.5"
1710
+ // }
1711
+ //
1712
+ // fetchBidsAsks
1713
+ //
1714
+ // {
1715
+ // "s": "kas_usdt",
1716
+ // "t": 1679539891853,
1717
+ // "ap": "0.016298",
1718
+ // "aq": "5119.09",
1719
+ // "bp": "0.016290",
1720
+ // "bq": "135.37"
1721
+ // }
1722
+ //
1723
+ const marketId = this.safeString(ticker, 's');
1724
+ let marketType = (market !== undefined) ? market['type'] : undefined;
1725
+ if (marketType === undefined) {
1726
+ marketType = ('cv' in ticker) || ('aq' in ticker) ? 'spot' : 'contract';
1727
+ }
1728
+ market = this.safeMarket(marketId, market, '_', marketType);
1729
+ const symbol = market['symbol'];
1730
+ const timestamp = this.safeInteger(ticker, 't');
1731
+ return this.safeTicker({
1732
+ 'symbol': symbol,
1733
+ 'timestamp': timestamp,
1734
+ 'datetime': this.iso8601(timestamp),
1735
+ 'high': this.safeNumber(ticker, 'h'),
1736
+ 'low': this.safeNumber(ticker, 'l'),
1737
+ 'bid': this.safeNumber(ticker, 'bp'),
1738
+ 'bidVolume': this.safeNumber(ticker, 'bq'),
1739
+ 'ask': this.safeNumber(ticker, 'ap'),
1740
+ 'askVolume': this.safeNumber(ticker, 'aq'),
1741
+ 'vwap': undefined,
1742
+ 'open': this.safeString(ticker, 'o'),
1743
+ 'close': this.safeString(ticker, 'c'),
1744
+ 'last': this.safeString(ticker, 'c'),
1745
+ 'previousClose': undefined,
1746
+ 'change': this.safeNumber(ticker, 'cv'),
1747
+ 'percentage': this.safeNumber2(ticker, 'cr', 'r'),
1748
+ 'average': undefined,
1749
+ 'baseVolume': undefined,
1750
+ 'quoteVolume': this.safeNumber2(ticker, 'a', 'v'),
1751
+ 'info': ticker,
1752
+ }, market);
1753
+ }
1754
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
1755
+ /**
1756
+ * @method
1757
+ * @name xt#fetchTrades
1758
+ * @description get the list of most recent trades for a particular symbol
1759
+ * @see https://doc.xt.com/#market5tradeRecent
1760
+ * @see https://doc.xt.com/#futures_quotesgetDeal
1761
+ * @param {string} symbol unified market symbol to fetch trades for
1762
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
1763
+ * @param {int} [limit] the maximum amount of trades to fetch
1764
+ * @param {object} params extra parameters specific to the xt api endpoint
1765
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
1766
+ */
1767
+ await this.loadMarkets();
1768
+ const market = this.market(symbol);
1769
+ const request = {
1770
+ 'symbol': market['id'],
1771
+ };
1772
+ let response = undefined;
1773
+ if (market['spot']) {
1774
+ if (limit !== undefined) {
1775
+ request['limit'] = limit;
1776
+ }
1777
+ response = await this.publicSpotGetTradeRecent(this.extend(request, params));
1778
+ }
1779
+ else {
1780
+ if (limit !== undefined) {
1781
+ request['num'] = limit;
1782
+ }
1783
+ if (market['linear']) {
1784
+ response = await this.publicLinearGetFutureMarketV1PublicQDeal(this.extend(request, params));
1785
+ }
1786
+ else if (market['inverse']) {
1787
+ response = await this.publicInverseGetFutureMarketV1PublicQDeal(this.extend(request, params));
1788
+ }
1789
+ }
1790
+ //
1791
+ // spot
1792
+ //
1793
+ // {
1794
+ // "rc": 0,
1795
+ // "mc": "SUCCESS",
1796
+ // "ma": [],
1797
+ // "result": [
1798
+ // {
1799
+ // "i": 203530723141917063,
1800
+ // "t": 1678227505815,
1801
+ // "p": "22038.81",
1802
+ // "q": "0.000978",
1803
+ // "v": "21.55395618",
1804
+ // "b": true
1805
+ // },
1806
+ // ]
1807
+ // }
1808
+ //
1809
+ // swap and future
1810
+ //
1811
+ // {
1812
+ // "returnCode": 0,
1813
+ // "msgInfo": "success",
1814
+ // "error": null,
1815
+ // "result": [
1816
+ // {
1817
+ // "t": 1678227683897,
1818
+ // "s": "btc_usdt",
1819
+ // "p": "22031",
1820
+ // "a": "1067",
1821
+ // "m": "BID"
1822
+ // },
1823
+ // ]
1824
+ // }
1825
+ //
1826
+ const trades = this.safeValue(response, 'result', []);
1827
+ return this.parseTrades(trades, market);
1828
+ }
1829
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1830
+ /**
1831
+ * @method
1832
+ * @name xt#fetchMyTrades
1833
+ * @description fetch all trades made by the user
1834
+ * @see https://doc.xt.com/#tradetradeGet
1835
+ * @see https://doc.xt.com/#futures_ordergetTrades
1836
+ * @param {string} [symbol] unified market symbol to fetch trades for
1837
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
1838
+ * @param {int} [limit] the maximum amount of trades to fetch
1839
+ * @param {object} params extra parameters specific to the xt api endpoint
1840
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
1841
+ */
1842
+ await this.loadMarkets();
1843
+ const request = {};
1844
+ let market = undefined;
1845
+ if (symbol !== undefined) {
1846
+ market = this.market(symbol);
1847
+ request['symbol'] = market['id'];
1848
+ }
1849
+ if (since !== undefined) {
1850
+ request['startTime'] = since;
1851
+ }
1852
+ let type = undefined;
1853
+ let subType = undefined;
1854
+ let response = undefined;
1855
+ [type, params] = this.handleMarketTypeAndParams('fetchMyTrades', market, params);
1856
+ [subType, params] = this.handleSubTypeAndParams('fetchMyTrades', market, params);
1857
+ if ((subType !== undefined) || (type === 'swap') || (type === 'future')) {
1858
+ if (limit !== undefined) {
1859
+ request['size'] = limit;
1860
+ }
1861
+ if (subType === 'inverse') {
1862
+ response = await this.privateInverseGetFutureTradeV1OrderTradeList(this.extend(request, params));
1863
+ }
1864
+ else {
1865
+ response = await this.privateLinearGetFutureTradeV1OrderTradeList(this.extend(request, params));
1866
+ }
1867
+ }
1868
+ else {
1869
+ let marginMode = undefined;
1870
+ [marginMode, params] = this.handleMarginModeAndParams('fetchMyTrades', params);
1871
+ const marginOrSpotRequest = (marginMode !== undefined) ? 'LEVER' : 'SPOT';
1872
+ request['bizType'] = marginOrSpotRequest;
1873
+ if (limit !== undefined) {
1874
+ request['limit'] = limit;
1875
+ }
1876
+ response = await this.privateSpotGetTrade(this.extend(request, params));
1877
+ }
1878
+ //
1879
+ // spot and margin
1880
+ //
1881
+ // {
1882
+ // "rc": 0,
1883
+ // "mc": "SUCCESS",
1884
+ // "ma": [],
1885
+ // "result": {
1886
+ // "hasPrev": false,
1887
+ // "hasNext": false,
1888
+ // "items": [
1889
+ // {
1890
+ // "symbol": "btc_usdt",
1891
+ // "tradeId": "206906233569974658",
1892
+ // "orderId": "206906233178463488",
1893
+ // "orderSide": "SELL",
1894
+ // "orderType": "MARKET",
1895
+ // "bizType": "SPOT",
1896
+ // "time": 1679032290215,
1897
+ // "price": "25703.46",
1898
+ // "quantity": "0.000099",
1899
+ // "quoteQty": "2.54464254",
1900
+ // "baseCurrency": "btc",
1901
+ // "quoteCurrency": "usdt",
1902
+ // "fee": "0.00508929",
1903
+ // "feeCurrency": "usdt",
1904
+ // "takerMaker": "TAKER"
1905
+ // },
1906
+ // ]
1907
+ // }
1908
+ // }
1909
+ //
1910
+ // swap and future
1911
+ //
1912
+ // {
1913
+ // "returnCode": 0,
1914
+ // "msgInfo": "success",
1915
+ // "error": null,
1916
+ // "result": {
1917
+ // "page": 1,
1918
+ // "ps": 10,
1919
+ // "total": 2,
1920
+ // "items": [
1921
+ // {
1922
+ // "orderId": "207260566170987200",
1923
+ // "execId": "207260566790603265",
1924
+ // "symbol": "btc_usdt",
1925
+ // "quantity": "13",
1926
+ // "price": "27368",
1927
+ // "fee": "0.02134704",
1928
+ // "feeCoin": "usdt",
1929
+ // "timestamp": 1679116769838,
1930
+ // "takerMaker": "TAKER"
1931
+ // },
1932
+ // ]
1933
+ // }
1934
+ // }
1935
+ //
1936
+ const data = this.safeValue(response, 'result', {});
1937
+ const trades = this.safeValue(data, 'items', []);
1938
+ return this.parseTrades(trades, market, since, limit);
1939
+ }
1940
+ parseTrade(trade, market = undefined) {
1941
+ //
1942
+ // spot: fetchTrades
1943
+ //
1944
+ // {
1945
+ // "i": 203530723141917063,
1946
+ // "t": 1678227505815,
1947
+ // "p": "22038.81",
1948
+ // "q": "0.000978",
1949
+ // "v": "21.55395618",
1950
+ // "b": true
1951
+ // }
1952
+ //
1953
+ // swap and future: fetchTrades
1954
+ //
1955
+ // {
1956
+ // "t": 1678227683897,
1957
+ // "s": "btc_usdt",
1958
+ // "p": "22031",
1959
+ // "a": "1067",
1960
+ // "m": "BID"
1961
+ // }
1962
+ //
1963
+ // spot: fetchMyTrades
1964
+ //
1965
+ // {
1966
+ // "symbol": "btc_usdt",
1967
+ // "tradeId": "206906233569974658",
1968
+ // "orderId": "206906233178463488",
1969
+ // "orderSide": "SELL",
1970
+ // "orderType": "MARKET",
1971
+ // "bizType": "SPOT",
1972
+ // "time": 1679032290215,
1973
+ // "price": "25703.46",
1974
+ // "quantity": "0.000099",
1975
+ // "quoteQty": "2.54464254",
1976
+ // "baseCurrency": "btc",
1977
+ // "quoteCurrency": "usdt",
1978
+ // "fee": "0.00508929",
1979
+ // "feeCurrency": "usdt",
1980
+ // "takerMaker": "TAKER"
1981
+ // }
1982
+ //
1983
+ // swap and future: fetchMyTrades
1984
+ //
1985
+ // {
1986
+ // "orderId": "207260566170987200",
1987
+ // "execId": "207260566790603265",
1988
+ // "symbol": "btc_usdt",
1989
+ // "quantity": "13",
1990
+ // "price": "27368",
1991
+ // "fee": "0.02134704",
1992
+ // "feeCoin": "usdt",
1993
+ // "timestamp": 1679116769838,
1994
+ // "takerMaker": "TAKER"
1995
+ // }
1996
+ //
1997
+ const marketId = this.safeString2(trade, 's', 'symbol');
1998
+ let marketType = (market !== undefined) ? market['type'] : undefined;
1999
+ if (marketType === undefined) {
2000
+ marketType = ('b' in trade) || ('bizType' in trade) ? 'spot' : 'contract';
2001
+ }
2002
+ market = this.safeMarket(marketId, market, '_', marketType);
2003
+ const bidOrAsk = this.safeString(trade, 'm');
2004
+ let side = this.safeStringLower(trade, 'orderSide');
2005
+ if (bidOrAsk !== undefined) {
2006
+ side = (bidOrAsk === 'BID') ? 'buy' : 'sell';
2007
+ }
2008
+ const buyerMaker = this.safeValue(trade, 'b');
2009
+ let takerOrMaker = this.safeStringLower(trade, 'takerMaker');
2010
+ if (buyerMaker !== undefined) {
2011
+ takerOrMaker = buyerMaker ? 'maker' : 'taker';
2012
+ }
2013
+ const timestamp = this.safeIntegerN(trade, ['t', 'time', 'timestamp']);
2014
+ const quantity = this.safeString2(trade, 'q', 'quantity');
2015
+ let amount = undefined;
2016
+ if (marketType === 'spot') {
2017
+ amount = quantity;
2018
+ }
2019
+ else {
2020
+ if (quantity === undefined) {
2021
+ amount = Precise.stringMul(this.safeString(trade, 'a'), this.numberToString(market['contractSize']));
2022
+ }
2023
+ else {
2024
+ amount = Precise.stringMul(quantity, this.numberToString(market['contractSize']));
2025
+ }
2026
+ }
2027
+ return this.safeTrade({
2028
+ 'info': trade,
2029
+ 'id': this.safeStringN(trade, ['i', 'tradeId', 'execId']),
2030
+ 'timestamp': timestamp,
2031
+ 'datetime': this.iso8601(timestamp),
2032
+ 'symbol': market['symbol'],
2033
+ 'order': this.safeString(trade, 'orderId'),
2034
+ 'type': this.safeStringLower(trade, 'orderType'),
2035
+ 'side': side,
2036
+ 'takerOrMaker': takerOrMaker,
2037
+ 'price': this.safeString2(trade, 'p', 'price'),
2038
+ 'amount': amount,
2039
+ 'cost': undefined,
2040
+ 'fee': {
2041
+ 'currency': this.safeCurrencyCode(this.safeString2(trade, 'feeCurrency', 'feeCoin')),
2042
+ 'cost': this.safeString(trade, 'fee'),
2043
+ 'rate': undefined,
2044
+ },
2045
+ }, market);
2046
+ }
2047
+ async fetchBalance(params = {}) {
2048
+ /**
2049
+ * @method
2050
+ * @name xt#fetchBalance
2051
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
2052
+ * @see https://doc.xt.com/#balancebalancesGet
2053
+ * @see https://doc.xt.com/#futures_usergetBalances
2054
+ * @param {object} params extra parameters specific to the xt api endpoint
2055
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/en/latest/manual.html?#balance-structure}
2056
+ */
2057
+ await this.loadMarkets();
2058
+ let type = undefined;
2059
+ let subType = undefined;
2060
+ let response = undefined;
2061
+ [type, params] = this.handleMarketTypeAndParams('fetchBalance', undefined, params);
2062
+ [subType, params] = this.handleSubTypeAndParams('fetchBalance', undefined, params);
2063
+ const isContractWallet = ((type === 'swap') || (type === 'future'));
2064
+ if (subType === 'inverse') {
2065
+ response = await this.privateInverseGetFutureUserV1BalanceList(params);
2066
+ }
2067
+ else if ((subType === 'linear') || isContractWallet) {
2068
+ response = await this.privateLinearGetFutureUserV1BalanceList(params);
2069
+ }
2070
+ else {
2071
+ response = await this.privateSpotGetBalances(params);
2072
+ }
2073
+ //
2074
+ // spot
2075
+ //
2076
+ // {
2077
+ // "rc": 0,
2078
+ // "mc": "SUCCESS",
2079
+ // "ma": [],
2080
+ // "result": {
2081
+ // "totalUsdtAmount": "31.75931133",
2082
+ // "totalBtcAmount": "0.00115951",
2083
+ // "assets": [
2084
+ // {
2085
+ // "currency": "usdt",
2086
+ // "currencyId": 11,
2087
+ // "frozenAmount": "0.03834082",
2088
+ // "availableAmount": "31.70995965",
2089
+ // "totalAmount": "31.74830047",
2090
+ // "convertBtcAmount": "0.00115911",
2091
+ // "convertUsdtAmount": "31.74830047"
2092
+ // },
2093
+ // ]
2094
+ // }
2095
+ // }
2096
+ //
2097
+ // swap and future
2098
+ //
2099
+ // {
2100
+ // "returnCode": 0,
2101
+ // "msgInfo": "success",
2102
+ // "error": null,
2103
+ // "result": [
2104
+ // {
2105
+ // "coin": "usdt",
2106
+ // "walletBalance": "19.29849875",
2107
+ // "openOrderMarginFrozen": "0",
2108
+ // "isolatedMargin": "0.709475",
2109
+ // "crossedMargin": "0",
2110
+ // "availableBalance": "18.58902375",
2111
+ // "bonus": "0",
2112
+ // "coupon":"0"
2113
+ // }
2114
+ // ]
2115
+ // }
2116
+ //
2117
+ let balances = undefined;
2118
+ if ((subType !== undefined) || isContractWallet) {
2119
+ balances = this.safeValue(response, 'result', []);
2120
+ }
2121
+ else {
2122
+ const data = this.safeValue(response, 'result', {});
2123
+ balances = this.safeValue(data, 'assets', []);
2124
+ }
2125
+ return this.parseBalance(balances);
2126
+ }
2127
+ parseBalance(response) {
2128
+ //
2129
+ // spot
2130
+ //
2131
+ // {
2132
+ // "currency": "usdt",
2133
+ // "currencyId": 11,
2134
+ // "frozenAmount": "0.03834082",
2135
+ // "availableAmount": "31.70995965",
2136
+ // "totalAmount": "31.74830047",
2137
+ // "convertBtcAmount": "0.00115911",
2138
+ // "convertUsdtAmount": "31.74830047"
2139
+ // }
2140
+ //
2141
+ // swap and future
2142
+ //
2143
+ // {
2144
+ // "coin": "usdt",
2145
+ // "walletBalance": "19.29849875",
2146
+ // "openOrderMarginFrozen": "0",
2147
+ // "isolatedMargin": "0.709475",
2148
+ // "crossedMargin": "0",
2149
+ // "availableBalance": "18.58902375",
2150
+ // "bonus": "0",
2151
+ // "coupon":"0"
2152
+ // }
2153
+ //
2154
+ const result = { 'info': response };
2155
+ for (let i = 0; i < response.length; i++) {
2156
+ const balance = response[i];
2157
+ const currencyId = this.safeString2(balance, 'currency', 'coin');
2158
+ const code = this.safeCurrencyCode(currencyId);
2159
+ const account = this.account();
2160
+ const free = this.safeString2(balance, 'availableAmount', 'availableBalance');
2161
+ let used = this.safeString(balance, 'frozenAmount');
2162
+ const total = this.safeString2(balance, 'totalAmount', 'walletBalance');
2163
+ if (used === undefined) {
2164
+ const crossedAndIsolatedMargin = Precise.stringAdd(this.safeString(balance, 'crossedMargin'), this.safeString(balance, 'isolatedMargin'));
2165
+ used = Precise.stringAdd(this.safeString(balance, 'openOrderMarginFrozen'), crossedAndIsolatedMargin);
2166
+ }
2167
+ account['free'] = free;
2168
+ account['used'] = used;
2169
+ account['total'] = total;
2170
+ result[code] = account;
2171
+ }
2172
+ return this.safeBalance(result);
2173
+ }
2174
+ async createMarketBuyOrderWithCost(symbol, cost, params = {}) {
2175
+ /**
2176
+ * @method
2177
+ * @name xt#createMarketBuyOrderWithCost
2178
+ * @see https://doc.xt.com/#orderorderPost
2179
+ * @description create a market buy order by providing the symbol and cost
2180
+ * @param {string} symbol unified symbol of the market to create an order in
2181
+ * @param {float} cost how much you want to trade in units of the quote currency
2182
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2183
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2184
+ */
2185
+ await this.loadMarkets();
2186
+ const market = this.market(symbol);
2187
+ if (!market['spot']) {
2188
+ throw new NotSupported(this.id + ' createMarketBuyOrderWithCost() supports spot orders only');
2189
+ }
2190
+ return await this.createOrder(symbol, 'market', 'buy', cost, 1, params);
2191
+ }
2192
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
2193
+ /**
2194
+ * @method
2195
+ * @name xt#createOrder
2196
+ * @description create a trade order
2197
+ * @see https://doc.xt.com/#orderorderPost
2198
+ * @see https://doc.xt.com/#futures_ordercreate
2199
+ * @see https://doc.xt.com/#futures_entrustcreatePlan
2200
+ * @see https://doc.xt.com/#futures_entrustcreateProfit
2201
+ * @param {string} symbol unified symbol of the market to create an order in
2202
+ * @param {string} type 'market' or 'limit'
2203
+ * @param {string} side 'buy' or 'sell'
2204
+ * @param {float} amount how much you want to trade in units of the base currency
2205
+ * @param {float} [price] the price to fulfill the order, in units of the quote currency, can be ignored in market orders
2206
+ * @param {object} params extra parameters specific to the xt api endpoint
2207
+ * @param {string} [params.timeInForce] 'GTC', 'IOC', 'FOK' or 'GTX'
2208
+ * @param {string} [params.entrustType] 'TAKE_PROFIT', 'STOP', 'TAKE_PROFIT_MARKET', 'STOP_MARKET', 'TRAILING_STOP_MARKET', required if stopPrice is defined, currently isn't functioning on xt's side
2209
+ * @param {string} [params.triggerPriceType] 'INDEX_PRICE', 'MARK_PRICE', 'LATEST_PRICE', required if stopPrice is defined
2210
+ * @param {float} [params.stopPrice] price to trigger a stop order
2211
+ * @param {float} [params.stopLoss] price to set a stop-loss on an open position
2212
+ * @param {float} [params.takeProfit] price to set a take-profit on an open position
2213
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
2214
+ */
2215
+ await this.loadMarkets();
2216
+ const market = this.market(symbol);
2217
+ symbol = market['symbol'];
2218
+ if (market['spot']) {
2219
+ return await this.createSpotOrder(symbol, type, side, amount, price, params);
2220
+ }
2221
+ else {
2222
+ return await this.createContractOrder(symbol, type, side, amount, price, params);
2223
+ }
2224
+ }
2225
+ async createSpotOrder(symbol, type, side, amount, price = undefined, params = {}) {
2226
+ await this.loadMarkets();
2227
+ const market = this.market(symbol);
2228
+ const request = {
2229
+ 'symbol': market['id'],
2230
+ 'side': side.toUpperCase(),
2231
+ 'type': type.toUpperCase(),
2232
+ };
2233
+ let timeInForce = undefined;
2234
+ let marginMode = undefined;
2235
+ [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
2236
+ const marginOrSpotRequest = (marginMode !== undefined) ? 'LEVER' : 'SPOT';
2237
+ request['bizType'] = marginOrSpotRequest;
2238
+ if (type === 'market') {
2239
+ timeInForce = this.safeStringUpper(params, 'timeInForce', 'FOK');
2240
+ if (side === 'buy') {
2241
+ const cost = this.safeString(params, 'cost');
2242
+ params = this.omit(params, 'cost');
2243
+ const createMarketBuyOrderRequiresPrice = this.safeBool(this.options, 'createMarketBuyOrderRequiresPrice', true);
2244
+ if (createMarketBuyOrderRequiresPrice) {
2245
+ if (price === undefined && (cost === undefined)) {
2246
+ throw new InvalidOrder(this.id + ' createOrder() requires a price argument or cost in params for market buy orders on spot markets to calculate the total amount to spend (amount * price), alternatively set the createMarketBuyOrderRequiresPrice option to false and pass in the cost to spend into the amount parameter');
2247
+ }
2248
+ else {
2249
+ const amountString = this.numberToString(amount);
2250
+ const priceString = this.numberToString(price);
2251
+ let costCalculated = undefined;
2252
+ if (price !== undefined) {
2253
+ costCalculated = Precise.stringMul(amountString, priceString);
2254
+ }
2255
+ else {
2256
+ costCalculated = cost;
2257
+ }
2258
+ request['quoteQty'] = this.costToPrecision(symbol, costCalculated);
2259
+ }
2260
+ }
2261
+ else {
2262
+ const amountCost = (cost !== undefined) ? cost : amount;
2263
+ request['quoteQty'] = this.costToPrecision(symbol, amountCost);
2264
+ }
2265
+ }
2266
+ }
2267
+ else {
2268
+ timeInForce = this.safeStringUpper(params, 'timeInForce', 'GTC');
2269
+ request['price'] = this.priceToPrecision(symbol, price);
2270
+ }
2271
+ if ((side === 'sell') || (type === 'limit')) {
2272
+ request['quantity'] = this.amountToPrecision(symbol, amount);
2273
+ }
2274
+ request['timeInForce'] = timeInForce;
2275
+ const response = await this.privateSpotPostOrder(this.extend(request, params));
2276
+ //
2277
+ // {
2278
+ // "rc": 0,
2279
+ // "mc": "SUCCESS",
2280
+ // "ma": [],
2281
+ // "result": {
2282
+ // "orderId": "204371980095156544"
2283
+ // }
2284
+ // }
2285
+ //
2286
+ const order = this.safeValue(response, 'result', {});
2287
+ return this.parseOrder(order, market);
2288
+ }
2289
+ async createContractOrder(symbol, type, side, amount, price = undefined, params = {}) {
2290
+ await this.loadMarkets();
2291
+ const market = this.market(symbol);
2292
+ const request = {
2293
+ 'symbol': market['id'],
2294
+ 'origQty': this.amountToPrecision(symbol, amount),
2295
+ };
2296
+ const timeInForce = this.safeStringUpper(params, 'timeInForce');
2297
+ if (timeInForce !== undefined) {
2298
+ request['timeInForce'] = timeInForce;
2299
+ }
2300
+ const reduceOnly = this.safeValue(params, 'reduceOnly', false);
2301
+ if (side === 'buy') {
2302
+ const requestType = (reduceOnly) ? 'SHORT' : 'LONG';
2303
+ request['positionSide'] = requestType;
2304
+ }
2305
+ else {
2306
+ const requestType = (reduceOnly) ? 'LONG' : 'SHORT';
2307
+ request['positionSide'] = requestType;
2308
+ }
2309
+ let response = undefined;
2310
+ const triggerPrice = this.safeNumber2(params, 'triggerPrice', 'stopPrice');
2311
+ const stopLoss = this.safeNumber2(params, 'stopLoss', 'triggerStopPrice');
2312
+ const takeProfit = this.safeNumber2(params, 'takeProfit', 'triggerProfitPrice');
2313
+ const isTrigger = (triggerPrice !== undefined);
2314
+ const isStopLoss = (stopLoss !== undefined);
2315
+ const isTakeProfit = (takeProfit !== undefined);
2316
+ if (price !== undefined) {
2317
+ if (!(isStopLoss) && !(isTakeProfit)) {
2318
+ request['price'] = this.priceToPrecision(symbol, price);
2319
+ }
2320
+ }
2321
+ if (isTrigger) {
2322
+ request['timeInForce'] = this.safeStringUpper(params, 'timeInForce', 'GTC');
2323
+ request['triggerPriceType'] = this.safeString(params, 'triggerPriceType', 'LATEST_PRICE');
2324
+ request['orderSide'] = side.toUpperCase();
2325
+ request['stopPrice'] = this.priceToPrecision(symbol, triggerPrice);
2326
+ const entrustType = (type === 'market') ? 'STOP_MARKET' : 'STOP';
2327
+ request['entrustType'] = entrustType;
2328
+ params = this.omit(params, 'triggerPrice');
2329
+ if (market['linear']) {
2330
+ response = await this.privateLinearPostFutureTradeV1EntrustCreatePlan(this.extend(request, params));
2331
+ }
2332
+ else if (market['inverse']) {
2333
+ response = await this.privateInversePostFutureTradeV1EntrustCreatePlan(this.extend(request, params));
2334
+ }
2335
+ }
2336
+ else if (isStopLoss || isTakeProfit) {
2337
+ if (isStopLoss) {
2338
+ request['triggerStopPrice'] = this.priceToPrecision(symbol, stopLoss);
2339
+ }
2340
+ else {
2341
+ request['triggerProfitPrice'] = this.priceToPrecision(symbol, takeProfit);
2342
+ }
2343
+ params = this.omit(params, ['stopLoss', 'takeProfit']);
2344
+ if (market['linear']) {
2345
+ response = await this.privateLinearPostFutureTradeV1EntrustCreateProfit(this.extend(request, params));
2346
+ }
2347
+ else if (market['inverse']) {
2348
+ response = await this.privateInversePostFutureTradeV1EntrustCreateProfit(this.extend(request, params));
2349
+ }
2350
+ }
2351
+ else {
2352
+ request['orderSide'] = side.toUpperCase();
2353
+ request['orderType'] = type.toUpperCase();
2354
+ if (market['linear']) {
2355
+ response = await this.privateLinearPostFutureTradeV1OrderCreate(this.extend(request, params));
2356
+ }
2357
+ else if (market['inverse']) {
2358
+ response = await this.privateInversePostFutureTradeV1OrderCreate(this.extend(request, params));
2359
+ }
2360
+ }
2361
+ //
2362
+ // {
2363
+ // "returnCode": 0,
2364
+ // "msgInfo": "success",
2365
+ // "error": null,
2366
+ // "result": "206410760006650176"
2367
+ // }
2368
+ //
2369
+ return this.parseOrder(response, market);
2370
+ }
2371
+ async fetchOrder(id, symbol = undefined, params = {}) {
2372
+ /**
2373
+ * @method
2374
+ * @name xt#fetchOrder
2375
+ * @description fetches information on an order made by the user
2376
+ * @see https://doc.xt.com/#orderorderGet
2377
+ * @see https://doc.xt.com/#futures_ordergetById
2378
+ * @see https://doc.xt.com/#futures_entrustgetPlanById
2379
+ * @see https://doc.xt.com/#futures_entrustgetProfitById
2380
+ * @param {string} id order id
2381
+ * @param {string} [symbol] unified symbol of the market the order was made in
2382
+ * @param {object} params extra parameters specific to the xt api endpoint
2383
+ * @param {bool} [params.stop] if the order is a stop trigger order or not
2384
+ * @param {bool} [params.stopLossTakeProfit] if the order is a stop-loss or take-profit order
2385
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
2386
+ */
2387
+ await this.loadMarkets();
2388
+ let market = undefined;
2389
+ if (symbol !== undefined) {
2390
+ market = this.market(symbol);
2391
+ }
2392
+ const request = {};
2393
+ let type = undefined;
2394
+ let subType = undefined;
2395
+ let response = undefined;
2396
+ [type, params] = this.handleMarketTypeAndParams('fetchOrder', market, params);
2397
+ [subType, params] = this.handleSubTypeAndParams('fetchOrder', market, params);
2398
+ const stop = this.safeValue(params, 'stop');
2399
+ const stopLossTakeProfit = this.safeValue(params, 'stopLossTakeProfit');
2400
+ if (stop) {
2401
+ request['entrustId'] = id;
2402
+ }
2403
+ else if (stopLossTakeProfit) {
2404
+ request['profitId'] = id;
2405
+ }
2406
+ else {
2407
+ request['orderId'] = id;
2408
+ }
2409
+ if (stop) {
2410
+ params = this.omit(params, 'stop');
2411
+ if (subType === 'inverse') {
2412
+ response = await this.privateInverseGetFutureTradeV1EntrustPlanDetail(this.extend(request, params));
2413
+ }
2414
+ else {
2415
+ response = await this.privateLinearGetFutureTradeV1EntrustPlanDetail(this.extend(request, params));
2416
+ }
2417
+ }
2418
+ else if (stopLossTakeProfit) {
2419
+ params = this.omit(params, 'stopLossTakeProfit');
2420
+ if (subType === 'inverse') {
2421
+ response = await this.privateInverseGetFutureTradeV1EntrustProfitDetail(this.extend(request, params));
2422
+ }
2423
+ else {
2424
+ response = await this.privateLinearGetFutureTradeV1EntrustProfitDetail(this.extend(request, params));
2425
+ }
2426
+ }
2427
+ else if (subType === 'inverse') {
2428
+ response = await this.privateInverseGetFutureTradeV1OrderDetail(this.extend(request, params));
2429
+ }
2430
+ else if ((subType === 'linear') || (type === 'swap') || (type === 'future')) {
2431
+ response = await this.privateLinearGetFutureTradeV1OrderDetail(this.extend(request, params));
2432
+ }
2433
+ else {
2434
+ response = await this.privateSpotGetOrderOrderId(this.extend(request, params));
2435
+ }
2436
+ //
2437
+ // spot
2438
+ //
2439
+ // {
2440
+ // "rc": 0,
2441
+ // "mc": "SUCCESS",
2442
+ // "ma": [],
2443
+ // "result": {
2444
+ // "symbol": "btc_usdt",
2445
+ // "orderId": "207505997850909952",
2446
+ // "clientOrderId": null,
2447
+ // "baseCurrency": "btc",
2448
+ // "quoteCurrency": "usdt",
2449
+ // "side": "BUY",
2450
+ // "type": "LIMIT",
2451
+ // "timeInForce": "GTC",
2452
+ // "price": "20000.00",
2453
+ // "origQty": "0.001000",
2454
+ // "origQuoteQty": "20.00",
2455
+ // "executedQty": "0.000000",
2456
+ // "leavingQty": "0.001000",
2457
+ // "tradeBase": "0.000000",
2458
+ // "tradeQuote": "0.00",
2459
+ // "avgPrice": null,
2460
+ // "fee": null,
2461
+ // "feeCurrency": null,
2462
+ // "closed": false,
2463
+ // "state": "NEW",
2464
+ // "time": 1679175285162,
2465
+ // "updatedTime": 1679175285255
2466
+ // }
2467
+ // }
2468
+ //
2469
+ // swap and future
2470
+ //
2471
+ // {
2472
+ // "returnCode": 0,
2473
+ // "msgInfo": "success",
2474
+ // "error": null,
2475
+ // "result": {
2476
+ // "orderId": "211451874783183936",
2477
+ // "clientOrderId": null,
2478
+ // "symbol": "btc_usdt",
2479
+ // "orderType": "LIMIT",
2480
+ // "orderSide": "BUY",
2481
+ // "positionSide": "LONG",
2482
+ // "timeInForce": "GTC",
2483
+ // "closePosition": false,
2484
+ // "price": "20000",
2485
+ // "origQty": "10",
2486
+ // "avgPrice": "0",
2487
+ // "executedQty": "0",
2488
+ // "marginFrozen": "1.34533334",
2489
+ // "remark": null,
2490
+ // "triggerProfitPrice": null,
2491
+ // "triggerStopPrice": null,
2492
+ // "sourceId": null,
2493
+ // "sourceType": "DEFAULT",
2494
+ // "forceClose": false,
2495
+ // "closeProfit": null,
2496
+ // "state": "NEW",
2497
+ // "createdTime": 1680116055693,
2498
+ // "updatedTime": 1680116055693
2499
+ // }
2500
+ // }
2501
+ //
2502
+ // trigger
2503
+ //
2504
+ // {
2505
+ // "returnCode": 0,
2506
+ // "msgInfo": "success",
2507
+ // "error": null,
2508
+ // "result": {
2509
+ // "entrustId": "216300248132756992",
2510
+ // "symbol": "btc_usdt",
2511
+ // "entrustType": "STOP",
2512
+ // "orderSide": "SELL",
2513
+ // "positionSide": "SHORT",
2514
+ // "timeInForce": "GTC",
2515
+ // "closePosition": null,
2516
+ // "price": "20000",
2517
+ // "origQty": "1",
2518
+ // "stopPrice": "19000",
2519
+ // "triggerPriceType": "LATEST_PRICE",
2520
+ // "state": "NOT_TRIGGERED",
2521
+ // "marketOrderLevel": null,
2522
+ // "createdTime": 1681271998064,
2523
+ // "updatedTime": 1681271998064,
2524
+ // "ordinary": false
2525
+ // }
2526
+ // }
2527
+ //
2528
+ // stop-loss and take-profit
2529
+ //
2530
+ // {
2531
+ // "returnCode": 0,
2532
+ // "msgInfo": "success",
2533
+ // "error": null,
2534
+ // "result": {
2535
+ // "profitId": "216306213226230400",
2536
+ // "symbol": "btc_usdt",
2537
+ // "positionSide": "LONG",
2538
+ // "origQty": "1",
2539
+ // "triggerPriceType": "LATEST_PRICE",
2540
+ // "triggerProfitPrice": null,
2541
+ // "triggerStopPrice": "20000",
2542
+ // "entryPrice": null,
2543
+ // "positionSize": null,
2544
+ // "isolatedMargin": null,
2545
+ // "executedQty": null,
2546
+ // "avgPrice": null,
2547
+ // "positionType": "ISOLATED",
2548
+ // "state": "NOT_TRIGGERED",
2549
+ // "createdTime": 1681273420039
2550
+ // }
2551
+ // }
2552
+ //
2553
+ const order = this.safeValue(response, 'result', {});
2554
+ return this.parseOrder(order, market);
2555
+ }
2556
+ async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2557
+ /**
2558
+ * @method
2559
+ * @name xt#fetchOrders
2560
+ * @description fetches information on multiple orders made by the user
2561
+ * @see https://doc.xt.com/#orderhistoryOrderGet
2562
+ * @see https://doc.xt.com/#futures_ordergetHistory
2563
+ * @see https://doc.xt.com/#futures_entrustgetPlanHistory
2564
+ * @param {string} [symbol] unified market symbol of the market the orders were made in
2565
+ * @param {int} [since] timestamp in ms of the earliest order
2566
+ * @param {int} [limit] the maximum number of order structures to retrieve
2567
+ * @param {object} params extra parameters specific to the xt api endpoint
2568
+ * @param {bool} [params.stop] if the order is a stop trigger order or not
2569
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
2570
+ */
2571
+ await this.loadMarkets();
2572
+ const request = {};
2573
+ let market = undefined;
2574
+ if (symbol !== undefined) {
2575
+ market = this.market(symbol);
2576
+ request['symbol'] = market['id'];
2577
+ }
2578
+ if (since !== undefined) {
2579
+ request['startTime'] = since;
2580
+ }
2581
+ if (limit !== undefined) {
2582
+ request['limit'] = limit;
2583
+ }
2584
+ let type = undefined;
2585
+ let subType = undefined;
2586
+ let response = undefined;
2587
+ [type, params] = this.handleMarketTypeAndParams('fetchOrders', market, params);
2588
+ [subType, params] = this.handleSubTypeAndParams('fetchOrders', market, params);
2589
+ const stop = this.safeValue(params, 'stop');
2590
+ if (stop) {
2591
+ params = this.omit(params, 'stop');
2592
+ if (subType === 'inverse') {
2593
+ response = await this.privateInverseGetFutureTradeV1EntrustPlanListHistory(this.extend(request, params));
2594
+ }
2595
+ else {
2596
+ response = await this.privateLinearGetFutureTradeV1EntrustPlanListHistory(this.extend(request, params));
2597
+ }
2598
+ }
2599
+ else if (subType === 'inverse') {
2600
+ response = await this.privateInverseGetFutureTradeV1OrderListHistory(this.extend(request, params));
2601
+ }
2602
+ else if ((subType === 'linear') || (type === 'swap') || (type === 'future')) {
2603
+ response = await this.privateLinearGetFutureTradeV1OrderListHistory(this.extend(request, params));
2604
+ }
2605
+ else {
2606
+ let marginMode = undefined;
2607
+ [marginMode, params] = this.handleMarginModeAndParams('fetchOrders', params);
2608
+ const marginOrSpotRequest = (marginMode !== undefined) ? 'LEVER' : 'SPOT';
2609
+ request['bizType'] = marginOrSpotRequest;
2610
+ response = await this.privateSpotGetHistoryOrder(this.extend(request, params));
2611
+ }
2612
+ //
2613
+ // spot and margin
2614
+ //
2615
+ // {
2616
+ // "rc": 0,
2617
+ // "mc": "SUCCESS",
2618
+ // "ma": [],
2619
+ // "result": {
2620
+ // "hasPrev": false,
2621
+ // "hasNext": true,
2622
+ // "items": [
2623
+ // {
2624
+ // "symbol": "btc_usdt",
2625
+ // "orderId": "207505997850909952",
2626
+ // "clientOrderId": null,
2627
+ // "baseCurrency": "btc",
2628
+ // "quoteCurrency": "usdt",
2629
+ // "side": "BUY",
2630
+ // "type": "LIMIT",
2631
+ // "timeInForce": "GTC",
2632
+ // "price": "20000.00",
2633
+ // "origQty": "0.001000",
2634
+ // "origQuoteQty": "20.00",
2635
+ // "executedQty": "0.000000",
2636
+ // "leavingQty": "0.000000",
2637
+ // "tradeBase": "0.000000",
2638
+ // "tradeQuote": "0.00",
2639
+ // "avgPrice": null,
2640
+ // "fee": null,
2641
+ // "feeCurrency": null,
2642
+ // "closed": true,
2643
+ // "state": "CANCELED",
2644
+ // "time": 1679175285162,
2645
+ // "updatedTime": 1679175488492
2646
+ // },
2647
+ // ]
2648
+ // }
2649
+ // }
2650
+ //
2651
+ // swap and future
2652
+ //
2653
+ // {
2654
+ // "returnCode": 0,
2655
+ // "msgInfo": "success",
2656
+ // "error": null,
2657
+ // "result": {
2658
+ // "hasPrev": false,
2659
+ // "hasNext": true,
2660
+ // "items": [
2661
+ // {
2662
+ // "orderId": "207519546930995456",
2663
+ // "clientOrderId": null,
2664
+ // "symbol": "btc_usdt",
2665
+ // "orderType": "LIMIT",
2666
+ // "orderSide": "BUY",
2667
+ // "positionSide": "LONG",
2668
+ // "timeInForce": "GTC",
2669
+ // "closePosition": false,
2670
+ // "price": "20000",
2671
+ // "origQty": "100",
2672
+ // "avgPrice": "0",
2673
+ // "executedQty": "0",
2674
+ // "marginFrozen": "4.12",
2675
+ // "remark": null,
2676
+ // "triggerProfitPrice": null,
2677
+ // "triggerStopPrice": null,
2678
+ // "sourceId": null,
2679
+ // "sourceType": "DEFAULT",
2680
+ // "forceClose": false,
2681
+ // "closeProfit": null,
2682
+ // "state": "CANCELED",
2683
+ // "createdTime": 1679178515689,
2684
+ // "updatedTime": 1679180096172
2685
+ // },
2686
+ // ]
2687
+ // }
2688
+ // }
2689
+ //
2690
+ // stop
2691
+ //
2692
+ // {
2693
+ // "returnCode": 0,
2694
+ // "msgInfo": "success",
2695
+ // "error": null,
2696
+ // "result": {
2697
+ // "hasPrev": false,
2698
+ // "hasNext": false,
2699
+ // "items": [
2700
+ // {
2701
+ // "entrustId": "216300248132756992",
2702
+ // "symbol": "btc_usdt",
2703
+ // "entrustType": "STOP",
2704
+ // "orderSide": "SELL",
2705
+ // "positionSide": "SHORT",
2706
+ // "timeInForce": "GTC",
2707
+ // "closePosition": null,
2708
+ // "price": "20000",
2709
+ // "origQty": "1",
2710
+ // "stopPrice": "19000",
2711
+ // "triggerPriceType": "LATEST_PRICE",
2712
+ // "state": "USER_REVOCATION",
2713
+ // "marketOrderLevel": null,
2714
+ // "createdTime": 1681271998064,
2715
+ // "updatedTime": 1681273188674,
2716
+ // "ordinary": false
2717
+ // },
2718
+ // ]
2719
+ // }
2720
+ // }
2721
+ //
2722
+ const data = this.safeValue(response, 'result', {});
2723
+ const orders = this.safeValue(data, 'items', []);
2724
+ return this.parseOrders(orders, market, since, limit);
2725
+ }
2726
+ async fetchOrdersByStatus(status, symbol = undefined, since = undefined, limit = undefined, params = {}) {
2727
+ await this.loadMarkets();
2728
+ const request = {};
2729
+ let market = undefined;
2730
+ if (symbol !== undefined) {
2731
+ market = this.market(symbol);
2732
+ request['symbol'] = market['id'];
2733
+ }
2734
+ let type = undefined;
2735
+ let subType = undefined;
2736
+ let response = undefined;
2737
+ [type, params] = this.handleMarketTypeAndParams('fetchOrdersByStatus', market, params);
2738
+ [subType, params] = this.handleSubTypeAndParams('fetchOrdersByStatus', market, params);
2739
+ const stop = this.safeValue(params, 'stop');
2740
+ const stopLossTakeProfit = this.safeValue(params, 'stopLossTakeProfit');
2741
+ if (status === 'open') {
2742
+ if (stop || stopLossTakeProfit) {
2743
+ request['state'] = 'NOT_TRIGGERED';
2744
+ }
2745
+ else if (subType !== undefined) {
2746
+ request['state'] = 'NEW';
2747
+ }
2748
+ }
2749
+ else if (status === 'closed') {
2750
+ if (stop || stopLossTakeProfit) {
2751
+ request['state'] = 'TRIGGERED';
2752
+ }
2753
+ else {
2754
+ request['state'] = 'FILLED';
2755
+ }
2756
+ }
2757
+ else if (status === 'canceled') {
2758
+ if (stop || stopLossTakeProfit) {
2759
+ request['state'] = 'USER_REVOCATION';
2760
+ }
2761
+ else {
2762
+ request['state'] = 'CANCELED';
2763
+ }
2764
+ }
2765
+ else {
2766
+ request['state'] = status;
2767
+ }
2768
+ if (stop || stopLossTakeProfit || (subType !== undefined) || (type === 'swap') || (type === 'future')) {
2769
+ if (since !== undefined) {
2770
+ request['startTime'] = since;
2771
+ }
2772
+ if (limit !== undefined) {
2773
+ request['size'] = limit;
2774
+ }
2775
+ }
2776
+ if (stop) {
2777
+ params = this.omit(params, 'stop');
2778
+ if (subType === 'inverse') {
2779
+ response = await this.privateInverseGetFutureTradeV1EntrustPlanList(this.extend(request, params));
2780
+ }
2781
+ else {
2782
+ response = await this.privateLinearGetFutureTradeV1EntrustPlanList(this.extend(request, params));
2783
+ }
2784
+ }
2785
+ else if (stopLossTakeProfit) {
2786
+ params = this.omit(params, 'stopLossTakeProfit');
2787
+ if (subType === 'inverse') {
2788
+ response = await this.privateInverseGetFutureTradeV1EntrustProfitList(this.extend(request, params));
2789
+ }
2790
+ else {
2791
+ response = await this.privateLinearGetFutureTradeV1EntrustProfitList(this.extend(request, params));
2792
+ }
2793
+ }
2794
+ else if ((subType !== undefined) || (type === 'swap') || (type === 'future')) {
2795
+ if (subType === 'inverse') {
2796
+ response = await this.privateInverseGetFutureTradeV1OrderList(this.extend(request, params));
2797
+ }
2798
+ else {
2799
+ response = await this.privateLinearGetFutureTradeV1OrderList(this.extend(request, params));
2800
+ }
2801
+ }
2802
+ else {
2803
+ let marginMode = undefined;
2804
+ [marginMode, params] = this.handleMarginModeAndParams('fetchOrdersByStatus', params);
2805
+ const marginOrSpotRequest = (marginMode !== undefined) ? 'LEVER' : 'SPOT';
2806
+ request['bizType'] = marginOrSpotRequest;
2807
+ if (status !== 'open') {
2808
+ if (since !== undefined) {
2809
+ request['startTime'] = since;
2810
+ }
2811
+ if (limit !== undefined) {
2812
+ request['limit'] = limit;
2813
+ }
2814
+ response = await this.privateSpotGetHistoryOrder(this.extend(request, params));
2815
+ }
2816
+ else {
2817
+ response = await this.privateSpotGetOpenOrder(this.extend(request, params));
2818
+ }
2819
+ }
2820
+ //
2821
+ // spot and margin
2822
+ //
2823
+ // {
2824
+ // "rc": 0,
2825
+ // "mc": "SUCCESS",
2826
+ // "ma": [],
2827
+ // "result": {
2828
+ // "hasPrev": false,
2829
+ // "hasNext": true,
2830
+ // "items": [
2831
+ // {
2832
+ // "symbol": "btc_usdt",
2833
+ // "orderId": "207505997850909952",
2834
+ // "clientOrderId": null,
2835
+ // "baseCurrency": "btc",
2836
+ // "quoteCurrency": "usdt",
2837
+ // "side": "BUY",
2838
+ // "type": "LIMIT",
2839
+ // "timeInForce": "GTC",
2840
+ // "price": "20000.00",
2841
+ // "origQty": "0.001000",
2842
+ // "origQuoteQty": "20.00",
2843
+ // "executedQty": "0.000000",
2844
+ // "leavingQty": "0.000000",
2845
+ // "tradeBase": "0.000000",
2846
+ // "tradeQuote": "0.00",
2847
+ // "avgPrice": null,
2848
+ // "fee": null,
2849
+ // "feeCurrency": null,
2850
+ // "closed": true,
2851
+ // "state": "CANCELED",
2852
+ // "time": 1679175285162,
2853
+ // "updatedTime": 1679175488492
2854
+ // },
2855
+ // ]
2856
+ // }
2857
+ // }
2858
+ //
2859
+ // spot and margin: fetchOpenOrders
2860
+ //
2861
+ // {
2862
+ // "rc": 0,
2863
+ // "mc": "SUCCESS",
2864
+ // "ma": [],
2865
+ // "result": [
2866
+ // {
2867
+ // "symbol": "eth_usdt",
2868
+ // "orderId": "208249323222264320",
2869
+ // "clientOrderId": null,
2870
+ // "baseCurrency": "eth",
2871
+ // "quoteCurrency": "usdt",
2872
+ // "side": "BUY",
2873
+ // "type": "LIMIT",
2874
+ // "timeInForce": "GTC",
2875
+ // "price": "1300.00",
2876
+ // "origQty": "0.0032",
2877
+ // "origQuoteQty": "4.16",
2878
+ // "executedQty": "0.0000",
2879
+ // "leavingQty": "0.0032",
2880
+ // "tradeBase": "0.0000",
2881
+ // "tradeQuote": "0.00",
2882
+ // "avgPrice": null,
2883
+ // "fee": null,
2884
+ // "feeCurrency": null,
2885
+ // "closed": false,
2886
+ // "state": "NEW",
2887
+ // "time": 1679352507741,
2888
+ // "updatedTime": 1679352507869
2889
+ // },
2890
+ // ]
2891
+ // }
2892
+ //
2893
+ // swap and future
2894
+ //
2895
+ // {
2896
+ // "returnCode": 0,
2897
+ // "msgInfo": "success",
2898
+ // "error": null,
2899
+ // "result": {
2900
+ // "page": 1,
2901
+ // "ps": 10,
2902
+ // "total": 25,
2903
+ // "items": [
2904
+ // {
2905
+ // "orderId": "207519546930995456",
2906
+ // "clientOrderId": null,
2907
+ // "symbol": "btc_usdt",
2908
+ // "orderType": "LIMIT",
2909
+ // "orderSide": "BUY",
2910
+ // "positionSide": "LONG",
2911
+ // "timeInForce": "GTC",
2912
+ // "closePosition": false,
2913
+ // "price": "20000",
2914
+ // "origQty": "100",
2915
+ // "avgPrice": "0",
2916
+ // "executedQty": "0",
2917
+ // "marginFrozen": "4.12",
2918
+ // "remark": null,
2919
+ // "triggerProfitPrice": null,
2920
+ // "triggerStopPrice": null,
2921
+ // "sourceId": null,
2922
+ // "sourceType": "DEFAULT",
2923
+ // "forceClose": false,
2924
+ // "closeProfit": null,
2925
+ // "state": "CANCELED",
2926
+ // "createdTime": 1679178515689,
2927
+ // "updatedTime": 1679180096172
2928
+ // },
2929
+ // ]
2930
+ // }
2931
+ // }
2932
+ //
2933
+ // stop
2934
+ //
2935
+ // {
2936
+ // "returnCode": 0,
2937
+ // "msgInfo": "success",
2938
+ // "error": null,
2939
+ // "result": {
2940
+ // "page": 1,
2941
+ // "ps": 3,
2942
+ // "total": 8,
2943
+ // "items": [
2944
+ // {
2945
+ // "entrustId": "216300248132756992",
2946
+ // "symbol": "btc_usdt",
2947
+ // "entrustType": "STOP",
2948
+ // "orderSide": "SELL",
2949
+ // "positionSide": "SHORT",
2950
+ // "timeInForce": "GTC",
2951
+ // "closePosition": null,
2952
+ // "price": "20000",
2953
+ // "origQty": "1",
2954
+ // "stopPrice": "19000",
2955
+ // "triggerPriceType": "LATEST_PRICE",
2956
+ // "state": "USER_REVOCATION",
2957
+ // "marketOrderLevel": null,
2958
+ // "createdTime": 1681271998064,
2959
+ // "updatedTime": 1681273188674,
2960
+ // "ordinary": false
2961
+ // },
2962
+ // ]
2963
+ // }
2964
+ // }
2965
+ //
2966
+ // stop-loss and take-profit
2967
+ //
2968
+ // {
2969
+ // "returnCode": 0,
2970
+ // "msgInfo": "success",
2971
+ // "error": null,
2972
+ // "result": {
2973
+ // "page": 1,
2974
+ // "ps": 3,
2975
+ // "total": 2,
2976
+ // "items": [
2977
+ // {
2978
+ // "profitId": "216306213226230400",
2979
+ // "symbol": "btc_usdt",
2980
+ // "positionSide": "LONG",
2981
+ // "origQty": "1",
2982
+ // "triggerPriceType": "LATEST_PRICE",
2983
+ // "triggerProfitPrice": null,
2984
+ // "triggerStopPrice": "20000",
2985
+ // "entryPrice": "0",
2986
+ // "positionSize": "0",
2987
+ // "isolatedMargin": "0",
2988
+ // "executedQty": "0",
2989
+ // "avgPrice": null,
2990
+ // "positionType": "ISOLATED",
2991
+ // "state": "USER_REVOCATION",
2992
+ // "createdTime": 1681273420039
2993
+ // },
2994
+ // ]
2995
+ // }
2996
+ // }
2997
+ //
2998
+ const isSpotOpenOrders = ((status === 'open') && (subType === undefined));
2999
+ const data = this.safeValue(response, 'result', {});
3000
+ const orders = isSpotOpenOrders ? this.safeValue(response, 'result', []) : this.safeValue(data, 'items', []);
3001
+ return this.parseOrders(orders, market, since, limit);
3002
+ }
3003
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3004
+ /**
3005
+ * @method
3006
+ * @name xt#fetchOpenOrders
3007
+ * @description fetch all unfilled currently open orders
3008
+ * @see https://doc.xt.com/#orderopenOrderGet
3009
+ * @see https://doc.xt.com/#futures_ordergetOrders
3010
+ * @see https://doc.xt.com/#futures_entrustgetPlan
3011
+ * @see https://doc.xt.com/#futures_entrustgetProfit
3012
+ * @param {string} [symbol] unified market symbol of the market the orders were made in
3013
+ * @param {int} [since] timestamp in ms of the earliest order
3014
+ * @param {int} [limit] the maximum number of open order structures to retrieve
3015
+ * @param {object} params extra parameters specific to the xt api endpoint
3016
+ * @param {bool} [params.stop] if the order is a stop trigger order or not
3017
+ * @param {bool} [params.stopLossTakeProfit] if the order is a stop-loss or take-profit order
3018
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
3019
+ */
3020
+ return await this.fetchOrdersByStatus('open', symbol, since, limit, params);
3021
+ }
3022
+ async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3023
+ /**
3024
+ * @method
3025
+ * @name xt#fetchClosedOrders
3026
+ * @description fetches information on multiple closed orders made by the user
3027
+ * @see https://doc.xt.com/#orderhistoryOrderGet
3028
+ * @see https://doc.xt.com/#futures_ordergetOrders
3029
+ * @see https://doc.xt.com/#futures_entrustgetPlan
3030
+ * @see https://doc.xt.com/#futures_entrustgetProfit
3031
+ * @param {string} [symbol] unified market symbol of the market the orders were made in
3032
+ * @param {int} [since] timestamp in ms of the earliest order
3033
+ * @param {int} [limit] the maximum number of order structures to retrieve
3034
+ * @param {object} params extra parameters specific to the xt api endpoint
3035
+ * @param {bool} [params.stop] if the order is a stop trigger order or not
3036
+ * @param {bool} [params.stopLossTakeProfit] if the order is a stop-loss or take-profit order
3037
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
3038
+ */
3039
+ return await this.fetchOrdersByStatus('closed', symbol, since, limit, params);
3040
+ }
3041
+ async fetchCanceledOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3042
+ /**
3043
+ * @method
3044
+ * @name xt#fetchCanceledOrders
3045
+ * @description fetches information on multiple canceled orders made by the user
3046
+ * @see https://doc.xt.com/#orderhistoryOrderGet
3047
+ * @see https://doc.xt.com/#futures_ordergetOrders
3048
+ * @see https://doc.xt.com/#futures_entrustgetPlan
3049
+ * @see https://doc.xt.com/#futures_entrustgetProfit
3050
+ * @param {string} [symbol] unified market symbol of the market the orders were made in
3051
+ * @param {int} [since] timestamp in ms of the earliest order
3052
+ * @param {int} [limit] the maximum number of order structures to retrieve
3053
+ * @param {object} params extra parameters specific to the xt api endpoint
3054
+ * @param {bool} [params.stop] if the order is a stop trigger order or not
3055
+ * @param {bool} [params.stopLossTakeProfit] if the order is a stop-loss or take-profit order
3056
+ * @returns {object} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
3057
+ */
3058
+ return await this.fetchOrdersByStatus('canceled', symbol, since, limit, params);
3059
+ }
3060
+ async cancelOrder(id, symbol = undefined, params = {}) {
3061
+ /**
3062
+ * @method
3063
+ * @name xt#cancelOrder
3064
+ * @description cancels an open order
3065
+ * @see https://doc.xt.com/#orderorderDel
3066
+ * @see https://doc.xt.com/#futures_ordercancel
3067
+ * @see https://doc.xt.com/#futures_entrustcancelPlan
3068
+ * @see https://doc.xt.com/#futures_entrustcancelProfit
3069
+ * @param {string} id order id
3070
+ * @param {string} [symbol] unified symbol of the market the order was made in
3071
+ * @param {object} params extra parameters specific to the xt api endpoint
3072
+ * @param {bool} [params.stop] if the order is a stop trigger order or not
3073
+ * @param {bool} [params.stopLossTakeProfit] if the order is a stop-loss or take-profit order
3074
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
3075
+ */
3076
+ await this.loadMarkets();
3077
+ let market = undefined;
3078
+ if (symbol !== undefined) {
3079
+ market = this.market(symbol);
3080
+ }
3081
+ const request = {};
3082
+ let type = undefined;
3083
+ let subType = undefined;
3084
+ let response = undefined;
3085
+ [type, params] = this.handleMarketTypeAndParams('cancelOrder', market, params);
3086
+ [subType, params] = this.handleSubTypeAndParams('cancelOrder', market, params);
3087
+ const stop = this.safeValue(params, 'stop');
3088
+ const stopLossTakeProfit = this.safeValue(params, 'stopLossTakeProfit');
3089
+ if (stop) {
3090
+ request['entrustId'] = id;
3091
+ }
3092
+ else if (stopLossTakeProfit) {
3093
+ request['profitId'] = id;
3094
+ }
3095
+ else {
3096
+ request['orderId'] = id;
3097
+ }
3098
+ if (stop) {
3099
+ params = this.omit(params, 'stop');
3100
+ if (subType === 'inverse') {
3101
+ response = await this.privateInversePostFutureTradeV1EntrustCancelPlan(this.extend(request, params));
3102
+ }
3103
+ else {
3104
+ response = await this.privateLinearPostFutureTradeV1EntrustCancelPlan(this.extend(request, params));
3105
+ }
3106
+ }
3107
+ else if (stopLossTakeProfit) {
3108
+ params = this.omit(params, 'stopLossTakeProfit');
3109
+ if (subType === 'inverse') {
3110
+ response = await this.privateInversePostFutureTradeV1EntrustCancelProfitStop(this.extend(request, params));
3111
+ }
3112
+ else {
3113
+ response = await this.privateLinearPostFutureTradeV1EntrustCancelProfitStop(this.extend(request, params));
3114
+ }
3115
+ }
3116
+ else if (subType === 'inverse') {
3117
+ response = await this.privateInversePostFutureTradeV1OrderCancel(this.extend(request, params));
3118
+ }
3119
+ else if ((subType === 'linear') || (type === 'swap') || (type === 'future')) {
3120
+ response = await this.privateLinearPostFutureTradeV1OrderCancel(this.extend(request, params));
3121
+ }
3122
+ else {
3123
+ response = await this.privateSpotDeleteOrderOrderId(this.extend(request, params));
3124
+ }
3125
+ //
3126
+ // spot
3127
+ //
3128
+ // {
3129
+ // "rc": 0,
3130
+ // "mc": "SUCCESS",
3131
+ // "ma": [],
3132
+ // "result": {
3133
+ // "cancelId": "208322474307982720"
3134
+ // }
3135
+ // }
3136
+ //
3137
+ // swap and future
3138
+ //
3139
+ // {
3140
+ // "returnCode": 0,
3141
+ // "msgInfo": "success",
3142
+ // "error": null,
3143
+ // "result": "208319789679471616"
3144
+ // }
3145
+ //
3146
+ const isContractResponse = ((subType !== undefined) || (type === 'swap') || (type === 'future'));
3147
+ const order = isContractResponse ? response : this.safeValue(response, 'result', {});
3148
+ return this.parseOrder(order, market);
3149
+ }
3150
+ async cancelAllOrders(symbol = undefined, params = {}) {
3151
+ /**
3152
+ * @method
3153
+ * @name xt#cancelAllOrders
3154
+ * @description cancel all open orders in a market
3155
+ * @see https://doc.xt.com/#orderopenOrderDel
3156
+ * @see https://doc.xt.com/#futures_ordercancelBatch
3157
+ * @see https://doc.xt.com/#futures_entrustcancelPlanBatch
3158
+ * @see https://doc.xt.com/#futures_entrustcancelProfitBatch
3159
+ * @param {string} [symbol] unified market symbol of the market to cancel orders in
3160
+ * @param {object} params extra parameters specific to the xt api endpoint
3161
+ * @param {bool} [params.stop] if the order is a stop trigger order or not
3162
+ * @param {bool} [params.stopLossTakeProfit] if the order is a stop-loss or take-profit order
3163
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
3164
+ */
3165
+ await this.loadMarkets();
3166
+ const request = {};
3167
+ let market = undefined;
3168
+ if (symbol !== undefined) {
3169
+ market = this.market(symbol);
3170
+ request['symbol'] = market['id'];
3171
+ }
3172
+ let type = undefined;
3173
+ let subType = undefined;
3174
+ let response = undefined;
3175
+ [type, params] = this.handleMarketTypeAndParams('cancelAllOrders', market, params);
3176
+ [subType, params] = this.handleSubTypeAndParams('cancelAllOrders', market, params);
3177
+ const stop = this.safeValue(params, 'stop');
3178
+ const stopLossTakeProfit = this.safeValue(params, 'stopLossTakeProfit');
3179
+ if (stop) {
3180
+ params = this.omit(params, 'stop');
3181
+ if (subType === 'inverse') {
3182
+ response = await this.privateInversePostFutureTradeV1EntrustCancelAllPlan(this.extend(request, params));
3183
+ }
3184
+ else {
3185
+ response = await this.privateLinearPostFutureTradeV1EntrustCancelAllPlan(this.extend(request, params));
3186
+ }
3187
+ }
3188
+ else if (stopLossTakeProfit) {
3189
+ params = this.omit(params, 'stopLossTakeProfit');
3190
+ if (subType === 'inverse') {
3191
+ response = await this.privateInversePostFutureTradeV1EntrustCancelAllProfitStop(this.extend(request, params));
3192
+ }
3193
+ else {
3194
+ response = await this.privateLinearPostFutureTradeV1EntrustCancelAllProfitStop(this.extend(request, params));
3195
+ }
3196
+ }
3197
+ else if (subType === 'inverse') {
3198
+ response = await this.privateInversePostFutureTradeV1OrderCancelAll(this.extend(request, params));
3199
+ }
3200
+ else if ((subType === 'linear') || (type === 'swap') || (type === 'future')) {
3201
+ response = await this.privateLinearPostFutureTradeV1OrderCancelAll(this.extend(request, params));
3202
+ }
3203
+ else {
3204
+ let marginMode = undefined;
3205
+ [marginMode, params] = this.handleMarginModeAndParams('cancelAllOrders', params);
3206
+ const marginOrSpotRequest = (marginMode !== undefined) ? 'LEVER' : 'SPOT';
3207
+ request['bizType'] = marginOrSpotRequest;
3208
+ response = await this.privateSpotDeleteOpenOrder(this.extend(request, params));
3209
+ }
3210
+ //
3211
+ // spot and margin
3212
+ //
3213
+ // {
3214
+ // "rc": 0,
3215
+ // "mc": "SUCCESS",
3216
+ // "ma": [],
3217
+ // "result": null
3218
+ // }
3219
+ //
3220
+ // swap and future
3221
+ //
3222
+ // {
3223
+ // "returnCode": 0,
3224
+ // "msgInfo": "success",
3225
+ // "error": null,
3226
+ // "result": true
3227
+ // }
3228
+ //
3229
+ return [
3230
+ this.safeOrder(response),
3231
+ ];
3232
+ }
3233
+ async cancelOrders(ids, symbol = undefined, params = {}) {
3234
+ /**
3235
+ * @method
3236
+ * @name xt#cancelOrders
3237
+ * @description cancel multiple orders
3238
+ * @see https://doc.xt.com/#orderbatchOrderDel
3239
+ * @param {string[]} ids order ids
3240
+ * @param {string} [symbol] unified market symbol of the market to cancel orders in
3241
+ * @param {object} params extra parameters specific to the xt api endpoint
3242
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
3243
+ */
3244
+ await this.loadMarkets();
3245
+ const request = {
3246
+ 'orderIds': ids,
3247
+ };
3248
+ let market = undefined;
3249
+ if (symbol !== undefined) {
3250
+ market = this.market(symbol);
3251
+ }
3252
+ let subType = undefined;
3253
+ [subType, params] = this.handleSubTypeAndParams('cancelOrders', market, params);
3254
+ if (subType !== undefined) {
3255
+ throw new NotSupported(this.id + ' cancelOrders() does not support swap and future orders, only spot orders are accepted');
3256
+ }
3257
+ const response = await this.privateSpotDeleteBatchOrder(this.extend(request, params));
3258
+ //
3259
+ // spot
3260
+ //
3261
+ // {
3262
+ // "rc": 0,
3263
+ // "mc": "SUCCESS",
3264
+ // "ma": [],
3265
+ // "result": null
3266
+ // }
3267
+ //
3268
+ return [
3269
+ this.safeOrder(response),
3270
+ ];
3271
+ }
3272
+ parseOrder(order, market = undefined) {
3273
+ //
3274
+ // spot: createOrder
3275
+ //
3276
+ // {
3277
+ // "orderId": "204371980095156544"
3278
+ // }
3279
+ //
3280
+ // spot: cancelOrder
3281
+ //
3282
+ // {
3283
+ // "cancelId": "208322474307982720"
3284
+ // }
3285
+ //
3286
+ // swap and future: createOrder, cancelOrder
3287
+ //
3288
+ // {
3289
+ // "returnCode": 0,
3290
+ // "msgInfo": "success",
3291
+ // "error": null,
3292
+ // "result": "206410760006650176"
3293
+ // }
3294
+ //
3295
+ // spot: fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
3296
+ //
3297
+ // {
3298
+ // "symbol": "btc_usdt",
3299
+ // "orderId": "207505997850909952",
3300
+ // "clientOrderId": null,
3301
+ // "baseCurrency": "btc",
3302
+ // "quoteCurrency": "usdt",
3303
+ // "side": "BUY",
3304
+ // "type": "LIMIT",
3305
+ // "timeInForce": "GTC",
3306
+ // "price": "20000.00",
3307
+ // "origQty": "0.001000",
3308
+ // "origQuoteQty": "20.00",
3309
+ // "executedQty": "0.000000",
3310
+ // "leavingQty": "0.001000",
3311
+ // "tradeBase": "0.000000",
3312
+ // "tradeQuote": "0.00",
3313
+ // "avgPrice": null,
3314
+ // "fee": null,
3315
+ // "feeCurrency": null,
3316
+ // "closed": false,
3317
+ // "state": "NEW",
3318
+ // "time": 1679175285162,
3319
+ // "updatedTime": 1679175285255
3320
+ // }
3321
+ //
3322
+ // swap and future: fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
3323
+ //
3324
+ // {
3325
+ // "orderId": "207519546930995456",
3326
+ // "clientOrderId": null,
3327
+ // "symbol": "btc_usdt",
3328
+ // "orderType": "LIMIT",
3329
+ // "orderSide": "BUY",
3330
+ // "positionSide": "LONG",
3331
+ // "timeInForce": "GTC",
3332
+ // "closePosition": false,
3333
+ // "price": "20000",
3334
+ // "origQty": "100",
3335
+ // "avgPrice": "0",
3336
+ // "executedQty": "0",
3337
+ // "marginFrozen": "4.12",
3338
+ // "remark": null,
3339
+ // "triggerProfitPrice": null,
3340
+ // "triggerStopPrice": null,
3341
+ // "sourceId": null,
3342
+ // "sourceType": "DEFAULT",
3343
+ // "forceClose": false,
3344
+ // "closeProfit": null,
3345
+ // "state": "CANCELED",
3346
+ // "createdTime": 1679178515689,
3347
+ // "updatedTime": 1679180096172
3348
+ // }
3349
+ //
3350
+ // trigger: fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
3351
+ //
3352
+ // {
3353
+ // "entrustId": "216300248132756992",
3354
+ // "symbol": "btc_usdt",
3355
+ // "entrustType": "STOP",
3356
+ // "orderSide": "SELL",
3357
+ // "positionSide": "SHORT",
3358
+ // "timeInForce": "GTC",
3359
+ // "closePosition": null,
3360
+ // "price": "20000",
3361
+ // "origQty": "1",
3362
+ // "stopPrice": "19000",
3363
+ // "triggerPriceType": "LATEST_PRICE",
3364
+ // "state": "NOT_TRIGGERED",
3365
+ // "marketOrderLevel": null,
3366
+ // "createdTime": 1681271998064,
3367
+ // "updatedTime": 1681271998064,
3368
+ // "ordinary": false
3369
+ // }
3370
+ //
3371
+ // stop-loss and take-profit: fetchOrder, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders, fetchOrdersByStatus
3372
+ //
3373
+ // {
3374
+ // "profitId": "216306213226230400",
3375
+ // "symbol": "btc_usdt",
3376
+ // "positionSide": "LONG",
3377
+ // "origQty": "1",
3378
+ // "triggerPriceType": "LATEST_PRICE",
3379
+ // "triggerProfitPrice": null,
3380
+ // "triggerStopPrice": "20000",
3381
+ // "entryPrice": null,
3382
+ // "positionSize": null,
3383
+ // "isolatedMargin": null,
3384
+ // "executedQty": null,
3385
+ // "avgPrice": null,
3386
+ // "positionType": "ISOLATED",
3387
+ // "state": "NOT_TRIGGERED",
3388
+ // "createdTime": 1681273420039
3389
+ // }
3390
+ //
3391
+ const marketId = this.safeString(order, 'symbol');
3392
+ const marketType = ('result' in order) || ('positionSide' in order) ? 'contract' : 'spot';
3393
+ market = this.safeMarket(marketId, market, undefined, marketType);
3394
+ const symbol = this.safeSymbol(marketId, market, undefined, marketType);
3395
+ const timestamp = this.safeInteger2(order, 'time', 'createdTime');
3396
+ const quantity = this.safeNumber(order, 'origQty');
3397
+ const amount = (marketType === 'spot') ? quantity : Precise.stringMul(this.numberToString(quantity), this.numberToString(market['contractSize']));
3398
+ const filledQuantity = this.safeNumber(order, 'executedQty');
3399
+ const filled = (marketType === 'spot') ? filledQuantity : Precise.stringMul(this.numberToString(filledQuantity), this.numberToString(market['contractSize']));
3400
+ const lastUpdatedTimestamp = this.safeInteger(order, 'updatedTime');
3401
+ return this.safeOrder({
3402
+ 'info': order,
3403
+ 'id': this.safeStringN(order, ['orderId', 'result', 'cancelId', 'entrustId', 'profitId']),
3404
+ 'clientOrderId': this.safeString(order, 'clientOrderId'),
3405
+ 'timestamp': timestamp,
3406
+ 'datetime': this.iso8601(timestamp),
3407
+ 'lastTradeTimestamp': lastUpdatedTimestamp,
3408
+ 'lastUpdateTimestamp': lastUpdatedTimestamp,
3409
+ 'symbol': symbol,
3410
+ 'type': this.safeStringLower2(order, 'type', 'orderType'),
3411
+ 'timeInForce': this.safeString(order, 'timeInForce'),
3412
+ 'postOnly': undefined,
3413
+ 'side': this.safeStringLower2(order, 'side', 'orderSide'),
3414
+ 'price': this.safeNumber(order, 'price'),
3415
+ 'stopPrice': this.safeNumber(order, 'stopPrice'),
3416
+ 'stopLoss': this.safeNumber(order, 'triggerStopPrice'),
3417
+ 'takeProfit': this.safeNumber(order, 'triggerProfitPrice'),
3418
+ 'amount': amount,
3419
+ 'filled': filled,
3420
+ 'remaining': this.safeNumber(order, 'leavingQty'),
3421
+ 'cost': undefined,
3422
+ 'average': this.safeNumber(order, 'avgPrice'),
3423
+ 'status': this.parseOrderStatus(this.safeString(order, 'state')),
3424
+ 'fee': {
3425
+ 'currency': this.safeCurrencyCode(this.safeString(order, 'feeCurrency')),
3426
+ 'cost': this.safeNumber(order, 'fee'),
3427
+ },
3428
+ 'trades': undefined,
3429
+ }, market);
3430
+ }
3431
+ parseOrderStatus(status) {
3432
+ const statuses = {
3433
+ 'NEW': 'open',
3434
+ 'PARTIALLY_FILLED': 'open',
3435
+ 'FILLED': 'closed',
3436
+ 'CANCELED': 'canceled',
3437
+ 'REJECTED': 'rejected',
3438
+ 'EXPIRED': 'expired',
3439
+ 'UNFINISHED': 'open',
3440
+ 'NOT_TRIGGERED': 'open',
3441
+ 'TRIGGERING': 'open',
3442
+ 'TRIGGERED': 'closed',
3443
+ 'USER_REVOCATION': 'canceled',
3444
+ 'PLATFORM_REVOCATION': 'rejected',
3445
+ 'HISTORY': 'expired',
3446
+ };
3447
+ return this.safeString(statuses, status, status);
3448
+ }
3449
+ async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
3450
+ /**
3451
+ * @method
3452
+ * @name xt#fetchLedger
3453
+ * @description fetch the history of changes, actions done by the user or operations that altered the balance of the user
3454
+ * @see https://doc.xt.com/#futures_usergetBalanceBill
3455
+ * @param {string} [code] unified currency code
3456
+ * @param {int} [since] timestamp in ms of the earliest ledger entry
3457
+ * @param {int} [limit] max number of ledger entries to return
3458
+ * @param {object} params extra parameters specific to the xt api endpoint
3459
+ * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/en/latest/manual.html#ledger-structure}
3460
+ */
3461
+ await this.loadMarkets();
3462
+ const request = {};
3463
+ let currency = undefined;
3464
+ if (code !== undefined) {
3465
+ currency = this.currency(code);
3466
+ }
3467
+ if (since !== undefined) {
3468
+ request['startTime'] = since;
3469
+ }
3470
+ if (limit !== undefined) {
3471
+ request['limit'] = limit;
3472
+ }
3473
+ let type = undefined;
3474
+ let subType = undefined;
3475
+ let response = undefined;
3476
+ [type, params] = this.handleMarketTypeAndParams('fetchLedger', undefined, params);
3477
+ [subType, params] = this.handleSubTypeAndParams('fetchLedger', undefined, params);
3478
+ if (subType === 'inverse') {
3479
+ response = await this.privateInverseGetFutureUserV1BalanceBills(this.extend(request, params));
3480
+ }
3481
+ else if ((subType === 'linear') || (type === 'swap') || (type === 'future')) {
3482
+ response = await this.privateLinearGetFutureUserV1BalanceBills(this.extend(request, params));
3483
+ }
3484
+ else {
3485
+ throw new NotSupported(this.id + ' fetchLedger() does not support spot transactions, only swap and future wallet transactions are supported');
3486
+ }
3487
+ //
3488
+ // {
3489
+ // "returnCode": 0,
3490
+ // "msgInfo": "success",
3491
+ // "error": null,
3492
+ // "result": {
3493
+ // "hasPrev": false,
3494
+ // "hasNext": false,
3495
+ // "items": [
3496
+ // {
3497
+ // "id": "207260567109387524",
3498
+ // "coin": "usdt",
3499
+ // "symbol": "btc_usdt",
3500
+ // "type": "FEE",
3501
+ // "amount": "-0.0213",
3502
+ // "side": "SUB",
3503
+ // "afterAmount": null,
3504
+ // "createdTime": 1679116769914
3505
+ // },
3506
+ // ]
3507
+ // }
3508
+ // }
3509
+ //
3510
+ const data = this.safeValue(response, 'result', {});
3511
+ const ledger = this.safeValue(data, 'items', []);
3512
+ return this.parseLedger(ledger, currency, since, limit);
3513
+ }
3514
+ parseLedgerEntry(item, currency = undefined) {
3515
+ //
3516
+ // {
3517
+ // "id": "207260567109387524",
3518
+ // "coin": "usdt",
3519
+ // "symbol": "btc_usdt",
3520
+ // "type": "FEE",
3521
+ // "amount": "-0.0213",
3522
+ // "side": "SUB",
3523
+ // "afterAmount": null,
3524
+ // "createdTime": 1679116769914
3525
+ // }
3526
+ //
3527
+ const side = this.safeString(item, 'side');
3528
+ const direction = (side === 'ADD') ? 'in' : 'out';
3529
+ const currencyId = this.safeString(item, 'coin');
3530
+ const timestamp = this.safeInteger(item, 'createdTime');
3531
+ return {
3532
+ 'id': this.safeString(item, 'id'),
3533
+ 'direction': direction,
3534
+ 'account': undefined,
3535
+ 'referenceId': undefined,
3536
+ 'referenceAccount': undefined,
3537
+ 'type': this.parseLedgerEntryType(this.safeString(item, 'type')),
3538
+ 'currency': this.safeCurrencyCode(currencyId, currency),
3539
+ 'amount': this.safeNumber(item, 'amount'),
3540
+ 'timestamp': timestamp,
3541
+ 'datetime': this.iso8601(timestamp),
3542
+ 'before': undefined,
3543
+ 'after': this.safeNumber(item, 'afterAmount'),
3544
+ 'status': undefined,
3545
+ 'fee': {
3546
+ 'currency': undefined,
3547
+ 'cost': undefined,
3548
+ },
3549
+ 'info': item,
3550
+ };
3551
+ }
3552
+ parseLedgerEntryType(type) {
3553
+ const ledgerType = {
3554
+ 'EXCHANGE': 'transfer',
3555
+ 'CLOSE_POSITION': 'trade',
3556
+ 'TAKE_OVER': 'trade',
3557
+ 'MERGE': 'trade',
3558
+ 'QIANG_PING_MANAGER': 'fee',
3559
+ 'FUND': 'fee',
3560
+ 'FEE': 'fee',
3561
+ 'ADL': 'auto-deleveraging',
3562
+ };
3563
+ return this.safeString(ledgerType, type, type);
3564
+ }
3565
+ async fetchDepositAddress(code, params = {}) {
3566
+ /**
3567
+ * @method
3568
+ * @name xt#fetchDepositAddress
3569
+ * @description fetch the deposit address for a currency associated with this account
3570
+ * @see https://doc.xt.com/#deposit_withdrawaldepositAddressGet
3571
+ * @param {string} code unified currency code
3572
+ * @param {object} params extra parameters specific to the xt api endpoint
3573
+ * @param {string} params.network required network id
3574
+ * @returns {object} an [address structure]{@link https://docs.ccxt.com/en/latest/manual.html#address-structure}
3575
+ */
3576
+ await this.loadMarkets();
3577
+ let networkCode = undefined;
3578
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
3579
+ const currency = this.currency(code);
3580
+ const networkId = this.networkCodeToId(networkCode, code);
3581
+ this.checkRequiredArgument('fetchDepositAddress', networkId, 'network');
3582
+ const request = {
3583
+ 'currency': currency['id'],
3584
+ 'chain': networkId,
3585
+ };
3586
+ const response = await this.privateSpotGetDepositAddress(this.extend(request, params));
3587
+ //
3588
+ // {
3589
+ // "rc": 0,
3590
+ // "mc": "SUCCESS",
3591
+ // "ma": [],
3592
+ // "result": {
3593
+ // "address": "0x7f7173cf29d3846d20ca5a3aec1120b93dbd157a",
3594
+ // "memo": ""
3595
+ // }
3596
+ // }
3597
+ //
3598
+ const result = this.safeValue(response, 'result', {});
3599
+ return this.parseDepositAddress(result, currency);
3600
+ }
3601
+ parseDepositAddress(depositAddress, currency = undefined) {
3602
+ //
3603
+ // {
3604
+ // "address": "0x7f7173cf29d3846d20ca5a3aec1120b93dbd157a",
3605
+ // "memo": ""
3606
+ // }
3607
+ //
3608
+ const address = this.safeString(depositAddress, 'address');
3609
+ this.checkAddress(address);
3610
+ return {
3611
+ 'currency': this.safeCurrencyCode(undefined, currency),
3612
+ 'address': address,
3613
+ 'tag': this.safeString(depositAddress, 'memo'),
3614
+ 'network': undefined,
3615
+ 'info': depositAddress,
3616
+ };
3617
+ }
3618
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
3619
+ /**
3620
+ * @method
3621
+ * @name xt#fetchDeposits
3622
+ * @description fetch all deposits made to an account
3623
+ * @see https://doc.xt.com/#deposit_withdrawalhistoryDepositGet
3624
+ * @param {string} [code] unified currency code
3625
+ * @param {int} [since] the earliest time in ms to fetch deposits for
3626
+ * @param {int} [limit] the maximum number of transaction structures to retrieve
3627
+ * @param {object} params extra parameters specific to the xt api endpoint
3628
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure}
3629
+ */
3630
+ await this.loadMarkets();
3631
+ const request = {};
3632
+ let currency = undefined;
3633
+ if (code !== undefined) {
3634
+ currency = this.currency(code);
3635
+ request['currency'] = currency['id'];
3636
+ }
3637
+ if (since !== undefined) {
3638
+ request['startTime'] = since;
3639
+ }
3640
+ if (limit !== undefined) {
3641
+ request['limit'] = limit; // default 10, max 200
3642
+ }
3643
+ const response = await this.privateSpotGetDepositHistory(this.extend(request, params));
3644
+ //
3645
+ // {
3646
+ // "rc": 0,
3647
+ // "mc": "SUCCESS",
3648
+ // "ma": [],
3649
+ // "result": {
3650
+ // "hasPrev": false,
3651
+ // "hasNext": false,
3652
+ // "items": [
3653
+ // {
3654
+ // "id": 170368702,
3655
+ // "currency": "usdt",
3656
+ // "chain": "Ethereum",
3657
+ // "memo": "",
3658
+ // "status": "SUCCESS",
3659
+ // "amount": "31.792528",
3660
+ // "confirmations": 12,
3661
+ // "transactionId": "0x90b8487c258b81b85e15e461b1839c49d4d8e6e9de4c1adb658cd47d4f5c5321",
3662
+ // "address": "0x7f7172cf29d3846d30ca5a3aec1120b92dbd150b",
3663
+ // "fromAddr": "0x7830c87c02e56aff27fa9ab1241711331fa86f58",
3664
+ // "createdTime": 1678491442000
3665
+ // },
3666
+ // ]
3667
+ // }
3668
+ // }
3669
+ //
3670
+ const data = this.safeValue(response, 'result', {});
3671
+ const deposits = this.safeValue(data, 'items', []);
3672
+ return this.parseTransactions(deposits, currency, since, limit, params);
3673
+ }
3674
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
3675
+ /**
3676
+ * @method
3677
+ * @name xt#fetchWithdrawals
3678
+ * @description fetch all withdrawals made from an account
3679
+ * @see https://doc.xt.com/#deposit_withdrawalwithdrawHistory
3680
+ * @param {string} [code] unified currency code
3681
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
3682
+ * @param {int} [limit] the maximum number of transaction structures to retrieve
3683
+ * @param {object} params extra parameters specific to the xt api endpoint
3684
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure}
3685
+ */
3686
+ await this.loadMarkets();
3687
+ const request = {};
3688
+ let currency = undefined;
3689
+ if (code !== undefined) {
3690
+ currency = this.currency(code);
3691
+ request['currency'] = currency['id'];
3692
+ }
3693
+ if (since !== undefined) {
3694
+ request['startTime'] = since;
3695
+ }
3696
+ if (limit !== undefined) {
3697
+ request['limit'] = limit; // default 10, max 200
3698
+ }
3699
+ const response = await this.privateSpotGetWithdrawHistory(this.extend(request, params));
3700
+ //
3701
+ // {
3702
+ // "rc": 0,
3703
+ // "mc": "SUCCESS",
3704
+ // "ma": [],
3705
+ // "result": {
3706
+ // "hasPrev": false,
3707
+ // "hasNext": false,
3708
+ // "items": [
3709
+ // {
3710
+ // "id": 950898,
3711
+ // "currency": "usdt",
3712
+ // "chain": "Tron",
3713
+ // "address": "TGB2vxTjiqraVZBy7YHXF8V3CSMVhQKcaf",
3714
+ // "memo": "",
3715
+ // "status": "SUCCESS",
3716
+ // "amount": "5",
3717
+ // "fee": "2",
3718
+ // "confirmations": 6,
3719
+ // "transactionId": "c36e230b879842b1d7afd19d15ee1a866e26eaa0626e367d6f545d2932a15156",
3720
+ // "createdTime": 1680049062000
3721
+ // }
3722
+ // ]
3723
+ // }
3724
+ // }
3725
+ //
3726
+ const data = this.safeValue(response, 'result', {});
3727
+ const withdrawals = this.safeValue(data, 'items', []);
3728
+ return this.parseTransactions(withdrawals, currency, since, limit, params);
3729
+ }
3730
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
3731
+ /**
3732
+ * @method
3733
+ * @name xt#withdraw
3734
+ * @description make a withdrawal
3735
+ * @see https://doc.xt.com/#deposit_withdrawalwithdraw
3736
+ * @param {string} code unified currency code
3737
+ * @param {float} amount the amount to withdraw
3738
+ * @param {string} address the address to withdraw to
3739
+ * @param {string} [tag]
3740
+ * @param {object} params extra parameters specific to the xt api endpoint
3741
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure}
3742
+ */
3743
+ this.checkAddress(address);
3744
+ await this.loadMarkets();
3745
+ const currency = this.currency(code);
3746
+ [tag, params] = this.handleWithdrawTagAndParams(tag, params);
3747
+ let networkCode = undefined;
3748
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
3749
+ const networkIdsByCodes = this.safeValue(this.options, 'networks', {});
3750
+ const networkId = this.safeString2(networkIdsByCodes, networkCode, code, code);
3751
+ const request = {
3752
+ 'currency': currency['id'],
3753
+ 'chain': networkId,
3754
+ 'amount': this.currencyToPrecision(code, amount),
3755
+ 'address': address,
3756
+ };
3757
+ if (tag !== undefined) {
3758
+ request['memo'] = tag;
3759
+ }
3760
+ const response = await this.privateSpotPostWithdraw(this.extend(request, params));
3761
+ //
3762
+ // {
3763
+ // "rc": 0,
3764
+ // "mc": "SUCCESS",
3765
+ // "ma": [],
3766
+ // "result": {
3767
+ // "id": 950898
3768
+ // }
3769
+ // }
3770
+ //
3771
+ const result = this.safeValue(response, 'result', {});
3772
+ return this.parseTransaction(result, currency);
3773
+ }
3774
+ parseTransaction(transaction, currency = undefined) {
3775
+ //
3776
+ // fetchDeposits
3777
+ //
3778
+ // {
3779
+ // "id": 170368702,
3780
+ // "currency": "usdt",
3781
+ // "chain": "Ethereum",
3782
+ // "memo": "",
3783
+ // "status": "SUCCESS",
3784
+ // "amount": "31.792528",
3785
+ // "confirmations": 12,
3786
+ // "transactionId": "0x90b8487c258b81b85e15e461b1839c49d4d8e6e9de4c1adb658cd47d4f5c5321",
3787
+ // "address": "0x7f7172cf29d3846d30ca5a3aec1120b92dbd150b",
3788
+ // "fromAddr": "0x7830c87c02e56aff27fa9ab1241711331fa86f58",
3789
+ // "createdTime": 1678491442000
3790
+ // }
3791
+ //
3792
+ // fetchWithdrawals
3793
+ //
3794
+ // {
3795
+ // "id": 950898,
3796
+ // "currency": "usdt",
3797
+ // "chain": "Tron",
3798
+ // "address": "TGB2vxTjiqraVZBy7YHXF8V3CSMVhQKcaf",
3799
+ // "memo": "",
3800
+ // "status": "SUCCESS",
3801
+ // "amount": "5",
3802
+ // "fee": "2",
3803
+ // "confirmations": 6,
3804
+ // "transactionId": "c36e230b879842b1d7afd19d15ee1a866e26eaa0626e367d6f545d2932a15156",
3805
+ // "createdTime": 1680049062000
3806
+ // }
3807
+ //
3808
+ // withdraw
3809
+ //
3810
+ // {
3811
+ // "id": 950898
3812
+ // }
3813
+ //
3814
+ const type = ('fromAddr' in transaction) ? 'deposit' : 'withdraw';
3815
+ const timestamp = this.safeInteger(transaction, 'createdTime');
3816
+ const address = this.safeString(transaction, 'address');
3817
+ const memo = this.safeString(transaction, 'memo');
3818
+ const currencyCode = this.safeCurrencyCode(this.safeString(transaction, 'currency'), currency);
3819
+ const fee = this.safeNumber(transaction, 'fee');
3820
+ const feeCurrency = (fee !== undefined) ? currencyCode : undefined;
3821
+ const networkId = this.safeString(transaction, 'chain');
3822
+ return {
3823
+ 'info': transaction,
3824
+ 'id': this.safeString(transaction, 'id'),
3825
+ 'txid': this.safeString(transaction, 'transactionId'),
3826
+ 'timestamp': timestamp,
3827
+ 'datetime': this.iso8601(timestamp),
3828
+ 'updated': undefined,
3829
+ 'addressFrom': this.safeString(transaction, 'fromAddr'),
3830
+ 'addressTo': address,
3831
+ 'address': address,
3832
+ 'tagFrom': undefined,
3833
+ 'tagTo': undefined,
3834
+ 'tag': memo,
3835
+ 'type': type,
3836
+ 'amount': this.safeNumber(transaction, 'amount'),
3837
+ 'currency': currencyCode,
3838
+ 'network': this.networkIdToCode(networkId, currencyCode),
3839
+ 'status': this.parseTransactionStatus(this.safeString(transaction, 'status')),
3840
+ 'comment': memo,
3841
+ 'fee': {
3842
+ 'currency': feeCurrency,
3843
+ 'cost': fee,
3844
+ 'rate': undefined,
3845
+ },
3846
+ 'internal': undefined,
3847
+ };
3848
+ }
3849
+ parseTransactionStatus(status) {
3850
+ const statuses = {
3851
+ 'SUBMIT': 'pending',
3852
+ 'REVIEW': 'pending',
3853
+ 'AUDITED': 'pending',
3854
+ 'PENDING': 'pending',
3855
+ 'CANCEL': 'canceled',
3856
+ 'FAIL': 'failed',
3857
+ 'SUCCESS': 'ok',
3858
+ };
3859
+ return this.safeString(statuses, status, status);
3860
+ }
3861
+ async setLeverage(leverage, symbol = undefined, params = {}) {
3862
+ /**
3863
+ * @method
3864
+ * @name xt#setLeverage
3865
+ * @description set the level of leverage for a market
3866
+ * @see https://doc.xt.com/#futures_useradjustLeverage
3867
+ * @param {float} leverage the rate of leverage
3868
+ * @param {string} symbol unified market symbol
3869
+ * @param {object} params extra parameters specific to the xt api endpoint
3870
+ * @param {string} params.positionSide 'LONG' or 'SHORT'
3871
+ * @returns {object} response from the exchange
3872
+ */
3873
+ if (symbol === undefined) {
3874
+ throw new ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
3875
+ }
3876
+ const positionSide = this.safeString(params, 'positionSide');
3877
+ this.checkRequiredArgument('setLeverage', positionSide, 'positionSide', ['LONG', 'SHORT']);
3878
+ if ((leverage < 1) || (leverage > 125)) {
3879
+ throw new BadRequest(this.id + ' setLeverage() leverage should be between 1 and 125');
3880
+ }
3881
+ await this.loadMarkets();
3882
+ const market = this.market(symbol);
3883
+ if (!(market['contract'])) {
3884
+ throw new BadSymbol(this.id + ' setLeverage() supports contract markets only');
3885
+ }
3886
+ const request = {
3887
+ 'symbol': market['id'],
3888
+ 'positionSide': positionSide,
3889
+ 'leverage': leverage,
3890
+ };
3891
+ let subType = undefined;
3892
+ [subType, params] = this.handleSubTypeAndParams('setLeverage', market, params);
3893
+ let response = undefined;
3894
+ if (subType === 'inverse') {
3895
+ response = await this.privateInversePostFutureUserV1PositionAdjustLeverage(this.extend(request, params));
3896
+ }
3897
+ else {
3898
+ response = await this.privateLinearPostFutureUserV1PositionAdjustLeverage(this.extend(request, params));
3899
+ }
3900
+ //
3901
+ // {
3902
+ // "returnCode": 0,
3903
+ // "msgInfo": "success",
3904
+ // "error": null,
3905
+ // "result": null
3906
+ // }
3907
+ //
3908
+ return response;
3909
+ }
3910
+ async addMargin(symbol, amount, params = {}) {
3911
+ /**
3912
+ * @method
3913
+ * @name xt#addMargin
3914
+ * @description add margin to a position
3915
+ * @see https://doc.xt.com/#futures_useradjustMargin
3916
+ * @param {string} symbol unified market symbol
3917
+ * @param {float} amount amount of margin to add
3918
+ * @param {object} params extra parameters specific to the xt api endpoint
3919
+ * @param {string} params.positionSide 'LONG' or 'SHORT'
3920
+ * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=add-margin-structure}
3921
+ */
3922
+ return await this.modifyMarginHelper(symbol, amount, 'ADD', params);
3923
+ }
3924
+ async reduceMargin(symbol, amount, params = {}) {
3925
+ /**
3926
+ * @method
3927
+ * @name xt#reduceMargin
3928
+ * @description remove margin from a position
3929
+ * @see https://doc.xt.com/#futures_useradjustMargin
3930
+ * @param {string} symbol unified market symbol
3931
+ * @param {float} amount the amount of margin to remove
3932
+ * @param {object} params extra parameters specific to the xt api endpoint
3933
+ * @param {string} params.positionSide 'LONG' or 'SHORT'
3934
+ * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=reduce-margin-structure}
3935
+ */
3936
+ return await this.modifyMarginHelper(symbol, amount, 'SUB', params);
3937
+ }
3938
+ async modifyMarginHelper(symbol, amount, addOrReduce, params = {}) {
3939
+ const positionSide = this.safeString(params, 'positionSide');
3940
+ this.checkRequiredArgument('setLeverage', positionSide, 'positionSide', ['LONG', 'SHORT']);
3941
+ await this.loadMarkets();
3942
+ const market = this.market(symbol);
3943
+ const request = {
3944
+ 'symbol': market['id'],
3945
+ 'margin': amount,
3946
+ 'type': addOrReduce,
3947
+ 'positionSide': positionSide,
3948
+ };
3949
+ let subType = undefined;
3950
+ [subType, params] = this.handleSubTypeAndParams('modifyMarginHelper', market, params);
3951
+ let response = undefined;
3952
+ if (subType === 'inverse') {
3953
+ response = await this.privateInversePostFutureUserV1PositionMargin(this.extend(request, params));
3954
+ }
3955
+ else {
3956
+ response = await this.privateLinearPostFutureUserV1PositionMargin(this.extend(request, params));
3957
+ }
3958
+ //
3959
+ // {
3960
+ // "returnCode": 0,
3961
+ // "msgInfo": "success",
3962
+ // "error": null,
3963
+ // "result": null
3964
+ // }
3965
+ //
3966
+ return this.parseMarginModification(response, market);
3967
+ }
3968
+ parseMarginModification(data, market = undefined) {
3969
+ return {
3970
+ 'info': data,
3971
+ 'type': undefined,
3972
+ 'amount': undefined,
3973
+ 'code': undefined,
3974
+ 'symbol': this.safeSymbol(undefined, market),
3975
+ 'status': undefined,
3976
+ 'marginMode': undefined,
3977
+ 'total': undefined,
3978
+ 'timestamp': undefined,
3979
+ 'datetime': undefined,
3980
+ };
3981
+ }
3982
+ async fetchLeverageTiers(symbols = undefined, params = {}) {
3983
+ /**
3984
+ * @method
3985
+ * @name xt#fetchLeverageTiers
3986
+ * @see https://doc.xt.com/#futures_quotesgetLeverageBrackets
3987
+ * @description retrieve information on the maximum leverage for different trade sizes
3988
+ * @param {string} [symbols] a list of unified market symbols
3989
+ * @param {object} params extra parameters specific to the xt api endpoint
3990
+ * @returns {object} a dictionary of [leverage tiers structures]{@link https://docs.ccxt.com/#/?id=leverage-tiers-structure}
3991
+ */
3992
+ await this.loadMarkets();
3993
+ let subType = undefined;
3994
+ [subType, params] = this.handleSubTypeAndParams('fetchLeverageTiers', undefined, params);
3995
+ let response = undefined;
3996
+ if (subType === 'inverse') {
3997
+ response = await this.publicInverseGetFutureMarketV1PublicLeverageBracketList(params);
3998
+ }
3999
+ else {
4000
+ response = await this.publicLinearGetFutureMarketV1PublicLeverageBracketList(params);
4001
+ }
4002
+ //
4003
+ // {
4004
+ // "returnCode": 0,
4005
+ // "msgInfo": "success",
4006
+ // "error": null,
4007
+ // "result": [
4008
+ // {
4009
+ // "symbol": "rad_usdt",
4010
+ // "leverageBrackets": [
4011
+ // {
4012
+ // "symbol": "rad_usdt",
4013
+ // "bracket": 1,
4014
+ // "maxNominalValue": "5000",
4015
+ // "maintMarginRate": "0.025",
4016
+ // "startMarginRate": "0.05",
4017
+ // "maxStartMarginRate": null,
4018
+ // "maxLeverage": "20",
4019
+ // "minLeverage": "1"
4020
+ // },
4021
+ // ]
4022
+ // },
4023
+ // ]
4024
+ // }
4025
+ //
4026
+ const data = this.safeValue(response, 'result', []);
4027
+ symbols = this.marketSymbols(symbols);
4028
+ return this.parseLeverageTiers(data, symbols, 'symbol');
4029
+ }
4030
+ parseLeverageTiers(response, symbols = undefined, marketIdKey = undefined) {
4031
+ //
4032
+ // {
4033
+ // "symbol": "rad_usdt",
4034
+ // "leverageBrackets": [
4035
+ // {
4036
+ // "symbol": "rad_usdt",
4037
+ // "bracket": 1,
4038
+ // "maxNominalValue": "5000",
4039
+ // "maintMarginRate": "0.025",
4040
+ // "startMarginRate": "0.05",
4041
+ // "maxStartMarginRate": null,
4042
+ // "maxLeverage": "20",
4043
+ // "minLeverage": "1"
4044
+ // },
4045
+ // ]
4046
+ // }
4047
+ //
4048
+ const result = {};
4049
+ for (let i = 0; i < response.length; i++) {
4050
+ const entry = response[i];
4051
+ const marketId = this.safeString(entry, 'symbol');
4052
+ const market = this.safeMarket(marketId, undefined, '_', 'contract');
4053
+ const symbol = this.safeSymbol(marketId, market);
4054
+ if (symbols !== undefined) {
4055
+ if (this.inArray(symbol, symbols)) {
4056
+ result[symbol] = this.parseMarketLeverageTiers(entry, market);
4057
+ }
4058
+ }
4059
+ else {
4060
+ result[symbol] = this.parseMarketLeverageTiers(response[i], market);
4061
+ }
4062
+ }
4063
+ return result;
4064
+ }
4065
+ async fetchMarketLeverageTiers(symbol, params = {}) {
4066
+ /**
4067
+ * @method
4068
+ * @name xt#fetchMarketLeverageTiers
4069
+ * @see https://doc.xt.com/#futures_quotesgetLeverageBracket
4070
+ * @description retrieve information on the maximum leverage for different trade sizes of a single market
4071
+ * @param {string} symbol unified market symbol
4072
+ * @param {object} params extra parameters specific to the xt api endpoint
4073
+ * @returns {object} a [leverage tiers structure]{@link https://docs.ccxt.com/#/?id=leverage-tiers-structure}
4074
+ */
4075
+ await this.loadMarkets();
4076
+ const market = this.market(symbol);
4077
+ const request = {
4078
+ 'symbol': market['id'],
4079
+ };
4080
+ let subType = undefined;
4081
+ [subType, params] = this.handleSubTypeAndParams('fetchMarketLeverageTiers', market, params);
4082
+ let response = undefined;
4083
+ if (subType === 'inverse') {
4084
+ response = await this.publicInverseGetFutureMarketV1PublicLeverageBracketDetail(this.extend(request, params));
4085
+ }
4086
+ else {
4087
+ response = await this.publicLinearGetFutureMarketV1PublicLeverageBracketDetail(this.extend(request, params));
4088
+ }
4089
+ //
4090
+ // {
4091
+ // "returnCode": 0,
4092
+ // "msgInfo": "success",
4093
+ // "error": null,
4094
+ // "result": {
4095
+ // "symbol": "btc_usdt",
4096
+ // "leverageBrackets": [
4097
+ // {
4098
+ // "symbol": "btc_usdt",
4099
+ // "bracket": 1,
4100
+ // "maxNominalValue": "500000",
4101
+ // "maintMarginRate": "0.004",
4102
+ // "startMarginRate": "0.008",
4103
+ // "maxStartMarginRate": null,
4104
+ // "maxLeverage": "125",
4105
+ // "minLeverage": "1"
4106
+ // },
4107
+ // ]
4108
+ // }
4109
+ // }
4110
+ //
4111
+ const data = this.safeValue(response, 'result', {});
4112
+ return this.parseMarketLeverageTiers(data, market);
4113
+ }
4114
+ parseMarketLeverageTiers(info, market = undefined) {
4115
+ //
4116
+ // {
4117
+ // "symbol": "rad_usdt",
4118
+ // "leverageBrackets": [
4119
+ // {
4120
+ // "symbol": "rad_usdt",
4121
+ // "bracket": 1,
4122
+ // "maxNominalValue": "5000",
4123
+ // "maintMarginRate": "0.025",
4124
+ // "startMarginRate": "0.05",
4125
+ // "maxStartMarginRate": null,
4126
+ // "maxLeverage": "20",
4127
+ // "minLeverage": "1"
4128
+ // },
4129
+ // ]
4130
+ // }
4131
+ //
4132
+ const tiers = [];
4133
+ const brackets = this.safeValue(info, 'leverageBrackets', []);
4134
+ for (let i = 0; i < brackets.length; i++) {
4135
+ const tier = brackets[i];
4136
+ const marketId = this.safeString(info, 'symbol');
4137
+ market = this.safeMarket(marketId, market, '_', 'contract');
4138
+ tiers.push({
4139
+ 'tier': this.safeInteger(tier, 'bracket'),
4140
+ 'currency': market['settle'],
4141
+ 'minNotional': this.safeNumber(brackets[i - 1], 'maxNominalValue', 0),
4142
+ 'maxNotional': this.safeNumber(tier, 'maxNominalValue'),
4143
+ 'maintenanceMarginRate': this.safeNumber(tier, 'maintMarginRate'),
4144
+ 'maxLeverage': this.safeNumber(tier, 'maxLeverage'),
4145
+ 'info': tier,
4146
+ });
4147
+ }
4148
+ return tiers;
4149
+ }
4150
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
4151
+ /**
4152
+ * @method
4153
+ * @name xt#fetchFundingRateHistory
4154
+ * @description fetches historical funding rates
4155
+ * @see https://doc.xt.com/#futures_quotesgetFundingRateRecord
4156
+ * @param {string} [symbol] unified symbol of the market to fetch the funding rate history for
4157
+ * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
4158
+ * @param {int} [limit] the maximum amount of [funding rate structures] to fetch
4159
+ * @param {object} params extra parameters specific to the xt api endpoint
4160
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/en/latest/manual.html?#funding-rate-history-structure}
4161
+ */
4162
+ if (symbol === undefined) {
4163
+ throw new ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
4164
+ }
4165
+ await this.loadMarkets();
4166
+ const market = this.market(symbol);
4167
+ if (!market['swap']) {
4168
+ throw new BadSymbol(this.id + ' fetchFundingRateHistory() supports swap contracts only');
4169
+ }
4170
+ const request = {
4171
+ 'symbol': market['id'],
4172
+ };
4173
+ if (limit !== undefined) {
4174
+ request['limit'] = limit;
4175
+ }
4176
+ let subType = undefined;
4177
+ [subType, params] = this.handleSubTypeAndParams('fetchFundingRateHistory', market, params);
4178
+ let response = undefined;
4179
+ if (subType === 'inverse') {
4180
+ response = await this.publicInverseGetFutureMarketV1PublicQFundingRateRecord(this.extend(request, params));
4181
+ }
4182
+ else {
4183
+ response = await this.publicLinearGetFutureMarketV1PublicQFundingRateRecord(this.extend(request, params));
4184
+ }
4185
+ //
4186
+ // {
4187
+ // "returnCode": 0,
4188
+ // "msgInfo": "success",
4189
+ // "error": null,
4190
+ // "result": {
4191
+ // "hasPrev": false,
4192
+ // "hasNext": true,
4193
+ // "items": [
4194
+ // {
4195
+ // "id": "210441653482221888",
4196
+ // "symbol": "btc_usdt",
4197
+ // "fundingRate": "0.000057",
4198
+ // "createdTime": 1679875200000,
4199
+ // "collectionInternal": 28800
4200
+ // },
4201
+ // ]
4202
+ // }
4203
+ // }
4204
+ //
4205
+ const result = this.safeValue(response, 'result', {});
4206
+ const items = this.safeValue(result, 'items', []);
4207
+ const rates = [];
4208
+ for (let i = 0; i < items.length; i++) {
4209
+ const entry = items[i];
4210
+ const marketId = this.safeString(entry, 'symbol');
4211
+ const symbolInner = this.safeSymbol(marketId, market);
4212
+ const timestamp = this.safeInteger(entry, 'createdTime');
4213
+ rates.push({
4214
+ 'info': entry,
4215
+ 'symbol': symbolInner,
4216
+ 'fundingRate': this.safeNumber(entry, 'fundingRate'),
4217
+ 'timestamp': timestamp,
4218
+ 'datetime': this.iso8601(timestamp),
4219
+ });
4220
+ }
4221
+ const sorted = this.sortBy(rates, 'timestamp');
4222
+ return this.filterBySymbolSinceLimit(sorted, market['symbol'], since, limit);
4223
+ }
4224
+ async fetchFundingRate(symbol, params = {}) {
4225
+ /**
4226
+ * @method
4227
+ * @name xt#fetchFundingRate
4228
+ * @description fetch the current funding rate
4229
+ * @see https://doc.xt.com/#futures_quotesgetFundingRate
4230
+ * @param {string} symbol unified market symbol
4231
+ * @param {object} params extra parameters specific to the xt api endpoint
4232
+ * @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
4233
+ */
4234
+ await this.loadMarkets();
4235
+ const market = this.market(symbol);
4236
+ if (!market['swap']) {
4237
+ throw new BadSymbol(this.id + ' fetchFundingRate() supports swap contracts only');
4238
+ }
4239
+ const request = {
4240
+ 'symbol': market['id'],
4241
+ };
4242
+ let subType = undefined;
4243
+ [subType, params] = this.handleSubTypeAndParams('fetchFundingRate', market, params);
4244
+ let response = undefined;
4245
+ if (subType === 'inverse') {
4246
+ response = await this.publicInverseGetFutureMarketV1PublicQFundingRate(this.extend(request, params));
4247
+ }
4248
+ else {
4249
+ response = await this.publicLinearGetFutureMarketV1PublicQFundingRate(this.extend(request, params));
4250
+ }
4251
+ //
4252
+ // {
4253
+ // "returnCode": 0,
4254
+ // "msgInfo": "success",
4255
+ // "error": null,
4256
+ // "result": {
4257
+ // "symbol": "btc_usdt",
4258
+ // "fundingRate": "0.000086",
4259
+ // "nextCollectionTime": 1680307200000,
4260
+ // "collectionInternal": 8
4261
+ // }
4262
+ // }
4263
+ //
4264
+ const result = this.safeValue(response, 'result', {});
4265
+ return this.parseFundingRate(result, market);
4266
+ }
4267
+ parseFundingRate(contract, market = undefined) {
4268
+ //
4269
+ // {
4270
+ // "symbol": "btc_usdt",
4271
+ // "fundingRate": "0.000086",
4272
+ // "nextCollectionTime": 1680307200000,
4273
+ // "collectionInternal": 8
4274
+ // }
4275
+ //
4276
+ const marketId = this.safeString(contract, 'symbol');
4277
+ const symbol = this.safeSymbol(marketId, market, '_', 'swap');
4278
+ const timestamp = this.safeInteger(contract, 'nextCollectionTime');
4279
+ return {
4280
+ 'info': contract,
4281
+ 'symbol': symbol,
4282
+ 'markPrice': undefined,
4283
+ 'indexPrice': undefined,
4284
+ 'interestRate': undefined,
4285
+ 'estimatedSettlePrice': undefined,
4286
+ 'timestamp': undefined,
4287
+ 'datetime': undefined,
4288
+ 'fundingRate': this.safeNumber(contract, 'fundingRate'),
4289
+ 'fundingTimestamp': timestamp,
4290
+ 'fundingDatetime': this.iso8601(timestamp),
4291
+ 'nextFundingRate': undefined,
4292
+ 'nextFundingTimestamp': undefined,
4293
+ 'nextFundingDatetime': undefined,
4294
+ 'previousFundingRate': undefined,
4295
+ 'previousFundingTimestamp': undefined,
4296
+ 'previousFundingDatetime': undefined,
4297
+ };
4298
+ }
4299
+ async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
4300
+ /**
4301
+ * @method
4302
+ * @name xt#fetchFundingHistory
4303
+ * @description fetch the funding history
4304
+ * @see https://doc.xt.com/#futures_usergetFunding
4305
+ * @param {string} symbol unified market symbol
4306
+ * @param {int} [since] the starting timestamp in milliseconds
4307
+ * @param {int} [limit] the number of entries to return
4308
+ * @param {object} params extra parameters specific to the xt api endpoint
4309
+ * @returns {object[]} a list of [funding history structures]{@link https://docs.ccxt.com/#/?id=funding-history-structure}
4310
+ */
4311
+ await this.loadMarkets();
4312
+ const market = this.market(symbol);
4313
+ if (!market['swap']) {
4314
+ throw new BadSymbol(this.id + ' fetchFundingHistory() supports swap contracts only');
4315
+ }
4316
+ const request = {
4317
+ 'symbol': market['id'],
4318
+ };
4319
+ if (since !== undefined) {
4320
+ request['startTime'] = since;
4321
+ }
4322
+ if (limit !== undefined) {
4323
+ request['limit'] = limit;
4324
+ }
4325
+ let subType = undefined;
4326
+ [subType, params] = this.handleSubTypeAndParams('fetchFundingHistory', market, params);
4327
+ let response = undefined;
4328
+ if (subType === 'inverse') {
4329
+ response = await this.privateInverseGetFutureUserV1BalanceFundingRateList(this.extend(request, params));
4330
+ }
4331
+ else {
4332
+ response = await this.privateLinearGetFutureUserV1BalanceFundingRateList(this.extend(request, params));
4333
+ }
4334
+ //
4335
+ // {
4336
+ // "returnCode": 0,
4337
+ // "msgInfo": "success",
4338
+ // "error": null,
4339
+ // "result": {
4340
+ // "hasPrev": false,
4341
+ // "hasNext": false,
4342
+ // "items": [
4343
+ // {
4344
+ // "id": "210804044057280512",
4345
+ // "symbol": "btc_usdt",
4346
+ // "cast": "-0.0013",
4347
+ // "coin": "usdt",
4348
+ // "positionSide": "SHORT",
4349
+ // "createdTime": 1679961600653
4350
+ // },
4351
+ // ]
4352
+ // }
4353
+ // }
4354
+ //
4355
+ const data = this.safeValue(response, 'result', {});
4356
+ const items = this.safeValue(data, 'items', []);
4357
+ const result = [];
4358
+ for (let i = 0; i < items.length; i++) {
4359
+ const entry = items[i];
4360
+ result.push(this.parseFundingHistory(entry, market));
4361
+ }
4362
+ const sorted = this.sortBy(result, 'timestamp');
4363
+ return this.filterBySinceLimit(sorted, since, limit);
4364
+ }
4365
+ parseFundingHistory(contract, market = undefined) {
4366
+ //
4367
+ // {
4368
+ // "id": "210804044057280512",
4369
+ // "symbol": "btc_usdt",
4370
+ // "cast": "-0.0013",
4371
+ // "coin": "usdt",
4372
+ // "positionSide": "SHORT",
4373
+ // "createdTime": 1679961600653
4374
+ // }
4375
+ //
4376
+ const marketId = this.safeString(contract, 'symbol');
4377
+ const symbol = this.safeSymbol(marketId, market, '_', 'swap');
4378
+ const currencyId = this.safeString(contract, 'coin');
4379
+ const code = this.safeCurrencyCode(currencyId);
4380
+ const timestamp = this.safeInteger(contract, 'createdTime');
4381
+ return {
4382
+ 'info': contract,
4383
+ 'symbol': symbol,
4384
+ 'code': code,
4385
+ 'timestamp': timestamp,
4386
+ 'datetime': this.iso8601(timestamp),
4387
+ 'id': this.safeString(contract, 'id'),
4388
+ 'amount': this.safeNumber(contract, 'cast'),
4389
+ };
4390
+ }
4391
+ async fetchPosition(symbol, params = {}) {
4392
+ /**
4393
+ * @method
4394
+ * @name xt#fetchPosition
4395
+ * @description fetch data on a single open contract trade position
4396
+ * @see https://doc.xt.com/#futures_usergetPosition
4397
+ * @param {string} symbol unified market symbol of the market the position is held in
4398
+ * @param {object} params extra parameters specific to the xt api endpoint
4399
+ * @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
4400
+ */
4401
+ await this.loadMarkets();
4402
+ const market = this.market(symbol);
4403
+ const request = {
4404
+ 'symbol': market['id'],
4405
+ };
4406
+ let subType = undefined;
4407
+ [subType, params] = this.handleSubTypeAndParams('fetchPosition', market, params);
4408
+ let response = undefined;
4409
+ if (subType === 'inverse') {
4410
+ response = await this.privateInverseGetFutureUserV1PositionList(this.extend(request, params));
4411
+ }
4412
+ else {
4413
+ response = await this.privateLinearGetFutureUserV1PositionList(this.extend(request, params));
4414
+ }
4415
+ //
4416
+ // {
4417
+ // "returnCode": 0,
4418
+ // "msgInfo": "success",
4419
+ // "error": null,
4420
+ // "result": [
4421
+ // {
4422
+ // "symbol": "btc_usdt",
4423
+ // "positionType": "ISOLATED",
4424
+ // "positionSide": "SHORT",
4425
+ // "contractType": "PERPETUAL",
4426
+ // "positionSize": "10",
4427
+ // "closeOrderSize": "0",
4428
+ // "availableCloseSize": "10",
4429
+ // "entryPrice": "27060",
4430
+ // "openOrderSize": "0",
4431
+ // "isolatedMargin": "1.0824",
4432
+ // "openOrderMarginFrozen": "0",
4433
+ // "realizedProfit": "-0.00130138",
4434
+ // "autoMargin": false,
4435
+ // "leverage": 25
4436
+ // },
4437
+ // ]
4438
+ // }
4439
+ //
4440
+ const positions = this.safeValue(response, 'result', []);
4441
+ for (let i = 0; i < positions.length; i++) {
4442
+ const entry = positions[i];
4443
+ const marketId = this.safeString(entry, 'symbol');
4444
+ const marketInner = this.safeMarket(marketId, undefined, undefined, 'contract');
4445
+ const positionSize = this.safeString(entry, 'positionSize');
4446
+ if (positionSize !== '0') {
4447
+ return this.parsePosition(entry, marketInner);
4448
+ }
4449
+ }
4450
+ return undefined;
4451
+ }
4452
+ async fetchPositions(symbols = undefined, params = {}) {
4453
+ /**
4454
+ * @method
4455
+ * @name xt#fetchPositions
4456
+ * @description fetch all open positions
4457
+ * @see https://doc.xt.com/#futures_usergetPosition
4458
+ * @param {string} [symbols] list of unified market symbols, not supported with xt
4459
+ * @param {object} params extra parameters specific to the xt api endpoint
4460
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
4461
+ */
4462
+ await this.loadMarkets();
4463
+ let subType = undefined;
4464
+ [subType, params] = this.handleSubTypeAndParams('fetchPositions', undefined, params);
4465
+ let response = undefined;
4466
+ if (subType === 'inverse') {
4467
+ response = await this.privateInverseGetFutureUserV1PositionList(params);
4468
+ }
4469
+ else {
4470
+ response = await this.privateLinearGetFutureUserV1PositionList(params);
4471
+ }
4472
+ //
4473
+ // {
4474
+ // "returnCode": 0,
4475
+ // "msgInfo": "success",
4476
+ // "error": null,
4477
+ // "result": [
4478
+ // {
4479
+ // "symbol": "btc_usdt",
4480
+ // "positionType": "ISOLATED",
4481
+ // "positionSide": "SHORT",
4482
+ // "contractType": "PERPETUAL",
4483
+ // "positionSize": "10",
4484
+ // "closeOrderSize": "0",
4485
+ // "availableCloseSize": "10",
4486
+ // "entryPrice": "27060",
4487
+ // "openOrderSize": "0",
4488
+ // "isolatedMargin": "1.0824",
4489
+ // "openOrderMarginFrozen": "0",
4490
+ // "realizedProfit": "-0.00130138",
4491
+ // "autoMargin": false,
4492
+ // "leverage": 25
4493
+ // },
4494
+ // ]
4495
+ // }
4496
+ //
4497
+ const positions = this.safeValue(response, 'result', []);
4498
+ const result = [];
4499
+ for (let i = 0; i < positions.length; i++) {
4500
+ const entry = positions[i];
4501
+ const marketId = this.safeString(entry, 'symbol');
4502
+ const marketInner = this.safeMarket(marketId, undefined, undefined, 'contract');
4503
+ result.push(this.parsePosition(entry, marketInner));
4504
+ }
4505
+ return this.filterByArrayPositions(result, 'symbol', symbols, false);
4506
+ }
4507
+ parsePosition(position, market = undefined) {
4508
+ //
4509
+ // {
4510
+ // "symbol": "btc_usdt",
4511
+ // "positionType": "ISOLATED",
4512
+ // "positionSide": "SHORT",
4513
+ // "contractType": "PERPETUAL",
4514
+ // "positionSize": "10",
4515
+ // "closeOrderSize": "0",
4516
+ // "availableCloseSize": "10",
4517
+ // "entryPrice": "27060",
4518
+ // "openOrderSize": "0",
4519
+ // "isolatedMargin": "1.0824",
4520
+ // "openOrderMarginFrozen": "0",
4521
+ // "realizedProfit": "-0.00130138",
4522
+ // "autoMargin": false,
4523
+ // "leverage": 25
4524
+ // }
4525
+ //
4526
+ const marketId = this.safeString(position, 'symbol');
4527
+ market = this.safeMarket(marketId, market, undefined, 'contract');
4528
+ const symbol = this.safeSymbol(marketId, market, undefined, 'contract');
4529
+ const positionType = this.safeString(position, 'positionType');
4530
+ const marginMode = (positionType === 'CROSSED') ? 'cross' : 'isolated';
4531
+ const collateral = this.safeNumber(position, 'isolatedMargin');
4532
+ return this.safePosition({
4533
+ 'info': position,
4534
+ 'id': undefined,
4535
+ 'symbol': symbol,
4536
+ 'timestamp': undefined,
4537
+ 'datetime': undefined,
4538
+ 'hedged': undefined,
4539
+ 'side': this.safeStringLower(position, 'positionSide'),
4540
+ 'contracts': this.safeNumber(position, 'positionSize'),
4541
+ 'contractSize': market['contractSize'],
4542
+ 'entryPrice': this.safeNumber(position, 'entryPrice'),
4543
+ 'markPrice': undefined,
4544
+ 'notional': undefined,
4545
+ 'leverage': this.safeInteger(position, 'leverage'),
4546
+ 'collateral': collateral,
4547
+ 'initialMargin': collateral,
4548
+ 'maintenanceMargin': undefined,
4549
+ 'initialMarginPercentage': undefined,
4550
+ 'maintenanceMarginPercentage': undefined,
4551
+ 'unrealizedPnl': undefined,
4552
+ 'liquidationPrice': undefined,
4553
+ 'marginMode': marginMode,
4554
+ 'percentage': undefined,
4555
+ 'marginRatio': undefined,
4556
+ });
4557
+ }
4558
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
4559
+ /**
4560
+ * @method
4561
+ * @name xt#transfer
4562
+ * @description transfer currency internally between wallets on the same account
4563
+ * @see https://doc.xt.com/#transfersubTransferPost
4564
+ * @param {string} code unified currency code
4565
+ * @param {float} amount amount to transfer
4566
+ * @param {string} fromAccount account to transfer from - spot, swap, leverage, finance
4567
+ * @param {string} toAccount account to transfer to - spot, swap, leverage, finance
4568
+ * @param {object} params extra parameters specific to the whitebit api endpoint
4569
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
4570
+ */
4571
+ await this.loadMarkets();
4572
+ const currency = this.currency(code);
4573
+ const accountsByType = this.safeValue(this.options, 'accountsById');
4574
+ const fromAccountId = this.safeString(accountsByType, fromAccount, fromAccount);
4575
+ const toAccountId = this.safeString(accountsByType, toAccount, toAccount);
4576
+ const amountString = this.currencyToPrecision(code, amount);
4577
+ const request = {
4578
+ 'bizId': this.uuid(),
4579
+ 'currency': currency['id'],
4580
+ 'amount': amountString,
4581
+ 'from': fromAccountId,
4582
+ 'to': toAccountId,
4583
+ };
4584
+ const response = await this.privateSpotPostBalanceTransfer(this.extend(request, params));
4585
+ //
4586
+ // {
4587
+ // info: { rc: '0', mc: 'SUCCESS', ma: [], result: '226971333791398656' },
4588
+ // id: '226971333791398656',
4589
+ // timestamp: undefined,
4590
+ // datetime: undefined,
4591
+ // currency: undefined,
4592
+ // amount: undefined,
4593
+ // fromAccount: undefined,
4594
+ // toAccount: undefined,
4595
+ // status: undefined
4596
+ // }
4597
+ //
4598
+ return this.parseTransfer(response, currency);
4599
+ }
4600
+ parseTransfer(transfer, currency = undefined) {
4601
+ return {
4602
+ 'info': transfer,
4603
+ 'id': this.safeString(transfer, 'result'),
4604
+ 'timestamp': undefined,
4605
+ 'datetime': undefined,
4606
+ 'currency': undefined,
4607
+ 'amount': undefined,
4608
+ 'fromAccount': undefined,
4609
+ 'toAccount': undefined,
4610
+ 'status': undefined,
4611
+ };
4612
+ }
4613
+ handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
4614
+ //
4615
+ // spot: error
4616
+ //
4617
+ // {
4618
+ // "rc": 1,
4619
+ // "mc": "AUTH_103",
4620
+ // "ma": [],
4621
+ // "result": null
4622
+ // }
4623
+ //
4624
+ // spot: success
4625
+ //
4626
+ // {
4627
+ // "returnCode": 0,
4628
+ // "msgInfo": "success",
4629
+ // "error": null,
4630
+ // "result": []
4631
+ // }
4632
+ //
4633
+ // swap and future: error
4634
+ //
4635
+ // {
4636
+ // "returnCode": 1,
4637
+ // "msgInfo": "failure",
4638
+ // "error": {
4639
+ // "code": "403",
4640
+ // "msg": "invalid signature"
4641
+ // },
4642
+ // "result": null
4643
+ // }
4644
+ //
4645
+ // swap and future: success
4646
+ //
4647
+ // {
4648
+ // "returnCode": 0,
4649
+ // "msgInfo": "success",
4650
+ // "error": null,
4651
+ // "result": null
4652
+ // }
4653
+ //
4654
+ // other:
4655
+ //
4656
+ // {
4657
+ // "rc": 0,
4658
+ // "mc": "SUCCESS",
4659
+ // "ma": [],
4660
+ // "result": {}
4661
+ // }
4662
+ //
4663
+ const status = this.safeStringUpper2(response, 'msgInfo', 'mc');
4664
+ if (status !== undefined && status !== 'SUCCESS') {
4665
+ const feedback = this.id + ' ' + body;
4666
+ const error = this.safeValue(response, 'error', {});
4667
+ const spotErrorCode = this.safeString(response, 'mc');
4668
+ const errorCode = this.safeString(error, 'code', spotErrorCode);
4669
+ const spotMessage = this.safeString(response, 'msgInfo');
4670
+ const message = this.safeString(error, 'msg', spotMessage);
4671
+ this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
4672
+ this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
4673
+ throw new ExchangeError(feedback);
4674
+ }
4675
+ return undefined;
4676
+ }
4677
+ sign(path, api = [], method = 'GET', params = {}, headers = undefined, body = undefined) {
4678
+ const signed = api[0] === 'private';
4679
+ const endpoint = api[1];
4680
+ const request = '/' + this.implodeParams(path, params);
4681
+ let payload = undefined;
4682
+ if ((endpoint === 'spot') || (endpoint === 'user')) {
4683
+ if (signed) {
4684
+ payload = '/' + this.version + request;
4685
+ }
4686
+ else {
4687
+ payload = '/' + this.version + '/public' + request;
4688
+ }
4689
+ }
4690
+ else {
4691
+ payload = request;
4692
+ }
4693
+ let url = this.urls['api'][endpoint] + payload;
4694
+ const query = this.omit(params, this.extractParams(path));
4695
+ const urlencoded = this.urlencode(this.keysort(query));
4696
+ headers = {
4697
+ 'Content-Type': 'application/json',
4698
+ };
4699
+ if (signed) {
4700
+ this.checkRequiredCredentials();
4701
+ const defaultRecvWindow = this.safeString(this.options, 'recvWindow');
4702
+ const recvWindow = this.safeString(query, 'recvWindow', defaultRecvWindow);
4703
+ const timestamp = this.numberToString(this.nonce());
4704
+ body = query;
4705
+ if ((payload === '/v4/order') || (payload === '/future/trade/v1/order/create') || (payload === '/future/trade/v1/entrust/create-plan') || (payload === '/future/trade/v1/entrust/create-profit') || (payload === '/future/trade/v1/order/create-batch')) {
4706
+ const id = 'CCXT';
4707
+ if (payload.indexOf('future') > -1) {
4708
+ body['clientMedia'] = id;
4709
+ }
4710
+ else {
4711
+ body['media'] = id;
4712
+ }
4713
+ }
4714
+ const isUndefinedBody = ((method === 'GET') || (path === 'order/{orderId}'));
4715
+ body = isUndefinedBody ? undefined : this.json(body);
4716
+ let payloadString = undefined;
4717
+ if ((endpoint === 'spot') || (endpoint === 'user')) {
4718
+ payloadString = 'xt-validate-algorithms=HmacSHA256&xt-validate-appkey=' + this.apiKey + '&xt-validate-recvwindow=' + recvWindow + '&xt-validate-t' + 'imestamp=' + timestamp;
4719
+ if (isUndefinedBody) {
4720
+ if (urlencoded) {
4721
+ url += '?' + urlencoded;
4722
+ payloadString += '#' + method + '#' + payload + '#' + urlencoded;
4723
+ }
4724
+ else {
4725
+ payloadString += '#' + method + '#' + payload;
4726
+ }
4727
+ }
4728
+ else {
4729
+ payloadString += '#' + method + '#' + payload + '#' + body;
4730
+ }
4731
+ headers['xt-validate-algorithms'] = 'HmacSHA256';
4732
+ headers['xt-validate-recvwindow'] = recvWindow;
4733
+ }
4734
+ else {
4735
+ payloadString = 'xt-validate-appkey=' + this.apiKey + '&xt-validate-t' + 'imestamp=' + timestamp; // we can't glue timestamp, breaks in php
4736
+ if (method === 'GET') {
4737
+ if (urlencoded) {
4738
+ url += '?' + urlencoded;
4739
+ payloadString += '#' + payload + '#' + urlencoded;
4740
+ }
4741
+ else {
4742
+ payloadString += '#' + payload;
4743
+ }
4744
+ }
4745
+ else {
4746
+ payloadString += '#' + payload + '#' + body;
4747
+ }
4748
+ }
4749
+ const signature = this.hmac(this.encode(payloadString), this.encode(this.secret), sha256);
4750
+ headers['xt-validate-appkey'] = this.apiKey;
4751
+ headers['xt-validate-timestamp'] = timestamp;
4752
+ headers['xt-validate-signature'] = signature;
4753
+ }
4754
+ else {
4755
+ if (urlencoded) {
4756
+ url += '?' + urlencoded;
4757
+ }
4758
+ }
4759
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
4760
+ }
4761
+ }