ccxt 4.2.60 → 4.2.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +6 -5
  2. package/build.sh +1 -1
  3. package/dist/ccxt.browser.js +11280 -3407
  4. package/dist/ccxt.browser.min.js +7 -7
  5. package/dist/cjs/ccxt.js +4 -1
  6. package/dist/cjs/src/abstract/hyperliquid.js +9 -0
  7. package/dist/cjs/src/base/Exchange.js +22 -1
  8. package/dist/cjs/src/base/functions/encode.js +5 -0
  9. package/dist/cjs/src/base/functions.js +1 -0
  10. package/dist/cjs/src/bitfinex2.js +1 -1
  11. package/dist/cjs/src/bitget.js +74 -23
  12. package/dist/cjs/src/coinbase.js +108 -103
  13. package/dist/cjs/src/coinex.js +61 -1
  14. package/dist/cjs/src/hyperliquid.js +2035 -0
  15. package/dist/cjs/src/kraken.js +8 -2
  16. package/dist/cjs/src/krakenfutures.js +28 -0
  17. package/dist/cjs/src/kucoinfutures.js +2 -2
  18. package/dist/cjs/src/okx.js +1 -1
  19. package/dist/cjs/src/phemex.js +2 -2
  20. package/dist/cjs/src/pro/bingx.js +1 -0
  21. package/dist/cjs/src/static_dependencies/ethers/abi-coder.js +158 -0
  22. package/dist/cjs/src/static_dependencies/ethers/address/address.js +144 -0
  23. package/dist/cjs/src/static_dependencies/ethers/coders/abstract-coder.js +407 -0
  24. package/dist/cjs/src/static_dependencies/ethers/coders/address.js +45 -0
  25. package/dist/cjs/src/static_dependencies/ethers/coders/anonymous.js +28 -0
  26. package/dist/cjs/src/static_dependencies/ethers/coders/array.js +176 -0
  27. package/dist/cjs/src/static_dependencies/ethers/coders/boolean.js +27 -0
  28. package/dist/cjs/src/static_dependencies/ethers/coders/bytes.js +52 -0
  29. package/dist/cjs/src/static_dependencies/ethers/coders/fixed-bytes.js +45 -0
  30. package/dist/cjs/src/static_dependencies/ethers/coders/null.js +30 -0
  31. package/dist/cjs/src/static_dependencies/ethers/coders/number.js +60 -0
  32. package/dist/cjs/src/static_dependencies/ethers/coders/string.js +27 -0
  33. package/dist/cjs/src/static_dependencies/ethers/coders/tuple.js +68 -0
  34. package/dist/cjs/src/static_dependencies/ethers/fragments.js +614 -0
  35. package/dist/cjs/src/static_dependencies/ethers/hash/typed-data.js +492 -0
  36. package/dist/cjs/src/static_dependencies/ethers/index.js +35 -0
  37. package/dist/cjs/src/static_dependencies/ethers/interface.js +44 -0
  38. package/dist/cjs/src/static_dependencies/ethers/typed.js +618 -0
  39. package/dist/cjs/src/static_dependencies/ethers/utils/base58.js +20 -0
  40. package/dist/cjs/src/static_dependencies/ethers/utils/data.js +134 -0
  41. package/dist/cjs/src/static_dependencies/ethers/utils/errors.js +228 -0
  42. package/dist/cjs/src/static_dependencies/ethers/utils/events.js +13 -0
  43. package/dist/cjs/src/static_dependencies/ethers/utils/fixednumber.js +29 -0
  44. package/dist/cjs/src/static_dependencies/ethers/utils/index.js +53 -0
  45. package/dist/cjs/src/static_dependencies/ethers/utils/maths.js +231 -0
  46. package/dist/cjs/src/static_dependencies/ethers/utils/properties.js +47 -0
  47. package/dist/cjs/src/static_dependencies/ethers/utils/utf8.js +218 -0
  48. package/dist/cjs/src/static_dependencies/messagepack/msgpack.js +292 -0
  49. package/dist/cjs/src/tokocrypto.js +22 -2
  50. package/dist/cjs/src/wazirx.js +308 -3
  51. package/js/ccxt.d.ts +5 -2
  52. package/js/ccxt.js +4 -2
  53. package/js/src/abstract/coinbase.d.ts +3 -3
  54. package/js/src/abstract/hyperliquid.d.ts +9 -0
  55. package/js/src/abstract/hyperliquid.js +11 -0
  56. package/js/src/base/Exchange.d.ts +4 -0
  57. package/js/src/base/Exchange.js +13 -1
  58. package/js/src/base/functions/encode.d.ts +2 -1
  59. package/js/src/base/functions/encode.js +5 -1
  60. package/js/src/bitfinex2.js +1 -1
  61. package/js/src/bitget.js +74 -23
  62. package/js/src/coinbase.js +108 -103
  63. package/js/src/coinex.d.ts +3 -1
  64. package/js/src/coinex.js +61 -1
  65. package/js/src/hyperliquid.d.ts +83 -0
  66. package/js/src/hyperliquid.js +2036 -0
  67. package/js/src/kraken.js +8 -2
  68. package/js/src/krakenfutures.d.ts +2 -1
  69. package/js/src/krakenfutures.js +28 -0
  70. package/js/src/kucoinfutures.js +2 -2
  71. package/js/src/okx.js +1 -1
  72. package/js/src/phemex.js +2 -2
  73. package/js/src/pro/bingx.js +1 -0
  74. package/js/src/static_dependencies/ethers/abi-coder.d.ts +50 -0
  75. package/js/src/static_dependencies/ethers/abi-coder.js +148 -0
  76. package/js/src/static_dependencies/ethers/address/address.d.ts +55 -0
  77. package/js/src/static_dependencies/ethers/address/address.js +162 -0
  78. package/js/src/static_dependencies/ethers/address/checks.d.ts +80 -0
  79. package/js/src/static_dependencies/ethers/address/checks.js +119 -0
  80. package/js/src/static_dependencies/ethers/address/contract-address.d.ts +47 -0
  81. package/js/src/static_dependencies/ethers/address/contract-address.js +73 -0
  82. package/js/src/static_dependencies/ethers/address/index.d.ts +48 -0
  83. package/js/src/static_dependencies/ethers/address/index.js +24 -0
  84. package/js/src/static_dependencies/ethers/bytes32.d.ts +14 -0
  85. package/js/src/static_dependencies/ethers/bytes32.js +45 -0
  86. package/js/src/static_dependencies/ethers/coders/abstract-coder.d.ts +120 -0
  87. package/js/src/static_dependencies/ethers/coders/abstract-coder.js +424 -0
  88. package/js/src/static_dependencies/ethers/coders/address.d.ts +12 -0
  89. package/js/src/static_dependencies/ethers/coders/address.js +34 -0
  90. package/js/src/static_dependencies/ethers/coders/anonymous.d.ts +14 -0
  91. package/js/src/static_dependencies/ethers/coders/anonymous.js +27 -0
  92. package/js/src/static_dependencies/ethers/coders/array.d.ts +24 -0
  93. package/js/src/static_dependencies/ethers/coders/array.js +162 -0
  94. package/js/src/static_dependencies/ethers/coders/boolean.d.ts +12 -0
  95. package/js/src/static_dependencies/ethers/coders/boolean.js +26 -0
  96. package/js/src/static_dependencies/ethers/coders/bytes.d.ts +18 -0
  97. package/js/src/static_dependencies/ethers/coders/bytes.js +39 -0
  98. package/js/src/static_dependencies/ethers/coders/fixed-bytes.d.ts +14 -0
  99. package/js/src/static_dependencies/ethers/coders/fixed-bytes.js +32 -0
  100. package/js/src/static_dependencies/ethers/coders/null.d.ts +11 -0
  101. package/js/src/static_dependencies/ethers/coders/null.js +29 -0
  102. package/js/src/static_dependencies/ethers/coders/number.d.ts +15 -0
  103. package/js/src/static_dependencies/ethers/coders/number.js +48 -0
  104. package/js/src/static_dependencies/ethers/coders/string.d.ts +12 -0
  105. package/js/src/static_dependencies/ethers/coders/string.js +26 -0
  106. package/js/src/static_dependencies/ethers/coders/tuple.d.ts +15 -0
  107. package/js/src/static_dependencies/ethers/coders/tuple.js +67 -0
  108. package/js/src/static_dependencies/ethers/fragments.d.ts +458 -0
  109. package/js/src/static_dependencies/ethers/fragments.js +1252 -0
  110. package/js/src/static_dependencies/ethers/hash/index.d.ts +10 -0
  111. package/js/src/static_dependencies/ethers/hash/index.js +15 -0
  112. package/js/src/static_dependencies/ethers/hash/solidity.d.ts +30 -0
  113. package/js/src/static_dependencies/ethers/hash/solidity.js +107 -0
  114. package/js/src/static_dependencies/ethers/hash/typed-data.d.ts +144 -0
  115. package/js/src/static_dependencies/ethers/hash/typed-data.js +490 -0
  116. package/js/src/static_dependencies/ethers/index.d.ts +19 -0
  117. package/js/src/static_dependencies/ethers/index.js +22 -0
  118. package/js/src/static_dependencies/ethers/interface.d.ts +380 -0
  119. package/js/src/static_dependencies/ethers/interface.js +990 -0
  120. package/js/src/static_dependencies/ethers/typed.d.ts +569 -0
  121. package/js/src/static_dependencies/ethers/typed.js +608 -0
  122. package/js/src/static_dependencies/ethers/utils/base58.d.ts +22 -0
  123. package/js/src/static_dependencies/ethers/utils/base58.js +68 -0
  124. package/js/src/static_dependencies/ethers/utils/base64-browser.d.ts +3 -0
  125. package/js/src/static_dependencies/ethers/utils/base64-browser.js +24 -0
  126. package/js/src/static_dependencies/ethers/utils/base64.d.ts +39 -0
  127. package/js/src/static_dependencies/ethers/utils/base64.js +58 -0
  128. package/js/src/static_dependencies/ethers/utils/data.d.ts +92 -0
  129. package/js/src/static_dependencies/ethers/utils/data.js +175 -0
  130. package/js/src/static_dependencies/ethers/utils/errors.d.ts +509 -0
  131. package/js/src/static_dependencies/ethers/utils/errors.js +227 -0
  132. package/js/src/static_dependencies/ethers/utils/events.d.ts +76 -0
  133. package/js/src/static_dependencies/ethers/utils/events.js +52 -0
  134. package/js/src/static_dependencies/ethers/utils/fixednumber.d.ts +251 -0
  135. package/js/src/static_dependencies/ethers/utils/fixednumber.js +529 -0
  136. package/js/src/static_dependencies/ethers/utils/index.d.ts +30 -0
  137. package/js/src/static_dependencies/ethers/utils/index.js +38 -0
  138. package/js/src/static_dependencies/ethers/utils/maths.d.ts +65 -0
  139. package/js/src/static_dependencies/ethers/utils/maths.js +220 -0
  140. package/js/src/static_dependencies/ethers/utils/properties.d.ts +22 -0
  141. package/js/src/static_dependencies/ethers/utils/properties.js +59 -0
  142. package/js/src/static_dependencies/ethers/utils/rlp-decode.d.ts +5 -0
  143. package/js/src/static_dependencies/ethers/utils/rlp-decode.js +84 -0
  144. package/js/src/static_dependencies/ethers/utils/rlp-encode.d.ts +5 -0
  145. package/js/src/static_dependencies/ethers/utils/rlp-encode.js +54 -0
  146. package/js/src/static_dependencies/ethers/utils/rlp.d.ts +16 -0
  147. package/js/src/static_dependencies/ethers/utils/rlp.js +14 -0
  148. package/js/src/static_dependencies/ethers/utils/units.d.ts +23 -0
  149. package/js/src/static_dependencies/ethers/utils/units.js +88 -0
  150. package/js/src/static_dependencies/ethers/utils/utf8.d.ts +95 -0
  151. package/js/src/static_dependencies/ethers/utils/utf8.js +225 -0
  152. package/js/src/static_dependencies/ethers/utils/uuid.d.ts +7 -0
  153. package/js/src/static_dependencies/ethers/utils/uuid.js +35 -0
  154. package/js/src/static_dependencies/messagepack/msgpack.d.ts +2 -0
  155. package/js/src/static_dependencies/messagepack/msgpack.js +572 -0
  156. package/js/src/tokocrypto.js +22 -2
  157. package/js/src/wazirx.d.ts +12 -1
  158. package/js/src/wazirx.js +308 -3
  159. package/package.json +1 -1
  160. package/skip-tests.json +18 -0
