ccxt 4.3.85 → 4.3.86

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 (44) hide show
  1. package/README.md +7 -5
  2. package/dist/ccxt.browser.min.js +15 -15
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/hashkey.js +9 -0
  5. package/dist/cjs/src/base/Exchange.js +1 -1
  6. package/dist/cjs/src/binance.js +4 -2
  7. package/dist/cjs/src/bitfinex.js +2 -2
  8. package/dist/cjs/src/hashkey.js +4328 -0
  9. package/dist/cjs/src/hyperliquid.js +85 -65
  10. package/dist/cjs/src/indodax.js +37 -9
  11. package/dist/cjs/src/krakenfutures.js +12 -10
  12. package/dist/cjs/src/pro/ascendex.js +45 -5
  13. package/dist/cjs/src/pro/bingx.js +13 -12
  14. package/dist/cjs/src/pro/hashkey.js +839 -0
  15. package/dist/cjs/src/pro/hyperliquid.js +123 -0
  16. package/dist/cjs/src/pro/mexc.js +13 -7
  17. package/dist/cjs/src/pro/woo.js +1 -0
  18. package/dist/cjs/src/pro/woofipro.js +1 -0
  19. package/dist/cjs/src/pro/xt.js +1 -0
  20. package/js/ccxt.d.ts +8 -2
  21. package/js/ccxt.js +6 -2
  22. package/js/src/abstract/hashkey.d.ts +70 -0
  23. package/js/src/abstract/hashkey.js +11 -0
  24. package/js/src/base/Exchange.js +1 -1
  25. package/js/src/binance.js +4 -2
  26. package/js/src/bitfinex.js +2 -2
  27. package/js/src/hashkey.d.ts +178 -0
  28. package/js/src/hashkey.js +4329 -0
  29. package/js/src/hyperliquid.d.ts +3 -0
  30. package/js/src/hyperliquid.js +85 -65
  31. package/js/src/indodax.js +37 -9
  32. package/js/src/krakenfutures.js +12 -10
  33. package/js/src/pro/ascendex.d.ts +2 -0
  34. package/js/src/pro/ascendex.js +45 -5
  35. package/js/src/pro/bingx.js +13 -12
  36. package/js/src/pro/hashkey.d.ts +34 -0
  37. package/js/src/pro/hashkey.js +840 -0
  38. package/js/src/pro/hyperliquid.d.ts +7 -1
  39. package/js/src/pro/hyperliquid.js +123 -0
  40. package/js/src/pro/mexc.js +13 -7
  41. package/js/src/pro/woo.js +1 -0
  42. package/js/src/pro/woofipro.js +1 -0
  43. package/js/src/pro/xt.js +1 -0
  44. package/package.json +1 -1
