ccxt 4.3.84 → 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.
- package/README.md +7 -5
- package/dist/ccxt.browser.min.js +15 -15
- package/dist/cjs/ccxt.js +7 -1
- package/dist/cjs/src/abstract/hashkey.js +9 -0
- package/dist/cjs/src/base/Exchange.js +1 -1
- package/dist/cjs/src/base/errors.js +8 -1
- package/dist/cjs/src/binance.js +4 -2
- package/dist/cjs/src/bitfinex.js +2 -2
- package/dist/cjs/src/bitmex.js +4 -0
- package/dist/cjs/src/bybit.js +15 -14
- package/dist/cjs/src/cryptocom.js +117 -2
- package/dist/cjs/src/hashkey.js +4328 -0
- package/dist/cjs/src/hyperliquid.js +85 -65
- package/dist/cjs/src/indodax.js +37 -9
- package/dist/cjs/src/kraken.js +29 -1
- package/dist/cjs/src/krakenfutures.js +12 -10
- package/dist/cjs/src/kucoinfutures.js +5 -0
- package/dist/cjs/src/mexc.js +2 -2
- package/dist/cjs/src/pro/ascendex.js +45 -5
- package/dist/cjs/src/pro/binance.js +1 -1
- package/dist/cjs/src/pro/bingx.js +13 -12
- package/dist/cjs/src/pro/bitget.js +113 -4
- package/dist/cjs/src/pro/hashkey.js +839 -0
- package/dist/cjs/src/pro/hyperliquid.js +123 -0
- package/dist/cjs/src/pro/mexc.js +13 -7
- package/dist/cjs/src/pro/okx.js +25 -4
- package/dist/cjs/src/pro/woo.js +1 -0
- package/dist/cjs/src/pro/woofipro.js +1 -0
- package/dist/cjs/src/pro/xt.js +1 -0
- package/js/ccxt.d.ts +9 -3
- package/js/ccxt.js +7 -3
- package/js/src/abstract/cryptocom.d.ts +2 -0
- package/js/src/abstract/hashkey.d.ts +70 -0
- package/js/src/abstract/hashkey.js +11 -0
- package/js/src/abstract/kucoinfutures.d.ts +2 -0
- package/js/src/base/Exchange.js +1 -1
- package/js/src/base/errorHierarchy.d.ts +1 -0
- package/js/src/base/errorHierarchy.js +1 -0
- package/js/src/base/errors.d.ts +5 -1
- package/js/src/base/errors.js +8 -2
- package/js/src/binance.js +4 -2
- package/js/src/bitfinex.js +2 -2
- package/js/src/bitmex.js +4 -0
- package/js/src/bybit.js +16 -15
- package/js/src/cryptocom.d.ts +5 -1
- package/js/src/cryptocom.js +117 -2
- package/js/src/hashkey.d.ts +178 -0
- package/js/src/hashkey.js +4329 -0
- package/js/src/hyperliquid.d.ts +3 -0
- package/js/src/hyperliquid.js +85 -65
- package/js/src/indodax.js +37 -9
- package/js/src/kraken.js +29 -1
- package/js/src/krakenfutures.js +12 -10
- package/js/src/kucoinfutures.js +5 -0
- package/js/src/mexc.js +2 -2
- package/js/src/pro/ascendex.d.ts +2 -0
- package/js/src/pro/ascendex.js +45 -5
- package/js/src/pro/binance.js +1 -1
- package/js/src/pro/bingx.js +13 -12
- package/js/src/pro/bitget.d.ts +4 -0
- package/js/src/pro/bitget.js +113 -4
- package/js/src/pro/hashkey.d.ts +34 -0
- package/js/src/pro/hashkey.js +840 -0
- package/js/src/pro/hyperliquid.d.ts +7 -1
- package/js/src/pro/hyperliquid.js +123 -0
- package/js/src/pro/mexc.js +13 -7
- package/js/src/pro/okx.js +25 -4
- package/js/src/pro/woo.js +1 -0
- package/js/src/pro/woofipro.js +1 -0
- package/js/src/pro/xt.js +1 -0
- 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;
|