@@ -0,0 +1,2036 @@
1
+ // ----------------------------------------------------------------------------
2
+
3
+ // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+ // EDIT THE CORRESPONDENT .ts FILE INSTEAD
6
+
7
+ // ---------------------------------------------------------------------------
8
+ import Exchange from './abstract/hyperliquid.js';
9
+ import { ExchangeError, ArgumentsRequired, NotSupported, InvalidOrder, OrderNotFound } from './base/errors.js';
10
+ import { Precise } from './base/Precise.js';
11
+ import { TICK_SIZE, ROUND } from './base/functions/number.js';
12
+ import { keccak_256 as keccak } from './static_dependencies/noble-hashes/sha3.js';
13
+ import { secp256k1 } from './static_dependencies/noble-curves/secp256k1.js';
14
+ import { ecdsa } from './base/functions/crypto.js';
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * @class hyperliquid
18
+ * @augments Exchange
19
+ */
20
+ export default class hyperliquid extends Exchange {
21
+ describe() {
22
+ return this.deepExtend(super.describe(), {
23
+ 'id': 'hyperliquid',
24
+ 'name': 'Hyperliquid',
25
+ 'countries': [],
26
+ 'version': 'v1',
27
+ 'rateLimit': 50,
28
+ 'certified': false,
29
+ 'pro': false,
30
+ 'has': {
31
+ 'CORS': undefined,
32
+ 'spot': false,
33
+ 'margin': false,
34
+ 'swap': true,
35
+ 'future': true,
36
+ 'option': false,
37
+ 'addMargin': true,
38
+ 'borrowCrossMargin': false,
39
+ 'borrowIsolatedMargin': false,
40
+ 'cancelAllOrders': false,
41
+ 'cancelOrder': true,
42
+ 'cancelOrders': true,
43
+ 'closeAllPositions': false,
44
+ 'closePosition': false,
45
+ 'createMarketBuyOrderWithCost': false,
46
+ 'createMarketOrderWithCost': false,
47
+ 'createMarketSellOrderWithCost': false,
48
+ 'createOrder': true,
49
+ 'createOrders': true,
50
+ 'createReduceOnlyOrder': false,
51
+ 'editOrder': true,
52
+ 'fetchAccounts': false,
53
+ 'fetchBalance': true,
54
+ 'fetchBorrowInterest': false,
55
+ 'fetchBorrowRateHistories': false,
56
+ 'fetchBorrowRateHistory': false,
57
+ 'fetchCanceledOrders': false,
58
+ 'fetchClosedOrders': true,
59
+ 'fetchCrossBorrowRate': false,
60
+ 'fetchCrossBorrowRates': false,
61
+ 'fetchCurrencies': true,
62
+ 'fetchDepositAddress': false,
63
+ 'fetchDepositAddresses': false,
64
+ 'fetchDeposits': false,
65
+ 'fetchDepositWithdrawFee': 'emulated',
66
+ 'fetchDepositWithdrawFees': false,
67
+ 'fetchFundingHistory': false,
68
+ 'fetchFundingRate': false,
69
+ 'fetchFundingRateHistory': true,
70
+ 'fetchFundingRates': false,
71
+ 'fetchIndexOHLCV': false,
72
+ 'fetchIsolatedBorrowRate': false,
73
+ 'fetchIsolatedBorrowRates': false,
74
+ 'fetchLedger': false,
75
+ 'fetchLeverage': false,
76
+ 'fetchLeverageTiers': false,
77
+ 'fetchLiquidations': false,
78
+ 'fetchMarginMode': undefined,
79
+ 'fetchMarketLeverageTiers': false,
80
+ 'fetchMarkets': true,
81
+ 'fetchMarkOHLCV': false,
82
+ 'fetchMyLiquidations': false,
83
+ 'fetchMyTrades': true,
84
+ 'fetchOHLCV': true,
85
+ 'fetchOpenInterest': false,
86
+ 'fetchOpenInterestHistory': false,
87
+ 'fetchOpenOrders': true,
88
+ 'fetchOrder': true,
89
+ 'fetchOrderBook': true,
90
+ 'fetchOrders': false,
91
+ 'fetchOrderTrades': false,
92
+ 'fetchPosition': true,
93
+ 'fetchPositionMode': false,
94
+ 'fetchPositions': true,
95
+ 'fetchPositionsRisk': false,
96
+ 'fetchPremiumIndexOHLCV': false,
97
+ 'fetchTicker': false,
98
+ 'fetchTickers': false,
99
+ 'fetchTime': false,
100
+ 'fetchTrades': true,
101
+ 'fetchTradingFee': false,
102
+ 'fetchTradingFees': false,
103
+ 'fetchTransfer': false,
104
+ 'fetchTransfers': false,
105
+ 'fetchWithdrawal': false,
106
+ 'fetchWithdrawals': false,
107
+ 'reduceMargin': true,
108
+ 'repayCrossMargin': false,
109
+ 'repayIsolatedMargin': false,
110
+ 'setLeverage': true,
111
+ 'setMarginMode': true,
112
+ 'setPositionMode': false,
113
+ 'transfer': true,
114
+ 'withdraw': true,
115
+ },
116
+ 'timeframes': {
117
+ '1m': '1m',
118
+ '3m': '3m',
119
+ '5m': '5m',
120
+ '15m': '15m',
121
+ '30m': '30m',
122
+ '1h': '1h',
123
+ '2h': '2h',
124
+ '4h': '4h',
125
+ '6h': '6h',
126
+ '12h': '12h',
127
+ '1d': '1d',
128
+ '3d': '3d',
129
+ '1w': '1w',
130
+ '1M': '1m',
131
+ },
132
+ 'hostname': 'hyperliquid.xyz',
133
+ 'urls': {
134
+ 'logo': 'https://github.com/ccxt/ccxt/assets/43336371/b371bc6c-4a8c-489f-87f4-20a913dd8d4b',
135
+ 'api': {
136
+ 'public': 'https://api.{hostname}',
137
+ 'private': 'https://api.{hostname}',
138
+ },
139
+ 'test': {
140
+ 'public': 'https://api.hyperliquid-testnet.xyz',
141
+ 'private': 'https://api.hyperliquid-testnet.xyz',
142
+ },
143
+ 'www': 'https://hyperliquid.xyz',
144
+ 'doc': 'https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api',
145
+ 'fees': 'https://hyperliquid.gitbook.io/hyperliquid-docs/trading/fees',
146
+ 'referral': 'https://app.hyperliquid.xyz/',
147
+ },
148
+ 'api': {
149
+ 'public': {
150
+ 'post': {
151
+ 'info': 1,
152
+ },
153
+ },
154
+ 'private': {
155
+ 'post': {
156
+ 'exchange': 1,
157
+ },
158
+ },
159
+ },
160
+ 'fees': {
161
+ 'swap': {
162
+ 'taker': this.parseNumber('0.00035'),
163
+ 'maker': this.parseNumber('0.0001'),
164
+ },
165
+ },
166
+ 'requiredCredentials': {
167
+ 'apiKey': false,
168
+ 'secret': false,
169
+ 'walletAddress': true,
170
+ 'privateKey': true,
171
+ },
172
+ 'exceptions': {
173
+ 'exact': {},
174
+ 'broad': {
175
+ 'Price must be divisible by tick size.': InvalidOrder,
176
+ 'Order must have minimum value of $10': InvalidOrder,
177
+ 'Insufficient margin to place order.': InvalidOrder,
178
+ 'Reduce only order would increase position.': InvalidOrder,
179
+ 'Post only order would have immediately matched,': InvalidOrder,
180
+ 'Order could not immediately match against any resting orders.': InvalidOrder,
181
+ 'Invalid TP/SL price.': InvalidOrder,
182
+ 'No liquidity available for market order.': InvalidOrder,
183
+ 'Order was never placed, already canceled, or filled.': OrderNotFound,
184
+ 'User or API Wallet ': InvalidOrder,
185
+ },
186
+ },
187
+ 'precisionMode': TICK_SIZE,
188
+ 'commonCurrencies': {},
189
+ 'options': {
190
+ 'sandboxMode': false,
191
+ 'defaultSlippage': 0.05,
192
+ 'zeroAddress': '0x0000000000000000000000000000000000000000',
193
+ },
194
+ });
195
+ }
196
+ setSandboxMode(enabled) {
197
+ super.setSandboxMode(enabled);
198
+ this.options['sandboxMode'] = enabled;
199
+ }
200
+ async fetchCurrencies(params = {}) {
201
+ /**
202
+ * @method
203
+ * @name hyperliquid#fetchCurrencies
204
+ * @description fetches all available currencies on an exchange
205
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-exchange-metadata
206
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
207
+ * @returns {object} an associative dictionary of currencies
208
+ */
209
+ const request = {
210
+ 'type': 'meta',
211
+ };
212
+ const response = await this.publicPostInfo(this.extend(request, params));
213
+ //
214
+ // [
215
+ // {
216
+ // "universe": [
217
+ // {
218
+ // "maxLeverage": 50,
219
+ // "name": "SOL",
220
+ // "onlyIsolated": false,
221
+ // "szDecimals": 2
222
+ // }
223
+ // ]
224
+ // }
225
+ // ]
226
+ //
227
+ const meta = this.safeList(response, 'universe', []);
228
+ const result = {};
229
+ for (let i = 0; i < meta.length; i++) {
230
+ const data = this.safeDict(meta, i, {});
231
+ const id = i;
232
+ const name = this.safeString(data, 'name');
233
+ const code = this.safeCurrencyCode(name);
234
+ result[code] = {
235
+ 'id': id,
236
+ 'name': name,
237
+ 'code': code,
238
+ 'precision': undefined,
239
+ 'info': data,
240
+ 'active': undefined,
241
+ 'deposit': undefined,
242
+ 'withdraw': undefined,
243
+ 'networks': undefined,
244
+ 'fee': undefined,
245
+ // 'fees': fees,
246
+ 'limits': undefined,
247
+ };
248
+ }
249
+ return result;
250
+ }
251
+ async fetchMarkets(params = {}) {
252
+ /**
253
+ * @method
254
+ * @name hyperliquid#fetchMarkets
255
+ * @description retrieves data on all markets for hyperliquid
256
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-asset-contexts-includes-mark-price-current-funding-open-interest-etc
257
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
258
+ * @returns {object[]} an array of objects representing market data
259
+ */
260
+ const request = {
261
+ 'type': 'metaAndAssetCtxs',
262
+ };
263
+ const response = await this.publicPostInfo(this.extend(request, params));
264
+ //
265
+ // [
266
+ // {
267
+ // "universe": [
268
+ // {
269
+ // "maxLeverage": 50,
270
+ // "name": "SOL",
271
+ // "onlyIsolated": false,
272
+ // "szDecimals": 2
273
+ // }
274
+ // ]
275
+ // },
276
+ // [
277
+ // {
278
+ // "dayNtlVlm": "9450588.2273",
279
+ // "funding": "0.0000198",
280
+ // "impactPxs": [
281
+ // "108.04",
282
+ // "108.06"
283
+ // ],
284
+ // "markPx": "108.04",
285
+ // "midPx": "108.05",
286
+ // "openInterest": "10764.48",
287
+ // "oraclePx": "107.99",
288
+ // "premium": "0.00055561",
289
+ // "prevDayPx": "111.81"
290
+ // }
291
+ // ]
292
+ // ]
293
+ //
294
+ let meta = this.safeDict(response, 0, {});
295
+ meta = this.safeList(meta, 'universe', []);
296
+ const assetCtxs = this.safeDict(response, 1, {});
297
+ const result = [];
298
+ for (let i = 0; i < meta.length; i++) {
299
+ const data = this.extend(this.safeDict(meta, i, {}), this.safeDict(assetCtxs, i, {}));
300
+ data['baseId'] = i;
301
+ result.push(data);
302
+ }
303
+ return this.parseMarkets(result);
304
+ }
305
+ parseMarket(market) {
306
+ //
307
+ // {
308
+ // "maxLeverage": "50",
309
+ // "name": "ETH",
310
+ // "onlyIsolated": false,
311
+ // "szDecimals": "4",
312
+ // "dayNtlVlm": "1709813.11535",
313
+ // "funding": "0.00004807",
314
+ // "impactPxs": [
315
+ // "2369.3",
316
+ // "2369.6"
317
+ // ],
318
+ // "markPx": "2369.6",
319
+ // "midPx": "2369.45",
320
+ // "openInterest": "1815.4712",
321
+ // "oraclePx": "2367.3",
322
+ // "premium": "0.00090821",
323
+ // "prevDayPx": "2381.5"
324
+ // }
325
+ //
326
+ const quoteId = 'USDC';
327
+ const base = this.safeString(market, 'name');
328
+ const quote = this.safeCurrencyCode(quoteId);
329
+ const baseId = this.safeString(market, 'baseId');
330
+ const settleId = 'USDC';
331
+ const settle = this.safeCurrencyCode(settleId);
332
+ let symbol = base + '/' + quote;
333
+ const contract = true;
334
+ const swap = true;
335
+ if (contract) {
336
+ if (swap) {
337
+ symbol = symbol + ':' + settle;
338
+ }
339
+ }
340
+ const fees = this.safeDict(this.fees, 'swap', {});
341
+ const taker = this.safeNumber(fees, 'taker');
342
+ const maker = this.safeNumber(fees, 'maker');
343
+ return {
344
+ 'id': baseId,
345
+ 'symbol': symbol,
346
+ 'base': base,
347
+ 'quote': quote,
348
+ 'settle': settle,
349
+ 'baseId': baseId,
350
+ 'quoteId': quoteId,
351
+ 'settleId': settleId,
352
+ 'type': 'swap',
353
+ 'spot': false,
354
+ 'margin': undefined,
355
+ 'swap': swap,
356
+ 'future': false,
357
+ 'option': false,
358
+ 'active': true,
359
+ 'contract': contract,
360
+ 'linear': true,
361
+ 'inverse': false,
362
+ 'taker': taker,
363
+ 'maker': maker,
364
+ 'contractSize': this.parseNumber('1'),
365
+ 'expiry': undefined,
366
+ 'expiryDatetime': undefined,
367
+ 'strike': undefined,
368
+ 'optionType': undefined,
369
+ 'precision': {
370
+ 'amount': 0.00000001,
371
+ 'price': 0.00000001,
372
+ },
373
+ 'limits': {
374
+ 'leverage': {
375
+ 'min': undefined,
376
+ 'max': undefined,
377
+ },
378
+ 'amount': {
379
+ 'min': undefined,
380
+ 'max': undefined,
381
+ },
382
+ 'price': {
383
+ 'min': undefined,
384
+ 'max': undefined,
385
+ },
386
+ 'cost': {
387
+ 'min': undefined,
388
+ 'max': undefined,
389
+ },
390
+ },
391
+ 'created': undefined,
392
+ 'info': market,
393
+ };
394
+ }
395
+ async fetchBalance(params = {}) {
396
+ /**
397
+ * @method
398
+ * @name hyperliquid#fetchBalance
399
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
400
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
401
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
402
+ * @param {string} [params.user] user address, will default to this.walletAddress if not provided
403
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
404
+ */
405
+ let userAddress = undefined;
406
+ [userAddress, params] = this.handlePublicAddress('fetchBalance', params);
407
+ const request = {
408
+ 'type': 'clearinghouseState',
409
+ 'user': userAddress,
410
+ };
411
+ const response = await this.publicPostInfo(this.extend(request, params));
412
+ //
413
+ // {
414
+ // "assetPositions": [],
415
+ // "crossMaintenanceMarginUsed": "0.0",
416
+ // "crossMarginSummary": {
417
+ // "accountValue": "100.0",
418
+ // "totalMarginUsed": "0.0",
419
+ // "totalNtlPos": "0.0",
420
+ // "totalRawUsd": "100.0"
421
+ // },
422
+ // "marginSummary": {
423
+ // "accountValue": "100.0",
424
+ // "totalMarginUsed": "0.0",
425
+ // "totalNtlPos": "0.0",
426
+ // "totalRawUsd": "100.0"
427
+ // },
428
+ // "time": "1704261007014",
429
+ // "withdrawable": "100.0"
430
+ // }
431
+ //
432
+ const data = this.safeDict(response, 'marginSummary', {});
433
+ const result = {
434
+ 'info': response,
435
+ 'USDC': {
436
+ 'total': this.safeFloat(data, 'accountValue'),
437
+ 'used': this.safeFloat(data, 'totalMarginUsed'),
438
+ },
439
+ };
440
+ const timestamp = this.safeInteger(response, 'time');
441
+ result['timestamp'] = timestamp;
442
+ result['datetime'] = this.iso8601(timestamp);
443
+ return this.safeBalance(result);
444
+ }
445
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
446
+ /**
447
+ * @method
448
+ * @name hyperliquid#fetchOrderBook
449
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
450
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#info
451
+ * @param {string} symbol unified symbol of the market to fetch the order book for
452
+ * @param {int} [limit] the maximum amount of order book entries to return
453
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
454
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
455
+ */
456
+ await this.loadMarkets();
457
+ const market = this.market(symbol);
458
+ const request = {
459
+ 'type': 'l2Book',
460
+ 'coin': market['base'],
461
+ };
462
+ const response = await this.publicPostInfo(this.extend(request, params));
463
+ //
464
+ // {
465
+ // "coin": "ETH",
466
+ // "levels": [
467
+ // [
468
+ // {
469
+ // "n": "2",
470
+ // "px": "2216.2",
471
+ // "sz": "74.0637"
472
+ // }
473
+ // ],
474
+ // [
475
+ // {
476
+ // "n": "2",
477
+ // "px": "2216.5",
478
+ // "sz": "70.5893"
479
+ // }
480
+ // ]
481
+ // ],
482
+ // "time": "1704290104840"
483
+ // }
484
+ //
485
+ const data = this.safeList(response, 'levels', []);
486
+ const result = {
487
+ 'bids': this.safeList(data, 0, []),
488
+ 'asks': this.safeList(data, 1, []),
489
+ };
490
+ const timestamp = this.safeInteger(response, 'time');
491
+ return this.parseOrderBook(result, market['symbol'], timestamp, 'bids', 'asks', 'px', 'sz');
492
+ }
493
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
494
+ /**
495
+ * @method
496
+ * @name hyperliquid#fetchOHLCV
497
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
498
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#info-1
499
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
500
+ * @param {string} timeframe the length of time each candle represents, support '1m', '15m', '1h', '1d'
501
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
502
+ * @param {int} [limit] the maximum amount of candles to fetch
503
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
504
+ * @param {int} [params.until] timestamp in ms of the latest candle to fetch
505
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
506
+ */
507
+ await this.loadMarkets();
508
+ const market = this.market(symbol);
509
+ const until = this.safeInteger(params, 'until', this.milliseconds());
510
+ if (since === undefined) {
511
+ since = 0;
512
+ }
513
+ if (limit === undefined) {
514
+ limit = 500;
515
+ }
516
+ params = this.omit(params, ['until']);
517
+ const request = {
518
+ 'type': 'candleSnapshot',
519
+ 'req': {
520
+ 'coin': market['base'],
521
+ 'interval': timeframe,
522
+ 'startTime': since,
523
+ 'endTime': until,
524
+ },
525
+ };
526
+ const response = await this.publicPostInfo(this.extend(request, params));
527
+ //
528
+ // [
529
+ // {
530
+ // "T": 1704287699999,
531
+ // "c": "2226.4",
532
+ // "h": "2247.9",
533
+ // "i": "15m",
534
+ // "l": "2224.6",
535
+ // "n": 46,
536
+ // "o": "2247.9",
537
+ // "s": "ETH",
538
+ // "t": 1704286800000,
539
+ // "v": "591.6427"
540
+ // }
541
+ // ]
542
+ //
543
+ return this.parseOHLCVs(response, market, timeframe, since, limit);
544
+ }
545
+ parseOHLCV(ohlcv, market = undefined) {
546
+ //
547
+ // {
548
+ // "T": 1704287699999,
549
+ // "c": "2226.4",
550
+ // "h": "2247.9",
551
+ // "i": "15m",
552
+ // "l": "2224.6",
553
+ // "n": 46,
554
+ // "o": "2247.9",
555
+ // "s": "ETH",
556
+ // "t": 1704286800000,
557
+ // "v": "591.6427"
558
+ // }
559
+ //
560
+ return [
561
+ this.safeInteger(ohlcv, 'T'),
562
+ this.safeNumber(ohlcv, 'o'),
563
+ this.safeNumber(ohlcv, 'h'),
564
+ this.safeNumber(ohlcv, 'l'),
565
+ this.safeNumber(ohlcv, 'c'),
566
+ this.safeNumber(ohlcv, 'v'),
567
+ ];
568
+ }
569
+ async fetchTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
570
+ /**
571
+ * @method
572
+ * @name hyperliquid#fetchTrades
573
+ * @description get the list of most recent trades for a particular symbol
574
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills
575
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills-by-time
576
+ * @param {string} symbol unified market symbol
577
+ * @param {int} [since] the earliest time in ms to fetch trades for
578
+ * @param {int} [limit] the maximum number of trades structures to retrieve
579
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
580
+ * @param {int} [params.until] timestamp in ms of the latest trade
581
+ * @param {string} [params.address] wallet address that made trades
582
+ * @param {string} [params.user] wallet address that made trades
583
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
584
+ */
585
+ let userAddress = undefined;
586
+ [userAddress, params] = this.handlePublicAddress('fetchTrades', params);
587
+ await this.loadMarkets();
588
+ const market = this.safeMarket(symbol);
589
+ const request = {
590
+ 'user': userAddress,
591
+ };
592
+ if (since !== undefined) {
593
+ request['type'] = 'userFillsByTime';
594
+ request['startTime'] = since;
595
+ }
596
+ else {
597
+ request['type'] = 'userFills';
598
+ }
599
+ const until = this.safeInteger(params, 'until');
600
+ params = this.omit(params, 'until');
601
+ if (until !== undefined) {
602
+ request['endTime'] = until;
603
+ }
604
+ const response = await this.publicPostInfo(this.extend(request, params));
605
+ //
606
+ // [
607
+ // {
608
+ // "closedPnl": "0.19343",
609
+ // "coin": "ETH",
610
+ // "crossed": true,
611
+ // "dir": "Close Long",
612
+ // "fee": "0.050062",
613
+ // "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
614
+ // "liquidationMarkPx": null,
615
+ // "oid": 3929354691,
616
+ // "px": "2381.1",
617
+ // "side": "A",
618
+ // "startPosition": "0.0841",
619
+ // "sz": "0.0841",
620
+ // "tid": 128423918764978,
621
+ // "time": 1704262888911
622
+ // }
623
+ // ]
624
+ //
625
+ return this.parseTrades(response, market, since, limit);
626
+ }
627
+ amountToPrecision(symbol, amount) {
628
+ return this.decimalToPrecision(amount, ROUND, this.markets[symbol]['precision']['amount'], this.precisionMode);
629
+ }
630
+ hashMessage(message) {
631
+ return '0x' + this.hash(message, keccak, 'hex');
632
+ }
633
+ signHash(hash, privateKey) {
634
+ const signature = ecdsa(hash.slice(-64), privateKey.slice(-64), secp256k1, undefined);
635
+ return {
636
+ 'r': '0x' + signature['r'],
637
+ 's': '0x' + signature['s'],
638
+ 'v': this.sum(27, signature['v']),
639
+ };
640
+ }
641
+ signMessage(message, privateKey) {
642
+ return this.signHash(this.hashMessage(message), privateKey.slice(-64));
643
+ }
644
+ constructPhantomAgent(hash, isTestnet = true) {
645
+ const source = (isTestnet) ? 'b' : 'a';
646
+ return {
647
+ 'source': source,
648
+ 'connectionId': hash,
649
+ };
650
+ }
651
+ actionHash(action, vaultAddress, nonce) {
652
+ const dataBinary = this.packb(action);
653
+ const dataHex = this.binaryToBase16(dataBinary);
654
+ let data = dataHex;
655
+ data += '00000' + this.intToBase16(nonce);
656
+ if (vaultAddress === undefined) {
657
+ data += '00';
658
+ }
659
+ else {
660
+ data += '01';
661
+ data += vaultAddress;
662
+ }
663
+ return this.hash(this.base16ToBinary(data), keccak, 'binary');
664
+ }
665
+ signL1Action(action, nonce, vaultAdress = undefined) {
666
+ const hash = this.actionHash(action, vaultAdress, nonce);
667
+ const isTestnet = this.safeBool(this.options, 'sandboxMode', false);
668
+ const phantomAgent = this.constructPhantomAgent(hash, isTestnet);
669
+ // const data = {
670
+ // 'domain': {
671
+ // 'chainId': 1337,
672
+ // 'name': 'Exchange',
673
+ // 'verifyingContract': '0x0000000000000000000000000000000000000000',
674
+ // 'version': '1',
675
+ // },
676
+ // 'types': {
677
+ // 'Agent': [
678
+ // { 'name': 'source', 'type': 'string' },
679
+ // { 'name': 'connectionId', 'type': 'bytes32' },
680
+ // ],
681
+ // 'EIP712Domain': [
682
+ // { 'name': 'name', 'type': 'string' },
683
+ // { 'name': 'version', 'type': 'string' },
684
+ // { 'name': 'chainId', 'type': 'uint256' },
685
+ // { 'name': 'verifyingContract', 'type': 'address' },
686
+ // ],
687
+ // },
688
+ // 'primaryType': 'Agent',
689
+ // 'message': phantomAgent,
690
+ // };
691
+ const zeroAddress = this.safeString(this.options, 'zeroAddress');
692
+ const chainId = 1337; // check this out
693
+ const domain = {
694
+ 'chainId': chainId,
695
+ 'name': 'Exchange',
696
+ 'verifyingContract': zeroAddress,
697
+ 'version': '1',
698
+ };
699
+ const messageTypes = {
700
+ 'Agent': [
701
+ { 'name': 'source', 'type': 'string' },
702
+ { 'name': 'connectionId', 'type': 'bytes32' },
703
+ ],
704
+ };
705
+ const msg = this.ethEncodeStructuredData(domain, messageTypes, phantomAgent);
706
+ const signature = this.signMessage(msg, this.privateKey);
707
+ return signature;
708
+ }
709
+ buildSig(chainId, messageTypes, message) {
710
+ const zeroAddress = this.safeString(this.options, 'zeroAddress');
711
+ const domain = {
712
+ 'chainId': chainId,
713
+ 'name': 'Exchange',
714
+ 'verifyingContract': zeroAddress,
715
+ 'version': '1',
716
+ };
717
+ const msg = this.ethEncodeStructuredData(domain, messageTypes, message);
718
+ const signature = this.signMessage(msg, this.privateKey);
719
+ return signature;
720
+ }
721
+ buildTransferSig(message) {
722
+ const isSandboxMode = this.safeBool(this.options, 'sandboxMode');
723
+ const chainId = (isSandboxMode) ? 421614 : 42161;
724
+ const messageTypes = {
725
+ 'UsdTransferSignPayload': [
726
+ { 'name': 'destination', 'type': 'string' },
727
+ { 'name': 'amount', 'type': 'string' },
728
+ { 'name': 'time', 'type': 'uint64' },
729
+ ],
730
+ };
731
+ return this.buildSig(chainId, messageTypes, message);
732
+ }
733
+ buildWithdrawSig(message) {
734
+ const isSandboxMode = this.safeBool(this.options, 'sandboxMode');
735
+ const chainId = (isSandboxMode) ? 421614 : 42161;
736
+ const messageTypes = {
737
+ 'WithdrawFromBridge2SignPayload': [
738
+ { 'name': 'destination', 'type': 'string' },
739
+ { 'name': 'usd', 'type': 'string' },
740
+ { 'name': 'time', 'type': 'uint64' },
741
+ ],
742
+ };
743
+ return this.buildSig(chainId, messageTypes, message);
744
+ }
745
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
746
+ /**
747
+ * @method
748
+ * @name hyperliquid#createOrder
749
+ * @description create a trade order
750
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
751
+ * @param {string} symbol unified symbol of the market to create an order in
752
+ * @param {string} type 'market' or 'limit'
753
+ * @param {string} side 'buy' or 'sell'
754
+ * @param {float} amount how much of currency you want to trade in units of base currency
755
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
756
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
757
+ * @param {string} [params.timeInForce] 'Gtc', 'Ioc', 'Alo'
758
+ * @param {bool} [params.postOnly] true or false whether the order is post-only
759
+ * @param {bool} [params.reduceOnly] true or false whether the order is reduce-only
760
+ * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
761
+ * @param {string} [params.clientOrderId] client order id, optional 128 bit hex string
762
+ * @param {string} [params.slippage] the slippage for market order
763
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
764
+ */
765
+ await this.loadMarkets();
766
+ const market = this.market(symbol);
767
+ symbol = market['symbol'];
768
+ const order = {
769
+ 'symbol': symbol,
770
+ 'type': type,
771
+ 'side': side,
772
+ 'amount': amount,
773
+ 'price': price,
774
+ 'params': params,
775
+ };
776
+ const response = await this.createOrders([order], params);
777
+ const first = this.safeDict(response, 0);
778
+ return first;
779
+ }
780
+ async createOrders(orders, params = {}) {
781
+ /**
782
+ * @method
783
+ * @name hyperliquid#createOrders
784
+ * @description create a list of trade orders
785
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
786
+ * @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
787
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
788
+ */
789
+ this.checkRequiredCredentials();
790
+ await this.loadMarkets();
791
+ let defaultSlippage = this.safeString(this.options, 'defaultSlippage');
792
+ defaultSlippage = this.safeString(params, 'slippage', defaultSlippage);
793
+ let hasClientOrderId = false;
794
+ for (let i = 0; i < orders.length; i++) {
795
+ const rawOrder = orders[i];
796
+ const orderParams = this.safeDict(rawOrder, 'params', {});
797
+ const clientOrderId = this.safeString2(orderParams, 'clientOrderId', 'client_id');
798
+ if (clientOrderId !== undefined) {
799
+ hasClientOrderId = true;
800
+ }
801
+ }
802
+ if (hasClientOrderId) {
803
+ for (let i = 0; i < orders.length; i++) {
804
+ const rawOrder = orders[i];
805
+ const orderParams = this.safeDict(rawOrder, 'params', {});
806
+ const clientOrderId = this.safeString2(orderParams, 'clientOrderId', 'client_id');
807
+ if (clientOrderId === undefined) {
808
+ throw new ArgumentsRequired(this.id + ' createOrders() all orders must have clientOrderId if at least one has a clientOrderId');
809
+ }
810
+ }
811
+ }
812
+ params = this.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice']);
813
+ const nonce = this.milliseconds();
814
+ const orderReq = [];
815
+ for (let i = 0; i < orders.length; i++) {
816
+ const rawOrder = orders[i];
817
+ const marketId = this.safeString(rawOrder, 'symbol');
818
+ const market = this.market(marketId);
819
+ const symbol = market['symbol'];
820
+ const type = this.safeStringUpper(rawOrder, 'type');
821
+ const isMarket = (type === 'MARKET');
822
+ const side = this.safeStringUpper(rawOrder, 'side');
823
+ const isBuy = (side === 'BUY');
824
+ const amount = this.safeString(rawOrder, 'amount');
825
+ const price = this.safeString(rawOrder, 'price');
826
+ let orderParams = this.safeDict(rawOrder, 'params', {});
827
+ orderParams = this.extend(params, orderParams);
828
+ const clientOrderId = this.safeString2(orderParams, 'clientOrderId', 'client_id');
829
+ const slippage = this.safeString(orderParams, 'slippage', defaultSlippage);
830
+ let defaultTimeInForce = (isMarket) ? 'ioc' : 'gtc';
831
+ const postOnly = this.safeBool(orderParams, 'postOnly', false);
832
+ if (postOnly) {
833
+ defaultTimeInForce = 'alo';
834
+ }
835
+ let timeInForce = this.safeStringLower(orderParams, 'timeInForce', defaultTimeInForce);
836
+ timeInForce = this.capitalize(timeInForce);
837
+ let triggerPrice = this.safeString2(orderParams, 'triggerPrice', 'stopPrice');
838
+ const stopLossPrice = this.safeString(orderParams, 'stopLossPrice', triggerPrice);
839
+ const takeProfitPrice = this.safeString(orderParams, 'takeProfitPrice');
840
+ const isTrigger = (stopLossPrice || takeProfitPrice);
841
+ let px = undefined;
842
+ if (isMarket) {
843
+ if (price === undefined) {
844
+ throw new ArgumentsRequired(this.id + ' market orders require price to calculate the max slippage price. Default slippage can be set in options (default is 5%).');
845
+ }
846
+ px = (isBuy) ? Precise.stringMul(price, Precise.stringAdd('1', slippage)) : Precise.stringMul(price, Precise.stringSub('1', slippage));
847
+ }
848
+ else {
849
+ px = this.priceToPrecision(symbol, price);
850
+ }
851
+ const sz = this.amountToPrecision(symbol, amount);
852
+ const reduceOnly = this.safeBool(orderParams, 'reduceOnly', false);
853
+ const orderType = {};
854
+ if (isTrigger) {
855
+ let isTp = false;
856
+ if (takeProfitPrice !== undefined) {
857
+ triggerPrice = this.priceToPrecision(symbol, takeProfitPrice);
858
+ isTp = true;
859
+ }
860
+ else {
861
+ triggerPrice = this.priceToPrecision(symbol, stopLossPrice);
862
+ }
863
+ orderType['trigger'] = {
864
+ 'isMarket': isMarket,
865
+ 'triggerPx': triggerPrice,
866
+ 'tpsl': (isTp) ? 'tp' : 'sl',
867
+ };
868
+ }
869
+ else {
870
+ orderType['limit'] = {
871
+ 'tif': timeInForce,
872
+ };
873
+ }
874
+ const orderObj = {
875
+ 'a': this.parseToInt(market['baseId']),
876
+ 'b': isBuy,
877
+ 'p': px,
878
+ 's': sz,
879
+ 'r': reduceOnly,
880
+ 't': orderType,
881
+ // 'c': clientOrderId,
882
+ };
883
+ if (clientOrderId !== undefined) {
884
+ orderObj['c'] = clientOrderId;
885
+ }
886
+ orderReq.push(orderObj);
887
+ }
888
+ const orderAction = {
889
+ 'type': 'order',
890
+ 'orders': orderReq,
891
+ 'grouping': 'na',
892
+ 'brokerCode': 1,
893
+ };
894
+ const vaultAddress = this.safeString(params, 'vaultAddress');
895
+ const signature = this.signL1Action(orderAction, nonce, vaultAddress);
896
+ const request = {
897
+ 'action': orderAction,
898
+ 'nonce': nonce,
899
+ 'signature': signature,
900
+ // 'vaultAddress': vaultAddress,
901
+ };
902
+ const response = await this.privatePostExchange(this.extend(request, params));
903
+ //
904
+ // {
905
+ // "status": "ok",
906
+ // "response": {
907
+ // "type": "order",
908
+ // "data": {
909
+ // "statuses": [
910
+ // {
911
+ // "resting": {
912
+ // "oid": 5063830287
913
+ // }
914
+ // }
915
+ // ]
916
+ // }
917
+ // }
918
+ // }
919
+ //
920
+ const responseObj = this.safeDict(response, 'response', {});
921
+ const data = this.safeDict(responseObj, 'data', {});
922
+ const statuses = this.safeList(data, 'statuses', []);
923
+ return this.parseOrders(statuses, undefined);
924
+ }
925
+ async cancelOrder(id, symbol = undefined, params = {}) {
926
+ /**
927
+ * @method
928
+ * @name hyperliquid#cancelOrder
929
+ * @description cancels an open order
930
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
931
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
932
+ * @param {string} id order id
933
+ * @param {string} symbol unified symbol of the market the order was made in
934
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
935
+ * @param {string} [params.clientOrderId] client order id (default undefined)
936
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
937
+ */
938
+ return await this.cancelOrders([id], symbol, params);
939
+ }
940
+ async cancelOrders(ids, symbol = undefined, params = {}) {
941
+ /**
942
+ * @method
943
+ * @name hyperliquid#cancelOrders
944
+ * @description cancel multiple orders
945
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
946
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
947
+ * @param {string[]} ids order ids
948
+ * @param {string} [symbol] unified market symbol
949
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
950
+ * @param {string|string[]} [params.clientOrderId] client order ids (default undefined)
951
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
952
+ */
953
+ this.checkRequiredCredentials();
954
+ if (symbol === undefined) {
955
+ throw new ArgumentsRequired(this.id + ' cancelOrders() requires a symbol argument');
956
+ }
957
+ await this.loadMarkets();
958
+ const market = this.market(symbol);
959
+ let clientOrderId = this.safeValue2(params, 'clientOrderId', 'client_id');
960
+ params = this.omit(params, ['clientOrderId', 'client_id']);
961
+ const nonce = this.milliseconds();
962
+ const request = {
963
+ 'nonce': nonce,
964
+ // 'vaultAddress': vaultAddress,
965
+ };
966
+ const cancelReq = [];
967
+ const cancelAction = {
968
+ 'type': '',
969
+ 'cancels': [],
970
+ };
971
+ const baseId = this.parseToNumeric(market['baseId']);
972
+ if (clientOrderId !== undefined) {
973
+ if (!Array.isArray(clientOrderId)) {
974
+ clientOrderId = [clientOrderId];
975
+ }
976
+ cancelAction['type'] = 'cancelByCloid';
977
+ for (let i = 0; i < clientOrderId.length; i++) {
978
+ cancelReq.push({
979
+ 'asset': baseId,
980
+ 'cloid': clientOrderId[i],
981
+ });
982
+ }
983
+ }
984
+ else {
985
+ cancelAction['type'] = 'cancel';
986
+ for (let i = 0; i < ids.length; i++) {
987
+ cancelReq.push({
988
+ 'a': baseId,
989
+ 'o': this.parseToNumeric(ids[i]),
990
+ });
991
+ }
992
+ }
993
+ cancelAction['cancels'] = cancelReq;
994
+ const vaultAddress = this.safeString(params, 'vaultAddress');
995
+ const signature = this.signL1Action(cancelAction, nonce, vaultAddress);
996
+ request['action'] = cancelAction;
997
+ request['signature'] = signature;
998
+ const response = await this.privatePostExchange(this.extend(request, params));
999
+ //
1000
+ // {
1001
+ // "status":"ok",
1002
+ // "response":{
1003
+ // "type":"cancel",
1004
+ // "data":{
1005
+ // "statuses":[
1006
+ // "success"
1007
+ // ]
1008
+ // }
1009
+ // }
1010
+ // }
1011
+ //
1012
+ return response;
1013
+ }
1014
+ async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
1015
+ /**
1016
+ * @method
1017
+ * @name hyperliquid#editOrder
1018
+ * @description edit a trade order
1019
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-an-order
1020
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
1021
+ * @param {string} id cancel order id
1022
+ * @param {string} symbol unified symbol of the market to create an order in
1023
+ * @param {string} type 'market' or 'limit'
1024
+ * @param {string} side 'buy' or 'sell'
1025
+ * @param {float} amount how much of currency you want to trade in units of base currency
1026
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
1027
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1028
+ * @param {string} [params.timeInForce] 'Gtc', 'Ioc', 'Alo'
1029
+ * @param {bool} [params.postOnly] true or false whether the order is post-only
1030
+ * @param {bool} [params.reduceOnly] true or false whether the order is reduce-only
1031
+ * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
1032
+ * @param {string} [params.clientOrderId] client order id, (optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1033
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1034
+ */
1035
+ this.checkRequiredCredentials();
1036
+ if (id === undefined) {
1037
+ throw new ArgumentsRequired(this.id + ' editOrder() requires an id argument');
1038
+ }
1039
+ await this.loadMarkets();
1040
+ const market = this.market(symbol);
1041
+ type = type.toUpperCase();
1042
+ const isMarket = (type === 'MARKET');
1043
+ side = side.toUpperCase();
1044
+ const isBuy = (side === 'BUY');
1045
+ const defaultSlippage = this.safeString(this.options, 'defaultSlippage');
1046
+ const slippage = this.safeString(params, 'slippage', defaultSlippage);
1047
+ let defaultTimeInForce = (isMarket) ? 'ioc' : 'gtc';
1048
+ const postOnly = this.safeBool(params, 'postOnly', false);
1049
+ if (postOnly) {
1050
+ defaultTimeInForce = 'alo';
1051
+ }
1052
+ let timeInForce = this.safeStringLower(params, 'timeInForce', defaultTimeInForce);
1053
+ timeInForce = this.capitalize(timeInForce);
1054
+ const clientOrderId = this.safeString2(params, 'clientOrderId', 'client_id');
1055
+ let triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
1056
+ const stopLossPrice = this.safeString(params, 'stopLossPrice', triggerPrice);
1057
+ const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
1058
+ const isTrigger = (stopLossPrice || takeProfitPrice);
1059
+ params = this.omit(params, ['slippage', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'clientOrderId', 'client_id']);
1060
+ let px = price.toString();
1061
+ if (isMarket) {
1062
+ px = (isBuy) ? Precise.stringMul(price.toString(), Precise.stringAdd('1', slippage)) : Precise.stringMul(price.toString(), Precise.stringSub('1', slippage));
1063
+ }
1064
+ else {
1065
+ px = this.priceToPrecision(symbol, price.toString());
1066
+ }
1067
+ const sz = this.amountToPrecision(symbol, amount);
1068
+ const reduceOnly = this.safeBool(params, 'reduceOnly', false);
1069
+ const orderType = {};
1070
+ if (isTrigger) {
1071
+ let isTp = false;
1072
+ if (takeProfitPrice !== undefined) {
1073
+ triggerPrice = this.priceToPrecision(symbol, takeProfitPrice);
1074
+ isTp = true;
1075
+ }
1076
+ else {
1077
+ triggerPrice = this.priceToPrecision(symbol, stopLossPrice);
1078
+ }
1079
+ orderType['trigger'] = {
1080
+ 'isMarket': isMarket,
1081
+ 'triggerPx': triggerPrice,
1082
+ 'tpsl': (isTp) ? 'tp' : 'sl',
1083
+ };
1084
+ }
1085
+ else {
1086
+ orderType['limit'] = {
1087
+ 'tif': timeInForce,
1088
+ };
1089
+ }
1090
+ if (triggerPrice === undefined) {
1091
+ triggerPrice = '0';
1092
+ }
1093
+ const nonce = this.milliseconds();
1094
+ const orderReq = {
1095
+ 'a': this.parseToInt(market['baseId']),
1096
+ 'b': isBuy,
1097
+ 'p': px,
1098
+ 's': sz,
1099
+ 'r': reduceOnly,
1100
+ 't': orderType,
1101
+ // 'c': clientOrderId,
1102
+ };
1103
+ if (clientOrderId !== undefined) {
1104
+ orderReq['c'] = clientOrderId;
1105
+ }
1106
+ const modifyReq = {
1107
+ 'oid': this.parseToInt(id),
1108
+ 'order': orderReq,
1109
+ };
1110
+ const modifyAction = {
1111
+ 'type': 'batchModify',
1112
+ 'modifies': [modifyReq],
1113
+ };
1114
+ const vaultAddress = this.safeString(params, 'vaultAddress');
1115
+ const signature = this.signL1Action(modifyAction, nonce, vaultAddress);
1116
+ const request = {
1117
+ 'action': modifyAction,
1118
+ 'nonce': nonce,
1119
+ 'signature': signature,
1120
+ // 'vaultAddress': vaultAddress,
1121
+ };
1122
+ const response = await this.privatePostExchange(this.extend(request, params));
1123
+ //
1124
+ // {
1125
+ // "status": "ok",
1126
+ // "response": {
1127
+ // "type": "order",
1128
+ // "data": {
1129
+ // "statuses": [
1130
+ // {
1131
+ // "resting": {
1132
+ // "oid": 5063830287
1133
+ // }
1134
+ // }
1135
+ // ]
1136
+ // }
1137
+ // }
1138
+ // }
1139
+ // when the order is filled immediately
1140
+ // {
1141
+ // "status":"ok",
1142
+ // "response":{
1143
+ // "type":"order",
1144
+ // "data":{
1145
+ // "statuses":[
1146
+ // {
1147
+ // "filled":{
1148
+ // "totalSz":"0.1",
1149
+ // "avgPx":"100.84",
1150
+ // "oid":6195281425
1151
+ // }
1152
+ // }
1153
+ // ]
1154
+ // }
1155
+ // }
1156
+ // }
1157
+ //
1158
+ const responseObject = this.safeDict(response, 'response', {});
1159
+ const dataObject = this.safeDict(responseObject, 'data', {});
1160
+ const statuses = this.safeList(dataObject, 'statuses', []);
1161
+ const first = this.safeDict(statuses, 0, {});
1162
+ return this.parseOrder(first, market);
1163
+ }
1164
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1165
+ /**
1166
+ * @method
1167
+ * @name hyperliquid#fetchFundingRateHistory
1168
+ * @description fetches historical funding rate prices
1169
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-historical-funding-rates
1170
+ * @param {string} symbol unified symbol of the market to fetch the funding rate history for
1171
+ * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
1172
+ * @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
1173
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1174
+ * @param {int} [params.until] timestamp in ms of the latest funding rate
1175
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
1176
+ */
1177
+ await this.loadMarkets();
1178
+ const market = this.market(symbol);
1179
+ const request = {
1180
+ 'type': 'fundingHistory',
1181
+ 'coin': market['base'],
1182
+ };
1183
+ if (since !== undefined) {
1184
+ request['startTime'] = since;
1185
+ }
1186
+ else {
1187
+ request['startTime'] = this.milliseconds() - 100 * 60 * 60 * 1000;
1188
+ }
1189
+ const until = this.safeInteger(params, 'until');
1190
+ params = this.omit(params, 'until');
1191
+ if (until !== undefined) {
1192
+ request['endTime'] = until;
1193
+ }
1194
+ const response = await this.publicPostInfo(this.extend(request, params));
1195
+ //
1196
+ // [
1197
+ // {
1198
+ // "coin": "ETH",
1199
+ // "fundingRate": "0.0000125",
1200
+ // "premium": "0.00057962",
1201
+ // "time": 1704290400031
1202
+ // }
1203
+ // ]
1204
+ //
1205
+ const result = [];
1206
+ for (let i = 0; i < response.length; i++) {
1207
+ const entry = response[i];
1208
+ const timestamp = this.safeInteger(entry, 'time');
1209
+ result.push({
1210
+ 'info': entry,
1211
+ 'symbol': this.safeSymbol(undefined, market),
1212
+ 'fundingRate': this.safeNumber(entry, 'fundingRate'),
1213
+ 'timestamp': timestamp,
1214
+ 'datetime': this.iso8601(timestamp),
1215
+ });
1216
+ }
1217
+ const sorted = this.sortBy(result, 'timestamp');
1218
+ return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
1219
+ }
1220
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1221
+ /**
1222
+ * @method
1223
+ * @name hyperliquid#fetchOpenOrders
1224
+ * @description fetch all unfilled currently open orders
1225
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-open-orders
1226
+ * @param {string} symbol unified market symbol
1227
+ * @param {int} [since] the earliest time in ms to fetch open orders for
1228
+ * @param {int} [limit] the maximum number of open orders structures to retrieve
1229
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1230
+ * @param {string} [params.user] user address, will default to this.walletAddress if not provided
1231
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1232
+ */
1233
+ let userAddress = undefined;
1234
+ [userAddress, params] = this.handlePublicAddress('fetchOpenOrders', params);
1235
+ await this.loadMarkets();
1236
+ const market = this.safeMarket(symbol);
1237
+ const request = {
1238
+ 'type': 'openOrders',
1239
+ 'user': userAddress,
1240
+ };
1241
+ const response = await this.publicPostInfo(this.extend(request, params));
1242
+ //
1243
+ // [
1244
+ // {
1245
+ // "coin": "ETH",
1246
+ // "limitPx": "2000.0",
1247
+ // "oid": 3991946565,
1248
+ // "origSz": "0.1",
1249
+ // "side": "B",
1250
+ // "sz": "0.1",
1251
+ // "timestamp": 1704346468838
1252
+ // }
1253
+ // ]
1254
+ //
1255
+ return this.parseOrders(response, market, since, limit);
1256
+ }
1257
+ async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1258
+ /**
1259
+ * @method
1260
+ * @name hyperliquid#fetchClosedOrders
1261
+ * @description fetch all unfilled currently closed orders
1262
+ * @param {string} symbol unified market symbol
1263
+ * @param {int} [since] the earliest time in ms to fetch open orders for
1264
+ * @param {int} [limit] the maximum number of open orders structures to retrieve
1265
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1266
+ * @param {string} [params.user] user address, will default to this.walletAddress if not provided
1267
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1268
+ */
1269
+ let userAddress = undefined;
1270
+ [userAddress, params] = this.handlePublicAddress('fetchClosedOrders', params);
1271
+ await this.loadMarkets();
1272
+ const market = this.safeMarket(symbol);
1273
+ const request = {
1274
+ 'type': 'historicalOrders',
1275
+ 'user': userAddress,
1276
+ };
1277
+ const response = await this.publicPostInfo(this.extend(request, params));
1278
+ //
1279
+ // [
1280
+ // {
1281
+ // "coin": "ETH",
1282
+ // "limitPx": "2000.0",
1283
+ // "oid": 3991946565,
1284
+ // "origSz": "0.1",
1285
+ // "side": "B",
1286
+ // "sz": "0.1",
1287
+ // "timestamp": 1704346468838
1288
+ // }
1289
+ // ]
1290
+ //
1291
+ return this.parseOrders(response, market, since, limit);
1292
+ }
1293
+ async fetchOrder(id, symbol = undefined, params = {}) {
1294
+ /**
1295
+ * @method
1296
+ * @name hyperliquid#fetchOrder
1297
+ * @description fetches information on an order made by the user
1298
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#query-order-status-by-oid-or-cloid
1299
+ * @param {string} symbol unified symbol of the market the order was made in
1300
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1301
+ * @param {string} [params.user] user address, will default to this.walletAddress if not provided
1302
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1303
+ */
1304
+ let userAddress = undefined;
1305
+ [userAddress, params] = this.handlePublicAddress('fetchOrder', params);
1306
+ await this.loadMarkets();
1307
+ const market = this.safeMarket(symbol);
1308
+ const request = {
1309
+ 'type': 'orderStatus',
1310
+ 'oid': this.parseToNumeric(id),
1311
+ 'user': userAddress,
1312
+ };
1313
+ const response = await this.publicPostInfo(this.extend(request, params));
1314
+ //
1315
+ // {
1316
+ // "order": {
1317
+ // "order": {
1318
+ // "children": [],
1319
+ // "cloid": null,
1320
+ // "coin": "ETH",
1321
+ // "isPositionTpsl": false,
1322
+ // "isTrigger": false,
1323
+ // "limitPx": "2000.0",
1324
+ // "oid": "3991946565",
1325
+ // "orderType": "Limit",
1326
+ // "origSz": "0.1",
1327
+ // "reduceOnly": false,
1328
+ // "side": "B",
1329
+ // "sz": "0.1",
1330
+ // "tif": "Gtc",
1331
+ // "timestamp": "1704346468838",
1332
+ // "triggerCondition": "N/A",
1333
+ // "triggerPx": "0.0"
1334
+ // },
1335
+ // "status": "open",
1336
+ // "statusTimestamp": "1704346468838"
1337
+ // },
1338
+ // "status": "order"
1339
+ // }
1340
+ //
1341
+ const data = this.safeDict(response, 'order');
1342
+ return this.parseOrder(data, market);
1343
+ }
1344
+ parseOrder(order, market = undefined) {
1345
+ //
1346
+ // fetchOpenOrders
1347
+ //
1348
+ // {
1349
+ // "coin": "ETH",
1350
+ // "limitPx": "2000.0",
1351
+ // "oid": 3991946565,
1352
+ // "origSz": "0.1",
1353
+ // "side": "B",
1354
+ // "sz": "0.1",
1355
+ // "timestamp": 1704346468838
1356
+ // }
1357
+ // fetchClosedorders
1358
+ // {
1359
+ // "cloid": null,
1360
+ // "closedPnl": "0.0",
1361
+ // "coin": "SOL",
1362
+ // "crossed": true,
1363
+ // "dir": "Open Long",
1364
+ // "fee": "0.003879",
1365
+ // "hash": "0x4a2647998682b7f07bc5040ab531e1011400f9a51bfa0346a0b41ebe510e8875",
1366
+ // "liquidationMarkPx": null,
1367
+ // "oid": "6463280784",
1368
+ // "px": "110.83",
1369
+ // "side": "B",
1370
+ // "startPosition": "1.64",
1371
+ // "sz": "0.1",
1372
+ // "tid": "232174667018988",
1373
+ // "time": "1709142268394"
1374
+ // }
1375
+ //
1376
+ // fetchOrder
1377
+ //
1378
+ // {
1379
+ // "order": {
1380
+ // "children": [],
1381
+ // "cloid": null,
1382
+ // "coin": "ETH",
1383
+ // "isPositionTpsl": false,
1384
+ // "isTrigger": false,
1385
+ // "limitPx": "2000.0",
1386
+ // "oid": "3991946565",
1387
+ // "orderType": "Limit",
1388
+ // "origSz": "0.1",
1389
+ // "reduceOnly": false,
1390
+ // "side": "B",
1391
+ // "sz": "0.1",
1392
+ // "tif": "Gtc",
1393
+ // "timestamp": "1704346468838",
1394
+ // "triggerCondition": "N/A",
1395
+ // "triggerPx": "0.0"
1396
+ // },
1397
+ // "status": "open",
1398
+ // "statusTimestamp": "1704346468838"
1399
+ // }
1400
+ //
1401
+ // createOrder
1402
+ //
1403
+ // {
1404
+ // "resting": {
1405
+ // "oid": 5063830287
1406
+ // }
1407
+ // }
1408
+ //
1409
+ // {
1410
+ // "filled":{
1411
+ // "totalSz":"0.1",
1412
+ // "avgPx":"100.84",
1413
+ // "oid":6195281425
1414
+ // }
1415
+ // }
1416
+ //
1417
+ let entry = this.safeDictN(order, ['order', 'resting', 'filled']);
1418
+ if (entry === undefined) {
1419
+ entry = order;
1420
+ }
1421
+ const coin = this.safeString(entry, 'coin');
1422
+ let marketId = undefined;
1423
+ if (coin !== undefined) {
1424
+ marketId = coin + '/USDC:USDC';
1425
+ }
1426
+ if (this.safeString(entry, 'id') === undefined) {
1427
+ market = this.safeMarket(marketId, undefined);
1428
+ }
1429
+ else {
1430
+ market = this.safeMarket(marketId, market);
1431
+ }
1432
+ const symbol = market['symbol'];
1433
+ const timestamp = this.safeInteger2(order, 'timestamp', 'statusTimestamp');
1434
+ const status = this.safeString(order, 'status');
1435
+ let side = this.safeString(entry, 'side');
1436
+ if (side !== undefined) {
1437
+ side = (side === 'A') ? 'sell' : 'buy';
1438
+ }
1439
+ return this.safeOrder({
1440
+ 'info': order,
1441
+ 'id': this.safeString(entry, 'oid'),
1442
+ 'clientOrderId': this.safeString(entry, 'cloid'),
1443
+ 'timestamp': timestamp,
1444
+ 'datetime': this.iso8601(timestamp),
1445
+ 'lastTradeTimestamp': undefined,
1446
+ 'lastUpdateTimestamp': undefined,
1447
+ 'symbol': symbol,
1448
+ 'type': this.safeStringLower(entry, 'orderType'),
1449
+ 'timeInForce': this.safeStringUpper(entry, 'tif'),
1450
+ 'postOnly': undefined,
1451
+ 'reduceOnly': this.safeBool(entry, 'reduceOnly'),
1452
+ 'side': side,
1453
+ 'price': this.safeNumber(entry, 'limitPx'),
1454
+ 'triggerPrice': this.safeBool(entry, 'isTrigger') ? this.safeNumber(entry, 'triggerPx') : undefined,
1455
+ 'amount': this.safeNumber2(entry, 'sz', 'totalSz'),
1456
+ 'cost': undefined,
1457
+ 'average': this.safeNumber(entry, 'avgPx'),
1458
+ 'filled': undefined,
1459
+ 'remaining': undefined,
1460
+ 'status': this.parseOrderStatus(status),
1461
+ 'fee': undefined,
1462
+ 'trades': undefined,
1463
+ }, market);
1464
+ }
1465
+ parseOrderStatus(status) {
1466
+ const statuses = {
1467
+ 'triggered': 'open',
1468
+ 'filled': 'closed',
1469
+ };
1470
+ return this.safeString(statuses, status, status);
1471
+ }
1472
+ parseOrderType(status) {
1473
+ const statuses = {
1474
+ 'stop limit': 'limit',
1475
+ 'stop market': 'market',
1476
+ };
1477
+ return this.safeString(statuses, status, status);
1478
+ }
1479
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1480
+ /**
1481
+ * @method
1482
+ * @name hyperliquid#fetchMyTrades
1483
+ * @description fetch all trades made by the user
1484
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills
1485
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-fills-by-time
1486
+ * @param {string} symbol unified market symbol
1487
+ * @param {int} [since] the earliest time in ms to fetch trades for
1488
+ * @param {int} [limit] the maximum number of trades structures to retrieve
1489
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1490
+ * @param {int} [params.until] timestamp in ms of the latest trade
1491
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1492
+ */
1493
+ let userAddress = undefined;
1494
+ [userAddress, params] = this.handlePublicAddress('fetchMyTrades', params);
1495
+ await this.loadMarkets();
1496
+ const market = this.safeMarket(symbol);
1497
+ const request = {
1498
+ 'user': userAddress,
1499
+ };
1500
+ if (since !== undefined) {
1501
+ request['type'] = 'userFillsByTime';
1502
+ request['startTime'] = since;
1503
+ }
1504
+ else {
1505
+ request['type'] = 'userFills';
1506
+ }
1507
+ const until = this.safeInteger(params, 'until');
1508
+ params = this.omit(params, 'until');
1509
+ if (until !== undefined) {
1510
+ request['endTime'] = until;
1511
+ }
1512
+ const response = await this.publicPostInfo(this.extend(request, params));
1513
+ //
1514
+ // [
1515
+ // {
1516
+ // "closedPnl": "0.19343",
1517
+ // "coin": "ETH",
1518
+ // "crossed": true,
1519
+ // "dir": "Close Long",
1520
+ // "fee": "0.050062",
1521
+ // "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
1522
+ // "liquidationMarkPx": null,
1523
+ // "oid": 3929354691,
1524
+ // "px": "2381.1",
1525
+ // "side": "A",
1526
+ // "startPosition": "0.0841",
1527
+ // "sz": "0.0841",
1528
+ // "tid": 128423918764978,
1529
+ // "time": 1704262888911
1530
+ // }
1531
+ // ]
1532
+ //
1533
+ return this.parseTrades(response, market, since, limit);
1534
+ }
1535
+ parseTrade(trade, market = undefined) {
1536
+ //
1537
+ // {
1538
+ // "closedPnl": "0.19343",
1539
+ // "coin": "ETH",
1540
+ // "crossed": true,
1541
+ // "dir": "Close Long",
1542
+ // "fee": "0.050062",
1543
+ // "hash": "0x09d77c96791e98b5775a04092584ab010d009445119c71e4005c0d634ea322bc",
1544
+ // "liquidationMarkPx": null,
1545
+ // "oid": 3929354691,
1546
+ // "px": "2381.1",
1547
+ // "side": "A",
1548
+ // "startPosition": "0.0841",
1549
+ // "sz": "0.0841",
1550
+ // "tid": 128423918764978,
1551
+ // "time": 1704262888911
1552
+ // }
1553
+ //
1554
+ const timestamp = this.safeInteger(trade, 'time');
1555
+ const price = this.safeString(trade, 'px');
1556
+ const amount = this.safeString(trade, 'sz');
1557
+ const coin = this.safeString(trade, 'coin');
1558
+ const marketId = coin + '/USDC:USDC';
1559
+ market = this.safeMarket(marketId, undefined);
1560
+ const symbol = market['symbol'];
1561
+ const id = this.safeString(trade, 'tid');
1562
+ let side = this.safeString(trade, 'side');
1563
+ if (side !== undefined) {
1564
+ side = (side === 'A') ? 'sell' : 'buy';
1565
+ }
1566
+ const fee = this.safeString(trade, 'fee');
1567
+ return this.safeTrade({
1568
+ 'info': trade,
1569
+ 'timestamp': timestamp,
1570
+ 'datetime': this.iso8601(timestamp),
1571
+ 'symbol': symbol,
1572
+ 'id': id,
1573
+ 'order': this.safeString(trade, 'oid'),
1574
+ 'type': undefined,
1575
+ 'side': side,
1576
+ 'takerOrMaker': undefined,
1577
+ 'price': price,
1578
+ 'amount': amount,
1579
+ 'cost': undefined,
1580
+ 'fee': { 'cost': fee, 'currency': 'USDC' },
1581
+ }, market);
1582
+ }
1583
+ async fetchPosition(symbol, params = {}) {
1584
+ /**
1585
+ * @method
1586
+ * @name hyperliquid#fetchPosition
1587
+ * @description fetch data on an open position
1588
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
1589
+ * @param {string} symbol unified market symbol of the market the position is held in
1590
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1591
+ * @param {string} [params.user] user address, will default to this.walletAddress if not provided
1592
+ * @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
1593
+ */
1594
+ const positions = await this.fetchPositions([symbol], params);
1595
+ return this.safeDict(positions, 0, {});
1596
+ }
1597
+ async fetchPositions(symbols = undefined, params = {}) {
1598
+ /**
1599
+ * @method
1600
+ * @name hyperliquid#fetchPositions
1601
+ * @description fetch all open positions
1602
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
1603
+ * @param {string[]} [symbols] list of unified market symbols
1604
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1605
+ * @param {string} [params.user] user address, will default to this.walletAddress if not provided
1606
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
1607
+ */
1608
+ await this.loadMarkets();
1609
+ let userAddress = undefined;
1610
+ [userAddress, params] = this.handlePublicAddress('fetchPositions', params);
1611
+ symbols = this.marketSymbols(symbols);
1612
+ const request = {
1613
+ 'type': 'clearinghouseState',
1614
+ 'user': userAddress,
1615
+ };
1616
+ const response = await this.publicPostInfo(this.extend(request, params));
1617
+ //
1618
+ // {
1619
+ // "assetPositions": [
1620
+ // {
1621
+ // "position": {
1622
+ // "coin": "ETH",
1623
+ // "cumFunding": {
1624
+ // "allTime": "0.0",
1625
+ // "sinceChange": "0.0",
1626
+ // "sinceOpen": "0.0"
1627
+ // },
1628
+ // "entryPx": "2213.9",
1629
+ // "leverage": {
1630
+ // "rawUsd": "-475.23904",
1631
+ // "type": "isolated",
1632
+ // "value": "20"
1633
+ // },
1634
+ // "liquidationPx": "2125.00856238",
1635
+ // "marginUsed": "24.88097",
1636
+ // "maxLeverage": "50",
1637
+ // "positionValue": "500.12001",
1638
+ // "returnOnEquity": "0.0",
1639
+ // "szi": "0.2259",
1640
+ // "unrealizedPnl": "0.0"
1641
+ // },
1642
+ // "type": "oneWay"
1643
+ // }
1644
+ // ],
1645
+ // "crossMaintenanceMarginUsed": "0.0",
1646
+ // "crossMarginSummary": {
1647
+ // "accountValue": "100.0",
1648
+ // "totalMarginUsed": "0.0",
1649
+ // "totalNtlPos": "0.0",
1650
+ // "totalRawUsd": "100.0"
1651
+ // },
1652
+ // "marginSummary": {
1653
+ // "accountValue": "100.0",
1654
+ // "totalMarginUsed": "0.0",
1655
+ // "totalNtlPos": "0.0",
1656
+ // "totalRawUsd": "100.0"
1657
+ // },
1658
+ // "time": "1704261007014",
1659
+ // "withdrawable": "100.0"
1660
+ // }
1661
+ //
1662
+ const data = this.safeList(response, 'assetPositions', []);
1663
+ const result = [];
1664
+ for (let i = 0; i < data.length; i++) {
1665
+ result.push(this.parsePosition(data[i], undefined));
1666
+ }
1667
+ return this.filterByArrayPositions(result, 'symbol', symbols, false);
1668
+ }
1669
+ parsePosition(position, market = undefined) {
1670
+ //
1671
+ // {
1672
+ // "position": {
1673
+ // "coin": "ETH",
1674
+ // "cumFunding": {
1675
+ // "allTime": "0.0",
1676
+ // "sinceChange": "0.0",
1677
+ // "sinceOpen": "0.0"
1678
+ // },
1679
+ // "entryPx": "2213.9",
1680
+ // "leverage": {
1681
+ // "rawUsd": "-475.23904",
1682
+ // "type": "isolated",
1683
+ // "value": "20"
1684
+ // },
1685
+ // "liquidationPx": "2125.00856238",
1686
+ // "marginUsed": "24.88097",
1687
+ // "maxLeverage": "50",
1688
+ // "positionValue": "500.12001",
1689
+ // "returnOnEquity": "0.0",
1690
+ // "szi": "0.2259",
1691
+ // "unrealizedPnl": "0.0"
1692
+ // },
1693
+ // "type": "oneWay"
1694
+ // }
1695
+ //
1696
+ const entry = this.safeDict(position, 'position', {});
1697
+ const coin = this.safeString(entry, 'coin');
1698
+ const marketId = coin + '/USDC:USDC';
1699
+ market = this.safeMarket(marketId, undefined);
1700
+ const symbol = market['symbol'];
1701
+ const leverage = this.safeDict(entry, 'leverage', {});
1702
+ const isIsolated = (this.safeString(leverage, 'type') === 'isolated');
1703
+ const quantity = this.safeNumber(leverage, 'rawUsd');
1704
+ let side = undefined;
1705
+ if (quantity !== undefined) {
1706
+ side = (quantity > 0) ? 'short' : 'long';
1707
+ }
1708
+ const unrealizedPnl = this.safeNumber(entry, 'unrealizedPnl');
1709
+ const initialMargin = this.safeNumber(entry, 'marginUsed');
1710
+ const percentage = unrealizedPnl / initialMargin * 100;
1711
+ return this.safePosition({
1712
+ 'info': position,
1713
+ 'id': undefined,
1714
+ 'symbol': symbol,
1715
+ 'timestamp': undefined,
1716
+ 'datetime': undefined,
1717
+ 'isolated': isIsolated,
1718
+ 'hedged': undefined,
1719
+ 'side': side,
1720
+ 'contracts': this.parseNumber(quantity),
1721
+ 'contractSize': undefined,
1722
+ 'entryPrice': this.safeNumber(entry, 'entryPx'),
1723
+ 'markPrice': undefined,
1724
+ 'notional': this.safeNumber(entry, 'positionValue'),
1725
+ 'leverage': this.safeNumber(leverage, 'value'),
1726
+ 'collateral': undefined,
1727
+ 'initialMargin': initialMargin,
1728
+ 'maintenanceMargin': undefined,
1729
+ 'initialMarginPercentage': undefined,
1730
+ 'maintenanceMarginPercentage': undefined,
1731
+ 'unrealizedPnl': unrealizedPnl,
1732
+ 'liquidationPrice': this.safeNumber(entry, 'liquidationPx'),
1733
+ 'marginMode': undefined,
1734
+ 'percentage': percentage,
1735
+ });
1736
+ }
1737
+ async setMarginMode(marginMode, symbol = undefined, params = {}) {
1738
+ /**
1739
+ * @method
1740
+ * @name hyperliquid#setMarginMode
1741
+ * @description set margin mode (symbol)
1742
+ * @param {string} marginMode margin mode must be either [isolated, cross]
1743
+ * @param {string} symbol unified market symbol of the market the position is held in, default is undefined
1744
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1745
+ * @param {string} [params.leverage] the rate of leverage, is required if setting trade mode (symbol)
1746
+ * @returns {object} response from the exchange
1747
+ */
1748
+ if (symbol === undefined) {
1749
+ throw new ArgumentsRequired(this.id + ' setMarginMode() requires a symbol argument');
1750
+ }
1751
+ await this.loadMarkets();
1752
+ const market = this.market(symbol);
1753
+ const leverage = this.safeInteger(params, 'leverage');
1754
+ if (leverage === undefined) {
1755
+ throw new ArgumentsRequired(this.id + ' setMarginMode() requires a leverage parameter');
1756
+ }
1757
+ const asset = this.parseToInt(market['baseId']);
1758
+ const isCross = (marginMode === 'isolated');
1759
+ const nonce = this.milliseconds();
1760
+ params = this.omit(params, ['leverage']);
1761
+ const updateAction = {
1762
+ 'type': 'updateLeverage',
1763
+ 'asset': asset,
1764
+ 'isCross': isCross,
1765
+ 'leverage': leverage,
1766
+ };
1767
+ const vaultAddress = this.safeString(params, 'vaultAddress');
1768
+ const signature = this.signL1Action(updateAction, nonce, vaultAddress);
1769
+ const request = {
1770
+ 'action': updateAction,
1771
+ 'nonce': nonce,
1772
+ 'signature': signature,
1773
+ // 'vaultAddress': vaultAddress,
1774
+ };
1775
+ const response = await this.privatePostExchange(this.extend(request, params));
1776
+ //
1777
+ // {
1778
+ // 'response': {
1779
+ // 'type': 'default'
1780
+ // },
1781
+ // 'status': 'ok'
1782
+ // }
1783
+ //
1784
+ return response;
1785
+ }
1786
+ async setLeverage(leverage, symbol = undefined, params = {}) {
1787
+ /**
1788
+ * @method
1789
+ * @name hyperliquid#setLeverage
1790
+ * @description set the level of leverage for a market
1791
+ * @param {float} leverage the rate of leverage
1792
+ * @param {string} symbol unified market symbol
1793
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1794
+ * @param {string} [params.marginMode] margin mode must be either [isolated, cross], default is cross
1795
+ * @returns {object} response from the exchange
1796
+ */
1797
+ if (symbol === undefined) {
1798
+ throw new ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
1799
+ }
1800
+ await this.loadMarkets();
1801
+ const market = this.market(symbol);
1802
+ const marginMode = this.safeString(params, 'marginMode', 'cross');
1803
+ const isCross = (marginMode === 'cross');
1804
+ const asset = this.parseToInt(market['baseId']);
1805
+ const nonce = this.milliseconds();
1806
+ params = this.omit(params, 'marginMode');
1807
+ const updateAction = {
1808
+ 'type': 'updateLeverage',
1809
+ 'asset': asset,
1810
+ 'isCross': isCross,
1811
+ 'leverage': leverage,
1812
+ };
1813
+ const vaultAddress = this.safeString(params, 'vaultAddress');
1814
+ const signature = this.signL1Action(updateAction, nonce, vaultAddress);
1815
+ const request = {
1816
+ 'action': updateAction,
1817
+ 'nonce': nonce,
1818
+ 'signature': signature,
1819
+ // 'vaultAddress': vaultAddress,
1820
+ };
1821
+ const response = await this.privatePostExchange(this.extend(request, params));
1822
+ //
1823
+ // {
1824
+ // 'response': {
1825
+ // 'type': 'default'
1826
+ // },
1827
+ // 'status': 'ok'
1828
+ // }
1829
+ //
1830
+ return response;
1831
+ }
1832
+ async addMargin(symbol, amount, params = {}) {
1833
+ /**
1834
+ * @method
1835
+ * @name hyperliquid#addMargin
1836
+ * @description add margin
1837
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
1838
+ * @param {string} symbol unified market symbol
1839
+ * @param {float} amount amount of margin to add
1840
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1841
+ * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=add-margin-structure}
1842
+ */
1843
+ return await this.modifyMarginHelper(symbol, amount, 'add', params);
1844
+ }
1845
+ async reduceMargin(symbol, amount, params = {}) {
1846
+ /**
1847
+ * @method
1848
+ * @name hyperliquid#reduceMargin
1849
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
1850
+ * @description remove margin from a position
1851
+ * @param {string} symbol unified market symbol
1852
+ * @param {float} amount the amount of margin to remove
1853
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1854
+ * @returns {object} a [margin structure]{@link https://docs.ccxt.com/#/?id=reduce-margin-structure}
1855
+ */
1856
+ return await this.modifyMarginHelper(symbol, amount, 'reduce', params);
1857
+ }
1858
+ async modifyMarginHelper(symbol, amount, type, params = {}) {
1859
+ await this.loadMarkets();
1860
+ const market = this.market(symbol);
1861
+ const asset = this.parseToInt(market['baseId']);
1862
+ let sz = this.parseToInt(Precise.stringMul(this.amountToPrecision(symbol, amount), '1000000'));
1863
+ if (type === 'reduce') {
1864
+ sz = -sz;
1865
+ }
1866
+ const nonce = this.milliseconds();
1867
+ const updateAction = {
1868
+ 'type': 'updateIsolatedMargin',
1869
+ 'asset': asset,
1870
+ 'isBuy': true,
1871
+ 'ntli': sz,
1872
+ };
1873
+ const vaultAddress = this.safeString(params, 'vaultAddress');
1874
+ const signature = this.signL1Action(updateAction, nonce, vaultAddress);
1875
+ const request = {
1876
+ 'action': updateAction,
1877
+ 'nonce': nonce,
1878
+ 'signature': signature,
1879
+ // 'vaultAddress': vaultAddress,
1880
+ };
1881
+ const response = await this.privatePostExchange(this.extend(request, params));
1882
+ //
1883
+ // {
1884
+ // 'response': {
1885
+ // 'type': 'default'
1886
+ // },
1887
+ // 'status': 'ok'
1888
+ // }
1889
+ //
1890
+ return response;
1891
+ // return this.extend (this.parseMarginModification (response, market), {
1892
+ // 'code': code,
1893
+ // });
1894
+ }
1895
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
1896
+ /**
1897
+ * @method
1898
+ * @name hyperliquid#transfer
1899
+ * @description transfer currency internally between wallets on the same account
1900
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#l1-usdc-transfer
1901
+ * @param {string} code unified currency code
1902
+ * @param {float} amount amount to transfer
1903
+ * @param {string} fromAccount account to transfer from
1904
+ * @param {string} toAccount account to transfer to
1905
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1906
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
1907
+ */
1908
+ this.checkRequiredCredentials();
1909
+ await this.loadMarkets();
1910
+ this.checkAddress(toAccount);
1911
+ if (code !== undefined) {
1912
+ code = code.toUpperCase();
1913
+ if (code !== 'USDC') {
1914
+ throw new NotSupported(this.id + 'withdraw() only support USDC');
1915
+ }
1916
+ }
1917
+ const isSandboxMode = this.safeBool(this.options, 'sandboxMode');
1918
+ const nonce = this.milliseconds();
1919
+ const payload = {
1920
+ 'destination': toAccount,
1921
+ 'amount': amount.toString(),
1922
+ 'time': nonce,
1923
+ };
1924
+ const sig = this.buildTransferSig(payload);
1925
+ const request = {
1926
+ 'action': {
1927
+ 'chain': (isSandboxMode) ? 'ArbitrumTestnet' : 'Arbitrum',
1928
+ 'payload': payload,
1929
+ 'type': 'usdTransfer',
1930
+ },
1931
+ 'nonce': nonce,
1932
+ 'signature': sig,
1933
+ };
1934
+ const response = await this.privatePostExchange(this.extend(request, params));
1935
+ return response;
1936
+ }
1937
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
1938
+ /**
1939
+ * @method
1940
+ * @name hyperliquid#withdraw
1941
+ * @description make a withdrawal (only support USDC)
1942
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#initiate-a-withdrawal-request
1943
+ * @param {string} code unified currency code
1944
+ * @param {float} amount the amount to withdraw
1945
+ * @param {string} address the address to withdraw to
1946
+ * @param {string} tag
1947
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1948
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1949
+ */
1950
+ this.checkRequiredCredentials();
1951
+ await this.loadMarkets();
1952
+ this.checkAddress(address);
1953
+ if (code !== undefined) {
1954
+ code = code.toUpperCase();
1955
+ if (code !== 'USDC') {
1956
+ throw new NotSupported(this.id + 'withdraw() only support USDC');
1957
+ }
1958
+ }
1959
+ const isSandboxMode = this.safeBool(this.options, 'sandboxMode');
1960
+ const nonce = this.milliseconds();
1961
+ const payload = {
1962
+ 'destination': address,
1963
+ 'usd': amount.toString(),
1964
+ 'time': nonce,
1965
+ };
1966
+ const sig = this.buildWithdrawSig(payload);
1967
+ const request = {
1968
+ 'action': {
1969
+ 'chain': (isSandboxMode) ? 'ArbitrumTestnet' : 'Arbitrum',
1970
+ 'payload': payload,
1971
+ 'type': 'withdraw2',
1972
+ },
1973
+ 'nonce': nonce,
1974
+ 'signature': sig,
1975
+ };
1976
+ const response = await this.privatePostExchange(this.extend(request, params));
1977
+ return response;
1978
+ }
1979
+ handlePublicAddress(methodName, params) {
1980
+ let userAux = undefined;
1981
+ [userAux, params] = this.handleOptionAndParams(params, methodName, 'user');
1982
+ let user = userAux;
1983
+ [user, params] = this.handleOptionAndParams(params, methodName, 'address', userAux);
1984
+ if (user !== undefined) {
1985
+ return [user, params];
1986
+ }
1987
+ if (this.walletAddress !== undefined) {
1988
+ return [this.walletAddress, params];
1989
+ }
1990
+ throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a user parameter inside \'params\' or the wallet address set');
1991
+ }
1992
+ handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1993
+ if (!response) {
1994
+ return undefined; // fallback to default error handler
1995
+ }
1996
+ // {"status":"err","response":"User or API Wallet 0xb8a6f8b26223de27c31938d56e470a5b832703a5 does not exist."}
1997
+ //
1998
+ // {
1999
+ // status: 'ok',
2000
+ // response: { type: 'order', data: { statuses: [ { error: 'Insufficient margin to place order. asset=4' } ] } }
2001
+ // }
2002
+ //
2003
+ const status = this.safeString(response, 'status', '');
2004
+ let message = undefined;
2005
+ if (status === 'err') {
2006
+ message = this.safeString(response, 'response');
2007
+ }
2008
+ else {
2009
+ const responsePayload = this.safeDict(response, 'response', {});
2010
+ const data = this.safeDict(responsePayload, 'data', {});
2011
+ const statuses = this.safeList(data, 'statuses', []);
2012
+ const firstStatus = this.safeDict(statuses, 0);
2013
+ message = this.safeString(firstStatus, 'error');
2014
+ }
2015
+ const feedback = this.id + ' ' + body;
2016
+ const nonEmptyMessage = ((message !== undefined) && (message !== ''));
2017
+ if (nonEmptyMessage) {
2018
+ this.throwExactlyMatchedException(this.exceptions['exact'], message, feedback);
2019
+ this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
2020
+ }
2021
+ if (nonEmptyMessage) {
2022
+ throw new ExchangeError(feedback); // unknown message
2023
+ }
2024
+ return undefined;
2025
+ }
2026
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2027
+ const url = this.implodeHostname(this.urls['api'][api]) + '/' + path;
2028
+ if (method === 'POST') {
2029
+ headers = {
2030
+ 'Content-Type': 'application/json',
2031
+ };
2032
+ body = this.json(params);
2033
+ }
2034
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2035
+ }
2036
+ }