@@ -0,0 +1,4328 @@
1
+ 'use strict';
2
+
3
+ var hashkey$1 = require('./abstract/hashkey.js');
4
+ var errors = require('./base/errors.js');
5
+ var Precise = require('./base/Precise.js');
6
+ var number = require('./base/functions/number.js');
7
+ var sha256 = require('./static_dependencies/noble-hashes/sha256.js');
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * @class hashkey
13
+ * @augments Exchange
14
+ */
15
+ class hashkey extends hashkey$1 {
16
+ describe() {
17
+ return this.deepExtend(super.describe(), {
18
+ 'id': 'hashkey',
19
+ 'name': 'HashKey Global',
20
+ 'countries': ['BM'],
21
+ 'rateLimit': 100,
22
+ 'version': 'v1',
23
+ 'certified': true,
24
+ 'pro': true,
25
+ 'hostname': '/api-glb',
26
+ 'has': {
27
+ 'CORS': undefined,
28
+ 'spot': true,
29
+ 'margin': false,
30
+ 'swap': false,
31
+ 'future': false,
32
+ 'option': false,
33
+ 'addMargin': false,
34
+ 'cancelAllOrders': true,
35
+ 'cancelAllOrdersAfter': false,
36
+ 'cancelOrder': true,
37
+ 'cancelOrders': true,
38
+ 'cancelWithdraw': false,
39
+ 'closePosition': false,
40
+ 'createConvertTrade': false,
41
+ 'createDepositAddress': false,
42
+ 'createMarketBuyOrderWithCost': true,
43
+ 'createMarketOrder': true,
44
+ 'createMarketOrderWithCost': false,
45
+ 'createMarketSellOrderWithCost': false,
46
+ 'createOrder': true,
47
+ 'createOrderWithTakeProfitAndStopLoss': false,
48
+ 'createReduceOnlyOrder': true,
49
+ 'createStopLimitOrder': true,
50
+ 'createStopLossOrder': false,
51
+ 'createStopMarketOrder': true,
52
+ 'createStopOrder': true,
53
+ 'createTakeProfitOrder': false,
54
+ 'createTrailingAmountOrder': false,
55
+ 'createTrailingPercentOrder': false,
56
+ 'createTriggerOrder': true,
57
+ 'fetchAccounts': true,
58
+ 'fetchBalance': true,
59
+ 'fetchCanceledAndClosedOrders': true,
60
+ 'fetchCanceledOrders': true,
61
+ 'fetchClosedOrder': true,
62
+ 'fetchClosedOrders': false,
63
+ 'fetchConvertCurrencies': false,
64
+ 'fetchConvertQuote': false,
65
+ 'fetchConvertTrade': false,
66
+ 'fetchConvertTradeHistory': false,
67
+ 'fetchCurrencies': true,
68
+ 'fetchDepositAddress': true,
69
+ 'fetchDeposits': true,
70
+ 'fetchDepositsWithdrawals': false,
71
+ 'fetchFundingHistory': false,
72
+ 'fetchFundingRate': true,
73
+ 'fetchFundingRateHistory': true,
74
+ 'fetchFundingRates': true,
75
+ 'fetchIndexOHLCV': false,
76
+ 'fetchLedger': true,
77
+ 'fetchLeverage': true,
78
+ 'fetchLeverageTiers': true,
79
+ 'fetchMarginAdjustmentHistory': false,
80
+ 'fetchMarginMode': false,
81
+ 'fetchMarkets': true,
82
+ 'fetchMarkOHLCV': false,
83
+ 'fetchMyTrades': true,
84
+ 'fetchOHLCV': true,
85
+ 'fetchOpenInterestHistory': false,
86
+ 'fetchOpenOrder': false,
87
+ 'fetchOpenOrders': true,
88
+ 'fetchOrder': true,
89
+ 'fetchOrderBook': true,
90
+ 'fetchOrders': false,
91
+ 'fetchOrderTrades': false,
92
+ 'fetchPosition': false,
93
+ 'fetchPositionHistory': false,
94
+ 'fetchPositionMode': false,
95
+ 'fetchPositions': true,
96
+ 'fetchPositionsForSymbol': true,
97
+ 'fetchPositionsHistory': false,
98
+ 'fetchPremiumIndexOHLCV': false,
99
+ 'fetchStatus': true,
100
+ 'fetchTicker': true,
101
+ 'fetchTickers': true,
102
+ 'fetchTime': true,
103
+ 'fetchTrades': true,
104
+ 'fetchTradingFee': true,
105
+ 'fetchTradingFees': true,
106
+ 'fetchTransactions': false,
107
+ 'fetchTransfers': false,
108
+ 'fetchWithdrawals': true,
109
+ 'reduceMargin': false,
110
+ 'sandbox': false,
111
+ 'setLeverage': true,
112
+ 'setMargin': false,
113
+ 'setPositionMode': false,
114
+ 'transfer': true,
115
+ 'withdraw': true,
116
+ },
117
+ 'timeframes': {
118
+ '1m': '1m',
119
+ '3m': '3m',
120
+ '5m': '5m',
121
+ '15m': '15m',
122
+ '30m': '30m',
123
+ '1h': '1h',
124
+ '2h': '2h',
125
+ '4h': '4h',
126
+ '6h': '6h',
127
+ '8h': '8h',
128
+ '12h': '12h',
129
+ '1d': '1d',
130
+ '1w': '1w',
131
+ '1M': '1M',
132
+ },
133
+ 'urls': {
134
+ 'logo': 'https://github.com/user-attachments/assets/6dd6127b-cc19-4a13-9b29-a98d81f80e98',
135
+ 'api': {
136
+ 'public': 'https://api-glb.hashkey.com',
137
+ 'private': 'https://api-glb.hashkey.com',
138
+ },
139
+ 'test': {
140
+ 'public': 'https://api-glb.sim.hashkeydev.com',
141
+ 'private': 'https://api-glb.sim.hashkeydev.com',
142
+ },
143
+ 'www': 'https://global.hashkey.com/',
144
+ 'doc': 'https://hashkeyglobal-apidoc.readme.io/',
145
+ 'fees': 'https://support.global.hashkey.com/hc/en-us/articles/13199900083612-HashKey-Global-Fee-Structure',
146
+ 'referral': '',
147
+ },
148
+ 'api': {
149
+ 'public': {
150
+ 'get': {
151
+ 'api/v1/exchangeInfo': 5,
152
+ 'quote/v1/depth': 1,
153
+ 'quote/v1/trades': 1,
154
+ 'quote/v1/klines': 1,
155
+ 'quote/v1/ticker/24hr': 1,
156
+ 'quote/v1/ticker/price': 1,
157
+ 'quote/v1/ticker/bookTicker': 1,
158
+ 'quote/v1/depth/merged': 1,
159
+ 'quote/v1/markPrice': 1,
160
+ 'quote/v1/index': 1,
161
+ 'api/v1/futures/fundingRate': 1,
162
+ 'api/v1/futures/historyFundingRate': 1,
163
+ 'api/v1/ping': 1,
164
+ 'api/v1/time': 1,
165
+ },
166
+ },
167
+ 'private': {
168
+ 'get': {
169
+ 'api/v1/spot/order': 1,
170
+ 'api/v1/spot/openOrders': 1,
171
+ 'api/v1/spot/tradeOrders': 5,
172
+ 'api/v1/futures/leverage': 1,
173
+ 'api/v1/futures/order': 1,
174
+ 'api/v1/futures/openOrders': 1,
175
+ 'api/v1/futures/userTrades': 1,
176
+ 'api/v1/futures/positions': 1,
177
+ 'api/v1/futures/historyOrders': 1,
178
+ 'api/v1/futures/balance': 1,
179
+ 'api/v1/futures/liquidationAssignStatus': 1,
180
+ 'api/v1/futures/riskLimit': 1,
181
+ 'api/v1/futures/commissionRate': 1,
182
+ 'api/v1/futures/getBestOrder': 1,
183
+ 'api/v1/account/vipInfo': 1,
184
+ 'api/v1/account': 1,
185
+ 'api/v1/account/trades': 5,
186
+ 'api/v1/account/type': 5,
187
+ 'api/v1/account/checkApiKey': 1,
188
+ 'api/v1/account/balanceFlow': 5,
189
+ 'api/v1/spot/subAccount/openOrders': 1,
190
+ 'api/v1/spot/subAccount/tradeOrders': 1,
191
+ 'api/v1/subAccount/trades': 1,
192
+ 'api/v1/futures/subAccount/openOrders': 1,
193
+ 'api/v1/futures/subAccount/historyOrders': 1,
194
+ 'api/v1/futures/subAccount/userTrades': 1,
195
+ 'api/v1/account/deposit/address': 1,
196
+ 'api/v1/account/depositOrders': 1,
197
+ 'api/v1/account/withdrawOrders': 1,
198
+ },
199
+ 'post': {
200
+ 'api/v1/userDataStream': 1,
201
+ 'api/v1/spot/orderTest': 1,
202
+ 'api/v1/spot/order': 1,
203
+ 'api/v1.1/spot/order': 1,
204
+ 'api/v1/spot/batchOrders': 5,
205
+ 'api/v1/futures/leverage': 1,
206
+ 'api/v1/futures/order': 1,
207
+ 'api/v1/futures/position/trading-stop': 3,
208
+ 'api/v1/futures/batchOrders': 5,
209
+ 'api/v1/account/assetTransfer': 1,
210
+ 'api/v1/account/authAddress': 1,
211
+ 'api/v1/account/withdraw': 1,
212
+ },
213
+ 'put': {
214
+ 'api/v1/userDataStream': 1,
215
+ },
216
+ 'delete': {
217
+ 'api/v1/spot/order': 1,
218
+ 'api/v1/spot/openOrders': 5,
219
+ 'api/v1/spot/cancelOrderByIds': 5,
220
+ 'api/v1/futures/order': 1,
221
+ 'api/v1/futures/batchOrders': 1,
222
+ 'api/v1/futures/cancelOrderByIds': 1,
223
+ 'api/v1/userDataStream': 1,
224
+ },
225
+ },
226
+ },
227
+ 'fees': {
228
+ 'trading': {
229
+ 'spot': {
230
+ 'tierBased': true,
231
+ 'percentage': true,
232
+ 'feeSide': 'get',
233
+ 'maker': this.parseNumber('0.0012'),
234
+ 'taker': this.parseNumber('0.0012'),
235
+ 'tiers': {
236
+ 'maker': [
237
+ [this.parseNumber('0'), this.parseNumber('0.0012')],
238
+ [this.parseNumber('1000000'), this.parseNumber('0.00080')],
239
+ [this.parseNumber('5000000'), this.parseNumber('0.00070')],
240
+ [this.parseNumber('10000000'), this.parseNumber('0.00060')],
241
+ [this.parseNumber('50000000'), this.parseNumber('0.00040')],
242
+ [this.parseNumber('200000000'), this.parseNumber('0.00030')],
243
+ [this.parseNumber('400000000'), this.parseNumber('0.00010')],
244
+ [this.parseNumber('800000000'), this.parseNumber('0.00')],
245
+ ],
246
+ 'taker': [
247
+ [this.parseNumber('0'), this.parseNumber('0.0012')],
248
+ [this.parseNumber('1000000'), this.parseNumber('0.00090')],
249
+ [this.parseNumber('5000000'), this.parseNumber('0.00085')],
250
+ [this.parseNumber('10000000'), this.parseNumber('0.00075')],
251
+ [this.parseNumber('50000000'), this.parseNumber('0.00065')],
252
+ [this.parseNumber('200000000'), this.parseNumber('0.00045')],
253
+ [this.parseNumber('400000000'), this.parseNumber('0.00040')],
254
+ [this.parseNumber('800000000'), this.parseNumber('0.00035')],
255
+ ],
256
+ },
257
+ },
258
+ 'swap': {
259
+ 'tierBased': true,
260
+ 'percentage': true,
261
+ 'feeSide': 'get',
262
+ 'maker': this.parseNumber('0.00025'),
263
+ 'taker': this.parseNumber('0.00060'),
264
+ 'tiers': {
265
+ 'maker': [
266
+ [this.parseNumber('0'), this.parseNumber('0.00025')],
267
+ [this.parseNumber('1000000'), this.parseNumber('0.00016')],
268
+ [this.parseNumber('5000000'), this.parseNumber('0.00014')],
269
+ [this.parseNumber('10000000'), this.parseNumber('0.00012')],
270
+ [this.parseNumber('50000000'), this.parseNumber('0.000080')],
271
+ [this.parseNumber('200000000'), this.parseNumber('0.000060')],
272
+ [this.parseNumber('400000000'), this.parseNumber('0.000020')],
273
+ [this.parseNumber('800000000'), this.parseNumber('0.00')],
274
+ ],
275
+ 'taker': [
276
+ [this.parseNumber('0'), this.parseNumber('0.00060')],
277
+ [this.parseNumber('1000000'), this.parseNumber('0.00050')],
278
+ [this.parseNumber('5000000'), this.parseNumber('0.00045')],
279
+ [this.parseNumber('10000000'), this.parseNumber('0.00040')],
280
+ [this.parseNumber('50000000'), this.parseNumber('0.00035')],
281
+ [this.parseNumber('200000000'), this.parseNumber('0.00030')],
282
+ [this.parseNumber('400000000'), this.parseNumber('0.00025')],
283
+ [this.parseNumber('800000000'), this.parseNumber('0.00020')],
284
+ ],
285
+ },
286
+ },
287
+ },
288
+ },
289
+ 'options': {
290
+ 'broker': '10000700011',
291
+ 'recvWindow': undefined,
292
+ 'sandboxMode': false,
293
+ 'networks': {
294
+ 'BTC': 'BTC',
295
+ 'ERC20': 'ETH',
296
+ 'AVAX': 'AvalancheC',
297
+ 'SOL': 'Solana',
298
+ 'MATIC': 'Polygon',
299
+ 'ATOM': 'Cosmos',
300
+ 'DOT': 'Polkadot',
301
+ 'LTC': 'LTC',
302
+ 'OPTIMISM': 'Optimism',
303
+ 'ARB': 'Arbitrum',
304
+ 'DOGE': 'Dogecoin',
305
+ 'TRC20': 'Tron',
306
+ 'ZKSYNC': 'zkSync',
307
+ 'TON': 'TON',
308
+ 'KLAYTN': 'Klaytn',
309
+ 'MERLINCHAIN': 'Merlin Chain',
310
+ },
311
+ 'networksById': {
312
+ 'BTC': 'BTC',
313
+ 'Bitcoin': 'BTC',
314
+ 'ETH': 'ERC20',
315
+ 'ERC20': 'ERC20',
316
+ 'AvalancheC': 'AVAX',
317
+ 'AVAX C-Chain': 'AVAX',
318
+ 'Solana': 'SOL',
319
+ 'Cosmos': 'ATOM',
320
+ 'Arbitrum': 'ARB',
321
+ 'Polygon': 'MATIC',
322
+ 'Optimism': 'OPTIMISM',
323
+ 'Polkadot': 'DOT',
324
+ 'LTC': 'LTC',
325
+ 'Litecoin': 'LTC',
326
+ 'Dogecoin': 'DOGE',
327
+ 'Merlin Chain': 'MERLINCHAIN',
328
+ 'zkSync': 'ZKSYNC',
329
+ 'TRC20': 'TRC20',
330
+ 'Tron': 'TRC20',
331
+ 'TON': 'TON',
332
+ 'BSC(BEP20)': 'BSC',
333
+ 'Klaytn': 'KLAYTN',
334
+ },
335
+ 'defaultNetwork': 'ERC20',
336
+ },
337
+ 'commonCurrencies': {},
338
+ 'exceptions': {
339
+ 'exact': {
340
+ '0001': errors.BadRequest,
341
+ '0002': errors.AuthenticationError,
342
+ '0003': errors.RateLimitExceeded,
343
+ '0102': errors.AuthenticationError,
344
+ '0103': errors.AuthenticationError,
345
+ '0104': errors.PermissionDenied,
346
+ '0201': errors.ExchangeError,
347
+ '0202': errors.PermissionDenied,
348
+ '0206': errors.BadRequest,
349
+ '0207': errors.BadRequest,
350
+ '0209': errors.BadRequest,
351
+ '0210': errors.BadRequest,
352
+ '0211': errors.OrderNotFound,
353
+ '0401': errors.InsufficientFunds,
354
+ '0402': errors.BadRequest,
355
+ '-1000': errors.ExchangeError,
356
+ '-1001': errors.ExchangeError,
357
+ '-100010': errors.BadSymbol,
358
+ '-100012': errors.BadSymbol,
359
+ '-1002': errors.AuthenticationError,
360
+ '-1004': errors.BadRequest,
361
+ '-1005': errors.PermissionDenied,
362
+ '-1006': errors.ExchangeError,
363
+ '-1007': errors.RequestTimeout,
364
+ '-1014': errors.InvalidOrder,
365
+ '-1015': errors.InvalidOrder,
366
+ '-1020': errors.OperationRejected,
367
+ '-1021': errors.InvalidNonce,
368
+ '-1024': errors.BadRequest,
369
+ '-1101': errors.ExchangeNotAvailable,
370
+ '-1115': errors.InvalidOrder,
371
+ '-1117': errors.InvalidOrder,
372
+ '-1123': errors.InvalidOrder,
373
+ '-1124': errors.InvalidOrder,
374
+ '-1126': errors.InvalidOrder,
375
+ '-1129': errors.BadRequest,
376
+ '-1130': errors.BadRequest,
377
+ '-1132': errors.BadRequest,
378
+ '-1133': errors.BadRequest,
379
+ '-1135': errors.BadRequest,
380
+ '-1136': errors.BadRequest,
381
+ '-1138': errors.InvalidOrder,
382
+ '-1137': errors.InvalidOrder,
383
+ '-1139': errors.OrderImmediatelyFillable,
384
+ '-1140': errors.InvalidOrder,
385
+ '-1141': errors.DuplicateOrderId,
386
+ '-1142': errors.OrderNotFillable,
387
+ '-1143': errors.OrderNotFound,
388
+ '-1144': errors.OperationRejected,
389
+ '-1145': errors.NotSupported,
390
+ '-1146': errors.RequestTimeout,
391
+ '-1147': errors.RequestTimeout,
392
+ '-1148': errors.InvalidOrder,
393
+ '-1149': errors.OperationRejected,
394
+ '-1150': errors.OperationFailed,
395
+ '-1151': errors.OperationRejected,
396
+ '-1152': errors.AccountNotEnabled,
397
+ '-1153': errors.InvalidOrder,
398
+ '-1154': errors.InvalidOrder,
399
+ '-1155': errors.OperationRejected,
400
+ '-1156': errors.OperationFailed,
401
+ '-1157': errors.OperationFailed,
402
+ '-1158': errors.OperationFailed,
403
+ '-1159': errors.AccountNotEnabled,
404
+ '-1160': errors.AccountNotEnabled,
405
+ '-1161': errors.OperationFailed,
406
+ '-1162': errors.ContractUnavailable,
407
+ '-1163': errors.InvalidAddress,
408
+ '-1164': errors.OperationFailed,
409
+ '-1165': errors.ArgumentsRequired,
410
+ '-1166': errors.OperationRejected,
411
+ '-1167': errors.BadRequest,
412
+ '-1168': errors.BadRequest,
413
+ '-1169': errors.PermissionDenied,
414
+ '-1170': errors.PermissionDenied,
415
+ '-1171': errors.PermissionDenied,
416
+ '-1172': errors.BadRequest,
417
+ '-1173': errors.BadRequest,
418
+ '-1174': errors.PermissionDenied,
419
+ '-1175': errors.BadRequest,
420
+ '-1176': errors.BadRequest,
421
+ '-1177': errors.InvalidOrder,
422
+ '-1178': errors.AccountNotEnabled,
423
+ '-1179': errors.AccountSuspended,
424
+ '-1181': errors.ExchangeError,
425
+ '-1193': errors.OperationRejected,
426
+ '-1194': errors.OperationRejected,
427
+ '-1195': errors.BadRequest,
428
+ '-1196': errors.BadRequest,
429
+ '-1200': errors.BadRequest,
430
+ '-1201': errors.BadRequest,
431
+ '-1202': errors.BadRequest,
432
+ '-1203': errors.BadRequest,
433
+ '-1204': errors.BadRequest,
434
+ '-1205': errors.AccountNotEnabled,
435
+ '-1206': errors.BadRequest,
436
+ '-1207': errors.BadRequest,
437
+ '-1208': errors.BadRequest,
438
+ '-1209': errors.BadRequest,
439
+ '-2001': errors.ExchangeNotAvailable,
440
+ '-2002': errors.OperationFailed,
441
+ '-2003': errors.OperationFailed,
442
+ '-2004': errors.OperationFailed,
443
+ '-2005': errors.RequestTimeout,
444
+ '-2010': errors.OperationRejected,
445
+ '-2011': errors.OperationRejected,
446
+ '-2016': errors.OperationRejected,
447
+ '-2017': errors.OperationRejected,
448
+ '-2018': errors.OperationRejected,
449
+ '-2019': errors.PermissionDenied,
450
+ '-2020': errors.PermissionDenied,
451
+ '-2021': errors.PermissionDenied,
452
+ '-2022': errors.OperationRejected,
453
+ '-2023': errors.AuthenticationError,
454
+ '-2024': errors.AccountNotEnabled,
455
+ '-2025': errors.AccountNotEnabled,
456
+ '-2026': errors.BadRequest,
457
+ '-2027': errors.OperationRejected,
458
+ '-2028': errors.OperationRejected,
459
+ '-2029': errors.OperationRejected,
460
+ '-2030': errors.InsufficientFunds,
461
+ '-2031': errors.NotSupported,
462
+ '-2032': errors.OperationRejected,
463
+ '-2033': errors.OperationFailed,
464
+ '-2034': errors.InsufficientFunds,
465
+ '-2035': errors.OperationRejected,
466
+ '-2036': errors.NotSupported,
467
+ '-2037': errors.ExchangeError,
468
+ '-2038': errors.InsufficientFunds,
469
+ '-2039': errors.NotSupported,
470
+ '-2040': errors.ExchangeNotAvailable,
471
+ '-2041': errors.BadRequest,
472
+ '-2042': errors.OperationRejected,
473
+ '-2043': errors.OperationRejected,
474
+ '-2044': errors.BadRequest,
475
+ '-2045': errors.BadRequest,
476
+ '-2046': errors.BadRequest,
477
+ '-2048': errors.BadRequest,
478
+ '-2049': errors.BadRequest,
479
+ '-2050': errors.BadRequest,
480
+ '-2051': errors.OperationRejected,
481
+ '-2052': errors.OperationRejected,
482
+ '-2053': errors.OperationRejected,
483
+ '-2054': errors.BadRequest,
484
+ '-2055': errors.BadRequest,
485
+ '-2056': errors.BadRequest,
486
+ '-2057': errors.BadRequest,
487
+ '-3117': errors.PermissionDenied,
488
+ '-3143': errors.PermissionDenied,
489
+ '-3144': errors.PermissionDenied,
490
+ '-3145': errors.DDoSProtection,
491
+ '-4001': errors.BadRequest,
492
+ '-4002': errors.BadRequest,
493
+ '-4003': errors.InsufficientFunds,
494
+ '-4004': errors.BadRequest,
495
+ '-4005': errors.BadRequest,
496
+ '-4006': errors.AccountNotEnabled,
497
+ '-4007': errors.NotSupported,
498
+ '-4008': errors.AccountNotEnabled,
499
+ '-4009': errors.PermissionDenied,
500
+ '-4010': errors.PermissionDenied,
501
+ '-4011': errors.ExchangeError,
502
+ '-4012': errors.ExchangeError,
503
+ '-4013': errors.OperationFailed, // Withdraw repeatly
504
+ },
505
+ 'broad': {},
506
+ },
507
+ 'precisionMode': number.TICK_SIZE,
508
+ });
509
+ }
510
+ async fetchTime(params = {}) {
511
+ /**
512
+ * @method
513
+ * @name hashkey#fetchTime
514
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
515
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/check-server-time
516
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
517
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
518
+ */
519
+ const response = await this.publicGetApiV1Time(params);
520
+ //
521
+ // {
522
+ // "serverTime": 1721661553214
523
+ // }
524
+ //
525
+ return this.safeInteger(response, 'serverTime');
526
+ }
527
+ async fetchStatus(params = {}) {
528
+ /**
529
+ * @method
530
+ * @name hashkey#fetchStatus
531
+ * @description the latest known information on the availability of the exchange API
532
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/test-connectivity
533
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
534
+ * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
535
+ */
536
+ const response = await this.publicGetApiV1Ping(params);
537
+ //
538
+ // {}
539
+ //
540
+ return {
541
+ 'status': 'ok',
542
+ 'updated': undefined,
543
+ 'eta': undefined,
544
+ 'url': undefined,
545
+ 'info': response,
546
+ };
547
+ }
548
+ async fetchMarkets(params = {}) {
549
+ /**
550
+ * @method
551
+ * @name hashkey#fetchMarkets
552
+ * @description retrieves data on all markets for the exchange
553
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/exchangeinfo
554
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
555
+ * @param {string} [params.symbol] the id of the market to fetch
556
+ * @returns {object[]} an array of objects representing market data
557
+ */
558
+ let symbol = undefined;
559
+ const request = {};
560
+ [symbol, params] = this.handleOptionAndParams(params, 'fetchMarkets', 'symbol');
561
+ if (symbol !== undefined) {
562
+ request['symbol'] = symbol;
563
+ }
564
+ const response = await this.publicGetApiV1ExchangeInfo(this.extend(request, params));
565
+ //
566
+ // {
567
+ // "timezone": "UTC",
568
+ // "serverTime": "1721661653952",
569
+ // "brokerFilters": [],
570
+ // "symbols": [
571
+ // {
572
+ // "symbol": "BTCUSDT",
573
+ // "symbolName": "BTCUSDT",
574
+ // "status": "TRADING",
575
+ // "baseAsset": "BTC",
576
+ // "baseAssetName": "BTC",
577
+ // "baseAssetPrecision": "0.00001",
578
+ // "quoteAsset": "USDT",
579
+ // "quoteAssetName": "USDT",
580
+ // "quotePrecision": "0.0000001",
581
+ // "retailAllowed": true,
582
+ // "piAllowed": true,
583
+ // "corporateAllowed": true,
584
+ // "omnibusAllowed": true,
585
+ // "icebergAllowed": false,
586
+ // "isAggregate": false,
587
+ // "allowMargin": false,
588
+ // "filters": [
589
+ // {
590
+ // "minPrice": "0.01",
591
+ // "maxPrice": "100000.00000000",
592
+ // "tickSize": "0.01",
593
+ // "filterType": "PRICE_FILTER"
594
+ // },
595
+ // {
596
+ // "minQty": "0.00001",
597
+ // "maxQty": "8",
598
+ // "stepSize": "0.00001",
599
+ // "marketOrderMinQty": "0.00001",
600
+ // "marketOrderMaxQty": "4",
601
+ // "filterType": "LOT_SIZE"
602
+ // },
603
+ // {
604
+ // "minNotional": "1",
605
+ // "filterType": "MIN_NOTIONAL"
606
+ // },
607
+ // {
608
+ // "minAmount": "1",
609
+ // "maxAmount": "400000",
610
+ // "minBuyPrice": "0",
611
+ // "marketOrderMinAmount": "1",
612
+ // "marketOrderMaxAmount": "200000",
613
+ // "filterType": "TRADE_AMOUNT"
614
+ // },
615
+ // {
616
+ // "maxSellPrice": "0",
617
+ // "buyPriceUpRate": "0.1",
618
+ // "sellPriceDownRate": "0.1",
619
+ // "filterType": "LIMIT_TRADING"
620
+ // },
621
+ // {
622
+ // "buyPriceUpRate": "0.1",
623
+ // "sellPriceDownRate": "0.1",
624
+ // "filterType": "MARKET_TRADING"
625
+ // },
626
+ // {
627
+ // "noAllowMarketStartTime": "1710485700000",
628
+ // "noAllowMarketEndTime": "1710486000000",
629
+ // "limitOrderStartTime": "0",
630
+ // "limitOrderEndTime": "0",
631
+ // "limitMinPrice": "0",
632
+ // "limitMaxPrice": "0",
633
+ // "filterType": "OPEN_QUOTE"
634
+ // }
635
+ // ]
636
+ // }
637
+ // ],
638
+ // "options": [],
639
+ // "contracts": [
640
+ // {
641
+ // "filters": [
642
+ // {
643
+ // "minPrice": "0.1",
644
+ // "maxPrice": "100000.00000000",
645
+ // "tickSize": "0.1",
646
+ // "filterType": "PRICE_FILTER"
647
+ // },
648
+ // {
649
+ // "minQty": "0.001",
650
+ // "maxQty": "10",
651
+ // "stepSize": "0.001",
652
+ // "marketOrderMinQty": "0",
653
+ // "marketOrderMaxQty": "0",
654
+ // "filterType": "LOT_SIZE"
655
+ // },
656
+ // {
657
+ // "minNotional": "0",
658
+ // "filterType": "MIN_NOTIONAL"
659
+ // },
660
+ // {
661
+ // "maxSellPrice": "999999",
662
+ // "buyPriceUpRate": "0.05",
663
+ // "sellPriceDownRate": "0.05",
664
+ // "maxEntrustNum": 200,
665
+ // "maxConditionNum": 200,
666
+ // "filterType": "LIMIT_TRADING"
667
+ // },
668
+ // {
669
+ // "buyPriceUpRate": "0.05",
670
+ // "sellPriceDownRate": "0.05",
671
+ // "filterType": "MARKET_TRADING"
672
+ // },
673
+ // {
674
+ // "noAllowMarketStartTime": "0",
675
+ // "noAllowMarketEndTime": "0",
676
+ // "limitOrderStartTime": "0",
677
+ // "limitOrderEndTime": "0",
678
+ // "limitMinPrice": "0",
679
+ // "limitMaxPrice": "0",
680
+ // "filterType": "OPEN_QUOTE"
681
+ // }
682
+ // ],
683
+ // "exchangeId": "301",
684
+ // "symbol": "BTCUSDT-PERPETUAL",
685
+ // "symbolName": "BTCUSDT-PERPETUAL",
686
+ // "status": "TRADING",
687
+ // "baseAsset": "BTCUSDT-PERPETUAL",
688
+ // "baseAssetPrecision": "0.001",
689
+ // "quoteAsset": "USDT",
690
+ // "quoteAssetPrecision": "0.1",
691
+ // "icebergAllowed": false,
692
+ // "inverse": false,
693
+ // "index": "USDT",
694
+ // "marginToken": "USDT",
695
+ // "marginPrecision": "0.0001",
696
+ // "contractMultiplier": "0.001",
697
+ // "underlying": "BTC",
698
+ // "riskLimits": [
699
+ // {
700
+ // "riskLimitId": "200000722",
701
+ // "quantity": "1000.00",
702
+ // "initialMargin": "0.10",
703
+ // "maintMargin": "0.005",
704
+ // "isWhite": false
705
+ // },
706
+ // {
707
+ // "riskLimitId": "200000723",
708
+ // "quantity": "2000.00",
709
+ // "initialMargin": "0.10",
710
+ // "maintMargin": "0.01",
711
+ // "isWhite": false
712
+ // }
713
+ // ]
714
+ // }
715
+ // ],
716
+ // "coins": [
717
+ // {
718
+ // "orgId": "9001",
719
+ // "coinId": "BTC",
720
+ // "coinName": "BTC",
721
+ // "coinFullName": "Bitcoin",
722
+ // "allowWithdraw": true,
723
+ // "allowDeposit": true,
724
+ // "tokenType": "CHAIN_TOKEN",
725
+ // "chainTypes": [
726
+ // {
727
+ // "chainType": "Bitcoin",
728
+ // "withdrawFee": "0",
729
+ // "minWithdrawQuantity": "0.002",
730
+ // "maxWithdrawQuantity": "0",
731
+ // "minDepositQuantity": "0.0005",
732
+ // "allowDeposit": true,
733
+ // "allowWithdraw": true
734
+ // }
735
+ // ]
736
+ // }
737
+ // ]
738
+ // }
739
+ //
740
+ const spotMarkets = this.safeList(response, 'symbols', []);
741
+ const swapMarkets = this.safeList(response, 'contracts', []);
742
+ let markets = this.arrayConcat(spotMarkets, swapMarkets);
743
+ if (this.isEmpty(markets)) {
744
+ markets = [response]; // if user provides params.symbol the exchange returns a single object insted of list of objects
745
+ }
746
+ return this.parseMarkets(markets);
747
+ }
748
+ parseMarket(market) {
749
+ // spot
750
+ // {
751
+ // "symbol": "BTCUSDT",
752
+ // "symbolName": "BTCUSDT",
753
+ // "status": "TRADING",
754
+ // "baseAsset": "BTC",
755
+ // "baseAssetName": "BTC",
756
+ // "baseAssetPrecision": "0.00001",
757
+ // "quoteAsset": "USDT",
758
+ // "quoteAssetName": "USDT",
759
+ // "quotePrecision": "0.0000001",
760
+ // "retailAllowed": true,
761
+ // "piAllowed": true,
762
+ // "corporateAllowed": true,
763
+ // "omnibusAllowed": true,
764
+ // "icebergAllowed": false,
765
+ // "isAggregate": false,
766
+ // "allowMargin": false,
767
+ // "filters": [
768
+ // {
769
+ // "minPrice": "0.01",
770
+ // "maxPrice": "100000.00000000",
771
+ // "tickSize": "0.01",
772
+ // "filterType": "PRICE_FILTER"
773
+ // },
774
+ // {
775
+ // "minQty": "0.00001",
776
+ // "maxQty": "8",
777
+ // "stepSize": "0.00001",
778
+ // "marketOrderMinQty": "0.00001",
779
+ // "marketOrderMaxQty": "4",
780
+ // "filterType": "LOT_SIZE"
781
+ // },
782
+ // {
783
+ // "minNotional": "1",
784
+ // "filterType": "MIN_NOTIONAL"
785
+ // },
786
+ // {
787
+ // "minAmount": "1",
788
+ // "maxAmount": "400000",
789
+ // "minBuyPrice": "0",
790
+ // "marketOrderMinAmount": "1",
791
+ // "marketOrderMaxAmount": "200000",
792
+ // "filterType": "TRADE_AMOUNT"
793
+ // },
794
+ // {
795
+ // "maxSellPrice": "0",
796
+ // "buyPriceUpRate": "0.1",
797
+ // "sellPriceDownRate": "0.1",
798
+ // "filterType": "LIMIT_TRADING"
799
+ // },
800
+ // {
801
+ // "buyPriceUpRate": "0.1",
802
+ // "sellPriceDownRate": "0.1",
803
+ // "filterType": "MARKET_TRADING"
804
+ // },
805
+ // {
806
+ // "noAllowMarketStartTime": "1710485700000",
807
+ // "noAllowMarketEndTime": "1710486000000",
808
+ // "limitOrderStartTime": "0",
809
+ // "limitOrderEndTime": "0",
810
+ // "limitMinPrice": "0",
811
+ // "limitMaxPrice": "0",
812
+ // "filterType": "OPEN_QUOTE"
813
+ // }
814
+ // ]
815
+ // }
816
+ //
817
+ // swap
818
+ // {
819
+ // "filters": [
820
+ // {
821
+ // "minPrice": "0.1",
822
+ // "maxPrice": "100000.00000000",
823
+ // "tickSize": "0.1",
824
+ // "filterType": "PRICE_FILTER"
825
+ // },
826
+ // {
827
+ // "minQty": "0.001",
828
+ // "maxQty": "10",
829
+ // "stepSize": "0.001",
830
+ // "marketOrderMinQty": "0",
831
+ // "marketOrderMaxQty": "0",
832
+ // "filterType": "LOT_SIZE"
833
+ // },
834
+ // {
835
+ // "minNotional": "0",
836
+ // "filterType": "MIN_NOTIONAL"
837
+ // },
838
+ // {
839
+ // "maxSellPrice": "999999",
840
+ // "buyPriceUpRate": "0.05",
841
+ // "sellPriceDownRate": "0.05",
842
+ // "maxEntrustNum": 200,
843
+ // "maxConditionNum": 200,
844
+ // "filterType": "LIMIT_TRADING"
845
+ // },
846
+ // {
847
+ // "buyPriceUpRate": "0.05",
848
+ // "sellPriceDownRate": "0.05",
849
+ // "filterType": "MARKET_TRADING"
850
+ // },
851
+ // {
852
+ // "noAllowMarketStartTime": "0",
853
+ // "noAllowMarketEndTime": "0",
854
+ // "limitOrderStartTime": "0",
855
+ // "limitOrderEndTime": "0",
856
+ // "limitMinPrice": "0",
857
+ // "limitMaxPrice": "0",
858
+ // "filterType": "OPEN_QUOTE"
859
+ // }
860
+ // ],
861
+ // "exchangeId": "301",
862
+ // "symbol": "BTCUSDT-PERPETUAL",
863
+ // "symbolName": "BTCUSDT-PERPETUAL",
864
+ // "status": "TRADING",
865
+ // "baseAsset": "BTCUSDT-PERPETUAL",
866
+ // "baseAssetPrecision": "0.001",
867
+ // "quoteAsset": "USDT",
868
+ // "quoteAssetPrecision": "0.1",
869
+ // "icebergAllowed": false,
870
+ // "inverse": false,
871
+ // "index": "USDT",
872
+ // "marginToken": "USDT",
873
+ // "marginPrecision": "0.0001",
874
+ // "contractMultiplier": "0.001",
875
+ // "underlying": "BTC",
876
+ // "riskLimits": [
877
+ // {
878
+ // "riskLimitId": "200000722",
879
+ // "quantity": "1000.00",
880
+ // "initialMargin": "0.10",
881
+ // "maintMargin": "0.005",
882
+ // "isWhite": false
883
+ // },
884
+ // {
885
+ // "riskLimitId": "200000723",
886
+ // "quantity": "2000.00",
887
+ // "initialMargin": "0.10",
888
+ // "maintMargin": "0.01",
889
+ // "isWhite": false
890
+ // }
891
+ // ]
892
+ // }
893
+ //
894
+ const marketId = this.safeString(market, 'symbol');
895
+ const quoteId = this.safeString(market, 'quoteAsset');
896
+ const quote = this.safeCurrencyCode(quoteId);
897
+ const settleId = this.safeString(market, 'marginToken');
898
+ const settle = this.safeCurrencyCode(settleId);
899
+ let baseId = this.safeString(market, 'baseAsset');
900
+ let marketType = 'spot';
901
+ let isSpot = true;
902
+ let isSwap = false;
903
+ let suffix = '';
904
+ const parts = marketId.split('-');
905
+ const secondPart = this.safeString(parts, 1);
906
+ if (secondPart === 'PERPETUAL') {
907
+ marketType = 'swap';
908
+ isSpot = false;
909
+ isSwap = true;
910
+ baseId = this.safeString(market, 'underlying');
911
+ suffix += ':' + settleId;
912
+ }
913
+ const base = this.safeCurrencyCode(baseId);
914
+ const symbol = base + '/' + quote + suffix;
915
+ const status = this.safeString(market, 'status');
916
+ const active = status === 'TRADING';
917
+ let isLinear = undefined;
918
+ let subType = undefined;
919
+ const isInverse = this.safeBool(market, 'inverse');
920
+ if (isInverse !== undefined) {
921
+ if (isInverse) {
922
+ isLinear = false;
923
+ subType = 'inverse';
924
+ }
925
+ else {
926
+ isLinear = true;
927
+ subType = 'linear';
928
+ }
929
+ }
930
+ const filtersList = this.safeList(market, 'filters', []);
931
+ const filters = this.indexBy(filtersList, 'filterType');
932
+ const priceFilter = this.safeDict(filters, 'PRICE_FILTER', {});
933
+ const amountFilter = this.safeDict(filters, 'LOT_SIZE', {});
934
+ const costFilter = this.safeDict(filters, 'MIN_NOTIONAL', {});
935
+ const minCostString = this.omitZero(this.safeString(costFilter, 'min_notional'));
936
+ const contractSizeString = this.safeString(market, 'contractMultiplier');
937
+ let amountPrecisionString = this.safeString(amountFilter, 'stepSize');
938
+ let amountMinLimitString = this.safeString(amountFilter, 'minQty');
939
+ let amountMaxLimitString = this.safeString(amountFilter, 'maxQty');
940
+ let minLeverage = undefined;
941
+ let maxLeverage = undefined;
942
+ if (isSwap) {
943
+ amountPrecisionString = Precise["default"].stringDiv(amountPrecisionString, contractSizeString);
944
+ amountMinLimitString = Precise["default"].stringDiv(amountMinLimitString, contractSizeString);
945
+ amountMaxLimitString = Precise["default"].stringDiv(amountMaxLimitString, contractSizeString);
946
+ const riskLimits = this.safeList(market, 'riskLimits');
947
+ if (riskLimits !== undefined) {
948
+ const first = this.safeDict(riskLimits, 0);
949
+ const arrayLength = riskLimits.length;
950
+ const last = this.safeDict(riskLimits, arrayLength - 1);
951
+ let minInitialMargin = this.safeString(first, 'initialMargin');
952
+ let maxInitialMargin = this.safeString(last, 'initialMargin');
953
+ if (Precise["default"].stringGt(minInitialMargin, maxInitialMargin)) {
954
+ [minInitialMargin, maxInitialMargin] = [maxInitialMargin, minInitialMargin];
955
+ }
956
+ minLeverage = this.parseToInt(Precise["default"].stringDiv('1', maxInitialMargin));
957
+ maxLeverage = this.parseToInt(Precise["default"].stringDiv('1', minInitialMargin));
958
+ }
959
+ }
960
+ const tradingFees = this.safeDict(this.fees, 'trading');
961
+ const fees = isSpot ? this.safeDict(tradingFees, 'spot') : this.safeDict(tradingFees, 'swap');
962
+ return this.safeMarketStructure({
963
+ 'id': marketId,
964
+ 'symbol': symbol,
965
+ 'base': base,
966
+ 'quote': quote,
967
+ 'baseId': baseId,
968
+ 'quoteId': quoteId,
969
+ 'active': active,
970
+ 'type': marketType,
971
+ 'subType': subType,
972
+ 'spot': isSpot,
973
+ 'margin': this.safeBool(market, 'allowMargin'),
974
+ 'swap': isSwap,
975
+ 'future': false,
976
+ 'option': false,
977
+ 'contract': isSwap,
978
+ 'settle': settle,
979
+ 'settleId': settleId,
980
+ 'contractSize': this.parseNumber(contractSizeString),
981
+ 'linear': isLinear,
982
+ 'inverse': isInverse,
983
+ 'taker': this.safeNumber(fees, 'taker'),
984
+ 'maker': this.safeNumber(fees, 'maker'),
985
+ 'percentage': this.safeBool(fees, 'percentage'),
986
+ 'tierBased': this.safeBool(fees, 'tierBased'),
987
+ 'feeSide': this.safeString(fees, 'feeSide'),
988
+ 'expiry': undefined,
989
+ 'expiryDatetime': undefined,
990
+ 'strike': undefined,
991
+ 'optionType': undefined,
992
+ 'precision': {
993
+ 'amount': this.parseNumber(amountPrecisionString),
994
+ 'price': this.safeNumber(priceFilter, 'tickSize'),
995
+ },
996
+ 'limits': {
997
+ 'amount': {
998
+ 'min': this.parseNumber(amountMinLimitString),
999
+ 'max': this.parseNumber(amountMaxLimitString),
1000
+ },
1001
+ 'price': {
1002
+ 'min': this.safeNumber(priceFilter, 'minPrice'),
1003
+ 'max': this.safeNumber(priceFilter, 'maxPrice'),
1004
+ },
1005
+ 'leverage': {
1006
+ 'min': minLeverage,
1007
+ 'max': maxLeverage,
1008
+ },
1009
+ 'cost': {
1010
+ 'min': this.parseNumber(minCostString),
1011
+ 'max': undefined,
1012
+ },
1013
+ },
1014
+ 'created': undefined,
1015
+ 'info': market,
1016
+ });
1017
+ }
1018
+ async fetchCurrencies(params = {}) {
1019
+ /**
1020
+ * @method
1021
+ * @name hashkey#fetchCurrencies
1022
+ * @description fetches all available currencies on an exchange
1023
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/exchangeinfo
1024
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1025
+ * @returns {object} an associative dictionary of currencies
1026
+ */
1027
+ const response = await this.publicGetApiV1ExchangeInfo(params);
1028
+ const coins = this.safeList(response, 'coins');
1029
+ //
1030
+ // {
1031
+ // ...
1032
+ // "coins": [
1033
+ // {
1034
+ // "orgId": "9001",
1035
+ // "coinId": "BTC",
1036
+ // "coinName": "BTC",
1037
+ // "coinFullName": "Bitcoin",
1038
+ // "allowWithdraw": true,
1039
+ // "allowDeposit": true,
1040
+ // "tokenType": "CHAIN_TOKEN",
1041
+ // "chainTypes": [
1042
+ // {
1043
+ // "chainType": "Bitcoin",
1044
+ // "withdrawFee": "0",
1045
+ // "minWithdrawQuantity": "0.002",
1046
+ // "maxWithdrawQuantity": "0",
1047
+ // "minDepositQuantity": "0.0005",
1048
+ // "allowDeposit": true,
1049
+ // "allowWithdraw": true
1050
+ // }
1051
+ // ]
1052
+ // }
1053
+ // ]
1054
+ // }
1055
+ //
1056
+ const result = {};
1057
+ for (let i = 0; i < coins.length; i++) {
1058
+ const currecy = coins[i];
1059
+ const currencyId = this.safeString(currecy, 'coinId');
1060
+ const code = this.safeCurrencyCode(currencyId);
1061
+ const allowWithdraw = this.safeBool(currecy, 'allowWithdraw');
1062
+ const allowDeposit = this.safeBool(currecy, 'allowDeposit');
1063
+ const networks = this.safeList(currecy, 'chainTypes');
1064
+ const networksById = this.safeDict(this.options, 'networksById');
1065
+ const parsedNetworks = {};
1066
+ for (let j = 0; j < networks.length; j++) {
1067
+ const network = networks[j];
1068
+ const networkId = this.safeString(network, 'chainType');
1069
+ const networkName = this.safeString(networksById, networkId, networkId);
1070
+ const maxWithdrawQuantity = this.omitZero(this.safeString(network, 'maxWithdrawQuantity'));
1071
+ const networkDeposit = this.safeBool(network, 'allowDeposit');
1072
+ const networkWithdraw = this.safeBool(network, 'allowWithdraw');
1073
+ parsedNetworks[networkName] = {
1074
+ 'id': networkId,
1075
+ 'network': networkName,
1076
+ 'limits': {
1077
+ 'withdraw': {
1078
+ 'min': this.safeNumber(network, 'minWithdrawQuantity'),
1079
+ 'max': this.parseNumber(maxWithdrawQuantity),
1080
+ },
1081
+ 'deposit': {
1082
+ 'min': this.safeNumber(network, 'minDepositQuantity'),
1083
+ 'max': undefined,
1084
+ },
1085
+ },
1086
+ 'active': networkDeposit && networkWithdraw,
1087
+ 'deposit': networkDeposit,
1088
+ 'withdraw': networkWithdraw,
1089
+ 'fee': this.safeNumber(network, 'withdrawFee'),
1090
+ 'precision': undefined,
1091
+ 'info': network,
1092
+ };
1093
+ }
1094
+ result[code] = {
1095
+ 'id': currencyId,
1096
+ 'code': code,
1097
+ 'precision': undefined,
1098
+ 'type': this.parseCurrencyType(this.safeString(currecy, 'tokenType')),
1099
+ 'name': this.safeString(currecy, 'coinFullName'),
1100
+ 'active': allowWithdraw && allowDeposit,
1101
+ 'deposit': allowDeposit,
1102
+ 'withdraw': allowWithdraw,
1103
+ 'fee': undefined,
1104
+ 'limits': {
1105
+ 'deposit': {
1106
+ 'min': undefined,
1107
+ 'max': undefined,
1108
+ },
1109
+ 'withdraw': {
1110
+ 'min': undefined,
1111
+ 'max': undefined,
1112
+ },
1113
+ },
1114
+ 'networks': parsedNetworks,
1115
+ 'info': currecy,
1116
+ };
1117
+ }
1118
+ return result;
1119
+ }
1120
+ parseCurrencyType(type) {
1121
+ const types = {
1122
+ 'CHAIN_TOKEN': 'crypto',
1123
+ 'ERC20_TOKEN': 'crypto',
1124
+ 'BSC_TOKEN': 'crypto',
1125
+ 'REAL_MONEY': 'fiat',
1126
+ };
1127
+ return this.safeString(types, type);
1128
+ }
1129
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
1130
+ /**
1131
+ * @method
1132
+ * @name hashkey#fetchOrderBook
1133
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1134
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-order-book
1135
+ * @param {string} symbol unified symbol of the market to fetch the order book for
1136
+ * @param {int} [limit] the maximum amount of order book entries to return (maximum value is 200)
1137
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1138
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
1139
+ */
1140
+ await this.loadMarkets();
1141
+ const market = this.market(symbol);
1142
+ const request = {
1143
+ 'symbol': market['id'],
1144
+ };
1145
+ if (limit !== undefined) {
1146
+ request['limit'] = limit;
1147
+ }
1148
+ const response = await this.publicGetQuoteV1Depth(this.extend(request, params));
1149
+ //
1150
+ // {
1151
+ // "t": 1721681436393,
1152
+ // "b": [
1153
+ // ["67902.49", "0.00112"],
1154
+ // ["67901.08", "0.01014"]
1155
+ // ...
1156
+ // ],
1157
+ // "a": [
1158
+ // ["67905.99", "0.87134"],
1159
+ // ["67906", "0.57361"]
1160
+ // ...
1161
+ // ]
1162
+ // }
1163
+ //
1164
+ const timestamp = this.safeInteger(response, 't');
1165
+ return this.parseOrderBook(response, symbol, timestamp, 'b', 'a');
1166
+ }
1167
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
1168
+ /**
1169
+ * @method
1170
+ * @name hashkey#fetchTrades
1171
+ * @description get the list of most recent trades for a particular symbol
1172
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-recent-trade-list
1173
+ * @param {string} symbol unified symbol of the market to fetch trades for
1174
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
1175
+ * @param {int} [limit] the maximum amount of trades to fetch (maximum value is 100)
1176
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1177
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
1178
+ */
1179
+ await this.loadMarkets();
1180
+ const market = this.market(symbol);
1181
+ const request = {
1182
+ 'symbol': market['id'],
1183
+ };
1184
+ if (limit !== undefined) {
1185
+ request['limit'] = limit;
1186
+ }
1187
+ const response = await this.publicGetQuoteV1Trades(this.extend(request, params));
1188
+ //
1189
+ // [
1190
+ // {
1191
+ // "t": 1721682745779,
1192
+ // "p": "67835.99",
1193
+ // "q": "0.00017",
1194
+ // "ibm": true
1195
+ // },
1196
+ // ...
1197
+ // ]
1198
+ //
1199
+ return this.parseTrades(response, market, since, limit);
1200
+ }
1201
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1202
+ /**
1203
+ * @method
1204
+ * @name hashkey#fetchMyTrades
1205
+ * @description fetch all trades made by the user
1206
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-account-trade-list
1207
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/query-futures-trades
1208
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-user
1209
+ * @param {string} symbol *is mandatory for swap markets* unified market symbol
1210
+ * @param {int} [since] the earliest time in ms to fetch trades for
1211
+ * @param {int} [limit] the maximum amount of trades to fetch (default 200, max 500)
1212
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1213
+ * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch trades for (default 'spot')
1214
+ * @param {int} [params.until] the latest time in ms to fetch trades for, only supports the last 30 days timeframe
1215
+ * @param {string} [params.fromId] srarting trade id
1216
+ * @param {string} [params.toId] ending trade id
1217
+ * @param {string} [params.clientOrderId] *spot markets only* filter trades by orderId
1218
+ * @param {string} [params.accountId] account id to fetch the orders from
1219
+ * @returns {Trade[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#trade-structure}
1220
+ */
1221
+ const methodName = 'fetchMyTrades';
1222
+ await this.loadMarkets();
1223
+ const request = {};
1224
+ let market = undefined;
1225
+ if (symbol !== undefined) {
1226
+ market = this.market(symbol);
1227
+ }
1228
+ let marketType = 'spot';
1229
+ [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params);
1230
+ if (since !== undefined) {
1231
+ request['startTime'] = since;
1232
+ }
1233
+ if (limit !== undefined) {
1234
+ request['limit'] = limit;
1235
+ }
1236
+ let until = undefined;
1237
+ [until, params] = this.handleOptionAndParams(params, methodName, 'until');
1238
+ if (until !== undefined) {
1239
+ request['endTime'] = until;
1240
+ }
1241
+ let accountId = undefined;
1242
+ [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
1243
+ let response = undefined;
1244
+ if (marketType === 'spot') {
1245
+ if (market !== undefined) {
1246
+ request['symbol'] = market['id'];
1247
+ }
1248
+ let clientOrderId = undefined;
1249
+ [clientOrderId, params] = this.handleOptionAndParams(params, methodName, 'clientOrderId');
1250
+ if (clientOrderId !== undefined) {
1251
+ request['clientOrderId'] = clientOrderId;
1252
+ }
1253
+ if (accountId !== undefined) {
1254
+ request['accountId'] = accountId;
1255
+ }
1256
+ response = await this.privateGetApiV1AccountTrades(this.extend(request, params));
1257
+ //
1258
+ // [
1259
+ // {
1260
+ // "id": "1739352552862964736",
1261
+ // "clientOrderId": "1722082982086472",
1262
+ // "ticketId": "1739352552795029504",
1263
+ // "symbol": "ETHUSDT",
1264
+ // "symbolName": "ETHUSDT",
1265
+ // "orderId": "1739352552762301440",
1266
+ // "matchOrderId": "0",
1267
+ // "price": "3289.96",
1268
+ // "qty": "0.001",
1269
+ // "commission": "0.0000012",
1270
+ // "commissionAsset": "ETH",
1271
+ // "time": "1722082982097",
1272
+ // "isBuyer": true,
1273
+ // "isMaker": false,
1274
+ // "fee": {
1275
+ // "feeCoinId": "ETH",
1276
+ // "feeCoinName": "ETH",
1277
+ // "fee": "0.0000012"
1278
+ // },
1279
+ // "feeCoinId": "ETH",
1280
+ // "feeAmount": "0.0000012",
1281
+ // "makerRebate": "0"
1282
+ // },
1283
+ // ...
1284
+ // ]
1285
+ //
1286
+ }
1287
+ else if (marketType === 'swap') {
1288
+ if (symbol === undefined) {
1289
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument for swap markets');
1290
+ }
1291
+ request['symbol'] = market['id'];
1292
+ if (accountId !== undefined) {
1293
+ request['subAccountId'] = accountId;
1294
+ response = await this.privateGetApiV1FuturesSubAccountUserTrades(this.extend(request, params));
1295
+ }
1296
+ else {
1297
+ response = await this.privateGetApiV1FuturesUserTrades(this.extend(request, params));
1298
+ //
1299
+ // [
1300
+ // {
1301
+ // "time": "1722429951648",
1302
+ // "tradeId": "1742263144691139328",
1303
+ // "orderId": "1742263144028363776",
1304
+ // "symbol": "ETHUSDT-PERPETUAL",
1305
+ // "price": "3327.54",
1306
+ // "quantity": "4",
1307
+ // "commissionAsset": "USDT",
1308
+ // "commission": "0.00798609",
1309
+ // "makerRebate": "0",
1310
+ // "type": "LIMIT",
1311
+ // "side": "BUY_OPEN",
1312
+ // "realizedPnl": "0",
1313
+ // "isMarker": false
1314
+ // }
1315
+ // ]
1316
+ //
1317
+ }
1318
+ }
1319
+ else {
1320
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
1321
+ }
1322
+ return this.parseTrades(response, market, since, limit);
1323
+ }
1324
+ parseTrade(trade, market = undefined) {
1325
+ //
1326
+ // fetchTrades
1327
+ //
1328
+ // {
1329
+ // "t": 1721682745779,
1330
+ // "p": "67835.99",
1331
+ // "q": "0.00017",
1332
+ // "ibm": true
1333
+ // }
1334
+ //
1335
+ // fetchMyTrades spot
1336
+ //
1337
+ // {
1338
+ // "id": "1739352552862964736",
1339
+ // "clientOrderId": "1722082982086472",
1340
+ // "ticketId": "1739352552795029504",
1341
+ // "symbol": "ETHUSDT",
1342
+ // "symbolName": "ETHUSDT",
1343
+ // "orderId": "1739352552762301440",
1344
+ // "matchOrderId": "0",
1345
+ // "price": "3289.96",
1346
+ // "qty": "0.001",
1347
+ // "commission": "0.0000012",
1348
+ // "commissionAsset": "ETH",
1349
+ // "time": "1722082982097",
1350
+ // "isBuyer": true,
1351
+ // "isMaker": false,
1352
+ // "fee": {
1353
+ // "feeCoinId": "ETH",
1354
+ // "feeCoinName": "ETH",
1355
+ // "fee": "0.0000012"
1356
+ // },
1357
+ // "feeCoinId": "ETH",
1358
+ // "feeAmount": "0.0000012",
1359
+ // "makerRebate": "0"
1360
+ // }
1361
+ //
1362
+ // fetchMyTrades swap
1363
+ // {
1364
+ // "time": "1722429951648",
1365
+ // "tradeId": "1742263144691139328",
1366
+ // "orderId": "1742263144028363776",
1367
+ // "symbol": "ETHUSDT-PERPETUAL",
1368
+ // "price": "3327.54",
1369
+ // "quantity": "4",
1370
+ // "commissionAsset": "USDT",
1371
+ // "commission": "0.00798609",
1372
+ // "makerRebate": "0",
1373
+ // "type": "LIMIT",
1374
+ // "side": "BUY_OPEN",
1375
+ // "realizedPnl": "0",
1376
+ // "isMarker": false
1377
+ // }
1378
+ const timestamp = this.safeInteger2(trade, 't', 'time');
1379
+ const marketId = this.safeString(trade, 'symbol');
1380
+ market = this.safeMarket(marketId, market);
1381
+ let side = this.safeStringLower(trade, 'side'); // swap trades have side param
1382
+ if (side !== undefined) {
1383
+ side = this.safeString(side.split('_'), 0);
1384
+ }
1385
+ const isBuyer = this.safeBool(trade, 'isBuyer');
1386
+ if (isBuyer !== undefined) {
1387
+ side = isBuyer ? 'buy' : 'sell';
1388
+ }
1389
+ let takerOrMaker = undefined;
1390
+ const isMaker = this.safeBoolN(trade, ['isMaker', 'isMarker', 'ibm']);
1391
+ if (isMaker !== undefined) {
1392
+ takerOrMaker = isMaker ? 'maker' : 'taker';
1393
+ }
1394
+ let feeCost = this.safeString(trade, 'commission');
1395
+ let feeCurrncyId = this.safeString(trade, 'commissionAsset');
1396
+ const feeInfo = this.safeDict(trade, 'fee');
1397
+ let fee = undefined;
1398
+ if (feeInfo !== undefined) {
1399
+ feeCost = this.safeString(feeInfo, 'fee');
1400
+ feeCurrncyId = this.safeString(feeInfo, 'feeCoinId');
1401
+ }
1402
+ if (feeCost !== undefined) {
1403
+ fee = {
1404
+ 'cost': this.parseNumber(feeCost),
1405
+ 'currency': this.safeCurrencyCode(feeCurrncyId),
1406
+ };
1407
+ }
1408
+ return this.safeTrade({
1409
+ 'id': this.safeString2(trade, 'id', 'tradeId'),
1410
+ 'timestamp': timestamp,
1411
+ 'datetime': this.iso8601(timestamp),
1412
+ 'symbol': market['symbol'],
1413
+ 'side': side,
1414
+ 'price': this.safeString2(trade, 'p', 'price'),
1415
+ 'amount': this.safeStringN(trade, ['q', 'qty', 'quantity']),
1416
+ 'cost': undefined,
1417
+ 'takerOrMaker': takerOrMaker,
1418
+ 'type': undefined,
1419
+ 'order': this.safeString(trade, 'orderId'),
1420
+ 'fee': fee,
1421
+ 'info': trade,
1422
+ }, market);
1423
+ }
1424
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1425
+ /**
1426
+ * @method
1427
+ * @name hashkey#fetchOHLCV
1428
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-kline
1429
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1430
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1431
+ * @param {string} timeframe the length of time each candle represents
1432
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
1433
+ * @param {int} [limit] the maximum amount of candles to fetch
1434
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1435
+ * @param {int} [params.until] timestamp in ms of the latest candle to fetch
1436
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1437
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1438
+ */
1439
+ const methodName = 'fetchOHLCV';
1440
+ await this.loadMarkets();
1441
+ let paginate = false;
1442
+ [paginate, params] = this.handleOptionAndParams(params, methodName, 'paginate');
1443
+ if (paginate) {
1444
+ return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1000);
1445
+ }
1446
+ const market = this.market(symbol);
1447
+ timeframe = this.safeString(this.timeframes, timeframe, timeframe);
1448
+ const request = {
1449
+ 'symbol': market['id'],
1450
+ 'interval': timeframe,
1451
+ };
1452
+ if (since !== undefined) {
1453
+ request['startTime'] = since;
1454
+ }
1455
+ if (limit !== undefined) {
1456
+ request['limit'] = limit;
1457
+ }
1458
+ let until = undefined;
1459
+ [until, params] = this.handleOptionAndParams(params, methodName, 'until');
1460
+ if (until !== undefined) {
1461
+ request['endTime'] = until;
1462
+ }
1463
+ const response = await this.publicGetQuoteV1Klines(this.extend(request, params));
1464
+ //
1465
+ // [
1466
+ // [
1467
+ // 1721684280000,
1468
+ // "67832.49",
1469
+ // "67862.5",
1470
+ // "67832.49",
1471
+ // "67861.44",
1472
+ // "0.01122",0,
1473
+ // "761.2763533",68,
1474
+ // "0.00561",
1475
+ // "380.640643"
1476
+ // ],
1477
+ // ...
1478
+ // ]
1479
+ //
1480
+ return this.parseOHLCVs(response, market, timeframe, since, limit);
1481
+ }
1482
+ parseOHLCV(ohlcv, market = undefined) {
1483
+ //
1484
+ // [
1485
+ // 1721684280000,
1486
+ // "67832.49",
1487
+ // "67862.5",
1488
+ // "67832.49",
1489
+ // "67861.44",
1490
+ // "0.01122",0,
1491
+ // "761.2763533",68,
1492
+ // "0.00561",
1493
+ // "380.640643"
1494
+ // ]
1495
+ //
1496
+ return [
1497
+ this.safeInteger(ohlcv, 0),
1498
+ this.safeNumber(ohlcv, 1),
1499
+ this.safeNumber(ohlcv, 2),
1500
+ this.safeNumber(ohlcv, 3),
1501
+ this.safeNumber(ohlcv, 4),
1502
+ this.safeNumber(ohlcv, 5),
1503
+ ];
1504
+ }
1505
+ async fetchTicker(symbol, params = {}) {
1506
+ /**
1507
+ * @method
1508
+ * @name hashkey#fetchTicker
1509
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1510
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-24hr-ticker-price-change
1511
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
1512
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1513
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1514
+ */
1515
+ await this.loadMarkets();
1516
+ const market = this.market(symbol);
1517
+ const request = {
1518
+ 'symbol': market['id'],
1519
+ };
1520
+ const response = await this.publicGetQuoteV1Ticker24hr(this.extend(request, params));
1521
+ //
1522
+ // [
1523
+ // {
1524
+ // "t": 1721685896846,
1525
+ // "s": "BTCUSDT-PERPETUAL",
1526
+ // "c": "67756.7",
1527
+ // "h": "68479.9",
1528
+ // "l": "66594.3",
1529
+ // "o": "68279.7",
1530
+ // "b": "67756.6",
1531
+ // "a": "67756.7",
1532
+ // "v": "1604722",
1533
+ // "qv": "108827258.7761"
1534
+ // }
1535
+ // ]
1536
+ //
1537
+ const ticker = this.safeDict(response, 0, {});
1538
+ return this.parseTicker(ticker, market);
1539
+ }
1540
+ async fetchTickers(symbols = undefined, params = {}) {
1541
+ /**
1542
+ * @method
1543
+ * @name hashkey#fetchTickers
1544
+ * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1545
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-24hr-ticker-price-change
1546
+ * @param {string[]} [symbols] unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1547
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1548
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1549
+ */
1550
+ await this.loadMarkets();
1551
+ symbols = this.marketSymbols(symbols);
1552
+ const response = await this.publicGetQuoteV1Ticker24hr(params);
1553
+ return this.parseTickers(response, symbols);
1554
+ }
1555
+ parseTicker(ticker, market = undefined) {
1556
+ //
1557
+ // {
1558
+ // "t": 1721685896846,
1559
+ // "s": "BTCUSDT-PERPETUAL",
1560
+ // "c": "67756.7",
1561
+ // "h": "68479.9",
1562
+ // "l": "66594.3",
1563
+ // "o": "68279.7",
1564
+ // "b": "67756.6",
1565
+ // "a": "67756.7",
1566
+ // "v": "1604722",
1567
+ // "qv": "108827258.7761"
1568
+ // }
1569
+ //
1570
+ const timestamp = this.safeInteger(ticker, 't');
1571
+ const marketId = this.safeString(ticker, 's');
1572
+ market = this.safeMarket(marketId, market);
1573
+ const symbol = market['symbol'];
1574
+ const last = this.safeString(ticker, 'c');
1575
+ return this.safeTicker({
1576
+ 'symbol': symbol,
1577
+ 'timestamp': timestamp,
1578
+ 'datetime': this.iso8601(timestamp),
1579
+ 'high': this.safeString(ticker, 'h'),
1580
+ 'low': this.safeString(ticker, 'l'),
1581
+ 'bid': this.safeString(ticker, 'b'),
1582
+ 'bidVolume': undefined,
1583
+ 'ask': this.safeString(ticker, 'a'),
1584
+ 'askVolume': undefined,
1585
+ 'vwap': undefined,
1586
+ 'open': this.safeString(ticker, 'o'),
1587
+ 'close': last,
1588
+ 'last': last,
1589
+ 'previousClose': undefined,
1590
+ 'change': undefined,
1591
+ 'percentage': undefined,
1592
+ 'average': undefined,
1593
+ 'baseVolume': this.safeString(ticker, 'v'),
1594
+ 'quoteVolume': this.safeString(ticker, 'qv'),
1595
+ 'info': ticker,
1596
+ }, market);
1597
+ }
1598
+ async fetchLastPrices(symbols = undefined, params = {}) {
1599
+ /**
1600
+ * @method
1601
+ * @name hashkey#fetchLastPrices
1602
+ * @description fetches the last price for multiple markets
1603
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-symbol-price-ticker
1604
+ * @param {string[]} [symbols] unified symbols of the markets to fetch the last prices
1605
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1606
+ * @param {string} [params.symbol] the id of the market to fetch last price for
1607
+ * @returns {object} a dictionary of lastprices structures
1608
+ */
1609
+ await this.loadMarkets();
1610
+ symbols = this.marketSymbols(symbols);
1611
+ const request = {};
1612
+ let symbol = undefined;
1613
+ [symbol, params] = this.handleOptionAndParams(params, 'fetchLastPrices', 'symbol');
1614
+ if (symbol !== undefined) {
1615
+ request['symbol'] = symbol;
1616
+ }
1617
+ const response = await this.publicGetQuoteV1TickerPrice(this.extend(request, params));
1618
+ //
1619
+ // [
1620
+ // {
1621
+ // "s": "BTCUSDT-PERPETUAL",
1622
+ // "p": "64871"
1623
+ // },
1624
+ // ...
1625
+ // ]
1626
+ //
1627
+ return this.parseLastPrices(response, symbols);
1628
+ }
1629
+ parseLastPrice(entry, market = undefined) {
1630
+ const marketId = this.safeString(entry, 's');
1631
+ market = this.safeMarket(marketId, market);
1632
+ return {
1633
+ 'symbol': market['symbol'],
1634
+ 'timestamp': undefined,
1635
+ 'datetime': undefined,
1636
+ 'price': this.safeNumber(entry, 'p'),
1637
+ 'side': undefined,
1638
+ 'info': entry,
1639
+ };
1640
+ }
1641
+ async fetchBalance(params = {}) {
1642
+ /**
1643
+ * @method
1644
+ * @name hashkey#fetchBalance
1645
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
1646
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-account-information
1647
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1648
+ * @param {string} [params.accountId] account ID, for Master Key only
1649
+ * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch balance for (default 'spot')
1650
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1651
+ */
1652
+ await this.loadMarkets();
1653
+ const request = {};
1654
+ const methodName = 'fetchBalance';
1655
+ let marketType = 'spot';
1656
+ [marketType, params] = this.handleMarketTypeAndParams(methodName, undefined, params, marketType);
1657
+ if (marketType === 'swap') {
1658
+ const response = await this.privateGetApiV1FuturesBalance(params);
1659
+ //
1660
+ // [
1661
+ // {
1662
+ // "balance": "30.63364672",
1663
+ // "availableBalance": "28.85635534",
1664
+ // "positionMargin": "4.3421",
1665
+ // "orderMargin": "0",
1666
+ // "asset": "USDT",
1667
+ // "crossUnRealizedPnl": "2.5649"
1668
+ // }
1669
+ // ]
1670
+ //
1671
+ const balance = this.safeDict(response, 0, {});
1672
+ return this.parseSwapBalance(balance);
1673
+ }
1674
+ else if (marketType === 'spot') {
1675
+ let accountId = undefined;
1676
+ [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
1677
+ if (accountId !== undefined) {
1678
+ request['accountId'] = accountId;
1679
+ }
1680
+ const response = await this.privateGetApiV1Account(this.extend(request, params));
1681
+ //
1682
+ // {
1683
+ // "balances": [
1684
+ // {
1685
+ // "asset":"USDT",
1686
+ // "assetId":"USDT",
1687
+ // "assetName":"USDT",
1688
+ // "total":"40",
1689
+ // "free":"40",
1690
+ // "locked":"0"
1691
+ // },
1692
+ // ...
1693
+ // ],
1694
+ // "userId": "1732885739572845312"
1695
+ // }
1696
+ //
1697
+ return this.parseBalance(response);
1698
+ }
1699
+ else {
1700
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
1701
+ }
1702
+ }
1703
+ parseBalance(balance) {
1704
+ //
1705
+ // {
1706
+ // "balances": [
1707
+ // {
1708
+ // "asset":"USDT",
1709
+ // "assetId":"USDT",
1710
+ // "assetName":"USDT",
1711
+ // "total":"40",
1712
+ // "free":"40",
1713
+ // "locked":"0"
1714
+ // },
1715
+ // ...
1716
+ // ],
1717
+ // "userId": "1732885739572845312"
1718
+ // }
1719
+ //
1720
+ const result = {
1721
+ 'info': balance,
1722
+ };
1723
+ const balances = this.safeList(balance, 'balances', []);
1724
+ for (let i = 0; i < balances.length; i++) {
1725
+ const balanceEntry = balances[i];
1726
+ const currencyId = this.safeString(balanceEntry, 'asset');
1727
+ const code = this.safeCurrencyCode(currencyId);
1728
+ const account = this.account();
1729
+ account['total'] = this.safeString(balanceEntry, 'total');
1730
+ account['free'] = this.safeString(balanceEntry, 'free');
1731
+ account['used'] = this.safeString(balanceEntry, 'locked');
1732
+ result[code] = account;
1733
+ }
1734
+ return this.safeBalance(result);
1735
+ }
1736
+ parseSwapBalance(balance) {
1737
+ //
1738
+ // {
1739
+ // "balance": "30.63364672",
1740
+ // "availableBalance": "28.85635534",
1741
+ // "positionMargin": "4.3421",
1742
+ // "orderMargin": "0",
1743
+ // "asset": "USDT",
1744
+ // "crossUnRealizedPnl": "2.5649"
1745
+ // }
1746
+ //
1747
+ const currencyId = this.safeString(balance, 'asset');
1748
+ const code = this.safeCurrencyCode(currencyId);
1749
+ const account = this.account();
1750
+ account['total'] = this.safeString(balance, 'balance');
1751
+ const positionMargin = this.safeString(balance, 'positionMargin');
1752
+ const orderMargin = this.safeString(balance, 'orderMargin');
1753
+ account['used'] = Precise["default"].stringAdd(positionMargin, orderMargin);
1754
+ const result = {
1755
+ 'info': balance,
1756
+ };
1757
+ result[code] = account;
1758
+ return this.safeBalance(result);
1759
+ }
1760
+ async fetchDepositAddress(code, params = {}) {
1761
+ /**
1762
+ * @method
1763
+ * @name hashkey#fetchDepositAddress
1764
+ * @description fetch the deposit address for a currency associated with this account
1765
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-deposit-address
1766
+ * @param {string} code unified currency code (default is 'USDT')
1767
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1768
+ * @param {string} [params.network] network for fetch deposit address (default is 'ETH')
1769
+ * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
1770
+ */
1771
+ await this.loadMarkets();
1772
+ const currency = this.currency(code);
1773
+ const request = {
1774
+ 'coin': currency['id'],
1775
+ };
1776
+ let networkCode = undefined;
1777
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
1778
+ if (networkCode === undefined) {
1779
+ networkCode = this.defaultNetworkCode(code);
1780
+ }
1781
+ request['chainType'] = this.networkCodeToId(networkCode, code);
1782
+ const response = await this.privateGetApiV1AccountDepositAddress(this.extend(request, params));
1783
+ //
1784
+ // {
1785
+ // "canDeposit": true,
1786
+ // "address": "0x61AAd7F763e2C7fF1CC996918740F67f9dC8BF4e",
1787
+ // "addressExt": "",
1788
+ // "minQuantity": "1",
1789
+ // "needAddressTag": false,
1790
+ // "requiredConfirmTimes": 64,
1791
+ // "canWithdrawConfirmTimes": 64,
1792
+ // "coinType": "ERC20_TOKEN"
1793
+ // }
1794
+ //
1795
+ const depositAddress = this.parseDepositAddress(response, currency);
1796
+ depositAddress['network'] = networkCode;
1797
+ return depositAddress;
1798
+ }
1799
+ parseDepositAddress(depositAddress, currency = undefined) {
1800
+ //
1801
+ // {
1802
+ // "canDeposit": true,
1803
+ // "address": "0x61AAd7F763e2C7fF1CC996918740F67f9dC8BF4e",
1804
+ // "addressExt": "",
1805
+ // "minQuantity": "1",
1806
+ // "needAddressTag": false,
1807
+ // "requiredConfirmTimes": 64,
1808
+ // "canWithdrawConfirmTimes": 64,
1809
+ // "coinType": "ERC20_TOKEN"
1810
+ // }
1811
+ //
1812
+ const address = this.safeString(depositAddress, 'address');
1813
+ this.checkAddress(address);
1814
+ let tag = this.safeString(depositAddress, 'addressExt');
1815
+ if (tag === '') {
1816
+ tag = undefined;
1817
+ }
1818
+ return {
1819
+ 'currency': currency['code'],
1820
+ 'address': address,
1821
+ 'tag': tag,
1822
+ 'network': undefined,
1823
+ 'info': depositAddress,
1824
+ };
1825
+ }
1826
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
1827
+ /**
1828
+ * @method
1829
+ * @name hashkey#fetchDeposits
1830
+ * @description fetch all deposits made to an account
1831
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-deposit-history
1832
+ * @param {string} code unified currency code of the currency transferred
1833
+ * @param {int} [since] the earliest time in ms to fetch transfers for (default 24 hours ago)
1834
+ * @param {int} [limit] the maximum number of transfer structures to retrieve (default 50, max 200)
1835
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1836
+ * @param {int} [params.until] the latest time in ms to fetch transfers for (default time now)
1837
+ * @param {int} [params.fromId] starting ID (To be released)
1838
+ * @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/#/?id=transfer-structure}
1839
+ */
1840
+ const methodName = 'fetchDeposits';
1841
+ await this.loadMarkets();
1842
+ const request = {};
1843
+ let currency = undefined;
1844
+ if (code !== undefined) {
1845
+ currency = this.currency(code);
1846
+ request['coin'] = currency['id'];
1847
+ }
1848
+ if (since !== undefined) {
1849
+ request['startTime'] = since;
1850
+ }
1851
+ if (limit !== undefined) {
1852
+ request['limit'] = limit;
1853
+ }
1854
+ let until = undefined;
1855
+ [until, params] = this.handleOptionAndParams(params, methodName, 'until');
1856
+ if (until !== undefined) {
1857
+ request['endTime'] = until;
1858
+ }
1859
+ const response = await this.privateGetApiV1AccountDepositOrders(this.extend(request, params));
1860
+ //
1861
+ // [
1862
+ // {
1863
+ // "time": "1721641082163",
1864
+ // "coin": "TRXUSDT",
1865
+ // "coinName": "TRXUSDT",
1866
+ // "address": "TBA6CypYJizwA9XdC7Ubgc5F1bxrQ7SqPt",
1867
+ // "quantity": "86.00000000000000000000",
1868
+ // "status": 4,
1869
+ // "statusCode": "4",
1870
+ // "txId": "0970c14da4d7412295fa7b21c03a08da319e746a0d59ef14462a74183d118da4"
1871
+ // }
1872
+ // ]
1873
+ //
1874
+ return this.parseTransactions(response, currency, since, limit, { 'type': 'deposit' });
1875
+ }
1876
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
1877
+ /**
1878
+ * @method
1879
+ * @name hashkey#fetchWithdrawals
1880
+ * @description fetch all withdrawals made from an account
1881
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/withdrawal-records
1882
+ * @param {string} code unified currency code of the currency transferred
1883
+ * @param {int} [since] the earliest time in ms to fetch transfers for (default 24 hours ago)
1884
+ * @param {int} [limit] the maximum number of transfer structures to retrieve (default 50, max 200)
1885
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1886
+ * @param {int} [params.until] the latest time in ms to fetch transfers for (default time now)
1887
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1888
+ */
1889
+ const methodName = 'fetchWithdrawals';
1890
+ await this.loadMarkets();
1891
+ const request = {};
1892
+ let currency = undefined;
1893
+ if (code !== undefined) {
1894
+ currency = this.currency(code);
1895
+ request['coin'] = currency['id'];
1896
+ }
1897
+ if (since !== undefined) {
1898
+ request['startTime'] = since;
1899
+ }
1900
+ if (limit !== undefined) {
1901
+ request['limit'] = limit;
1902
+ }
1903
+ let until = undefined;
1904
+ [until, params] = this.handleOptionAndParams(params, methodName, 'until');
1905
+ if (until !== undefined) {
1906
+ request['endTime'] = until;
1907
+ }
1908
+ const response = await this.privateGetApiV1AccountWithdrawOrders(this.extend(request, params));
1909
+ //
1910
+ // [
1911
+ // {
1912
+ // "time": "1723545505366",
1913
+ // "id": "W611267400947572736",
1914
+ // "coin": "USDT",
1915
+ // "coinId": "USDT",
1916
+ // "coinName": "USDT",
1917
+ // "address": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
1918
+ // "quantity": "2.00000000",
1919
+ // "arriveQuantity": "2.00000000",
1920
+ // "txId": "f83f94e7d2e81fbec98c66c25d6615872cc2d426145629b6cf22e5e0a0753715",
1921
+ // "addressUrl": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
1922
+ // "feeCoinId": "USDT",
1923
+ // "feeCoinName": "USDT",
1924
+ // "fee": "1.00000000",
1925
+ // "remark": "",
1926
+ // "platform": ""
1927
+ // }
1928
+ // ]
1929
+ //
1930
+ return this.parseTransactions(response, currency, since, limit, { 'type': 'withdrawal' });
1931
+ }
1932
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
1933
+ /**
1934
+ * @method
1935
+ * @name hashkey#withdraw
1936
+ * @description make a withdrawal
1937
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/withdraw
1938
+ * @param {string} code unified currency code
1939
+ * @param {float} amount the amount to withdraw
1940
+ * @param {string} address the address to withdraw to
1941
+ * @param {string} tag
1942
+ * @param {string} [params.network] network for withdraw
1943
+ * @param {string} [params.clientOrderId] client order id
1944
+ * @param {string} [params.platform] the platform to withdraw to (hashkey, HashKey HK)
1945
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1946
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1947
+ */
1948
+ [tag, params] = this.handleWithdrawTagAndParams(tag, params);
1949
+ await this.loadMarkets();
1950
+ const currency = this.currency(code);
1951
+ const request = {
1952
+ 'coin': currency['id'],
1953
+ 'address': address,
1954
+ 'quantity': amount,
1955
+ };
1956
+ if (tag !== undefined) {
1957
+ request['addressExt'] = tag;
1958
+ }
1959
+ let clientOrderId = undefined;
1960
+ [clientOrderId, params] = this.handleOptionAndParams(params, 'withdraw', 'clientOrderId');
1961
+ if (clientOrderId !== undefined) {
1962
+ request['clientOrderId'] = clientOrderId;
1963
+ }
1964
+ let networkCode = undefined;
1965
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
1966
+ if (networkCode !== undefined) {
1967
+ request['chainType'] = this.networkCodeToId(networkCode);
1968
+ }
1969
+ let platform = undefined;
1970
+ [platform, params] = this.handleOptionAndParams(params, 'withdraw', 'platform');
1971
+ if (platform !== undefined) {
1972
+ request['platform'] = platform;
1973
+ }
1974
+ const response = await this.privatePostApiV1AccountWithdraw(this.extend(request, params));
1975
+ //
1976
+ // {
1977
+ // "success": true,
1978
+ // "id": "0",
1979
+ // "orderId": "W611267400947572736",
1980
+ // "accountId": "1732885739589466115"
1981
+ // }
1982
+ //
1983
+ return this.parseTransaction(response, currency);
1984
+ }
1985
+ parseTransaction(transaction, currency = undefined) {
1986
+ //
1987
+ // fetchDeposits
1988
+ // {
1989
+ // "time": "1721641082163",
1990
+ // "coin": "TRXUSDT", // todo how to parse it?
1991
+ // "coinName": "TRXUSDT",
1992
+ // "address": "TBA6CypYJizwA9XdC7Ubgc5F1bxrQ7SqPt",
1993
+ // "quantity": "86.00000000000000000000",
1994
+ // "status": 4,
1995
+ // "statusCode": "4",
1996
+ // "txId": "0970c14da4d7412295fa7b21c03a08da319e746a0d59ef14462a74183d118da4"
1997
+ // }
1998
+ //
1999
+ // fetchWithdrawals
2000
+ // {
2001
+ // "time": "1723545505366",
2002
+ // "id": "W611267400947572736",
2003
+ // "coin": "USDT",
2004
+ // "coinId": "USDT",
2005
+ // "coinName": "USDT",
2006
+ // "address": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
2007
+ // "quantity": "2.00000000",
2008
+ // "arriveQuantity": "2.00000000",
2009
+ // "txId": "f83f94e7d2e81fbec98c66c25d6615872cc2d426145629b6cf22e5e0a0753715",
2010
+ // "addressUrl": "TQbkBMnWnJNGTAUpFS4kvv4NRLzUAnGAes",
2011
+ // "feeCoinId": "USDT",
2012
+ // "feeCoinName": "USDT",
2013
+ // "fee": "1.00000000",
2014
+ // "remark": "",
2015
+ // "platform": ""
2016
+ // }
2017
+ //
2018
+ // withdraw
2019
+ // {
2020
+ // "success": true,
2021
+ // "id": "0",
2022
+ // "orderId": "W611267400947572736",
2023
+ // "accountId": "1732885739589466115"
2024
+ // }
2025
+ //
2026
+ const id = this.safeString2(transaction, 'id', 'orderId');
2027
+ const address = this.safeString(transaction, 'address');
2028
+ let status = this.safeString(transaction, 'status'); // for fetchDeposits
2029
+ if (status === undefined) {
2030
+ const success = this.safeBool(transaction, 'success', false); // for withdraw
2031
+ if (success) {
2032
+ status = 'ok';
2033
+ }
2034
+ else {
2035
+ const addressUrl = this.safeString(transaction, 'addressUrl'); // for fetchWithdrawals
2036
+ if (addressUrl !== undefined) {
2037
+ status = 'ok';
2038
+ }
2039
+ }
2040
+ }
2041
+ const txid = this.safeString(transaction, 'txId');
2042
+ const coin = this.safeString(transaction, 'coin');
2043
+ const code = this.safeCurrencyCode(coin, currency);
2044
+ const timestamp = this.safeInteger(transaction, 'time');
2045
+ const amount = this.safeNumber(transaction, 'quantity');
2046
+ const feeCost = this.safeNumber(transaction, 'fee');
2047
+ let fee = undefined;
2048
+ if (feeCost !== undefined) {
2049
+ fee = {
2050
+ 'cost': feeCost,
2051
+ 'currency': code,
2052
+ };
2053
+ }
2054
+ return {
2055
+ 'info': transaction,
2056
+ 'id': id,
2057
+ 'txid': txid,
2058
+ 'timestamp': timestamp,
2059
+ 'datetime': this.iso8601(timestamp),
2060
+ 'network': undefined,
2061
+ 'address': address,
2062
+ 'addressTo': undefined,
2063
+ 'addressFrom': undefined,
2064
+ 'tag': undefined,
2065
+ 'tagTo': undefined,
2066
+ 'tagFrom': undefined,
2067
+ 'type': undefined,
2068
+ 'amount': amount,
2069
+ 'currency': code,
2070
+ 'status': this.parseTransactionStatus(status),
2071
+ 'updated': undefined,
2072
+ 'internal': undefined,
2073
+ 'comment': undefined,
2074
+ 'fee': fee,
2075
+ };
2076
+ }
2077
+ parseTransactionStatus(status) {
2078
+ const statuses = {
2079
+ '1': 'pending',
2080
+ '2': 'pending',
2081
+ '3': 'failed',
2082
+ '4': 'ok',
2083
+ '5': 'pending',
2084
+ '6': 'ok',
2085
+ '7': 'failed',
2086
+ '8': 'cancelled',
2087
+ '9': 'failed',
2088
+ '10': 'failed',
2089
+ 'successful': 'ok',
2090
+ 'success': 'ok',
2091
+ };
2092
+ return this.safeString(statuses, status, status);
2093
+ }
2094
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
2095
+ /**
2096
+ * @method
2097
+ * @name hashkey#transfer
2098
+ * @description transfer currency internally between wallets on the same account
2099
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/new-account-transfer
2100
+ * @param {string} code unified currency code
2101
+ * @param {float} amount amount to transfer
2102
+ * @param {string} fromAccount account id to transfer from
2103
+ * @param {string} toAccount account id to transfer to
2104
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2105
+ * @param {string} [params.clientOrderId] a unique id for the transfer
2106
+ * @param {string} [params.remark] a note for the transfer
2107
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
2108
+ */
2109
+ await this.loadMarkets();
2110
+ const currency = this.currency(code);
2111
+ const request = {
2112
+ 'coin': currency['id'],
2113
+ 'quantity': this.currencyToPrecision(code, amount),
2114
+ 'fromAccountId': fromAccount,
2115
+ 'toAccountId': toAccount,
2116
+ };
2117
+ let clientOrderId = undefined;
2118
+ [clientOrderId, params] = this.handleOptionAndParams(params, 'transfer', 'clientOrderId');
2119
+ if (clientOrderId !== undefined) {
2120
+ request['clientOrderId'] = clientOrderId;
2121
+ }
2122
+ let remark = undefined;
2123
+ [remark, params] = this.handleOptionAndParams(params, 'transfer', 'remark');
2124
+ if (remark !== undefined) {
2125
+ request['remark'] = remark;
2126
+ }
2127
+ const response = await this.privatePostApiV1AccountAssetTransfer(this.extend(request, params));
2128
+ //
2129
+ // {
2130
+ // "success": true,
2131
+ // "timestamp": 1722260230773,
2132
+ // "clientOrderId": "",
2133
+ // "orderId": "1740839420695806720"
2134
+ // }
2135
+ //
2136
+ return this.parseTransfer(response, currency);
2137
+ }
2138
+ parseTransfer(transfer, currency = undefined) {
2139
+ const timestamp = this.safeInteger(transfer, 'timestamp');
2140
+ const currencyId = this.safeString(currency, 'id');
2141
+ let status = undefined;
2142
+ const success = this.safeBool(transfer, 'success', false);
2143
+ if (success) {
2144
+ status = 'ok';
2145
+ }
2146
+ return {
2147
+ 'id': this.safeString(transfer, 'orderId'),
2148
+ 'timestamp': timestamp,
2149
+ 'datetime': this.iso8601(timestamp),
2150
+ 'currency': this.safeCurrencyCode(currencyId, currency),
2151
+ 'amount': undefined,
2152
+ 'fromAccount': undefined,
2153
+ 'toAccount': undefined,
2154
+ 'status': status,
2155
+ 'info': transfer,
2156
+ };
2157
+ }
2158
+ async fetchAccounts(params = {}) {
2159
+ /**
2160
+ * @method
2161
+ * @name hashkey#fetchAccounts
2162
+ * @description fetch all the accounts associated with a profile
2163
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/query-sub-account
2164
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2165
+ * @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type
2166
+ */
2167
+ await this.loadMarkets();
2168
+ const response = await this.privateGetApiV1AccountType(params);
2169
+ //
2170
+ // [
2171
+ // {
2172
+ // "accountId": "1732885739589466112",
2173
+ // "accountLabel": "Main Trading Account",
2174
+ // "accountType": 1,
2175
+ // "accountIndex": 0
2176
+ // },
2177
+ // ...
2178
+ // ]
2179
+ //
2180
+ return this.parseAccounts(response, params);
2181
+ }
2182
+ parseAccount(account) {
2183
+ const accountLabel = this.safeString(account, 'accountLabel');
2184
+ let label = '';
2185
+ if (accountLabel === 'Main Trading Account' || accountLabel === 'Main Future Account') {
2186
+ label = 'main';
2187
+ }
2188
+ else if (accountLabel === 'Sub Main Trading Account' || accountLabel === 'Sub Main Future Account') {
2189
+ label = 'sub';
2190
+ }
2191
+ const accountType = this.parseAccountType(this.safeString(account, 'accountType'));
2192
+ const type = label + ' ' + accountType;
2193
+ return {
2194
+ 'id': this.safeString(account, 'accountId'),
2195
+ 'type': type,
2196
+ 'code': undefined,
2197
+ 'info': account,
2198
+ };
2199
+ }
2200
+ parseAccountType(type) {
2201
+ const types = {
2202
+ '1': 'spot account',
2203
+ '3': 'swap account',
2204
+ '5': 'custody account',
2205
+ '6': 'fiat account',
2206
+ };
2207
+ return this.safeString(types, type, type);
2208
+ }
2209
+ encodeAccountType(type) {
2210
+ const types = {
2211
+ 'spot': '1',
2212
+ 'swap': '3',
2213
+ 'custody': '5',
2214
+ };
2215
+ return this.safeInteger(types, type, type);
2216
+ }
2217
+ encodeFlowType(type) {
2218
+ const types = {
2219
+ 'trade': '1',
2220
+ 'fee': '3',
2221
+ 'transfer': '51',
2222
+ 'deposit': '900',
2223
+ 'withdraw': '904',
2224
+ };
2225
+ return this.safeInteger(types, type, type);
2226
+ }
2227
+ async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
2228
+ /**
2229
+ * @method
2230
+ * @name hashkey#fetchLedger
2231
+ * @description fetch the history of changes, actions done by the user or operations that altered balance of the user
2232
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-account-transaction-list
2233
+ * @param {string} code unified currency code, default is undefined (not used)
2234
+ * @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
2235
+ * @param {int} [limit] max number of ledger entrys to return, default is undefined
2236
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2237
+ * @param {int} [params.until] the latest time in ms to fetch entries for
2238
+ * @param {int} [params.flowType] trade, fee, transfer, deposit, withdrawal
2239
+ * @param {int} [params.accountType] spot, swap, custody
2240
+ * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger-structure}
2241
+ */
2242
+ const methodName = 'fetchLedger';
2243
+ if (since === undefined) {
2244
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a since argument');
2245
+ }
2246
+ let until = undefined;
2247
+ [until, params] = this.handleOptionAndParams(params, methodName, 'until');
2248
+ if (until === undefined) {
2249
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires an until argument');
2250
+ }
2251
+ await this.loadMarkets();
2252
+ const currency = this.currency(code);
2253
+ const request = {};
2254
+ request['startTime'] = since;
2255
+ if (limit !== undefined) {
2256
+ request['limit'] = limit;
2257
+ }
2258
+ request['endTime'] = until;
2259
+ let flowType = undefined;
2260
+ [flowType, params] = this.handleOptionAndParams(params, methodName, 'flowType');
2261
+ if (flowType !== undefined) {
2262
+ request['flowType'] = this.encodeFlowType(flowType);
2263
+ }
2264
+ let accountType = undefined;
2265
+ [accountType, params] = this.handleOptionAndParams(params, methodName, 'accountType');
2266
+ if (accountType !== undefined) {
2267
+ request['accountType'] = this.encodeAccountType(accountType);
2268
+ }
2269
+ const response = await this.privateGetApiV1AccountBalanceFlow(this.extend(request, params));
2270
+ //
2271
+ // [
2272
+ // {
2273
+ // "id": "1740844413612065537",
2274
+ // "accountId": "1732885739589466112",
2275
+ // "coin": "USDT",
2276
+ // "coinId": "USDT",
2277
+ // "coinName": "USDT",
2278
+ // "flowTypeValue": 51,
2279
+ // "flowType": "USER_ACCOUNT_TRANSFER",
2280
+ // "flowName": "",
2281
+ // "change": "-1",
2282
+ // "total": "8.015680088",
2283
+ // "created": "1722260825765"
2284
+ // },
2285
+ // ...
2286
+ // ]
2287
+ //
2288
+ return this.parseLedger(response, currency, since, limit);
2289
+ }
2290
+ parseLedgerEntryType(type) {
2291
+ const types = {
2292
+ '1': 'trade',
2293
+ '2': 'fee',
2294
+ '51': 'transfer',
2295
+ '900': 'deposit',
2296
+ '904': 'withdraw',
2297
+ };
2298
+ return this.safeString(types, type, type);
2299
+ }
2300
+ parseLedgerEntry(item, currency = undefined) {
2301
+ //
2302
+ // {
2303
+ // "id": "1740844413612065537",
2304
+ // "accountId": "1732885739589466112",
2305
+ // "coin": "USDT",
2306
+ // "coinId": "USDT",
2307
+ // "coinName": "USDT",
2308
+ // "flowTypeValue": 51,
2309
+ // "flowType": "USER_ACCOUNT_TRANSFER",
2310
+ // "flowName": "",
2311
+ // "change": "-1",
2312
+ // "total": "8.015680088",
2313
+ // "created": "1722260825765"
2314
+ // }
2315
+ //
2316
+ const id = this.safeString(item, 'id');
2317
+ const account = this.safeString(item, 'accountId');
2318
+ const timestamp = this.safeInteger(item, 'created');
2319
+ const type = this.parseLedgerEntryType(this.safeString(item, 'flowTypeValue'));
2320
+ const code = this.safeCurrencyCode(this.safeString(item, 'coin'), currency);
2321
+ const amountString = this.safeString(item, 'change');
2322
+ const amount = this.parseNumber(amountString);
2323
+ let direction = 'in';
2324
+ if (amountString.indexOf('-') >= 0) {
2325
+ direction = 'out';
2326
+ }
2327
+ const afterString = this.safeString(item, 'total');
2328
+ const after = this.parseNumber(afterString);
2329
+ const status = 'ok';
2330
+ return {
2331
+ 'id': id,
2332
+ 'info': item,
2333
+ 'timestamp': timestamp,
2334
+ 'datetime': this.iso8601(timestamp),
2335
+ 'account': account,
2336
+ 'direction': direction,
2337
+ 'referenceId': undefined,
2338
+ 'referenceAccount': undefined,
2339
+ 'type': type,
2340
+ 'currency': code,
2341
+ 'symbol': undefined,
2342
+ 'amount': amount,
2343
+ 'before': undefined,
2344
+ 'after': after,
2345
+ 'status': status,
2346
+ 'fee': undefined,
2347
+ };
2348
+ }
2349
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
2350
+ /**
2351
+ * @method
2352
+ * @name hashkey#createOrder
2353
+ * @description create a trade order
2354
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/test-new-order
2355
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/create-order
2356
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/create-new-futures-order
2357
+ * @param {string} symbol unified symbol of the market to create an order in
2358
+ * @param {string} type 'market' or 'limit' or 'LIMIT_MAKER' for spot, 'market' or 'limit' or 'STOP' for swap
2359
+ * @param {string} side 'buy' or 'sell'
2360
+ * @param {float} amount how much of you want to trade in units of the base currency
2361
+ * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2362
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2363
+ * @param {float} [params.cost] *spot market buy only* the quote quantity that can be used as an alternative for the amount
2364
+ * @param {boolean} [params.test] *spot markets only* whether to use the test endpoint or not, default is false
2365
+ * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
2366
+ * @param {string} [params.timeInForce] "GTC" or "IOC" or "PO" for spot, 'GTC' or 'FOK' or 'IOC' or 'LIMIT_MAKER' or 'PO' for swap
2367
+ * @param {string} [params.clientOrderId] a unique id for the order - is mandatory for swap
2368
+ * @param {float} [params.triggerPrice] *swap markets only* The price at which a trigger order is triggered at
2369
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2370
+ */
2371
+ await this.loadMarkets();
2372
+ const market = this.market(symbol);
2373
+ if (market['spot']) {
2374
+ return await this.createSpotOrder(symbol, type, side, amount, price, params);
2375
+ }
2376
+ else if (market['swap']) {
2377
+ return await this.createSwapOrder(symbol, type, side, amount, price, params);
2378
+ }
2379
+ else {
2380
+ throw new errors.NotSupported(this.id + ' createOrder() is not supported for ' + market['type'] + ' type of markets');
2381
+ }
2382
+ }
2383
+ async createMarketBuyOrderWithCost(symbol, cost, params = {}) {
2384
+ /**
2385
+ * @method
2386
+ * @name createMarketBuyOrderWithCost
2387
+ * @description create a market buy order by providing the symbol and cost
2388
+ * @param {string} symbol unified symbol of the market to create an order in
2389
+ * @param {float} cost how much you want to trade in units of the quote currency
2390
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2391
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2392
+ */
2393
+ await this.loadMarkets();
2394
+ const market = this.market(symbol);
2395
+ if (!market['spot']) {
2396
+ throw new errors.NotSupported(this.id + ' createMarketBuyOrderWithCost() is supported for spot markets only');
2397
+ }
2398
+ params['cost'] = cost;
2399
+ return await this.createOrder(symbol, 'market', 'buy', cost, undefined, params);
2400
+ }
2401
+ async createSpotOrder(symbol, type, side, amount, price = undefined, params = {}) {
2402
+ /**
2403
+ * @method
2404
+ * @name hashkey#createSpotOrder
2405
+ * @description create a trade order on spot market
2406
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/test-new-order
2407
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/create-order
2408
+ * @param {string} symbol unified symbol of the market to create an order in
2409
+ * @param {string} type 'market' or 'limit' or 'LIMIT_MAKER'
2410
+ * @param {string} side 'buy' or 'sell'
2411
+ * @param {float} amount how much of you want to trade in units of the base currency
2412
+ * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2413
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2414
+ * @param {float} [params.cost] *market buy only* the quote quantity that can be used as an alternative for the amount
2415
+ * @param {bool} [params.test] whether to use the test endpoint or not, default is false
2416
+ * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
2417
+ * @param {string} [params.timeInForce] 'GTC', 'IOC', or 'PO'
2418
+ * @param {string} [params.clientOrderId] a unique id for the order
2419
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2420
+ */
2421
+ const triggerPrice = this.safeString2(params, 'stopPrice', 'triggerPrice');
2422
+ if (triggerPrice !== undefined) {
2423
+ throw new errors.NotSupported(this.id + ' trigger orders are not supported for spot markets');
2424
+ }
2425
+ await this.loadMarkets();
2426
+ const market = this.market(symbol);
2427
+ const isMarketBuy = (type === 'market') && (side === 'buy');
2428
+ const cost = this.safeString(params, 'cost');
2429
+ if ((!isMarketBuy) && (cost !== undefined)) {
2430
+ throw new errors.NotSupported(this.id + ' createOrder() supports cost parameter for spot market buy orders only');
2431
+ }
2432
+ const request = this.createSpotOrderRequest(symbol, type, side, amount, price, params);
2433
+ let response = {};
2434
+ const test = this.safeBool(params, 'test');
2435
+ if (test) {
2436
+ params = this.omit(params, 'test');
2437
+ response = await this.privatePostApiV1SpotOrderTest(request);
2438
+ }
2439
+ else if (isMarketBuy && (cost === undefined)) {
2440
+ response = await this.privatePostApiV11SpotOrder(request); // the endpoint for market buy orders by amount
2441
+ //
2442
+ // {
2443
+ // "accountId": "1732885739589466112",
2444
+ // "symbol": "ETHUSDT",
2445
+ // "symbolName": "ETHUSDT",
2446
+ // "clientOrderId": "1722005792096557",
2447
+ // "orderId": "1738705036219839744",
2448
+ // "transactTime": "1722005792106",
2449
+ // "price": "0",
2450
+ // "origQty": "0.006",
2451
+ // "executedQty": "0.0059",
2452
+ // "status": "FILLED",
2453
+ // "timeInForce": "IOC",
2454
+ // "type": "MARKET",
2455
+ // "side": "BUY",
2456
+ // "reqAmount": "0",
2457
+ // "concentration": ""
2458
+ // }
2459
+ //
2460
+ }
2461
+ else {
2462
+ response = await this.privatePostApiV1SpotOrder(request); // the endpoint for market buy orders by cost and other orders
2463
+ //
2464
+ // market buy
2465
+ // {
2466
+ // "accountId": "1732885739589466112",
2467
+ // "symbol": "ETHUSDT",
2468
+ // "symbolName": "ETHUSDT",
2469
+ // "clientOrderId": "1722004623170558",
2470
+ // "orderId": "1738695230608169984",
2471
+ // "transactTime": "1722004623186",
2472
+ // "price": "0",
2473
+ // "origQty": "0",
2474
+ // "executedQty": "0.0061",
2475
+ // "status": "FILLED",
2476
+ // "timeInForce": "IOC",
2477
+ // "type": "MARKET",
2478
+ // "side": "BUY",
2479
+ // "reqAmount": "20",
2480
+ // "concentration": ""
2481
+ // }
2482
+ //
2483
+ // market sell
2484
+ // {
2485
+ // "accountId": "1732885739589466112",
2486
+ // "symbol": "ETHUSDT",
2487
+ // "symbolName": "ETHUSDT",
2488
+ // "clientOrderId": "1722005654516362",
2489
+ // "orderId": "1738703882140316928",
2490
+ // "transactTime": "1722005654529",
2491
+ // "price": "0",
2492
+ // "origQty": "0.006",
2493
+ // "executedQty": "0.006",
2494
+ // "status": "FILLED",
2495
+ // "timeInForce": "IOC",
2496
+ // "type": "MARKET",
2497
+ // "side": "SELL",
2498
+ // "reqAmount": "0",
2499
+ // "concentration": ""
2500
+ // }
2501
+ //
2502
+ // limit
2503
+ // {
2504
+ // "accountId": "1732885739589466112",
2505
+ // "symbol": "ETHUSDT",
2506
+ // "symbolName": "ETHUSDT",
2507
+ // "clientOrderId": "1722006209978370",
2508
+ // "orderId": "1738708541676585728",
2509
+ // "transactTime": "1722006209989",
2510
+ // "price": "5000",
2511
+ // "origQty": "0.005",
2512
+ // "executedQty": "0",
2513
+ // "status": "NEW",
2514
+ // "timeInForce": "GTC",
2515
+ // "type": "LIMIT_MAKER",
2516
+ // "side": "SELL",
2517
+ // "reqAmount": "0",
2518
+ // "concentration": ""
2519
+ // }
2520
+ //
2521
+ }
2522
+ return this.parseOrder(response, market);
2523
+ }
2524
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
2525
+ const market = this.market(symbol);
2526
+ if (market['spot']) {
2527
+ return this.createSpotOrderRequest(symbol, type, side, amount, price, params);
2528
+ }
2529
+ else if (market['swap']) {
2530
+ return this.createSwapOrderRequest(symbol, type, side, amount, price, params);
2531
+ }
2532
+ else {
2533
+ throw new errors.NotSupported(this.id + ' ' + 'createOrderRequest() is not supported for ' + market['type'] + ' type of markets');
2534
+ }
2535
+ }
2536
+ createSpotOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
2537
+ /**
2538
+ * @method
2539
+ * @ignore
2540
+ * @name hashkey#createSpotOrderRequest
2541
+ * @description helper function to build request
2542
+ * @param {string} symbol unified symbol of the market to create an order in
2543
+ * @param {string} type 'market' or 'limit' or 'LIMIT_MAKER'
2544
+ * @param {string} side 'buy' or 'sell'
2545
+ * @param {float} amount how much of you want to trade in units of the base currency
2546
+ * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2547
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2548
+ * @param {float} [params.cost] *market buy only* the quote quantity that can be used as an alternative for the amount
2549
+ * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
2550
+ * @param {string} [params.timeInForce] "GTC", "IOC", or "PO"
2551
+ * @param {string} [params.clientOrderId] a unique id for the order
2552
+ * @returns {object} request to be sent to the exchange
2553
+ */
2554
+ const market = this.market(symbol);
2555
+ type = type.toUpperCase();
2556
+ const request = {
2557
+ 'symbol': market['id'],
2558
+ 'side': side.toUpperCase(),
2559
+ 'type': type,
2560
+ };
2561
+ if (amount !== undefined) {
2562
+ request['quantity'] = this.amountToPrecision(symbol, amount);
2563
+ }
2564
+ let cost = undefined;
2565
+ [cost, params] = this.handleParamString(params, 'cost');
2566
+ if (cost !== undefined) {
2567
+ request['quantity'] = this.costToPrecision(symbol, cost);
2568
+ }
2569
+ if (price !== undefined) {
2570
+ request['price'] = this.priceToPrecision(symbol, price);
2571
+ }
2572
+ const isMarketOrder = type === 'MARKET';
2573
+ let postOnly = false;
2574
+ [postOnly, params] = this.handlePostOnly(isMarketOrder, type === 'LIMIT_MAKER', params);
2575
+ if (postOnly && (type === 'LIMIT')) {
2576
+ request['type'] = 'LIMIT_MAKER';
2577
+ }
2578
+ let clientOrderId = undefined;
2579
+ [clientOrderId, params] = this.handleParamString(params, 'clientOrderId');
2580
+ if (clientOrderId !== undefined) {
2581
+ params['newClientOrderId'] = clientOrderId;
2582
+ }
2583
+ return this.extend(request, params);
2584
+ }
2585
+ createSwapOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
2586
+ /**
2587
+ * @method
2588
+ * @ignore
2589
+ * @name hashkey#createSwapOrderRequest
2590
+ * @description helper function to build request
2591
+ * @param {string} symbol unified symbol of the market to create an order in
2592
+ * @param {string} type 'market' or 'limit' or 'STOP'
2593
+ * @param {string} side 'buy' or 'sell'
2594
+ * @param {float} amount how much of you want to trade in units of the base currency
2595
+ * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2596
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2597
+ * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
2598
+ * @param {bool} [params.reduceOnly] true or false whether the order is reduce only
2599
+ * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
2600
+ * @param {string} [params.timeInForce] 'GTC', 'FOK', 'IOC', 'LIMIT_MAKER' or 'PO'
2601
+ * @param {string} [params.clientOrderId] a unique id for the order
2602
+ * @returns {object} request to be sent to the exchange
2603
+ */
2604
+ const market = this.market(symbol);
2605
+ const request = {
2606
+ 'symbol': market['id'],
2607
+ 'type': 'LIMIT',
2608
+ 'quantity': this.amountToPrecision(symbol, amount),
2609
+ };
2610
+ const isMarketOrder = type === 'market';
2611
+ if (isMarketOrder) {
2612
+ request['priceType'] = 'MARKET';
2613
+ }
2614
+ if (price !== undefined) {
2615
+ request['price'] = this.priceToPrecision(symbol, price);
2616
+ request['priceType'] = 'INPUT';
2617
+ }
2618
+ let reduceOnly = false;
2619
+ [reduceOnly, params] = this.handleParamBool(params, 'reduceOnly', reduceOnly);
2620
+ let suffix = '_OPEN';
2621
+ if (reduceOnly) {
2622
+ suffix = '_CLOSE';
2623
+ }
2624
+ request['side'] = side.toUpperCase() + suffix;
2625
+ let timeInForce = undefined;
2626
+ [timeInForce, params] = this.handleParamString(params, 'timeInForce');
2627
+ let postOnly = false;
2628
+ [postOnly, params] = this.handlePostOnly(isMarketOrder, timeInForce === 'LIMIT_MAKER', params);
2629
+ if (postOnly) {
2630
+ timeInForce = 'LIMIT_MAKER';
2631
+ }
2632
+ if (timeInForce !== undefined) {
2633
+ request['timeInForce'] = timeInForce;
2634
+ }
2635
+ const clientOrderId = this.safeString(params, 'clientOrderId');
2636
+ if (clientOrderId === undefined) {
2637
+ request['clientOrderId'] = this.uuid();
2638
+ }
2639
+ const triggerPrice = this.safeString(params, 'triggerPrice');
2640
+ if (triggerPrice !== undefined) {
2641
+ request['stopPrice'] = this.priceToPrecision(symbol, triggerPrice);
2642
+ request['type'] = 'STOP';
2643
+ params = this.omit(params, 'triggerPrice');
2644
+ }
2645
+ return this.extend(request, params);
2646
+ }
2647
+ async createSwapOrder(symbol, type, side, amount, price = undefined, params = {}) {
2648
+ /**
2649
+ * @method
2650
+ * @name hashkey#createSwapOrder
2651
+ * @description create a trade order on swap market
2652
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/create-new-futures-order
2653
+ * @param {string} symbol unified symbol of the market to create an order in
2654
+ * @param {string} type 'market' or 'limit' or 'STOP'
2655
+ * @param {string} side 'buy' or 'sell'
2656
+ * @param {float} amount how much of you want to trade in units of the base currency
2657
+ * @param {float} [price] the price that the order is to be fulfilled, in units of the quote currency, ignored in market orders
2658
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2659
+ * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
2660
+ * @param {bool} [params.reduceOnly] true or false whether the order is reduce only
2661
+ * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
2662
+ * @param {string} [params.timeInForce] 'GTC', 'FOK', 'IOC', 'LIMIT_MAKER' or 'PO'
2663
+ * @param {string} [params.clientOrderId] a unique id for the order
2664
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2665
+ */
2666
+ await this.loadMarkets();
2667
+ const market = this.market(symbol);
2668
+ const request = this.createSwapOrderRequest(symbol, type, side, amount, price, params);
2669
+ const response = await this.privatePostApiV1FuturesOrder(this.extend(request, params));
2670
+ //
2671
+ // {
2672
+ // "time": "1722429951611",
2673
+ // "updateTime": "1722429951648",
2674
+ // "orderId": "1742263144028363776",
2675
+ // "clientOrderId": "1722429950315",
2676
+ // "symbol": "ETHUSDT-PERPETUAL",
2677
+ // "price": "3460.62",
2678
+ // "leverage": "5",
2679
+ // "origQty": "10",
2680
+ // "executedQty": "10",
2681
+ // "avgPrice": "0",
2682
+ // "marginLocked": "6.9212",
2683
+ // "type": "LIMIT",
2684
+ // "side": "BUY_OPEN",
2685
+ // "timeInForce": "IOC",
2686
+ // "status": "FILLED",
2687
+ // "priceType": "MARKET",
2688
+ // "contractMultiplier": "0.00100000"
2689
+ // }
2690
+ //
2691
+ return this.parseOrder(response, market);
2692
+ }
2693
+ async createOrders(orders, params = {}) {
2694
+ /**
2695
+ * @method
2696
+ * @name hashkey#createOrders
2697
+ * @description create a list of trade orders (all orders should be of the same symbol)
2698
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/create-multiple-orders
2699
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/batch-create-new-futures-order
2700
+ * @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
2701
+ * @param {object} [params] extra parameters specific to the api endpoint
2702
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2703
+ */
2704
+ await this.loadMarkets();
2705
+ const ordersRequests = [];
2706
+ for (let i = 0; i < orders.length; i++) {
2707
+ const rawOrder = orders[i];
2708
+ const symbol = this.safeString(rawOrder, 'symbol');
2709
+ const type = this.safeString(rawOrder, 'type');
2710
+ const side = this.safeString(rawOrder, 'side');
2711
+ const amount = this.safeNumber(rawOrder, 'amount');
2712
+ const price = this.safeNumber(rawOrder, 'price');
2713
+ const orderParams = this.safeDict(rawOrder, 'params', {});
2714
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, orderParams);
2715
+ const clientOrderId = this.safeString(orderRequest, 'clientOrderId');
2716
+ if (clientOrderId === undefined) {
2717
+ orderRequest['clientOrderId'] = this.uuid(); // both spot and swap endpoints require clientOrderId
2718
+ }
2719
+ ordersRequests.push(orderRequest);
2720
+ }
2721
+ const firstOrder = ordersRequests[0];
2722
+ const firstSymbol = this.safeString(firstOrder, 'symbol');
2723
+ const market = this.market(firstSymbol);
2724
+ const request = {
2725
+ 'orders': ordersRequests,
2726
+ };
2727
+ let response = undefined;
2728
+ if (market['spot']) {
2729
+ response = await this.privatePostApiV1SpotBatchOrders(this.extend(request, params));
2730
+ //
2731
+ // {
2732
+ // "code": 0,
2733
+ // "result": [
2734
+ // {
2735
+ // "code": "0000",
2736
+ // "order": {
2737
+ // "accountId": "1732885739589466112",
2738
+ // "symbol": "ETHUSDT",
2739
+ // "symbolName": "ETHUSDT",
2740
+ // "clientOrderId": "1722701490163000",
2741
+ // "orderId": "1744540984757258752",
2742
+ // "transactTime": "1722701491385",
2743
+ // "price": "1500",
2744
+ // "origQty": "0.001",
2745
+ // "executedQty": "0",
2746
+ // "status": "NEW",
2747
+ // "timeInForce": "GTC",
2748
+ // "type": "LIMIT",
2749
+ // "side": "BUY",
2750
+ // "reqAmount": "0"
2751
+ // }
2752
+ // }
2753
+ // ],
2754
+ // "concentration": ""
2755
+ // }
2756
+ //
2757
+ }
2758
+ else if (market['swap']) {
2759
+ response = await this.privatePostApiV1FuturesBatchOrders(this.extend(request, params));
2760
+ //
2761
+ // {
2762
+ // "code": "0000",
2763
+ // "result": [
2764
+ // {
2765
+ // "code": "0000",
2766
+ // "order": {
2767
+ // "time": "1722704251911",
2768
+ // "updateTime": "1722704251918",
2769
+ // "orderId": "1744564141727808768",
2770
+ // "clientOrderId": "1722704250648000",
2771
+ // "symbol": "ETHUSDT-PERPETUAL",
2772
+ // "price": "1500",
2773
+ // "leverage": "4",
2774
+ // "origQty": "1",
2775
+ // "executedQty": "0",
2776
+ // "avgPrice": "0",
2777
+ // "marginLocked": "0.375",
2778
+ // "type": "LIMIT",
2779
+ // "side": "BUY_OPEN",
2780
+ // "timeInForce": "GTC",
2781
+ // "status": "NEW",
2782
+ // "priceType": "INPUT",
2783
+ // "isLiquidationOrder": false,
2784
+ // "indexPrice": "0",
2785
+ // "liquidationType": ""
2786
+ // }
2787
+ // },
2788
+ // {
2789
+ // "code": "0207",
2790
+ // "msg": "Create limit order sell price too low"
2791
+ // }
2792
+ // ]
2793
+ // }
2794
+ //
2795
+ }
2796
+ else {
2797
+ throw new errors.NotSupported(this.id + ' ' + 'createOrderRequest() is not supported for ' + market['type'] + ' type of markets');
2798
+ }
2799
+ const result = this.safeList(response, 'result', []);
2800
+ const responseOrders = [];
2801
+ for (let i = 0; i < result.length; i++) {
2802
+ const responseEntry = this.safeDict(result, i, {});
2803
+ const responseOrder = this.safeDict(responseEntry, 'order', {});
2804
+ responseOrders.push(responseOrder);
2805
+ }
2806
+ return this.parseOrders(responseOrders);
2807
+ }
2808
+ async cancelOrder(id, symbol = undefined, params = {}) {
2809
+ /**
2810
+ * @method
2811
+ * @name hashkey#cancelOrder
2812
+ * @description cancels an open order
2813
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/cancel-order
2814
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/cancel-futures-order
2815
+ * @param {string} id order id
2816
+ * @param {string} symbol unified symbol of the market the order was made in
2817
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2818
+ * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entry for (default 'spot')
2819
+ * @param {string} [params.clientOrderId] a unique id for the order that can be used as an alternative for the id
2820
+ * @param {bool} [params.trigger] *swap markets only* true for canceling a trigger order (default false)
2821
+ * @param {bool} [params.stop] *swap markets only* an alternative for trigger param
2822
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2823
+ */
2824
+ const methodName = 'cancelOrder';
2825
+ this.checkTypeParam(methodName, params);
2826
+ await this.loadMarkets();
2827
+ const request = {};
2828
+ const clientOrderId = this.safeString(params, 'clientOrderId');
2829
+ if (clientOrderId === undefined) {
2830
+ request['orderId'] = id;
2831
+ }
2832
+ let market = undefined;
2833
+ if (symbol !== undefined) {
2834
+ market = this.market(symbol);
2835
+ }
2836
+ let marketType = 'spot';
2837
+ [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
2838
+ let response = undefined;
2839
+ if (marketType === 'spot') {
2840
+ response = await this.privateDeleteApiV1SpotOrder(this.extend(request, params));
2841
+ //
2842
+ // {
2843
+ // "accountId": "1732885739589466112",
2844
+ // "symbol": "ETHUSDT",
2845
+ // "clientOrderId": "1722006209978370",
2846
+ // "orderId": "1738708541676585728",
2847
+ // "transactTime": "1722006209989",
2848
+ // "price": "5000",
2849
+ // "origQty": "0.005",
2850
+ // "executedQty": "0",
2851
+ // "status": "NEW",
2852
+ // "timeInForce": "GTC",
2853
+ // "type": "LIMIT_MAKER",
2854
+ // "side": "SELL"
2855
+ // }
2856
+ //
2857
+ }
2858
+ else if (marketType === 'swap') {
2859
+ let isTrigger = false;
2860
+ [isTrigger, params] = this.handleTriggerOptionAndParams(params, methodName, isTrigger);
2861
+ if (isTrigger) {
2862
+ request['type'] = 'STOP';
2863
+ }
2864
+ else {
2865
+ request['type'] = 'LIMIT';
2866
+ }
2867
+ if (market !== undefined) {
2868
+ request['symbol'] = market['id'];
2869
+ }
2870
+ response = await this.privateDeleteApiV1FuturesOrder(this.extend(request, params));
2871
+ //
2872
+ // {
2873
+ // "time": "1722432302919",
2874
+ // "updateTime": "1722432302925",
2875
+ // "orderId": "1742282868229463040",
2876
+ // "clientOrderId": "1722432301670",
2877
+ // "symbol": "ETHUSDT-PERPETUAL",
2878
+ // "price": "4000",
2879
+ // "leverage": "5",
2880
+ // "origQty": "10",
2881
+ // "executedQty": "0",
2882
+ // "avgPrice": "0",
2883
+ // "marginLocked": "0",
2884
+ // "type": "LIMIT_MAKER",
2885
+ // "side": "SELL_CLOSE",
2886
+ // "timeInForce": "GTC",
2887
+ // "status": "NEW",
2888
+ // "priceType": "INPUT",
2889
+ // "isLiquidationOrder": false,
2890
+ // "indexPrice": "0",
2891
+ // "liquidationType": ""
2892
+ // }
2893
+ //
2894
+ }
2895
+ else {
2896
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
2897
+ }
2898
+ return this.parseOrder(response);
2899
+ }
2900
+ async cancelAllOrders(symbol = undefined, params = {}) {
2901
+ /**
2902
+ * @method
2903
+ * @name hashkey#cancelAllOrders
2904
+ * @description cancel all open orders
2905
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/cancel-all-open-orders
2906
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/batch-cancel-futures-order
2907
+ * @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
2908
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2909
+ * @param {string} [params.side] 'buy' or 'sell'
2910
+ * @returns {object} response from exchange
2911
+ */
2912
+ // Does not cancel trigger orders. For canceling trigger order use cancelOrder() or cancelOrders()
2913
+ const methodName = 'cancelAllOrders';
2914
+ if (symbol === undefined) {
2915
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument');
2916
+ }
2917
+ await this.loadMarkets();
2918
+ const market = this.market(symbol);
2919
+ const request = {
2920
+ 'symbol': market['id'],
2921
+ };
2922
+ const side = this.safeString(params, 'side');
2923
+ if (side !== undefined) {
2924
+ request['side'] = side;
2925
+ }
2926
+ let response = undefined;
2927
+ if (market['spot']) {
2928
+ response = await this.privateDeleteApiV1SpotOpenOrders(this.extend(request, params));
2929
+ //
2930
+ // { "success": true }
2931
+ //
2932
+ }
2933
+ else if (market['swap']) {
2934
+ response = await this.privateDeleteApiV1FuturesBatchOrders(this.extend(request, params));
2935
+ //
2936
+ // { "message": "success", "timestamp": "1723127222198", "code": "0000" }
2937
+ //
2938
+ }
2939
+ else {
2940
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + market['type'] + ' type of markets');
2941
+ }
2942
+ const order = this.safeOrder(response);
2943
+ order['info'] = response;
2944
+ return [order];
2945
+ }
2946
+ async cancelOrders(ids, symbol = undefined, params = {}) {
2947
+ /**
2948
+ * @method
2949
+ * @name hashkey#cancelOrders
2950
+ * @description cancel multiple orders
2951
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/cancel-multiple-orders
2952
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/batch-cancel-futures-order-by-order-id
2953
+ * @param {string[]} ids order ids
2954
+ * @param {string} [symbol] unified market symbol (not used by hashkey)
2955
+ * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entry for (default 'spot')
2956
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2957
+ */
2958
+ const methodName = 'cancelOrders';
2959
+ await this.loadMarkets();
2960
+ const request = {};
2961
+ const orderIds = ids.join(',');
2962
+ request['ids'] = orderIds;
2963
+ let market = undefined;
2964
+ if (symbol !== undefined) {
2965
+ market = this.market(symbol);
2966
+ }
2967
+ let marketType = 'spot';
2968
+ [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
2969
+ let response = undefined;
2970
+ if (marketType === 'spot') {
2971
+ response = await this.privateDeleteApiV1SpotCancelOrderByIds(this.extend(request));
2972
+ //
2973
+ // {
2974
+ // "code": "0000",
2975
+ // "result": []
2976
+ // }
2977
+ //
2978
+ }
2979
+ else if (marketType === 'swap') {
2980
+ response = this.privateDeleteApiV1FuturesCancelOrderByIds(this.extend(request));
2981
+ }
2982
+ else {
2983
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
2984
+ }
2985
+ const order = this.safeOrder(response);
2986
+ order['info'] = response;
2987
+ return [order];
2988
+ }
2989
+ async fetchOrder(id, symbol = undefined, params = {}) {
2990
+ /**
2991
+ * @method
2992
+ * @name hashkey#fetchOrder
2993
+ * @description fetches information on an order made by the user
2994
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/query-order
2995
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-order
2996
+ * @param {string} id the order id
2997
+ * @param {string} symbol unified symbol of the market the order was made in
2998
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2999
+ * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entry for (default 'spot')
3000
+ * @param {string} [params.clientOrderId] a unique id for the order that can be used as an alternative for the id
3001
+ * @param {string} [params.accountId] *spot markets only* account id to fetch the order from
3002
+ * @param {bool} [params.trigger] *swap markets only* true for fetching a trigger order (default false)
3003
+ * @param {bool} [params.stop] *swap markets only* an alternative for trigger param
3004
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
3005
+ */
3006
+ const methodName = 'fetchOrder';
3007
+ this.checkTypeParam(methodName, params);
3008
+ await this.loadMarkets();
3009
+ const request = {};
3010
+ let clientOrderId = undefined;
3011
+ [clientOrderId, params] = this.handleParamString(params, 'clientOrderId');
3012
+ if (clientOrderId === undefined) {
3013
+ request['orderId'] = id;
3014
+ }
3015
+ let market = undefined;
3016
+ if (symbol !== undefined) {
3017
+ market = this.market(symbol);
3018
+ }
3019
+ let marketType = 'spot';
3020
+ [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
3021
+ let response = undefined;
3022
+ if (marketType === 'spot') {
3023
+ if (clientOrderId !== undefined) {
3024
+ request['origClientOrderId'] = clientOrderId;
3025
+ }
3026
+ let accountId = undefined;
3027
+ [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
3028
+ if (accountId !== undefined) {
3029
+ request['accountId'] = accountId;
3030
+ }
3031
+ response = await this.privateGetApiV1SpotOrder(this.extend(request, params));
3032
+ //
3033
+ // {
3034
+ // "accountId": "1732885739589466112",
3035
+ // "exchangeId": "301",
3036
+ // "symbol": "ETHUSDT",
3037
+ // "symbolName": "ETHUSDT",
3038
+ // "clientOrderId": "1722004623170558",
3039
+ // "orderId": "1738695230608169984",
3040
+ // "price": "0",
3041
+ // "origQty": "0",
3042
+ // "executedQty": "0.0061",
3043
+ // "cummulativeQuoteQty": "19.736489",
3044
+ // "cumulativeQuoteQty": "19.736489",
3045
+ // "avgPrice": "3235.49",
3046
+ // "status": "FILLED",
3047
+ // "timeInForce": "IOC",
3048
+ // "type": "MARKET",
3049
+ // "side": "BUY",
3050
+ // "stopPrice": "0.0",
3051
+ // "icebergQty": "0.0",
3052
+ // "time": "1722004623186",
3053
+ // "updateTime": "1722004623406",
3054
+ // "isWorking": true,
3055
+ // "reqAmount": "20",
3056
+ // "feeCoin": "",
3057
+ // "feeAmount": "0",
3058
+ // "sumFeeAmount": "0"
3059
+ // }
3060
+ //
3061
+ }
3062
+ else if (marketType === 'swap') {
3063
+ let isTrigger = false;
3064
+ [isTrigger, params] = this.handleTriggerOptionAndParams(params, methodName, isTrigger);
3065
+ if (isTrigger) {
3066
+ request['type'] = 'STOP';
3067
+ }
3068
+ response = await this.privateGetApiV1FuturesOrder(this.extend(request, params));
3069
+ //
3070
+ // {
3071
+ // "time": "1722429951611",
3072
+ // "updateTime": "1722429951700",
3073
+ // "orderId": "1742263144028363776",
3074
+ // "clientOrderId": "1722429950315",
3075
+ // "symbol": "ETHUSDT-PERPETUAL",
3076
+ // "price": "3460.62",
3077
+ // "leverage": "5",
3078
+ // "origQty": "10",
3079
+ // "executedQty": "10",
3080
+ // "avgPrice": "3327.52",
3081
+ // "marginLocked": "0",
3082
+ // "type": "LIMIT",
3083
+ // "side": "BUY_OPEN",
3084
+ // "timeInForce": "IOC",
3085
+ // "status": "FILLED",
3086
+ // "priceType": "MARKET",
3087
+ // "isLiquidationOrder": false,
3088
+ // "indexPrice": "0",
3089
+ // "liquidationType": ""
3090
+ // }
3091
+ //
3092
+ }
3093
+ else {
3094
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
3095
+ }
3096
+ return this.parseOrder(response);
3097
+ }
3098
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3099
+ /**
3100
+ * @method
3101
+ * @name hashkey#fetchOpenOrders
3102
+ * @description fetch all unfilled currently open orders
3103
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-current-open-orders
3104
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-open-orders
3105
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/sub
3106
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/query-open-futures-orders
3107
+ * @param {string} [symbol] unified market symbol of the market orders were made in - is mandatory for swap markets
3108
+ * @param {int} [since] the earliest time in ms to fetch orders for
3109
+ * @param {int} [limit] the maximum number of order structures to retrieve - default 500, maximum 1000
3110
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3111
+ * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entries for (default 'spot')
3112
+ * @param {string} [params.orderId] *spot markets only* the id of the order to fetch
3113
+ * @param {string} [params.side] *spot markets only* 'buy' or 'sell' - the side of the orders to fetch
3114
+ * @param {string} [params.fromOrderId] *swap markets only* the id of the order to start from
3115
+ * @param {bool} [params.trigger] *swap markets only* true for fetching trigger orders (default false)
3116
+ * @param {bool} [params.stop] *swap markets only* an alternative for trigger param
3117
+ * @param {string} [params.accountId] account id to fetch the orders from
3118
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
3119
+ */
3120
+ const methodName = 'fetchOpenOrders';
3121
+ this.checkTypeParam(methodName, params);
3122
+ await this.loadMarkets();
3123
+ let market = undefined;
3124
+ if (symbol !== undefined) {
3125
+ market = this.market(symbol);
3126
+ }
3127
+ let marketType = 'spot';
3128
+ [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
3129
+ params = this.extend({ 'methodName': methodName }, params);
3130
+ if (marketType === 'spot') {
3131
+ return await this.fetchOpenSpotOrders(symbol, since, limit, params);
3132
+ }
3133
+ else if (marketType === 'swap') {
3134
+ return await this.fetchOpenSwapOrders(symbol, since, limit, params);
3135
+ }
3136
+ else {
3137
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
3138
+ }
3139
+ }
3140
+ async fetchOpenSpotOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3141
+ /**
3142
+ * @method
3143
+ * @ignore
3144
+ * @name hashkey#fetchOpenSpotOrders
3145
+ * @description fetch all unfilled currently open orders for spot markets
3146
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-current-open-orders
3147
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/sub
3148
+ * @param {string} [symbol] unified market symbol of the market orders were made in
3149
+ * @param {int} [since] the earliest time in ms to fetch orders for
3150
+ * @param {int} [limit] the maximum number of order structures to retrieve - default 500, maximum 1000
3151
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3152
+ * @param {string} [params.orderId] the id of the order to fetch
3153
+ * @param {string} [params.side] 'buy' or 'sell' - the side of the orders to fetch
3154
+ * @param {string} [params.accountId] account id to fetch the orders from
3155
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
3156
+ */
3157
+ await this.loadMarkets();
3158
+ let methodName = 'fetchOpenSpotOrders';
3159
+ [methodName, params] = this.handleParamString(params, 'methodName', methodName);
3160
+ let market = undefined;
3161
+ const request = {};
3162
+ let response = undefined;
3163
+ let accountId = undefined;
3164
+ [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
3165
+ if (accountId !== undefined) {
3166
+ request['subAccountId'] = accountId;
3167
+ response = await this.privateGetApiV1SpotSubAccountOpenOrders(this.extend(request, params));
3168
+ }
3169
+ else {
3170
+ if (symbol !== undefined) {
3171
+ market = this.market(symbol);
3172
+ request['symbol'] = market['id'];
3173
+ }
3174
+ if (limit !== undefined) {
3175
+ request['limit'] = limit;
3176
+ }
3177
+ let orderId = undefined;
3178
+ [orderId, params] = this.handleOptionAndParams(params, methodName, 'orderId');
3179
+ if (orderId !== undefined) {
3180
+ request['orderId'] = orderId;
3181
+ }
3182
+ let side = undefined;
3183
+ [side, params] = this.handleOptionAndParams(params, methodName, 'side');
3184
+ if (side !== undefined) {
3185
+ request['side'] = side.toUpperCase();
3186
+ }
3187
+ response = await this.privateGetApiV1SpotOpenOrders(this.extend(request, params));
3188
+ //
3189
+ // [
3190
+ // {
3191
+ // "accountId": "1732885739589466112",
3192
+ // "exchangeId": "301",
3193
+ // "symbol": "ETHUSDT",
3194
+ // "symbolName": "ETHUSDT",
3195
+ // "clientOrderId": "1",
3196
+ // "orderId": "1739491435386897152",
3197
+ // "price": "2000",
3198
+ // "origQty": "0.001",
3199
+ // "executedQty": "0",
3200
+ // "cummulativeQuoteQty": "0",
3201
+ // "cumulativeQuoteQty": "0",
3202
+ // "avgPrice": "0",
3203
+ // "status": "NEW",
3204
+ // "timeInForce": "GTC",
3205
+ // "type": "LIMIT",
3206
+ // "side": "BUY",
3207
+ // "stopPrice": "0.0",
3208
+ // "icebergQty": "0.0",
3209
+ // "time": "1722099538193",
3210
+ // "updateTime": "1722099538197",
3211
+ // "isWorking": true,
3212
+ // "reqAmount": "0"
3213
+ // }
3214
+ // ]
3215
+ //
3216
+ }
3217
+ return this.parseOrders(response, market, since, limit);
3218
+ }
3219
+ async fetchOpenSwapOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3220
+ /**
3221
+ * @method
3222
+ * @ignore
3223
+ * @name hashkey#fetchOpenSwapOrders
3224
+ * @description fetch all unfilled currently open orders for swap markets
3225
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/query-open-futures-orders
3226
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-open-orders
3227
+ * @param {string} symbol *is mandatory* unified market symbol of the market orders were made in
3228
+ * @param {int} [since] the earliest time in ms to fetch orders for
3229
+ * @param {int} [limit] the maximum number of order structures to retrieve - maximum 500
3230
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3231
+ * @param {string} [params.fromOrderId] the id of the order to start from
3232
+ * @param {bool} [params.trigger] true for fetching trigger orders (default false)
3233
+ * @param {bool} [params.stop] an alternative for trigger param
3234
+ * @param {string} [params.accountId] account id to fetch the orders from
3235
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
3236
+ */
3237
+ let methodName = 'fetchOpenSwapOrders';
3238
+ [methodName, params] = this.handleParamString(params, 'methodName', methodName);
3239
+ if (symbol === undefined) {
3240
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument for swap market orders');
3241
+ }
3242
+ const market = this.market(symbol);
3243
+ const request = {
3244
+ 'symbol': market['id'],
3245
+ };
3246
+ let isTrigger = false;
3247
+ [isTrigger, params] = this.handleTriggerOptionAndParams(params, methodName, isTrigger);
3248
+ if (isTrigger) {
3249
+ request['type'] = 'STOP';
3250
+ }
3251
+ else {
3252
+ request['type'] = 'LIMIT';
3253
+ }
3254
+ if (limit !== undefined) {
3255
+ request['limit'] = limit;
3256
+ }
3257
+ let fromOrderId = undefined;
3258
+ [fromOrderId, params] = this.handleOptionAndParams(params, methodName, 'fromOrderId');
3259
+ if (fromOrderId !== undefined) {
3260
+ request['fromOrderId'] = fromOrderId;
3261
+ }
3262
+ let response = undefined;
3263
+ let accountId = undefined;
3264
+ [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
3265
+ if (accountId !== undefined) {
3266
+ request['subAccountId'] = accountId;
3267
+ response = await this.privateGetApiV1FuturesSubAccountOpenOrders(this.extend(request, params));
3268
+ }
3269
+ else {
3270
+ response = await this.privateGetApiV1FuturesOpenOrders(this.extend(request, params));
3271
+ // 'LIMIT'
3272
+ // [
3273
+ // {
3274
+ // "time": "1722432302919",
3275
+ // "updateTime": "1722432302925",
3276
+ // "orderId": "1742282868229463040",
3277
+ // "clientOrderId": "1722432301670",
3278
+ // "symbol": "ETHUSDT-PERPETUAL",
3279
+ // "price": "4000",
3280
+ // "leverage": "5",
3281
+ // "origQty": "10",
3282
+ // "executedQty": "0",
3283
+ // "avgPrice": "0",
3284
+ // "marginLocked": "0",
3285
+ // "type": "LIMIT_MAKER",
3286
+ // "side": "SELL_CLOSE",
3287
+ // "timeInForce": "GTC",
3288
+ // "status": "NEW",
3289
+ // "priceType": "INPUT",
3290
+ // "isLiquidationOrder": false,
3291
+ // "indexPrice": "0",
3292
+ // "liquidationType": ""
3293
+ // }
3294
+ // ]
3295
+ //
3296
+ // 'STOP'
3297
+ // [
3298
+ // {
3299
+ // "time": "1722433095688",
3300
+ // "updateTime": "1722433095688",
3301
+ // "orderId": "1742289518466225664",
3302
+ // "accountId": "1735619524953226496",
3303
+ // "clientOrderId": "1722433094438",
3304
+ // "symbol": "ETHUSDT-PERPETUAL",
3305
+ // "price": "3700",
3306
+ // "leverage": "0",
3307
+ // "origQty": "10",
3308
+ // "type": "STOP",
3309
+ // "side": "SELL_CLOSE",
3310
+ // "status": "ORDER_NEW",
3311
+ // "stopPrice": "3600"
3312
+ // }
3313
+ // ]
3314
+ }
3315
+ return this.parseOrders(response, market, since, limit);
3316
+ }
3317
+ async fetchCanceledAndClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3318
+ /**
3319
+ * @method
3320
+ * @name hashkey#fetchCanceledAndClosedOrders
3321
+ * @description fetches information on multiple canceled and closed orders made by the user
3322
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-all-orders
3323
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/query-futures-history-orders
3324
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-sub-account-history-orders
3325
+ * @param {string} symbol *is mandatory for swap markets* unified market symbol of the market orders were made in
3326
+ * @param {int} [since] the earliest time in ms to fetch orders for
3327
+ * @param {int} [limit] the maximum number of order structures to retrieve - default 500, maximum 1000
3328
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3329
+ * @param {int} [params.until] the latest time in ms to fetch entries for - only supports the last 90 days timeframe
3330
+ * @param {string} [params.type] 'spot' or 'swap' - the type of the market to fetch entries for (default 'spot')
3331
+ * @param {string} [params.orderId] *spot markets only* the id of the order to fetch
3332
+ * @param {string} [params.side] *spot markets only* 'buy' or 'sell' - the side of the orders to fetch
3333
+ * @param {string} [params.fromOrderId] *swap markets only* the id of the order to start from
3334
+ * @param {bool} [params.trigger] *swap markets only* the id of the order to start from true for fetching trigger orders (default false)
3335
+ * @param {bool} [params.stop] *swap markets only* the id of the order to start from an alternative for trigger param
3336
+ * @param {string} [params.accountId] account id to fetch the orders from
3337
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
3338
+ */
3339
+ const methodName = 'fetchCanceledAndClosedOrders';
3340
+ this.checkTypeParam(methodName, params);
3341
+ await this.loadMarkets();
3342
+ const request = {};
3343
+ if (limit !== undefined) {
3344
+ request['limit'] = limit;
3345
+ }
3346
+ if (since !== undefined) {
3347
+ request['startTime'] = since;
3348
+ }
3349
+ let until = undefined;
3350
+ [until, params] = this.handleOptionAndParams(params, methodName, 'until');
3351
+ if (until !== undefined) {
3352
+ request['endTime'] = until;
3353
+ }
3354
+ let accountId = undefined;
3355
+ [accountId, params] = this.handleOptionAndParams(params, methodName, 'accountId');
3356
+ let market = undefined;
3357
+ if (symbol !== undefined) {
3358
+ market = this.market(symbol);
3359
+ }
3360
+ let marketType = 'spot';
3361
+ [marketType, params] = this.handleMarketTypeAndParams(methodName, market, params, marketType);
3362
+ let response = undefined;
3363
+ if (marketType === 'spot') {
3364
+ if (market !== undefined) {
3365
+ request['symbol'] = market['id'];
3366
+ }
3367
+ let orderId = undefined;
3368
+ [orderId, params] = this.handleOptionAndParams(params, methodName, 'orderId');
3369
+ if (orderId !== undefined) {
3370
+ request['orderId'] = orderId;
3371
+ }
3372
+ let side = undefined;
3373
+ [side, params] = this.handleOptionAndParams(params, methodName, 'side');
3374
+ if (side !== undefined) {
3375
+ request['side'] = side.toUpperCase();
3376
+ }
3377
+ if (accountId !== undefined) {
3378
+ request['accountId'] = accountId;
3379
+ }
3380
+ response = await this.privateGetApiV1SpotTradeOrders(this.extend(request, params));
3381
+ //
3382
+ // [
3383
+ // {
3384
+ // "accountId": "1732885739589466112",
3385
+ // "exchangeId": "301",
3386
+ // "symbol": "ETHUSDT",
3387
+ // "symbolName": "ETHUSDT",
3388
+ // "clientOrderId": "1722082982086472",
3389
+ // "orderId": "1739352552762301440",
3390
+ // "price": "0",
3391
+ // "origQty": "0.001",
3392
+ // "executedQty": "0.001",
3393
+ // "cummulativeQuoteQty": "3.28996",
3394
+ // "cumulativeQuoteQty": "3.28996",
3395
+ // "avgPrice": "3289.96",
3396
+ // "status": "FILLED",
3397
+ // "timeInForce": "IOC",
3398
+ // "type": "MARKET",
3399
+ // "side": "BUY",
3400
+ // "stopPrice": "0.0",
3401
+ // "icebergQty": "0.0",
3402
+ // "time": "1722082982093",
3403
+ // "updateTime": "1722082982097",
3404
+ // "isWorking": true,
3405
+ // "reqAmount": "0"
3406
+ // },
3407
+ // ...
3408
+ // ]
3409
+ //
3410
+ }
3411
+ else if (marketType === 'swap') {
3412
+ if (symbol === undefined) {
3413
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument for swap markets');
3414
+ }
3415
+ request['symbol'] = market['id'];
3416
+ let isTrigger = false;
3417
+ [isTrigger, params] = this.handleTriggerOptionAndParams(params, methodName, isTrigger);
3418
+ if (isTrigger) {
3419
+ request['type'] = 'STOP';
3420
+ }
3421
+ else {
3422
+ request['type'] = 'LIMIT';
3423
+ }
3424
+ let fromOrderId = undefined;
3425
+ [fromOrderId, params] = this.handleOptionAndParams(params, methodName, 'fromOrderId');
3426
+ if (fromOrderId !== undefined) {
3427
+ request['fromOrderId'] = fromOrderId;
3428
+ }
3429
+ if (accountId !== undefined) {
3430
+ request['subAccountId'] = accountId;
3431
+ response = await this.privateGetApiV1FuturesSubAccountHistoryOrders(this.extend(request, params));
3432
+ }
3433
+ else {
3434
+ response = await this.privateGetApiV1FuturesHistoryOrders(this.extend(request, params));
3435
+ //
3436
+ // [
3437
+ // {
3438
+ // "time": "1722429951611",
3439
+ // "updateTime": "1722429951700",
3440
+ // "orderId": "1742263144028363776",
3441
+ // "clientOrderId": "1722429950315",
3442
+ // "symbol": "ETHUSDT-PERPETUAL",
3443
+ // "price": "3460.62",
3444
+ // "leverage": "5",
3445
+ // "origQty": "10",
3446
+ // "executedQty": "10",
3447
+ // "avgPrice": "3327.52",
3448
+ // "marginLocked": "0",
3449
+ // "type": "LIMIT",
3450
+ // "side": "BUY_OPEN",
3451
+ // "timeInForce": "IOC",
3452
+ // "status": "FILLED",
3453
+ // "priceType": "MARKET",
3454
+ // "isLiquidationOrder": false,
3455
+ // "indexPrice": "0",
3456
+ // "liquidationType": ""
3457
+ // }
3458
+ // ]
3459
+ //
3460
+ }
3461
+ }
3462
+ else {
3463
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + marketType + ' type of markets');
3464
+ }
3465
+ return this.parseOrders(response, market, since, limit);
3466
+ }
3467
+ checkTypeParam(methodName, params) {
3468
+ // some hashkey endpoints have a type param for swap markets that defines the type of an order
3469
+ // type param is reserved in ccxt for defining the type of the market
3470
+ // current method warns user if he provides the exchange specific value in type parameter
3471
+ const paramsType = this.safeString(params, 'type');
3472
+ if ((paramsType !== undefined) && (paramsType !== 'spot') && (paramsType !== 'swap')) {
3473
+ throw new errors.BadRequest(this.id + ' ' + methodName + ' () type parameter can not be "' + paramsType + '". It should define the type of the market ("spot" or "swap"). To define the type of an order use the trigger parameter (true for trigger orders)');
3474
+ }
3475
+ }
3476
+ handleTriggerOptionAndParams(params, methodName, defaultValue = undefined) {
3477
+ let isStop = defaultValue;
3478
+ [isStop, params] = this.handleOptionAndParams(params, methodName, 'stop', isStop);
3479
+ let isTrigger = isStop;
3480
+ [isTrigger, params] = this.handleOptionAndParams(params, methodName, 'trigger', isTrigger);
3481
+ return [isTrigger, params];
3482
+ }
3483
+ parseOrder(order, market = undefined) {
3484
+ //
3485
+ // createOrder spot
3486
+ // {
3487
+ // "accountId": "1732885739589466112",
3488
+ // "symbol": "ETHUSDT",
3489
+ // "symbolName": "ETHUSDT",
3490
+ // "clientOrderId": "1722004623170558",
3491
+ // "orderId": "1738695230608169984",
3492
+ // "transactTime": "1722004623186",
3493
+ // "price": "0",
3494
+ // "origQty": "0",
3495
+ // "executedQty": "0.0061",
3496
+ // "status": "FILLED",
3497
+ // "timeInForce": "IOC",
3498
+ // "type": "MARKET",
3499
+ // "side": "BUY",
3500
+ // "reqAmount": "20",
3501
+ // "concentration": ""
3502
+ // }
3503
+ //
3504
+ // fetchOrder spot
3505
+ // {
3506
+ // "accountId": "1732885739589466112",
3507
+ // "exchangeId": "301",
3508
+ // "symbol": "ETHUSDT",
3509
+ // "symbolName": "ETHUSDT",
3510
+ // "clientOrderId": "1722004623170558",
3511
+ // "orderId": "1738695230608169984",
3512
+ // "price": "0",
3513
+ // "origQty": "0",
3514
+ // "executedQty": "0.0061",
3515
+ // "cummulativeQuoteQty": "19.736489",
3516
+ // "cumulativeQuoteQty": "19.736489",
3517
+ // "avgPrice": "3235.49",
3518
+ // "status": "FILLED",
3519
+ // "timeInForce": "IOC",
3520
+ // "type": "MARKET",
3521
+ // "side": "BUY",
3522
+ // "stopPrice": "0.0",
3523
+ // "icebergQty": "0.0",
3524
+ // "time": "1722004623186",
3525
+ // "updateTime": "1722004623406",
3526
+ // "isWorking": true,
3527
+ // "reqAmount": "20",
3528
+ // "feeCoin": "",
3529
+ // "feeAmount": "0",
3530
+ // "sumFeeAmount": "0"
3531
+ // }
3532
+ //
3533
+ // cancelOrder
3534
+ // {
3535
+ // "accountId": "1732885739589466112",
3536
+ // "symbol": "ETHUSDT",
3537
+ // "clientOrderId": "1722006209978370",
3538
+ // "orderId": "1738708541676585728",
3539
+ // "transactTime": "1722006209989",
3540
+ // "price": "5000",
3541
+ // "origQty": "0.005",
3542
+ // "executedQty": "0",
3543
+ // "status": "NEW",
3544
+ // "timeInForce": "GTC",
3545
+ // "type": "LIMIT_MAKER",
3546
+ // "side": "SELL"
3547
+ // }
3548
+ //
3549
+ // createOrder swap
3550
+ // {
3551
+ // "time": "1722429951611",
3552
+ // "updateTime": "1722429951648",
3553
+ // "orderId": "1742263144028363776",
3554
+ // "clientOrderId": "1722429950315",
3555
+ // "symbol": "ETHUSDT-PERPETUAL",
3556
+ // "price": "3460.62",
3557
+ // "leverage": "5",
3558
+ // "origQty": "10",
3559
+ // "executedQty": "10",
3560
+ // "avgPrice": "0",
3561
+ // "marginLocked": "6.9212",
3562
+ // "type": "LIMIT",
3563
+ // "side": "BUY_OPEN",
3564
+ // "timeInForce": "IOC",
3565
+ // "status": "FILLED",
3566
+ // "priceType": "MARKET",
3567
+ // "contractMultiplier": "0.00100000"
3568
+ // }
3569
+ //
3570
+ // fetchOrder swap
3571
+ // {
3572
+ // "time": "1722429951611",
3573
+ // "updateTime": "1722429951700",
3574
+ // "orderId": "1742263144028363776",
3575
+ // "clientOrderId": "1722429950315",
3576
+ // "symbol": "ETHUSDT-PERPETUAL",
3577
+ // "price": "3460.62",
3578
+ // "leverage": "5",
3579
+ // "origQty": "10",
3580
+ // "executedQty": "10",
3581
+ // "avgPrice": "3327.52",
3582
+ // "marginLocked": "0",
3583
+ // "type": "LIMIT",
3584
+ // "side": "BUY_OPEN",
3585
+ // "timeInForce": "IOC",
3586
+ // "status": "FILLED",
3587
+ // "priceType": "MARKET",
3588
+ // "isLiquidationOrder": false,
3589
+ // "indexPrice": "0",
3590
+ // "liquidationType": ""
3591
+ // }
3592
+ //
3593
+ const marketId = this.safeString(order, 'symbol');
3594
+ market = this.safeMarket(marketId, market);
3595
+ const timestamp = this.safeInteger2(order, 'transactTime', 'time');
3596
+ const status = this.safeString(order, 'status');
3597
+ let type = this.safeString(order, 'type');
3598
+ const priceType = this.safeString(order, 'priceType');
3599
+ if (priceType === 'MARKET') {
3600
+ type = 'market';
3601
+ }
3602
+ let price = this.omitZero(this.safeString(order, 'price'));
3603
+ if (type === 'STOP') {
3604
+ if (price === undefined) {
3605
+ type = 'market';
3606
+ }
3607
+ else {
3608
+ type = 'limit';
3609
+ }
3610
+ }
3611
+ let timeInForce = this.safeString(order, 'timeInForce');
3612
+ let postOnly = undefined;
3613
+ [type, timeInForce, postOnly] = this.parseOrderTypeTimeInForceAndPostOnly(type, timeInForce);
3614
+ const average = this.omitZero(this.safeString(order, 'avgPrice'));
3615
+ if (price === undefined) {
3616
+ price = average;
3617
+ }
3618
+ let side = this.safeStringLower(order, 'side');
3619
+ let reduceOnly = undefined;
3620
+ [side, reduceOnly] = this.parseOrderSideAndReduceOnly(side);
3621
+ let feeCurrncyId = this.safeString(order, 'feeCoin');
3622
+ if (feeCurrncyId === '') {
3623
+ feeCurrncyId = undefined;
3624
+ }
3625
+ const triggerPrice = this.omitZero(this.safeString(order, 'stopPrice'));
3626
+ return this.safeOrder({
3627
+ 'id': this.safeString(order, 'orderId'),
3628
+ 'clientOrderId': this.safeString(order, 'clientOrderId'),
3629
+ 'datetime': this.iso8601(timestamp),
3630
+ 'timestamp': timestamp,
3631
+ 'lastTradeTimestamp': undefined,
3632
+ 'lastUpdateTimestamp': this.safeInteger(order, 'updateTime'),
3633
+ 'status': this.parseOrderStatus(status),
3634
+ 'symbol': market['symbol'],
3635
+ 'type': type,
3636
+ 'timeInForce': timeInForce,
3637
+ 'side': side,
3638
+ 'price': price,
3639
+ 'average': average,
3640
+ 'amount': this.omitZero(this.safeString(order, 'origQty')),
3641
+ 'filled': this.safeString(order, 'executedQty'),
3642
+ 'remaining': undefined,
3643
+ 'stopPrice': triggerPrice,
3644
+ 'triggerPrice': triggerPrice,
3645
+ 'takeProfitPrice': undefined,
3646
+ 'stopLossPrice': undefined,
3647
+ 'cost': this.omitZero(this.safeString2(order, 'cumulativeQuoteQty', 'cummulativeQuoteQty')),
3648
+ 'trades': undefined,
3649
+ 'fee': {
3650
+ 'currency': this.safeCurrencyCode(feeCurrncyId),
3651
+ 'amount': this.omitZero(this.safeString(order, 'feeAmount')),
3652
+ },
3653
+ 'reduceOnly': reduceOnly,
3654
+ 'postOnly': postOnly,
3655
+ 'info': order,
3656
+ }, market);
3657
+ }
3658
+ parseOrderSideAndReduceOnly(unparsed) {
3659
+ const parts = unparsed.split('_');
3660
+ const side = parts[0];
3661
+ let reduceOnly = undefined;
3662
+ const secondPart = this.safeString(parts, 1);
3663
+ if (secondPart !== undefined) {
3664
+ if (secondPart === 'open') {
3665
+ reduceOnly = false;
3666
+ }
3667
+ else if ((secondPart === 'close')) {
3668
+ reduceOnly = true;
3669
+ }
3670
+ }
3671
+ return [side, reduceOnly];
3672
+ }
3673
+ parseOrderStatus(status) {
3674
+ const statuses = {
3675
+ 'NEW': 'open',
3676
+ 'PARTIALLY_FILLED': 'open',
3677
+ 'PARTIALLY_CANCELED': 'canceled',
3678
+ 'FILLED': 'closed',
3679
+ 'CANCELED': 'canceled',
3680
+ 'ORDER_CANCELED': 'canceled',
3681
+ 'PENDING_CANCEL': 'canceled',
3682
+ 'REJECTED': 'rejected',
3683
+ 'ORDER_NEW': 'open',
3684
+ };
3685
+ return this.safeString(statuses, status, status);
3686
+ }
3687
+ parseOrderTypeTimeInForceAndPostOnly(type, timeInForce) {
3688
+ let postOnly = undefined;
3689
+ if (type === 'LIMIT_MAKER') {
3690
+ postOnly = true;
3691
+ }
3692
+ else if ((timeInForce === 'LIMIT_MAKER') || (timeInForce === 'MAKER')) {
3693
+ postOnly = true;
3694
+ timeInForce = 'PO';
3695
+ }
3696
+ type = this.parseOrderType(type);
3697
+ return [type, timeInForce, postOnly];
3698
+ }
3699
+ parseOrderType(type) {
3700
+ const types = {
3701
+ 'MARKET': 'market',
3702
+ 'LIMIT': 'limit',
3703
+ 'LIMIT_MAKER': 'limit',
3704
+ 'MARKET_OF_BASE': 'market',
3705
+ };
3706
+ return this.safeString(types, type, type);
3707
+ }
3708
+ async fetchFundingRate(symbol, params = {}) {
3709
+ /**
3710
+ * @method
3711
+ * @name hashkey#fetchFundingRate
3712
+ * @description fetch the current funding rate
3713
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-funding-rate
3714
+ * @param {string} symbol unified market symbol
3715
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3716
+ * @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
3717
+ */
3718
+ await this.loadMarkets();
3719
+ const market = this.market(symbol);
3720
+ const request = {
3721
+ 'symbol': market['id'],
3722
+ 'timestamp': this.milliseconds(),
3723
+ };
3724
+ const response = await this.publicGetApiV1FuturesFundingRate(this.extend(request, params));
3725
+ //
3726
+ // [
3727
+ // { "symbol": "ETHUSDT-PERPETUAL", "rate": "0.0001", "nextSettleTime": "1722297600000" }
3728
+ // ]
3729
+ //
3730
+ const rate = this.safeDict(response, 0, {});
3731
+ return this.parseFundingRate(rate, market);
3732
+ }
3733
+ async fetchFundingRates(symbols = undefined, params = {}) {
3734
+ /**
3735
+ * @method
3736
+ * @name hashkey#fetchFundingRates
3737
+ * @description fetch the funding rate for multiple markets
3738
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-funding-rate
3739
+ * @param {string[]|undefined} symbols list of unified market symbols
3740
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3741
+ * @returns {object} a dictionary of [funding rates structures]{@link https://docs.ccxt.com/#/?id=funding-rates-structure}, indexe by market symbols
3742
+ */
3743
+ await this.loadMarkets();
3744
+ symbols = this.marketSymbols(symbols);
3745
+ const request = {
3746
+ 'timestamp': this.milliseconds(),
3747
+ };
3748
+ const response = await this.publicGetApiV1FuturesFundingRate(this.extend(request, params));
3749
+ //
3750
+ // [
3751
+ // { "symbol": "BTCUSDT-PERPETUAL", "rate": "0.0001", "nextSettleTime": "1722297600000" },
3752
+ // { "symbol": "ETHUSDT-PERPETUAL", "rate": "0.0001", "nextSettleTime": "1722297600000" }
3753
+ // ]
3754
+ //
3755
+ const fundingRates = this.parseFundingRates(response);
3756
+ return this.filterByArray(fundingRates, 'symbol', symbols);
3757
+ }
3758
+ parseFundingRate(contract, market = undefined) {
3759
+ //
3760
+ // fetchFundingRates
3761
+ // {
3762
+ // "symbol": "ETHUSDT-PERPETUAL",
3763
+ // "rate": "0.0001",
3764
+ // "nextSettleTime": "1722297600000"
3765
+ // }
3766
+ //
3767
+ const marketId = this.safeString(contract, 'symbol');
3768
+ market = this.safeMarket(marketId, market, undefined, 'swap');
3769
+ const fundingRate = this.safeNumber(contract, 'rate');
3770
+ const fundingTimestamp = this.safeInteger(contract, 'nextSettleTime');
3771
+ return {
3772
+ 'info': contract,
3773
+ 'symbol': market['symbol'],
3774
+ 'markPrice': undefined,
3775
+ 'indexPrice': undefined,
3776
+ 'interestRate': undefined,
3777
+ 'estimatedSettlePrice': undefined,
3778
+ 'timestamp': undefined,
3779
+ 'datetime': undefined,
3780
+ 'fundingRate': fundingRate,
3781
+ 'fundingTimestamp': undefined,
3782
+ 'fundingDatetime': undefined,
3783
+ 'nextFundingRate': undefined,
3784
+ 'nextFundingTimestamp': fundingTimestamp,
3785
+ 'nextFundingDatetime': this.iso8601(fundingTimestamp),
3786
+ 'previousFundingRate': undefined,
3787
+ 'previousFundingTimestamp': undefined,
3788
+ 'previousFundingDatetime': undefined,
3789
+ };
3790
+ }
3791
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3792
+ /**
3793
+ * @method
3794
+ * @name hashkey#fetchFundingRateHistory
3795
+ * @description fetches historical funding rate prices
3796
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-history-funding-rate
3797
+ * @param {string} symbol unified symbol of the market to fetch the funding rate history for
3798
+ * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
3799
+ * @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
3800
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3801
+ * @param {int} [params.fromId] the id of the entry to start from
3802
+ * @param {int} [params.endId] the id of the entry to end with
3803
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
3804
+ */
3805
+ await this.loadMarkets();
3806
+ if (symbol === undefined) {
3807
+ throw new errors.ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
3808
+ }
3809
+ const market = this.market(symbol);
3810
+ const request = {
3811
+ 'symbol': market['id'],
3812
+ };
3813
+ if (limit !== undefined) {
3814
+ request['limit'] = limit;
3815
+ }
3816
+ const response = await this.publicGetApiV1FuturesHistoryFundingRate(this.extend(request, params));
3817
+ //
3818
+ // [
3819
+ // {
3820
+ // "id": "10698",
3821
+ // "symbol": "ETHUSDT-PERPETUAL",
3822
+ // "settleTime": "1722268800000",
3823
+ // "settleRate": "0.0001"
3824
+ // },
3825
+ // ...
3826
+ // ]
3827
+ //
3828
+ const rates = [];
3829
+ for (let i = 0; i < response.length; i++) {
3830
+ const entry = response[i];
3831
+ const timestamp = this.safeInteger(entry, 'settleTime');
3832
+ rates.push({
3833
+ 'info': entry,
3834
+ 'symbol': this.safeSymbol(this.safeString(entry, 'symbol'), market, undefined, 'swap'),
3835
+ 'fundingRate': this.safeNumber(entry, 'settleRate'),
3836
+ 'timestamp': timestamp,
3837
+ 'datetime': this.iso8601(timestamp),
3838
+ });
3839
+ }
3840
+ const sorted = this.sortBy(rates, 'timestamp');
3841
+ return this.filterBySinceLimit(sorted, since, limit);
3842
+ }
3843
+ async fetchPositions(symbols = undefined, params = {}) {
3844
+ /**
3845
+ * @method
3846
+ * @description fetch open positions for a market
3847
+ * @name hashkey#fetchPositions
3848
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-positions
3849
+ * @description fetch all open positions
3850
+ * @param {string[]|undefined} symbols list of unified market symbols
3851
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3852
+ * @param {string} [params.side] 'LONG' or 'SHORT' - the direction of the position (if not provided, positions for both sides will be returned)
3853
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
3854
+ */
3855
+ const methodName = 'fetchPositions';
3856
+ if ((symbols === undefined)) {
3857
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a symbol argument with one single market symbol');
3858
+ }
3859
+ else {
3860
+ const symbolsLength = symbols.length;
3861
+ if (symbolsLength !== 1) {
3862
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is supported for a symbol argument with one single market symbol only');
3863
+ }
3864
+ }
3865
+ await this.loadMarkets();
3866
+ return await this.fetchPositionsForSymbol(symbols[0], this.extend({ 'methodName': 'fetchPositions' }, params));
3867
+ }
3868
+ async fetchPositionsForSymbol(symbol, params = {}) {
3869
+ /**
3870
+ * @method
3871
+ * @description fetch open positions for a single market
3872
+ * @name hashkey#fetchPositionsForSymbol
3873
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-positions
3874
+ * @description fetch all open positions for specific symbol
3875
+ * @param {string} symbol unified market symbol
3876
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3877
+ * @param {string} [params.side] 'LONG' or 'SHORT' - the direction of the position (if not provided, positions for both sides will be returned)
3878
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
3879
+ */
3880
+ await this.loadMarkets();
3881
+ const market = this.market(symbol);
3882
+ let methodName = 'fetchPosition';
3883
+ [methodName, params] = this.handleParamString(params, 'methodName', methodName);
3884
+ if (!market['swap']) {
3885
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() supports swap markets only');
3886
+ }
3887
+ const request = {
3888
+ 'symbol': market['id'],
3889
+ };
3890
+ let side = undefined;
3891
+ [side, params] = this.handleOptionAndParams(params, methodName, 'side');
3892
+ if (side !== undefined) {
3893
+ request['side'] = side.toUpperCase();
3894
+ }
3895
+ const response = await this.privateGetApiV1FuturesPositions(this.extend(request, params));
3896
+ //
3897
+ // [
3898
+ // {
3899
+ // "symbol": "ETHUSDT-PERPETUAL",
3900
+ // "side": "LONG",
3901
+ // "avgPrice": "3327.52",
3902
+ // "position": "10",
3903
+ // "available": "0",
3904
+ // "leverage": "5",
3905
+ // "lastPrice": "3324.44",
3906
+ // "positionValue": "33.2752",
3907
+ // "liquidationPrice": "-953.83",
3908
+ // "margin": "6.9012",
3909
+ // "marginRate": "",
3910
+ // "unrealizedPnL": "-0.0288",
3911
+ // "profitRate": "-0.0041",
3912
+ // "realizedPnL": "-0.0199",
3913
+ // "minMargin": "0.2173"
3914
+ // }
3915
+ // ]
3916
+ //
3917
+ return this.parsePositions(response, [symbol]);
3918
+ }
3919
+ parsePosition(position, market = undefined) {
3920
+ const marketId = this.safeString(position, 'symbol');
3921
+ market = this.safeMarket(marketId, market);
3922
+ const symbol = market['symbol'];
3923
+ return this.safePosition({
3924
+ 'symbol': symbol,
3925
+ 'id': undefined,
3926
+ 'timestamp': undefined,
3927
+ 'datetime': undefined,
3928
+ 'contracts': this.safeNumber(position, 'position'),
3929
+ 'contractSize': undefined,
3930
+ 'side': this.safeStringLower(position, 'side'),
3931
+ 'notional': this.safeNumber(position, 'positionValue'),
3932
+ 'leverage': this.safeInteger(position, 'leverage'),
3933
+ 'unrealizedPnl': this.safeNumber(position, 'unrealizedPnL'),
3934
+ 'realizedPnl': this.safeNumber(position, 'realizedPnL'),
3935
+ 'collateral': undefined,
3936
+ 'entryPrice': this.safeNumber(position, 'avgPrice'),
3937
+ 'markPrice': undefined,
3938
+ 'liquidationPrice': this.safeNumber(position, 'liquidationPrice'),
3939
+ 'marginMode': 'cross',
3940
+ 'hedged': true,
3941
+ 'maintenanceMargin': this.safeNumber(position, 'minMargin'),
3942
+ 'maintenanceMarginPercentage': undefined,
3943
+ 'initialMargin': this.safeNumber(position, 'margin'),
3944
+ 'initialMarginPercentage': undefined,
3945
+ 'marginRatio': undefined,
3946
+ 'lastUpdateTimestamp': undefined,
3947
+ 'lastPrice': this.safeNumber(position, 'lastPrice'),
3948
+ 'stopLossPrice': undefined,
3949
+ 'takeProfitPrice': undefined,
3950
+ 'percentage': undefined,
3951
+ 'info': position,
3952
+ });
3953
+ }
3954
+ async fetchLeverage(symbol, params = {}) {
3955
+ /**
3956
+ * @method
3957
+ * @name hashkey#fetchLeverage
3958
+ * @description fetch the set leverage for a market
3959
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/query-futures-leverage-trade
3960
+ * @param {string} symbol unified market symbol
3961
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3962
+ * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
3963
+ */
3964
+ await this.loadMarkets();
3965
+ const market = this.market(symbol);
3966
+ const request = {
3967
+ 'symbol': market['id'],
3968
+ };
3969
+ const response = await this.privateGetApiV1FuturesLeverage(this.extend(request, params));
3970
+ //
3971
+ // [
3972
+ // {
3973
+ // "symbolId": "ETHUSDT-PERPETUAL",
3974
+ // "leverage": "5",
3975
+ // "marginType": "CROSS"
3976
+ // }
3977
+ // ]
3978
+ //
3979
+ const leverage = this.safeDict(response, 0, {});
3980
+ return this.parseLeverage(leverage, market);
3981
+ }
3982
+ parseLeverage(leverage, market = undefined) {
3983
+ const marginMode = this.safeStringLower(leverage, 'marginType');
3984
+ const leverageValue = this.safeNumber(leverage, 'leverage');
3985
+ return {
3986
+ 'info': leverage,
3987
+ 'symbol': market['symbol'],
3988
+ 'marginMode': marginMode,
3989
+ 'longLeverage': leverageValue,
3990
+ 'shortLeverage': leverageValue,
3991
+ };
3992
+ }
3993
+ async setLeverage(leverage, symbol = undefined, params = {}) {
3994
+ /**
3995
+ * @method
3996
+ * @name hashkey#setLeverage
3997
+ * @description set the level of leverage for a market
3998
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/change-futures-leverage-trade
3999
+ * @param {float} leverage the rate of leverage
4000
+ * @param {string} symbol unified market symbol
4001
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4002
+ * @returns {object} response from the exchange
4003
+ */
4004
+ if (symbol === undefined) {
4005
+ throw new errors.ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
4006
+ }
4007
+ await this.loadMarkets();
4008
+ const request = {
4009
+ 'leverage': leverage,
4010
+ };
4011
+ const market = this.market(symbol);
4012
+ request['symbol'] = market['id'];
4013
+ const response = await this.privatePostApiV1FuturesLeverage(this.extend(request, params));
4014
+ //
4015
+ // {
4016
+ // "code": "0000",
4017
+ // "symbolId": "ETHUSDT-PERPETUAL",
4018
+ // "leverage": "3"
4019
+ // }
4020
+ //
4021
+ return this.parseLeverage(response, market);
4022
+ }
4023
+ async fetchLeverageTiers(symbols = undefined, params = {}) {
4024
+ /**
4025
+ * @method
4026
+ * @name hashkey#fetchLeverageTiers
4027
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/exchangeinfo
4028
+ * @description retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
4029
+ * @param {string[]|undefined} symbols list of unified market symbols
4030
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4031
+ * @returns {object} a dictionary of [leverage tiers structures]{@link https://docs.ccxt.com/#/?id=leverage-tiers-structure}, indexed by market symbols
4032
+ */
4033
+ await this.loadMarkets();
4034
+ const response = await this.publicGetApiV1ExchangeInfo(params);
4035
+ // response is the same as in fetchMarkets()
4036
+ const data = this.safeList(response, 'contracts', []);
4037
+ symbols = this.marketSymbols(symbols);
4038
+ return this.parseLeverageTiers(data, symbols, 'symbol');
4039
+ }
4040
+ parseMarketLeverageTiers(info, market = undefined) {
4041
+ //
4042
+ // {
4043
+ // "filters": [
4044
+ // {
4045
+ // "minPrice": "0.1",
4046
+ // "maxPrice": "100000.00000000",
4047
+ // "tickSize": "0.1",
4048
+ // "filterType": "PRICE_FILTER"
4049
+ // },
4050
+ // {
4051
+ // "minQty": "0.001",
4052
+ // "maxQty": "10",
4053
+ // "stepSize": "0.001",
4054
+ // "marketOrderMinQty": "0",
4055
+ // "marketOrderMaxQty": "0",
4056
+ // "filterType": "LOT_SIZE"
4057
+ // },
4058
+ // {
4059
+ // "minNotional": "0",
4060
+ // "filterType": "MIN_NOTIONAL"
4061
+ // },
4062
+ // {
4063
+ // "maxSellPrice": "999999",
4064
+ // "buyPriceUpRate": "0.05",
4065
+ // "sellPriceDownRate": "0.05",
4066
+ // "maxEntrustNum": 200,
4067
+ // "maxConditionNum": 200,
4068
+ // "filterType": "LIMIT_TRADING"
4069
+ // },
4070
+ // {
4071
+ // "buyPriceUpRate": "0.05",
4072
+ // "sellPriceDownRate": "0.05",
4073
+ // "filterType": "MARKET_TRADING"
4074
+ // },
4075
+ // {
4076
+ // "noAllowMarketStartTime": "0",
4077
+ // "noAllowMarketEndTime": "0",
4078
+ // "limitOrderStartTime": "0",
4079
+ // "limitOrderEndTime": "0",
4080
+ // "limitMinPrice": "0",
4081
+ // "limitMaxPrice": "0",
4082
+ // "filterType": "OPEN_QUOTE"
4083
+ // }
4084
+ // ],
4085
+ // "exchangeId": "301",
4086
+ // "symbol": "BTCUSDT-PERPETUAL",
4087
+ // "symbolName": "BTCUSDT-PERPETUAL",
4088
+ // "status": "TRADING",
4089
+ // "baseAsset": "BTCUSDT-PERPETUAL",
4090
+ // "baseAssetPrecision": "0.001",
4091
+ // "quoteAsset": "USDT",
4092
+ // "quoteAssetPrecision": "0.1",
4093
+ // "icebergAllowed": false,
4094
+ // "inverse": false,
4095
+ // "index": "USDT",
4096
+ // "marginToken": "USDT",
4097
+ // "marginPrecision": "0.0001",
4098
+ // "contractMultiplier": "0.001",
4099
+ // "underlying": "BTC",
4100
+ // "riskLimits": [
4101
+ // {
4102
+ // "riskLimitId": "200000722",
4103
+ // "quantity": "1000.00",
4104
+ // "initialMargin": "0.10",
4105
+ // "maintMargin": "0.005",
4106
+ // "isWhite": false
4107
+ // },
4108
+ // {
4109
+ // "riskLimitId": "200000723",
4110
+ // "quantity": "2000.00",
4111
+ // "initialMargin": "0.10",
4112
+ // "maintMargin": "0.01",
4113
+ // "isWhite": false
4114
+ // }
4115
+ // ]
4116
+ // }
4117
+ //
4118
+ const riskLimits = this.safeList(info, 'riskLimits', []);
4119
+ const id = this.safeString(info, 'symbol');
4120
+ market = this.safeMarket(id, market);
4121
+ const tiers = [];
4122
+ for (let i = 0; i < riskLimits.length; i++) {
4123
+ const tier = riskLimits[i];
4124
+ const initialMarginRate = this.safeString(tier, 'initialMargin');
4125
+ tiers.push({
4126
+ 'tier': this.sum(i, 1),
4127
+ 'currency': market['settle'],
4128
+ 'minNotional': undefined,
4129
+ 'maxNotional': this.safeNumber(tier, 'quantity'),
4130
+ 'maintenanceMarginRate': this.safeNumber(tier, 'maintMargin'),
4131
+ 'maxLeverage': this.parseNumber(Precise["default"].stringDiv('1', initialMarginRate)),
4132
+ 'info': tier,
4133
+ });
4134
+ }
4135
+ return tiers;
4136
+ }
4137
+ async fetchTradingFee(symbol, params = {}) {
4138
+ /**
4139
+ * @method
4140
+ * @name hashkey#fetchTradingFee
4141
+ * @description fetch the trading fees for a market
4142
+ * @see https://developers.binance.com/docs/wallet/asset/trade-fee // spot
4143
+ * @see https://hashkeyglobal-apidoc.readme.io/reference/get-futures-commission-rate-request-weight // swap
4144
+ * @param {string} symbol unified market symbol
4145
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4146
+ * @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
4147
+ */
4148
+ await this.loadMarkets();
4149
+ const market = this.market(symbol);
4150
+ const methodName = 'fetchTradingFee';
4151
+ let response = undefined;
4152
+ if (market['spot']) {
4153
+ response = await this.fetchTradingFees(params);
4154
+ return this.safeDict(response, symbol);
4155
+ }
4156
+ else if (market['swap']) {
4157
+ response = await this.privateGetApiV1FuturesCommissionRate(this.extend({ 'symbol': market['id'] }, params));
4158
+ return this.parseTradingFee(response, market);
4159
+ //
4160
+ // {
4161
+ // "openMakerFee": "0.00025",
4162
+ // "openTakerFee": "0.0006",
4163
+ // "closeMakerFee": "0.00025",
4164
+ // "closeTakerFee": "0.0006"
4165
+ // }
4166
+ //
4167
+ }
4168
+ else {
4169
+ throw new errors.NotSupported(this.id + ' ' + methodName + '() is not supported for ' + market['type'] + ' type of markets');
4170
+ }
4171
+ }
4172
+ async fetchTradingFees(params = {}) {
4173
+ /**
4174
+ * @method
4175
+ * @name binance#fetchTradingFees
4176
+ * @description *for spot markets only* fetch the trading fees for multiple markets
4177
+ * @see https://developers.binance.com/docs/wallet/asset/trade-fee
4178
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4179
+ * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
4180
+ */
4181
+ await this.loadMarkets();
4182
+ const response = await this.privateGetApiV1AccountVipInfo(params);
4183
+ //
4184
+ // {
4185
+ // "code": 0,
4186
+ // "vipLevel": "0",
4187
+ // "tradeVol30Day": "67",
4188
+ // "totalAssetBal": "0",
4189
+ // "data": [
4190
+ // {
4191
+ // "symbol": "UXLINKUSDT",
4192
+ // "productType": "Token-Token",
4193
+ // "buyMakerFeeCurrency": "UXLINK",
4194
+ // "buyTakerFeeCurrency": "UXLINK",
4195
+ // "sellMakerFeeCurrency": "USDT",
4196
+ // "sellTakerFeeCurrency": "USDT",
4197
+ // "actualMakerRate": "0.0012",
4198
+ // "actualTakerRate": "0.0012"
4199
+ // },
4200
+ // ...
4201
+ // ],
4202
+ // "updateTimestamp": "1722320137809"
4203
+ // }
4204
+ //
4205
+ const data = this.safeList(response, 'data', []);
4206
+ const result = {};
4207
+ for (let i = 0; i < data.length; i++) {
4208
+ const fee = this.safeDict(data, i, {});
4209
+ const parsedFee = this.parseTradingFee(fee);
4210
+ result[parsedFee['symbol']] = parsedFee;
4211
+ }
4212
+ return result;
4213
+ }
4214
+ parseTradingFee(fee, market = undefined) {
4215
+ //
4216
+ // spot
4217
+ // {
4218
+ // "symbol": "UXLINKUSDT",
4219
+ // "productType": "Token-Token",
4220
+ // "buyMakerFeeCurrency": "UXLINK",
4221
+ // "buyTakerFeeCurrency": "UXLINK",
4222
+ // "sellMakerFeeCurrency": "USDT",
4223
+ // "sellTakerFeeCurrency": "USDT",
4224
+ // "actualMakerRate": "0.0012",
4225
+ // "actualTakerRate": "0.0012"
4226
+ // }
4227
+ //
4228
+ // swap
4229
+ // {
4230
+ // "openMakerFee": "0.00025",
4231
+ // "openTakerFee": "0.0006",
4232
+ // "closeMakerFee": "0.00025",
4233
+ // "closeTakerFee": "0.0006"
4234
+ // }
4235
+ //
4236
+ const marketId = this.safeString(fee, 'symbol');
4237
+ market = this.safeMarket(marketId, market);
4238
+ return {
4239
+ 'info': fee,
4240
+ 'symbol': market['symbol'],
4241
+ 'maker': this.safeNumber2(fee, 'openMakerFee', 'actualMakerRate'),
4242
+ 'taker': this.safeNumber2(fee, 'openTakerFee', 'actualTakerRate'),
4243
+ 'percentage': true,
4244
+ 'tierBased': true,
4245
+ };
4246
+ }
4247
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
4248
+ let url = this.urls['api'][api] + '/' + path;
4249
+ let query = undefined;
4250
+ if (api === 'private') {
4251
+ this.checkRequiredCredentials();
4252
+ const timestamp = this.milliseconds();
4253
+ const additionalParams = {
4254
+ 'timestamp': timestamp,
4255
+ };
4256
+ const recvWindow = this.safeInteger(this.options, 'recvWindow');
4257
+ if (recvWindow !== undefined) {
4258
+ additionalParams['recvWindow'] = recvWindow;
4259
+ }
4260
+ headers = {
4261
+ 'X-HK-APIKEY': this.apiKey,
4262
+ 'Content-Type': 'application/x-www-form-urlencoded',
4263
+ };
4264
+ let signature = undefined;
4265
+ if ((method === 'POST') && ((path === 'api/v1/spot/batchOrders') || (path === 'api/v1/futures/batchOrders'))) {
4266
+ headers['Content-Type'] = 'application/json';
4267
+ body = this.json(this.safeList(params, 'orders'));
4268
+ signature = this.hmac(this.encode(this.customUrlencode(additionalParams)), this.encode(this.secret), sha256.sha256);
4269
+ query = this.customUrlencode(this.extend(additionalParams, { 'signature': signature }));
4270
+ url += '?' + query;
4271
+ }
4272
+ else {
4273
+ const totalParams = this.extend(additionalParams, params);
4274
+ signature = this.hmac(this.encode(this.customUrlencode(totalParams)), this.encode(this.secret), sha256.sha256);
4275
+ totalParams['signature'] = signature;
4276
+ query = this.customUrlencode(totalParams);
4277
+ if (method === 'GET') {
4278
+ url += '?' + query;
4279
+ }
4280
+ else {
4281
+ body = query;
4282
+ }
4283
+ }
4284
+ headers['INPUT-SOURCE'] = this.safeString(this.options, 'broker', '10000700011');
4285
+ headers['broker_sign'] = signature;
4286
+ }
4287
+ else {
4288
+ query = this.urlencode(params);
4289
+ if (query.length !== 0) {
4290
+ url += '?' + query;
4291
+ }
4292
+ }
4293
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
4294
+ }
4295
+ customUrlencode(params = {}) {
4296
+ let result = this.urlencode(params);
4297
+ result = result.replace('%2C', ',');
4298
+ return result;
4299
+ }
4300
+ handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
4301
+ if (response === undefined) {
4302
+ return undefined;
4303
+ }
4304
+ let errorInArray = false;
4305
+ let responseCodeString = this.safeString(response, 'code', undefined);
4306
+ const responseCodeInteger = this.safeInteger(response, 'code', undefined); // some codes in response are returned as '0000' others as 0
4307
+ if (responseCodeInteger === 0) {
4308
+ const result = this.safeList(response, 'result', []); // for batch methods
4309
+ for (let i = 0; i < result.length; i++) {
4310
+ const entry = this.safeDict(result, i);
4311
+ const entryCodeInteger = this.safeInteger(entry, 'code');
4312
+ if (entryCodeInteger !== 0) {
4313
+ errorInArray = true;
4314
+ responseCodeString = this.safeString(entry, 'code');
4315
+ }
4316
+ }
4317
+ }
4318
+ if ((code !== 200) || errorInArray) {
4319
+ const feedback = this.id + ' ' + body;
4320
+ this.throwBroadlyMatchedException(this.exceptions['broad'], responseCodeString, feedback);
4321
+ this.throwExactlyMatchedException(this.exceptions['exact'], responseCodeString, feedback);
4322
+ throw new errors.ExchangeError(feedback);
4323
+ }
4324
+ return undefined;
4325
+ }
4326
+ }
4327
+
4328
+ module.exports = hashkey;