ccxt 4.2.60 → 4.2.61

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