@pear-protocol/hyperliquid-sdk 0.0.66-usdh-1 → 0.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/clients/hyperliquid.d.ts +1 -1
- package/dist/clients/orders.d.ts +0 -41
- package/dist/clients/positions.d.ts +2 -2
- package/dist/clients/watchlist.d.ts +1 -1
- package/dist/hooks/index.d.ts +0 -2
- package/dist/hooks/useMarketData.d.ts +7 -9
- package/dist/hooks/useTrading.d.ts +3 -0
- package/dist/hooks/useWebData.d.ts +3 -21
- package/dist/index.d.ts +41 -216
- package/dist/index.js +192 -1181
- package/dist/provider.d.ts +1 -1
- package/dist/store/tokenSelectionMetadataStore.d.ts +1 -1
- package/dist/types.d.ts +21 -74
- package/dist/utils/symbol-translator.d.ts +3 -32
- package/dist/utils/token-metadata-extractor.d.ts +5 -9
- package/package.json +1 -1
- package/dist/hooks/useSpotBalances.d.ts +0 -7
- package/dist/hooks/useSpotOrder.d.ts +0 -13
package/dist/index.js
CHANGED
|
@@ -23,7 +23,6 @@ const useUserData = create((set) => ({
|
|
|
23
23
|
twapDetails: null,
|
|
24
24
|
notifications: null,
|
|
25
25
|
userExtraAgents: null,
|
|
26
|
-
spotState: null,
|
|
27
26
|
setAccessToken: (token) => set({ accessToken: token }),
|
|
28
27
|
setRefreshToken: (token) => set({ refreshToken: token }),
|
|
29
28
|
setIsAuthenticated: (value) => set({ isAuthenticated: value }),
|
|
@@ -44,7 +43,6 @@ const useUserData = create((set) => ({
|
|
|
44
43
|
setAccountSummary: (value) => set({ accountSummary: value }),
|
|
45
44
|
setTwapDetails: (value) => set({ twapDetails: value }),
|
|
46
45
|
setNotifications: (value) => set({ notifications: value }),
|
|
47
|
-
setSpotState: (value) => set({ spotState: value }),
|
|
48
46
|
clean: () => set({
|
|
49
47
|
accessToken: null,
|
|
50
48
|
refreshToken: null,
|
|
@@ -56,7 +54,6 @@ const useUserData = create((set) => ({
|
|
|
56
54
|
accountSummary: null,
|
|
57
55
|
twapDetails: null,
|
|
58
56
|
notifications: null,
|
|
59
|
-
spotState: null,
|
|
60
57
|
}),
|
|
61
58
|
setUserExtraAgents: (value) => set({ userExtraAgents: value }),
|
|
62
59
|
}));
|
|
@@ -74,71 +71,18 @@ const useMarketData = create((set) => ({
|
|
|
74
71
|
* Convert a full/prefixed symbol (e.g., "xyz:XYZ100") to a display symbol (e.g., "XYZ100").
|
|
75
72
|
*/
|
|
76
73
|
function toDisplaySymbol(symbol) {
|
|
77
|
-
const parts = symbol.split(
|
|
74
|
+
const parts = symbol.split(":");
|
|
78
75
|
return parts.length > 1 ? parts.slice(-1)[0] : symbol;
|
|
79
76
|
}
|
|
80
77
|
/**
|
|
81
78
|
* Convert a display symbol back to backend form using a provided map.
|
|
82
79
|
* If mapping is missing, returns the original symbol.
|
|
83
|
-
*
|
|
84
|
-
* @param
|
|
85
|
-
* @param hip3Assets map of display -> all full market names (e.g., "TSLA" -> ["xyz:TSLA", "flx:TSLA"])
|
|
80
|
+
* @param displaySymbol e.g., "XYZ100"
|
|
81
|
+
* @param displayToFull map of display -> full (e.g., "XYZ100" -> "xyz:XYZ100")
|
|
86
82
|
*/
|
|
87
|
-
function toBackendSymbol(displaySymbol,
|
|
88
|
-
const markets = hip3Assets.get(displaySymbol);
|
|
89
|
-
// Return first market if available, otherwise return original symbol
|
|
90
|
-
return markets && markets.length > 0 ? markets[0] : displaySymbol;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Convert a display symbol to backend form for a specific market prefix.
|
|
94
|
-
* This is useful when an asset is available on multiple markets (e.g., xyz:TSLA and flx:TSLA).
|
|
95
|
-
* @param displaySymbol e.g., "TSLA"
|
|
96
|
-
* @param marketPrefix e.g., "xyz" or "flx"
|
|
97
|
-
* @param hip3Assets map of display -> all full market names
|
|
98
|
-
* @returns Full market name if found, null if prefix not specified for multi-market asset, otherwise displaySymbol with prefix
|
|
99
|
-
*/
|
|
100
|
-
function toBackendSymbolWithMarket(displaySymbol, marketPrefix, hip3Assets) {
|
|
101
|
-
const availableMarkets = hip3Assets.get(displaySymbol);
|
|
102
|
-
if (!availableMarkets || availableMarkets.length === 0) {
|
|
103
|
-
// Not a HIP-3 asset, return as-is or with prefix if provided
|
|
104
|
-
return marketPrefix ? `${marketPrefix}:${displaySymbol}` : displaySymbol;
|
|
105
|
-
}
|
|
106
|
-
if (marketPrefix) {
|
|
107
|
-
// Find the market with the specified prefix
|
|
108
|
-
const targetMarket = availableMarkets.find((market) => market.toLowerCase().startsWith(`${marketPrefix.toLowerCase()}:`));
|
|
109
|
-
if (targetMarket) {
|
|
110
|
-
return targetMarket;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
// No prefix specified or not found, return null to force explicit market selection
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Get all available markets for a display symbol.
|
|
118
|
-
* @param displaySymbol e.g., "TSLA"
|
|
119
|
-
* @param hip3Assets map of display -> all full market names
|
|
120
|
-
* @returns Array of full market names, e.g., ["xyz:TSLA", "flx:TSLA"]
|
|
121
|
-
*/
|
|
122
|
-
function getAvailableMarkets(displaySymbol, hip3Assets) {
|
|
83
|
+
function toBackendSymbol(displaySymbol, displayToFull) {
|
|
123
84
|
var _a;
|
|
124
|
-
return (_a =
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Extract the market prefix from a full market name.
|
|
128
|
-
* @param fullSymbol e.g., "xyz:TSLA"
|
|
129
|
-
* @returns The prefix (e.g., "xyz") or undefined if no prefix
|
|
130
|
-
*/
|
|
131
|
-
function getMarketPrefix(fullSymbol) {
|
|
132
|
-
const parts = fullSymbol.split(':');
|
|
133
|
-
return parts.length > 1 ? parts[0] : undefined;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Check if a symbol is a HIP-3 market (has a prefix).
|
|
137
|
-
* @param symbol e.g., "xyz:TSLA" or "TSLA"
|
|
138
|
-
* @returns true if the symbol has a market prefix
|
|
139
|
-
*/
|
|
140
|
-
function isHip3Market(symbol) {
|
|
141
|
-
return symbol.includes(':');
|
|
85
|
+
return (_a = displayToFull.get(displaySymbol)) !== null && _a !== void 0 ? _a : displaySymbol;
|
|
142
86
|
}
|
|
143
87
|
|
|
144
88
|
const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
@@ -155,8 +99,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
155
99
|
try {
|
|
156
100
|
const message = JSON.parse(event.data);
|
|
157
101
|
// Handle subscription responses (only if they don't have channel data)
|
|
158
|
-
if (('success' in message || 'error' in message) &&
|
|
159
|
-
!('channel' in message)) {
|
|
102
|
+
if (('success' in message || 'error' in message) && !('channel' in message)) {
|
|
160
103
|
if (message.error) {
|
|
161
104
|
setLastError(message.error);
|
|
162
105
|
}
|
|
@@ -175,21 +118,12 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
175
118
|
switch (dataMessage.channel) {
|
|
176
119
|
case 'trade-histories':
|
|
177
120
|
{
|
|
178
|
-
const mapAsset = (a) => {
|
|
179
|
-
var _a, _b;
|
|
180
|
-
const extractedPrefix = getMarketPrefix(a.coin);
|
|
181
|
-
return {
|
|
182
|
-
...a,
|
|
183
|
-
coin: toDisplaySymbol(a.coin),
|
|
184
|
-
marketPrefix: (_b = (_a = a.marketPrefix) !== null && _a !== void 0 ? _a : extractedPrefix) !== null && _b !== void 0 ? _b : null,
|
|
185
|
-
};
|
|
186
|
-
};
|
|
187
121
|
const list = dataMessage.data.map((item) => {
|
|
188
122
|
var _a, _b;
|
|
189
123
|
return ({
|
|
190
124
|
...item,
|
|
191
|
-
closedLongAssets: item.closedLongAssets.map(
|
|
192
|
-
closedShortAssets: item.closedShortAssets.map(
|
|
125
|
+
closedLongAssets: item.closedLongAssets.map((a) => ({ ...a, coin: toDisplaySymbol(a.coin) })),
|
|
126
|
+
closedShortAssets: item.closedShortAssets.map((a) => ({ ...a, coin: toDisplaySymbol(a.coin) })),
|
|
193
127
|
positionLongAssets: (_a = item.positionLongAssets) === null || _a === void 0 ? void 0 : _a.map((a) => toDisplaySymbol(a)),
|
|
194
128
|
positionShortAssets: (_b = item.positionShortAssets) === null || _b === void 0 ? void 0 : _b.map((a) => toDisplaySymbol(a)),
|
|
195
129
|
});
|
|
@@ -199,19 +133,10 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
199
133
|
break;
|
|
200
134
|
case 'open-positions':
|
|
201
135
|
{
|
|
202
|
-
const enrichAsset = (a) => {
|
|
203
|
-
var _a, _b;
|
|
204
|
-
const extractedPrefix = getMarketPrefix(a.coin);
|
|
205
|
-
return {
|
|
206
|
-
...a,
|
|
207
|
-
coin: toDisplaySymbol(a.coin),
|
|
208
|
-
marketPrefix: (_b = (_a = a.marketPrefix) !== null && _a !== void 0 ? _a : extractedPrefix) !== null && _b !== void 0 ? _b : null,
|
|
209
|
-
};
|
|
210
|
-
};
|
|
211
136
|
const list = dataMessage.data.map((pos) => ({
|
|
212
137
|
...pos,
|
|
213
|
-
longAssets: pos.longAssets.map(
|
|
214
|
-
shortAssets: pos.shortAssets.map(
|
|
138
|
+
longAssets: pos.longAssets.map((a) => ({ ...a, coin: toDisplaySymbol(a.coin) })),
|
|
139
|
+
shortAssets: pos.shortAssets.map((a) => ({ ...a, coin: toDisplaySymbol(a.coin) })),
|
|
215
140
|
}));
|
|
216
141
|
setRawOpenPositions(list);
|
|
217
142
|
}
|
|
@@ -220,14 +145,8 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
220
145
|
{
|
|
221
146
|
const list = dataMessage.data.map((order) => ({
|
|
222
147
|
...order,
|
|
223
|
-
longAssets: order.longAssets.map((a) => ({
|
|
224
|
-
|
|
225
|
-
asset: toDisplaySymbol(a.asset),
|
|
226
|
-
})),
|
|
227
|
-
shortAssets: order.shortAssets.map((a) => ({
|
|
228
|
-
...a,
|
|
229
|
-
asset: toDisplaySymbol(a.asset),
|
|
230
|
-
})),
|
|
148
|
+
longAssets: order.longAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
|
|
149
|
+
shortAssets: order.shortAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
|
|
231
150
|
}));
|
|
232
151
|
setOpenOrders(list);
|
|
233
152
|
}
|
|
@@ -237,20 +156,10 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
237
156
|
break;
|
|
238
157
|
case 'twap-details':
|
|
239
158
|
{
|
|
240
|
-
const mapTwapAsset = (a) => {
|
|
241
|
-
var _a, _b, _c;
|
|
242
|
-
const extractedPrefix = getMarketPrefix(a.asset);
|
|
243
|
-
return {
|
|
244
|
-
...a,
|
|
245
|
-
asset: toDisplaySymbol(a.asset),
|
|
246
|
-
marketPrefix: (_b = (_a = a.marketPrefix) !== null && _a !== void 0 ? _a : extractedPrefix) !== null && _b !== void 0 ? _b : null,
|
|
247
|
-
collateralToken: (_c = a.collateralToken) !== null && _c !== void 0 ? _c : undefined,
|
|
248
|
-
};
|
|
249
|
-
};
|
|
250
159
|
const list = dataMessage.data.map((twap) => ({
|
|
251
160
|
...twap,
|
|
252
|
-
longAssets: twap.longAssets.map(
|
|
253
|
-
shortAssets: twap.shortAssets.map(
|
|
161
|
+
longAssets: twap.longAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
|
|
162
|
+
shortAssets: twap.shortAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
|
|
254
163
|
}));
|
|
255
164
|
setTwapDetails(list);
|
|
256
165
|
}
|
|
@@ -263,14 +172,8 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
263
172
|
const md = dataMessage.data;
|
|
264
173
|
const mapGroup = (g) => ({
|
|
265
174
|
...g,
|
|
266
|
-
longAssets: g.longAssets.map((a) => ({
|
|
267
|
-
|
|
268
|
-
asset: toDisplaySymbol(a.asset),
|
|
269
|
-
})),
|
|
270
|
-
shortAssets: g.shortAssets.map((a) => ({
|
|
271
|
-
...a,
|
|
272
|
-
asset: toDisplaySymbol(a.asset),
|
|
273
|
-
})),
|
|
175
|
+
longAssets: g.longAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
|
|
176
|
+
shortAssets: g.shortAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
|
|
274
177
|
});
|
|
275
178
|
const mapped = {
|
|
276
179
|
active: md.active.map(mapGroup),
|
|
@@ -288,15 +191,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
288
191
|
catch (error) {
|
|
289
192
|
setLastError(`Failed to parse message: ${error instanceof Error ? error.message : String(error)}`);
|
|
290
193
|
}
|
|
291
|
-
}, [
|
|
292
|
-
setTradeHistories,
|
|
293
|
-
setRawOpenPositions,
|
|
294
|
-
setOpenOrders,
|
|
295
|
-
setAccountSummary,
|
|
296
|
-
setTwapDetails,
|
|
297
|
-
setNotifications,
|
|
298
|
-
setMarketData,
|
|
299
|
-
]);
|
|
194
|
+
}, [setTradeHistories, setRawOpenPositions, setOpenOrders, setAccountSummary, setTwapDetails, setNotifications, setMarketData]);
|
|
300
195
|
const connect = useCallback(() => {
|
|
301
196
|
if (!enabled || !wsUrl)
|
|
302
197
|
return;
|
|
@@ -365,7 +260,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
365
260
|
'open-orders',
|
|
366
261
|
'twap-details',
|
|
367
262
|
'fills-checkpoint',
|
|
368
|
-
'notifications'
|
|
263
|
+
'notifications'
|
|
369
264
|
];
|
|
370
265
|
const globalChannels = ['market-data'];
|
|
371
266
|
if (address && address !== lastSubscribedAddress) {
|
|
@@ -374,14 +269,14 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
374
269
|
sendMessage(JSON.stringify({
|
|
375
270
|
action: 'unsubscribe',
|
|
376
271
|
address: lastSubscribedAddress,
|
|
377
|
-
channels: addressSpecificChannels
|
|
272
|
+
channels: addressSpecificChannels
|
|
378
273
|
}));
|
|
379
274
|
}
|
|
380
275
|
// Subscribe to all channels (global + address-specific)
|
|
381
276
|
sendMessage(JSON.stringify({
|
|
382
277
|
action: 'subscribe',
|
|
383
278
|
address: address,
|
|
384
|
-
channels: [...globalChannels, ...addressSpecificChannels]
|
|
279
|
+
channels: [...globalChannels, ...addressSpecificChannels]
|
|
385
280
|
}));
|
|
386
281
|
setLastSubscribedAddress(address);
|
|
387
282
|
setLastError(null);
|
|
@@ -391,7 +286,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
391
286
|
sendMessage(JSON.stringify({
|
|
392
287
|
action: 'unsubscribe',
|
|
393
288
|
address: lastSubscribedAddress,
|
|
394
|
-
channels: addressSpecificChannels
|
|
289
|
+
channels: addressSpecificChannels
|
|
395
290
|
}));
|
|
396
291
|
setLastSubscribedAddress(null);
|
|
397
292
|
}
|
|
@@ -399,7 +294,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
399
294
|
// If no address but connected, subscribe to global channels only
|
|
400
295
|
sendMessage(JSON.stringify({
|
|
401
296
|
action: 'subscribe',
|
|
402
|
-
channels: globalChannels
|
|
297
|
+
channels: globalChannels
|
|
403
298
|
}));
|
|
404
299
|
}
|
|
405
300
|
}, [isConnected, address, lastSubscribedAddress, sendMessage]);
|
|
@@ -423,12 +318,10 @@ const useHyperliquidData = create((set, get) => ({
|
|
|
423
318
|
finalAtOICaps: null,
|
|
424
319
|
aggregatedClearingHouseState: null,
|
|
425
320
|
perpMetaAssets: null,
|
|
426
|
-
|
|
427
|
-
hip3Assets: new Map(),
|
|
428
|
-
hip3MarketPrefixes: new Map(),
|
|
321
|
+
hip3DisplayToFull: new Map(),
|
|
429
322
|
setAllMids: (value) => set({ allMids: value }),
|
|
430
323
|
setActiveAssetData: (value) => set((state) => ({
|
|
431
|
-
activeAssetData: typeof value === 'function' ? value(state.activeAssetData) : value
|
|
324
|
+
activeAssetData: typeof value === 'function' ? value(state.activeAssetData) : value
|
|
432
325
|
})),
|
|
433
326
|
deleteActiveAssetData: (key) => {
|
|
434
327
|
set((state) => {
|
|
@@ -463,15 +356,13 @@ const useHyperliquidData = create((set, get) => ({
|
|
|
463
356
|
activeAssetData: {
|
|
464
357
|
...state.activeAssetData,
|
|
465
358
|
[key]: value,
|
|
466
|
-
}
|
|
359
|
+
}
|
|
467
360
|
})),
|
|
468
361
|
setFinalAssetContexts: (value) => set({ finalAssetContexts: value }),
|
|
469
362
|
setFinalAtOICaps: (value) => set({ finalAtOICaps: value }),
|
|
470
363
|
setAggregatedClearingHouseState: (value) => set({ aggregatedClearingHouseState: value }),
|
|
471
364
|
setPerpMetaAssets: (value) => set({ perpMetaAssets: value }),
|
|
472
|
-
|
|
473
|
-
setHip3Assets: (value) => set({ hip3Assets: value }),
|
|
474
|
-
setHip3MarketPrefixes: (value) => set({ hip3MarketPrefixes: value }),
|
|
365
|
+
setHip3DisplayToFull: (value) => set({ hip3DisplayToFull: value })
|
|
475
366
|
}));
|
|
476
367
|
|
|
477
368
|
/**
|
|
@@ -734,12 +625,11 @@ const useUserSelection$1 = create((set, get) => ({
|
|
|
734
625
|
}));
|
|
735
626
|
|
|
736
627
|
const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
737
|
-
const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState
|
|
738
|
-
const { setSpotState } = useUserData();
|
|
628
|
+
const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState } = useHyperliquidData();
|
|
739
629
|
const { candleInterval } = useUserSelection$1();
|
|
740
630
|
const longTokens = useUserSelection$1((s) => s.longTokens);
|
|
741
631
|
const shortTokens = useUserSelection$1((s) => s.shortTokens);
|
|
742
|
-
const selectedTokenSymbols = useMemo(() => [...longTokens, ...shortTokens].map((t) => t.symbol), [longTokens, shortTokens]);
|
|
632
|
+
const selectedTokenSymbols = useMemo(() => ([...longTokens, ...shortTokens].map((t) => t.symbol)), [longTokens, shortTokens]);
|
|
743
633
|
const [lastError, setLastError] = useState(null);
|
|
744
634
|
const [subscribedAddress, setSubscribedAddress] = useState(null);
|
|
745
635
|
const [subscribedTokens, setSubscribedTokens] = useState([]);
|
|
@@ -788,7 +678,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
788
678
|
.map(([, s]) => s)
|
|
789
679
|
.filter(Boolean);
|
|
790
680
|
const sum = (values) => values.reduce((acc, v) => acc + (parseFloat(v || '0') || 0), 0);
|
|
791
|
-
const toStr = (n) => Number.isFinite(n) ? n.toString() : '0';
|
|
681
|
+
const toStr = (n) => (Number.isFinite(n) ? n.toString() : '0');
|
|
792
682
|
const assetPositions = states.flatMap((s) => s.assetPositions || []);
|
|
793
683
|
const crossMaintenanceMarginUsed = toStr(sum(states.map((s) => s.crossMaintenanceMarginUsed)));
|
|
794
684
|
const crossMarginSummary = {
|
|
@@ -819,42 +709,19 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
819
709
|
case 'allMids':
|
|
820
710
|
{
|
|
821
711
|
const data = response.data;
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
// This matches how we look up tokens in the SDK
|
|
829
|
-
let normalizedKey = k;
|
|
830
|
-
if (k.includes(':')) {
|
|
831
|
-
const [prefix, ...rest] = k.split(':');
|
|
832
|
-
normalizedKey = `${prefix.toLowerCase()}:${rest.join(':')}`;
|
|
833
|
-
}
|
|
834
|
-
// Store with normalized key
|
|
835
|
-
mids[normalizedKey] = v;
|
|
836
|
-
// Also store with original key for backward compatibility
|
|
837
|
-
if (k !== normalizedKey) {
|
|
838
|
-
mids[k] = v;
|
|
839
|
-
}
|
|
840
|
-
// Also store with display symbol for backward compatibility
|
|
841
|
-
const displayKey = toDisplaySymbol(k);
|
|
842
|
-
// Only set display key if it doesn't already exist (avoid overwriting market-specific prices)
|
|
843
|
-
if (!(displayKey in mids)) {
|
|
844
|
-
mids[displayKey] = v;
|
|
845
|
-
}
|
|
846
|
-
});
|
|
847
|
-
setAllMids({ mids });
|
|
712
|
+
const remapped = {
|
|
713
|
+
mids: Object.fromEntries(
|
|
714
|
+
// only support non hip-3 and xyz market
|
|
715
|
+
Object.entries(data.mids || {}).filter(([k, v]) => !k.includes(':') || k.includes('xyz:')).map(([k, v]) => [toDisplaySymbol(k), v]))
|
|
716
|
+
};
|
|
717
|
+
setAllMids(remapped);
|
|
848
718
|
}
|
|
849
719
|
break;
|
|
850
720
|
case 'activeAssetData':
|
|
851
721
|
{
|
|
852
722
|
const assetData = response.data;
|
|
853
723
|
const symbol = toDisplaySymbol(assetData.coin);
|
|
854
|
-
const normalized = {
|
|
855
|
-
...assetData,
|
|
856
|
-
coin: symbol,
|
|
857
|
-
};
|
|
724
|
+
const normalized = { ...assetData, coin: symbol };
|
|
858
725
|
upsertActiveAssetData(symbol, normalized);
|
|
859
726
|
}
|
|
860
727
|
break;
|
|
@@ -866,14 +733,6 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
866
733
|
addCandleData(symbol, normalized);
|
|
867
734
|
}
|
|
868
735
|
break;
|
|
869
|
-
case 'spotState':
|
|
870
|
-
{
|
|
871
|
-
const spotStateData = response.data;
|
|
872
|
-
if (spotStateData === null || spotStateData === void 0 ? void 0 : spotStateData.spotState) {
|
|
873
|
-
setSpotState(spotStateData.spotState);
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
break;
|
|
877
736
|
default:
|
|
878
737
|
console.warn(`[HyperLiquid WS] Unknown channel: ${response.channel}`);
|
|
879
738
|
}
|
|
@@ -884,15 +743,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
884
743
|
console.error('[HyperLiquid WS] Parse error:', errorMessage, 'Raw message:', event.data);
|
|
885
744
|
setLastError(errorMessage);
|
|
886
745
|
}
|
|
887
|
-
}, [
|
|
888
|
-
setAllMids,
|
|
889
|
-
upsertActiveAssetData,
|
|
890
|
-
addCandleData,
|
|
891
|
-
setFinalAssetContexts,
|
|
892
|
-
setFinalAtOICaps,
|
|
893
|
-
setAggregatedClearingHouseState,
|
|
894
|
-
setSpotState,
|
|
895
|
-
]);
|
|
746
|
+
}, [setAllMids, upsertActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState]);
|
|
896
747
|
const connect = useCallback(() => {
|
|
897
748
|
if (!enabled)
|
|
898
749
|
return;
|
|
@@ -990,17 +841,6 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
990
841
|
},
|
|
991
842
|
};
|
|
992
843
|
sendJsonMessage(unsubscribeMessage);
|
|
993
|
-
// Unsubscribe from spotState for previous address
|
|
994
|
-
if (subscribedAddress !== DEFAULT_ADDRESS) {
|
|
995
|
-
const unsubscribeSpotState = {
|
|
996
|
-
method: 'unsubscribe',
|
|
997
|
-
subscription: {
|
|
998
|
-
type: 'spotState',
|
|
999
|
-
user: subscribedAddress,
|
|
1000
|
-
},
|
|
1001
|
-
};
|
|
1002
|
-
sendJsonMessage(unsubscribeSpotState);
|
|
1003
|
-
}
|
|
1004
844
|
const unsubscribeAllDexsClearinghouseState = {
|
|
1005
845
|
method: 'unsubscribe',
|
|
1006
846
|
subscription: {
|
|
@@ -1044,34 +884,13 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
1044
884
|
sendJsonMessage(subscribeAllDexsClearinghouseState);
|
|
1045
885
|
sendJsonMessage(subscribeAllMids);
|
|
1046
886
|
sendJsonMessage(subscribeAllDexsAssetCtxs);
|
|
1047
|
-
// Subscribe to spotState for real-time spot balances (USDH, USDC, etc.)
|
|
1048
|
-
// Only subscribe if we have a real user address (not the default)
|
|
1049
|
-
if (userAddress !== DEFAULT_ADDRESS) {
|
|
1050
|
-
const subscribeSpotState = {
|
|
1051
|
-
method: 'subscribe',
|
|
1052
|
-
subscription: {
|
|
1053
|
-
type: 'spotState',
|
|
1054
|
-
user: userAddress,
|
|
1055
|
-
},
|
|
1056
|
-
};
|
|
1057
|
-
sendJsonMessage(subscribeSpotState);
|
|
1058
|
-
}
|
|
1059
887
|
setSubscribedAddress(userAddress);
|
|
1060
888
|
// Clear previous data when address changes
|
|
1061
889
|
if (subscribedAddress && subscribedAddress !== userAddress) {
|
|
1062
890
|
// clear aggregatedClearingHouseState
|
|
1063
891
|
setAggregatedClearingHouseState(null);
|
|
1064
|
-
// clear spotState
|
|
1065
|
-
setSpotState(null);
|
|
1066
892
|
}
|
|
1067
|
-
}, [
|
|
1068
|
-
isConnected,
|
|
1069
|
-
address,
|
|
1070
|
-
subscribedAddress,
|
|
1071
|
-
sendJsonMessage,
|
|
1072
|
-
setAggregatedClearingHouseState,
|
|
1073
|
-
setSpotState,
|
|
1074
|
-
]);
|
|
893
|
+
}, [isConnected, address, subscribedAddress, sendJsonMessage, setAggregatedClearingHouseState]);
|
|
1075
894
|
// Handle token subscriptions for activeAssetData
|
|
1076
895
|
useEffect(() => {
|
|
1077
896
|
if (!isConnected || !address)
|
|
@@ -1080,7 +899,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
1080
899
|
const tokensToSubscribe = effectiveTokens.filter((token) => token && !subscribedTokens.includes(token));
|
|
1081
900
|
const tokensToUnsubscribe = subscribedTokens.filter((token) => !effectiveTokens.includes(token));
|
|
1082
901
|
// Unsubscribe from tokens no longer in the list
|
|
1083
|
-
tokensToUnsubscribe.forEach(
|
|
902
|
+
tokensToUnsubscribe.forEach(token => {
|
|
1084
903
|
const unsubscribeMessage = {
|
|
1085
904
|
method: 'unsubscribe',
|
|
1086
905
|
subscription: {
|
|
@@ -1092,7 +911,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
1092
911
|
sendJsonMessage(unsubscribeMessage);
|
|
1093
912
|
});
|
|
1094
913
|
// Subscribe to new tokens
|
|
1095
|
-
tokensToSubscribe.forEach(
|
|
914
|
+
tokensToSubscribe.forEach(token => {
|
|
1096
915
|
const subscribeMessage = {
|
|
1097
916
|
method: 'subscribe',
|
|
1098
917
|
subscription: {
|
|
@@ -1107,14 +926,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
1107
926
|
setSubscribedTokens(effectiveTokens.filter((token) => token));
|
|
1108
927
|
tokensToSubscribe.forEach((token) => deleteActiveAssetData(token));
|
|
1109
928
|
}
|
|
1110
|
-
}, [
|
|
1111
|
-
isConnected,
|
|
1112
|
-
address,
|
|
1113
|
-
selectedTokenSymbols,
|
|
1114
|
-
subscribedTokens,
|
|
1115
|
-
sendJsonMessage,
|
|
1116
|
-
setActiveAssetData,
|
|
1117
|
-
]);
|
|
929
|
+
}, [isConnected, address, selectedTokenSymbols, subscribedTokens, sendJsonMessage, setActiveAssetData]);
|
|
1118
930
|
// Handle candle subscriptions for tokens and interval changes
|
|
1119
931
|
useEffect(() => {
|
|
1120
932
|
if (!isConnected)
|
|
@@ -1123,7 +935,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
1123
935
|
// Unsubscribe from previous candle subscriptions if interval changed
|
|
1124
936
|
const prevInterval = prevCandleIntervalRef.current;
|
|
1125
937
|
if (prevInterval && prevInterval !== candleInterval) {
|
|
1126
|
-
subscribedCandleTokens.forEach(
|
|
938
|
+
subscribedCandleTokens.forEach(token => {
|
|
1127
939
|
const unsubscribeMessage = {
|
|
1128
940
|
method: 'unsubscribe',
|
|
1129
941
|
subscription: {
|
|
@@ -1164,21 +976,12 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
|
|
|
1164
976
|
sendJsonMessage(subscribeMessage);
|
|
1165
977
|
});
|
|
1166
978
|
// Update subscribed state
|
|
1167
|
-
if (tokensToSubscribe.length > 0 ||
|
|
1168
|
-
tokensToUnsubscribe.length > 0 ||
|
|
1169
|
-
prevInterval !== candleInterval) {
|
|
979
|
+
if (tokensToSubscribe.length > 0 || tokensToUnsubscribe.length > 0 || prevInterval !== candleInterval) {
|
|
1170
980
|
setSubscribedCandleTokens(effectiveTokens.filter((token) => token));
|
|
1171
981
|
prevCandleIntervalRef.current = candleInterval;
|
|
1172
982
|
tokensToUnsubscribe.forEach((token) => deleteCandleSymbol(token));
|
|
1173
983
|
}
|
|
1174
|
-
}, [
|
|
1175
|
-
isConnected,
|
|
1176
|
-
selectedTokenSymbols,
|
|
1177
|
-
candleInterval,
|
|
1178
|
-
subscribedCandleTokens,
|
|
1179
|
-
sendJsonMessage,
|
|
1180
|
-
setCandleData,
|
|
1181
|
-
]);
|
|
984
|
+
}, [isConnected, selectedTokenSymbols, candleInterval, subscribedCandleTokens, sendJsonMessage, setCandleData]);
|
|
1182
985
|
return {
|
|
1183
986
|
isConnected,
|
|
1184
987
|
lastError,
|
|
@@ -1267,112 +1070,20 @@ const useAccountSummary = () => {
|
|
|
1267
1070
|
return { data: calculated, isLoading };
|
|
1268
1071
|
};
|
|
1269
1072
|
|
|
1270
|
-
function findAssetMeta$4(coinName, perpMetaAssets, knownPrefix, desiredCollateral) {
|
|
1271
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
1272
|
-
if (!perpMetaAssets) {
|
|
1273
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
1274
|
-
}
|
|
1275
|
-
if (desiredCollateral) {
|
|
1276
|
-
const collateralMatch = perpMetaAssets.find((a) => a.name === coinName && a.collateralToken === desiredCollateral);
|
|
1277
|
-
if (collateralMatch) {
|
|
1278
|
-
return {
|
|
1279
|
-
collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
|
|
1280
|
-
marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
|
|
1281
|
-
};
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
if (coinName.includes(':')) {
|
|
1285
|
-
const [prefix, symbol] = coinName.split(':');
|
|
1286
|
-
const exactMatch = perpMetaAssets.find((a) => {
|
|
1287
|
-
var _a;
|
|
1288
|
-
return a.name === symbol &&
|
|
1289
|
-
((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
|
|
1290
|
-
});
|
|
1291
|
-
if (exactMatch) {
|
|
1292
|
-
return {
|
|
1293
|
-
collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
|
|
1294
|
-
marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
|
|
1295
|
-
};
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
if (knownPrefix) {
|
|
1299
|
-
const exactMatch = perpMetaAssets.find((a) => {
|
|
1300
|
-
var _a;
|
|
1301
|
-
return a.name === coinName &&
|
|
1302
|
-
((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
|
|
1303
|
-
});
|
|
1304
|
-
if (exactMatch) {
|
|
1305
|
-
return {
|
|
1306
|
-
collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
|
|
1307
|
-
marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
|
|
1308
|
-
};
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
const exactMatch = perpMetaAssets.find((a) => a.name === coinName && !a.marketPrefix);
|
|
1312
|
-
if (exactMatch) {
|
|
1313
|
-
return {
|
|
1314
|
-
collateralToken: (_g = exactMatch.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
|
|
1315
|
-
marketPrefix: (_h = exactMatch.marketPrefix) !== null && _h !== void 0 ? _h : null,
|
|
1316
|
-
};
|
|
1317
|
-
}
|
|
1318
|
-
const hip3Matches = perpMetaAssets.filter((a) => a.name === coinName && a.marketPrefix);
|
|
1319
|
-
if (hip3Matches.length > 0) {
|
|
1320
|
-
if (desiredCollateral) {
|
|
1321
|
-
const collateralMatch = hip3Matches.find((a) => a.collateralToken === desiredCollateral);
|
|
1322
|
-
if (collateralMatch) {
|
|
1323
|
-
return {
|
|
1324
|
-
collateralToken: (_j = collateralMatch.collateralToken) !== null && _j !== void 0 ? _j : 'USDC',
|
|
1325
|
-
marketPrefix: (_k = collateralMatch.marketPrefix) !== null && _k !== void 0 ? _k : null,
|
|
1326
|
-
};
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
const usdHMatch = hip3Matches.find((a) => a.collateralToken === 'USDH');
|
|
1330
|
-
const chosen = usdHMatch !== null && usdHMatch !== void 0 ? usdHMatch : hip3Matches[0];
|
|
1331
|
-
return {
|
|
1332
|
-
collateralToken: (_l = chosen.collateralToken) !== null && _l !== void 0 ? _l : 'USDC',
|
|
1333
|
-
marketPrefix: (_m = chosen.marketPrefix) !== null && _m !== void 0 ? _m : null,
|
|
1334
|
-
};
|
|
1335
|
-
}
|
|
1336
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
1337
|
-
}
|
|
1338
|
-
function enrichTradeHistoryAssets(assets, perpMetaAssets) {
|
|
1339
|
-
return assets.map((asset) => {
|
|
1340
|
-
var _a;
|
|
1341
|
-
if (asset.marketPrefix && asset.collateralToken) {
|
|
1342
|
-
return asset;
|
|
1343
|
-
}
|
|
1344
|
-
const meta = findAssetMeta$4(asset.coin, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
|
|
1345
|
-
return {
|
|
1346
|
-
...asset,
|
|
1347
|
-
marketPrefix: asset.marketPrefix || meta.marketPrefix,
|
|
1348
|
-
collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
|
|
1349
|
-
};
|
|
1350
|
-
});
|
|
1351
|
-
}
|
|
1352
|
-
function enrichTradeHistories(histories, perpMetaAssets) {
|
|
1353
|
-
return histories.map((history) => ({
|
|
1354
|
-
...history,
|
|
1355
|
-
closedLongAssets: enrichTradeHistoryAssets(history.closedLongAssets, perpMetaAssets),
|
|
1356
|
-
closedShortAssets: enrichTradeHistoryAssets(history.closedShortAssets, perpMetaAssets),
|
|
1357
|
-
}));
|
|
1358
|
-
}
|
|
1359
1073
|
const useTradeHistories = () => {
|
|
1360
1074
|
const context = useContext(PearHyperliquidContext);
|
|
1361
1075
|
if (!context) {
|
|
1362
1076
|
throw new Error('useTradeHistories must be used within a PearHyperliquidProvider');
|
|
1363
1077
|
}
|
|
1364
1078
|
const tradeHistories = useUserData((state) => state.tradeHistories);
|
|
1365
|
-
const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
|
|
1366
1079
|
const isLoading = useMemo(() => {
|
|
1367
1080
|
return tradeHistories === null && context.isConnected;
|
|
1368
1081
|
}, [tradeHistories, context.isConnected]);
|
|
1369
|
-
|
|
1370
|
-
if (!tradeHistories)
|
|
1371
|
-
return null;
|
|
1372
|
-
return enrichTradeHistories(tradeHistories, allPerpMetaAssets);
|
|
1373
|
-
}, [tradeHistories, allPerpMetaAssets]);
|
|
1374
|
-
return { data: enrichedTradeHistories, isLoading };
|
|
1082
|
+
return { data: tradeHistories, isLoading };
|
|
1375
1083
|
};
|
|
1084
|
+
/**
|
|
1085
|
+
* Hook to access open orders with loading state
|
|
1086
|
+
*/
|
|
1376
1087
|
const useOpenOrders = () => {
|
|
1377
1088
|
const context = useContext(PearHyperliquidContext);
|
|
1378
1089
|
if (!context) {
|
|
@@ -1401,51 +1112,21 @@ const useWebData = () => {
|
|
|
1401
1112
|
const perpMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
|
|
1402
1113
|
const aggregatedClearinghouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
|
|
1403
1114
|
const finalAtOICaps = useHyperliquidData((state) => state.finalAtOICaps);
|
|
1404
|
-
const hip3Assets = useHyperliquidData((state) => state.
|
|
1405
|
-
const hip3MarketPrefixes = useHyperliquidData((state) => state.hip3MarketPrefixes);
|
|
1115
|
+
const hip3Assets = useHyperliquidData((state) => state.hip3DisplayToFull);
|
|
1406
1116
|
let marketDataBySymbol = {};
|
|
1407
1117
|
if (finalAssetContexts && perpMetaAssets) {
|
|
1408
1118
|
const result = {};
|
|
1409
|
-
// Build a map of display name -> asset context index (for unique display names)
|
|
1410
|
-
const displayNameToContextIndex = new Map();
|
|
1411
|
-
const seenNames = new Set();
|
|
1412
|
-
let contextIndex = 0;
|
|
1413
|
-
// First pass: map unique display names to their context index
|
|
1414
1119
|
for (let index = 0; index < perpMetaAssets.length; index++) {
|
|
1415
1120
|
const name = perpMetaAssets[index].name;
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
contextIndex++;
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
// Second pass: create nested entries for all market variants
|
|
1425
|
-
for (let index = 0; index < perpMetaAssets.length; index++) {
|
|
1426
|
-
const universeAsset = perpMetaAssets[index];
|
|
1427
|
-
const displayName = universeAsset.name;
|
|
1428
|
-
const marketPrefix = universeAsset.marketPrefix;
|
|
1429
|
-
const ctxIndex = displayNameToContextIndex.get(displayName);
|
|
1430
|
-
if (ctxIndex !== undefined) {
|
|
1431
|
-
const assetContext = finalAssetContexts[ctxIndex];
|
|
1432
|
-
// Initialize the symbol entry if it doesn't exist
|
|
1433
|
-
if (!result[displayName]) {
|
|
1434
|
-
result[displayName] = {};
|
|
1435
|
-
}
|
|
1436
|
-
// Use marketPrefix as key for HIP-3 assets, "default" for regular assets
|
|
1437
|
-
const variantKey = marketPrefix || 'default';
|
|
1438
|
-
result[displayName][variantKey] = {
|
|
1439
|
-
asset: assetContext,
|
|
1440
|
-
universe: universeAsset,
|
|
1441
|
-
};
|
|
1442
|
-
}
|
|
1121
|
+
result[name] = {
|
|
1122
|
+
asset: finalAssetContexts[index],
|
|
1123
|
+
universe: perpMetaAssets[index],
|
|
1124
|
+
};
|
|
1443
1125
|
}
|
|
1444
1126
|
marketDataBySymbol = result;
|
|
1445
1127
|
}
|
|
1446
1128
|
return {
|
|
1447
1129
|
hip3Assets,
|
|
1448
|
-
hip3MarketPrefixes,
|
|
1449
1130
|
clearinghouseState: aggregatedClearinghouseState,
|
|
1450
1131
|
perpsAtOpenInterestCap: finalAtOICaps,
|
|
1451
1132
|
marketDataBySymbol,
|
|
@@ -1460,60 +1141,30 @@ const useWebData = () => {
|
|
|
1460
1141
|
class TokenMetadataExtractor {
|
|
1461
1142
|
/**
|
|
1462
1143
|
* Extracts comprehensive token metadata
|
|
1463
|
-
* @param symbol - Token symbol
|
|
1144
|
+
* @param symbol - Token symbol
|
|
1464
1145
|
* @param perpMetaAssets - Aggregated universe assets (flattened across dexes)
|
|
1465
1146
|
* @param finalAssetContexts - Aggregated asset contexts (flattened across dexes)
|
|
1466
1147
|
* @param allMids - AllMids data containing current prices
|
|
1467
1148
|
* @param activeAssetData - Optional active asset data containing leverage information
|
|
1468
|
-
* @param marketPrefix - Optional market prefix (e.g., "xyz", "flx") for HIP3 multi-market assets
|
|
1469
1149
|
* @returns TokenMetadata or null if token not found
|
|
1470
1150
|
*/
|
|
1471
|
-
static extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData
|
|
1151
|
+
static extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData) {
|
|
1472
1152
|
if (!perpMetaAssets || !finalAssetContexts || !allMids) {
|
|
1473
1153
|
return null;
|
|
1474
1154
|
}
|
|
1475
1155
|
// Find token index in aggregated universe
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
if (asset.name !== symbol)
|
|
1479
|
-
return false;
|
|
1480
|
-
// If marketPrefix is specified, match it; otherwise match assets without prefix
|
|
1481
|
-
if (marketPrefix) {
|
|
1482
|
-
return asset.marketPrefix === marketPrefix;
|
|
1483
|
-
}
|
|
1484
|
-
// No prefix specified - match non-HIP3 asset (no marketPrefix) or first matching asset
|
|
1485
|
-
return !asset.marketPrefix;
|
|
1486
|
-
});
|
|
1487
|
-
// If no exact match found and prefix was specified, try finding the specific market variant
|
|
1488
|
-
const finalIndex = universeIndex === -1 && marketPrefix
|
|
1489
|
-
? perpMetaAssets.findIndex((asset) => asset.name === symbol && asset.marketPrefix === marketPrefix)
|
|
1490
|
-
: universeIndex;
|
|
1491
|
-
// Fallback: if still not found and no prefix, find first matching by name (for backward compatibility)
|
|
1492
|
-
const resolvedIndex = finalIndex === -1
|
|
1493
|
-
? perpMetaAssets.findIndex((asset) => asset.name === symbol)
|
|
1494
|
-
: finalIndex;
|
|
1495
|
-
if (resolvedIndex === -1) {
|
|
1156
|
+
const universeIndex = perpMetaAssets.findIndex(asset => asset.name === symbol);
|
|
1157
|
+
if (universeIndex === -1) {
|
|
1496
1158
|
return null;
|
|
1497
1159
|
}
|
|
1498
|
-
const universeAsset = perpMetaAssets[
|
|
1499
|
-
const assetCtx = finalAssetContexts[
|
|
1160
|
+
const universeAsset = perpMetaAssets[universeIndex];
|
|
1161
|
+
const assetCtx = finalAssetContexts[universeIndex];
|
|
1500
1162
|
if (!assetCtx) {
|
|
1501
1163
|
return null;
|
|
1502
1164
|
}
|
|
1503
|
-
// Get current price
|
|
1504
|
-
|
|
1505
|
-
const
|
|
1506
|
-
let currentPrice = 0;
|
|
1507
|
-
// Primary source: assetCtx.midPx (already properly indexed)
|
|
1508
|
-
if (assetCtx.midPx) {
|
|
1509
|
-
currentPrice = parseFloat(assetCtx.midPx);
|
|
1510
|
-
}
|
|
1511
|
-
// Fallback: allMids lookup with multiple key formats for HIP3 markets
|
|
1512
|
-
if (!currentPrice || isNaN(currentPrice)) {
|
|
1513
|
-
const currentPriceStr = (prefixedKeyColon && allMids.mids[prefixedKeyColon]) ||
|
|
1514
|
-
allMids.mids[symbol];
|
|
1515
|
-
currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
|
|
1516
|
-
}
|
|
1165
|
+
// Get current price from allMids
|
|
1166
|
+
const currentPriceStr = allMids.mids[symbol];
|
|
1167
|
+
const currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
|
|
1517
1168
|
// Get previous day price
|
|
1518
1169
|
const prevDayPrice = parseFloat(assetCtx.prevDayPx);
|
|
1519
1170
|
// Calculate 24h price change
|
|
@@ -1524,11 +1175,7 @@ class TokenMetadataExtractor {
|
|
|
1524
1175
|
const markPrice = parseFloat(assetCtx.markPx);
|
|
1525
1176
|
const oraclePrice = parseFloat(assetCtx.oraclePx);
|
|
1526
1177
|
// Extract leverage info from activeAssetData if available
|
|
1527
|
-
|
|
1528
|
-
const activeDataKey = prefixedKeyColon && (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[prefixedKeyColon])
|
|
1529
|
-
? prefixedKeyColon
|
|
1530
|
-
: symbol;
|
|
1531
|
-
const tokenActiveData = activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[activeDataKey];
|
|
1178
|
+
const tokenActiveData = activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[symbol];
|
|
1532
1179
|
const leverage = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.leverage;
|
|
1533
1180
|
const maxTradeSzs = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.maxTradeSzs;
|
|
1534
1181
|
const availableToTrade = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.availableToTrade;
|
|
@@ -1546,27 +1193,21 @@ class TokenMetadataExtractor {
|
|
|
1546
1193
|
leverage,
|
|
1547
1194
|
maxTradeSzs,
|
|
1548
1195
|
availableToTrade,
|
|
1549
|
-
collateralToken: universeAsset.collateralToken,
|
|
1550
1196
|
};
|
|
1551
1197
|
}
|
|
1552
1198
|
/**
|
|
1553
1199
|
* Extracts metadata for multiple tokens
|
|
1554
|
-
* @param
|
|
1200
|
+
* @param symbols - Array of token symbols
|
|
1555
1201
|
* @param perpMetaAssets - Aggregated universe assets
|
|
1556
1202
|
* @param finalAssetContexts - Aggregated asset contexts
|
|
1557
1203
|
* @param allMids - AllMids data
|
|
1558
1204
|
* @param activeAssetData - Optional active asset data containing leverage information
|
|
1559
|
-
* @returns Record of
|
|
1205
|
+
* @returns Record of symbol to TokenMetadata
|
|
1560
1206
|
*/
|
|
1561
|
-
static extractMultipleTokensMetadata(
|
|
1207
|
+
static extractMultipleTokensMetadata(symbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData) {
|
|
1562
1208
|
const result = {};
|
|
1563
|
-
for (const
|
|
1564
|
-
|
|
1565
|
-
// This ensures xyz:TSLA and flx:TSLA get separate entries
|
|
1566
|
-
const resultKey = token.marketPrefix
|
|
1567
|
-
? `${token.marketPrefix}:${token.symbol}`
|
|
1568
|
-
: token.symbol;
|
|
1569
|
-
result[resultKey] = this.extractTokenMetadata(token.symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, token.marketPrefix);
|
|
1209
|
+
for (const symbol of symbols) {
|
|
1210
|
+
result[symbol] = this.extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData);
|
|
1570
1211
|
}
|
|
1571
1212
|
return result;
|
|
1572
1213
|
}
|
|
@@ -1579,30 +1220,10 @@ class TokenMetadataExtractor {
|
|
|
1579
1220
|
static isTokenAvailable(symbol, perpMetaAssets) {
|
|
1580
1221
|
if (!perpMetaAssets)
|
|
1581
1222
|
return false;
|
|
1582
|
-
return perpMetaAssets.some(
|
|
1223
|
+
return perpMetaAssets.some(asset => asset.name === symbol);
|
|
1583
1224
|
}
|
|
1584
1225
|
}
|
|
1585
1226
|
|
|
1586
|
-
/**
|
|
1587
|
-
* Parse a token string that may have a market prefix (e.g., "xyz:GOOGL" -> { prefix: "xyz", symbol: "GOOGL" })
|
|
1588
|
-
* This allows us to keep the full name (xyz:GOOGL) for URLs/tags while extracting just the symbol for SDK lookups.
|
|
1589
|
-
*/
|
|
1590
|
-
function parseTokenWithPrefix(token) {
|
|
1591
|
-
if (token.includes(':')) {
|
|
1592
|
-
const [prefix, ...rest] = token.split(':');
|
|
1593
|
-
const symbol = rest.join(':').toUpperCase();
|
|
1594
|
-
return {
|
|
1595
|
-
prefix: prefix.toLowerCase(),
|
|
1596
|
-
symbol,
|
|
1597
|
-
fullName: `${prefix.toLowerCase()}:${symbol}`,
|
|
1598
|
-
};
|
|
1599
|
-
}
|
|
1600
|
-
return {
|
|
1601
|
-
prefix: null,
|
|
1602
|
-
symbol: token.toUpperCase(),
|
|
1603
|
-
fullName: token.toUpperCase(),
|
|
1604
|
-
};
|
|
1605
|
-
}
|
|
1606
1227
|
const useTokenSelectionMetadataStore = create((set) => ({
|
|
1607
1228
|
isPriceDataReady: false,
|
|
1608
1229
|
isLoading: true,
|
|
@@ -1612,65 +1233,23 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1612
1233
|
weightedRatio24h: 1,
|
|
1613
1234
|
priceRatio: 1,
|
|
1614
1235
|
priceRatio24h: 1,
|
|
1615
|
-
openInterest:
|
|
1616
|
-
volume:
|
|
1236
|
+
openInterest: "0",
|
|
1237
|
+
volume: "0",
|
|
1617
1238
|
sumNetFunding: 0,
|
|
1618
1239
|
maxLeverage: 0,
|
|
1619
1240
|
minMargin: 0,
|
|
1620
1241
|
leverageMatched: true,
|
|
1621
|
-
recompute: ({ perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketData, longTokens, shortTokens
|
|
1622
|
-
const isPriceDataReady = !!(perpMetaAssets &&
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
...t,
|
|
1629
|
-
parsed: parseTokenWithPrefix(t.symbol),
|
|
1630
|
-
}));
|
|
1631
|
-
const parsedShortTokens = shortTokens.map((t) => ({
|
|
1632
|
-
...t,
|
|
1633
|
-
parsed: parseTokenWithPrefix(t.symbol),
|
|
1634
|
-
}));
|
|
1635
|
-
// Extract base symbols with their market prefixes for SDK lookups
|
|
1636
|
-
// This ensures xyz:TSLA and flx:TSLA get different market data
|
|
1637
|
-
const longTokensForLookup = parsedLongTokens.map((t) => ({
|
|
1638
|
-
symbol: t.parsed.symbol,
|
|
1639
|
-
marketPrefix: t.parsed.prefix,
|
|
1640
|
-
}));
|
|
1641
|
-
const shortTokensForLookup = parsedShortTokens.map((t) => ({
|
|
1642
|
-
symbol: t.parsed.symbol,
|
|
1643
|
-
marketPrefix: t.parsed.prefix,
|
|
1644
|
-
}));
|
|
1645
|
-
// Also extract just the base symbols (without prefix) for lookups that don't support prefixes
|
|
1646
|
-
const longBaseSymbols = longTokensForLookup.map((t) => t.symbol);
|
|
1647
|
-
const shortBaseSymbols = shortTokensForLookup.map((t) => t.symbol);
|
|
1648
|
-
// Get metadata using base symbols with market prefix for proper market differentiation
|
|
1649
|
-
const longBaseMetadata = isPriceDataReady
|
|
1650
|
-
? TokenMetadataExtractor.extractMultipleTokensMetadata(longTokensForLookup, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
|
|
1242
|
+
recompute: ({ perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketData, longTokens, shortTokens }) => {
|
|
1243
|
+
const isPriceDataReady = !!(perpMetaAssets && finalAssetContexts && allMids);
|
|
1244
|
+
// Compute metadata when ready
|
|
1245
|
+
const longSymbols = longTokens.map((t) => t.symbol);
|
|
1246
|
+
const shortSymbols = shortTokens.map((t) => t.symbol);
|
|
1247
|
+
const longTokensMetadata = isPriceDataReady
|
|
1248
|
+
? TokenMetadataExtractor.extractMultipleTokensMetadata(longSymbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
|
|
1651
1249
|
: {};
|
|
1652
|
-
const
|
|
1653
|
-
? TokenMetadataExtractor.extractMultipleTokensMetadata(
|
|
1250
|
+
const shortTokensMetadata = isPriceDataReady
|
|
1251
|
+
? TokenMetadataExtractor.extractMultipleTokensMetadata(shortSymbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
|
|
1654
1252
|
: {};
|
|
1655
|
-
// Re-map metadata using original full names (with prefix) as keys for UI consistency
|
|
1656
|
-
// The extractor now keys by "{prefix}:{symbol}" for prefixed tokens, which matches our parsed.fullName
|
|
1657
|
-
const longTokensMetadata = {};
|
|
1658
|
-
parsedLongTokens.forEach((t) => {
|
|
1659
|
-
var _a;
|
|
1660
|
-
// Use the full name (e.g., "xyz:TSLA") as the lookup key since extractor uses the same format
|
|
1661
|
-
const lookupKey = t.parsed.prefix
|
|
1662
|
-
? `${t.parsed.prefix}:${t.parsed.symbol}`
|
|
1663
|
-
: t.parsed.symbol;
|
|
1664
|
-
longTokensMetadata[t.symbol] = (_a = longBaseMetadata[lookupKey]) !== null && _a !== void 0 ? _a : null;
|
|
1665
|
-
});
|
|
1666
|
-
const shortTokensMetadata = {};
|
|
1667
|
-
parsedShortTokens.forEach((t) => {
|
|
1668
|
-
var _a;
|
|
1669
|
-
const lookupKey = t.parsed.prefix
|
|
1670
|
-
? `${t.parsed.prefix}:${t.parsed.symbol}`
|
|
1671
|
-
: t.parsed.symbol;
|
|
1672
|
-
shortTokensMetadata[t.symbol] = (_a = shortBaseMetadata[lookupKey]) !== null && _a !== void 0 ? _a : null;
|
|
1673
|
-
});
|
|
1674
1253
|
// Determine loading state
|
|
1675
1254
|
const allTokens = [...longTokens, ...shortTokens];
|
|
1676
1255
|
const isLoading = (() => {
|
|
@@ -1678,33 +1257,26 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1678
1257
|
return true;
|
|
1679
1258
|
if (allTokens.length === 0)
|
|
1680
1259
|
return false;
|
|
1681
|
-
const allMetadata = {
|
|
1682
|
-
...longTokensMetadata,
|
|
1683
|
-
...shortTokensMetadata,
|
|
1684
|
-
};
|
|
1260
|
+
const allMetadata = { ...longTokensMetadata, ...shortTokensMetadata };
|
|
1685
1261
|
return allTokens.some((token) => !allMetadata[token.symbol]);
|
|
1686
1262
|
})();
|
|
1687
1263
|
// Open interest and volume (from market data for matching asset basket)
|
|
1688
|
-
// Use base symbols (without prefix) for matching against market data
|
|
1689
1264
|
const { openInterest, volume } = (() => {
|
|
1690
|
-
const empty = { openInterest:
|
|
1265
|
+
const empty = { openInterest: "0", volume: "0" };
|
|
1691
1266
|
if (!(marketData === null || marketData === void 0 ? void 0 : marketData.active) || (!longTokens.length && !shortTokens.length))
|
|
1692
1267
|
return empty;
|
|
1693
|
-
const selectedLong =
|
|
1694
|
-
const selectedShort =
|
|
1268
|
+
const selectedLong = longTokens.map((t) => t.symbol).sort();
|
|
1269
|
+
const selectedShort = shortTokens.map((t) => t.symbol).sort();
|
|
1695
1270
|
const match = marketData.active.find((item) => {
|
|
1696
1271
|
const longs = [...item.longAssets].sort();
|
|
1697
1272
|
const shorts = [...item.shortAssets].sort();
|
|
1698
|
-
if (longs.length !== selectedLong.length ||
|
|
1699
|
-
shorts.length !== selectedShort.length)
|
|
1273
|
+
if (longs.length !== selectedLong.length || shorts.length !== selectedShort.length)
|
|
1700
1274
|
return false;
|
|
1701
1275
|
const longsEqual = longs.every((s, i) => s.asset === selectedLong[i]);
|
|
1702
1276
|
const shortsEqual = shorts.every((s, i) => s.asset === selectedShort[i]);
|
|
1703
1277
|
return longsEqual && shortsEqual;
|
|
1704
1278
|
});
|
|
1705
|
-
return match
|
|
1706
|
-
? { openInterest: match.openInterest, volume: match.volume }
|
|
1707
|
-
: empty;
|
|
1279
|
+
return match ? { openInterest: match.openInterest, volume: match.volume } : empty;
|
|
1708
1280
|
})();
|
|
1709
1281
|
// Price ratio (only when exactly one long and one short)
|
|
1710
1282
|
const { priceRatio, priceRatio24h } = (() => {
|
|
@@ -1784,27 +1356,17 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1784
1356
|
return totalFunding;
|
|
1785
1357
|
})();
|
|
1786
1358
|
// Max leverage (minimum across all tokens)
|
|
1787
|
-
// Use tokens with their market prefixes for proper lookup in perpMetaAssets
|
|
1788
1359
|
const maxLeverage = (() => {
|
|
1789
1360
|
if (!perpMetaAssets)
|
|
1790
1361
|
return 0;
|
|
1791
|
-
const
|
|
1792
|
-
|
|
1793
|
-
...shortTokensForLookup,
|
|
1794
|
-
];
|
|
1795
|
-
if (allTokensForLookup.length === 0)
|
|
1362
|
+
const allTokenSymbols = [...longTokens, ...shortTokens].map((t) => t.symbol);
|
|
1363
|
+
if (allTokenSymbols.length === 0)
|
|
1796
1364
|
return 0;
|
|
1797
1365
|
let minLev = Infinity;
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
(
|
|
1802
|
-
? u.marketPrefix === marketPrefix
|
|
1803
|
-
: !u.marketPrefix));
|
|
1804
|
-
// Fallback to just matching by name if no exact match
|
|
1805
|
-
const fallbackUniverse = tokenUniverse || perpMetaAssets.find((u) => u.name === symbol);
|
|
1806
|
-
if (fallbackUniverse === null || fallbackUniverse === void 0 ? void 0 : fallbackUniverse.maxLeverage)
|
|
1807
|
-
minLev = Math.min(minLev, fallbackUniverse.maxLeverage);
|
|
1366
|
+
allTokenSymbols.forEach((symbol) => {
|
|
1367
|
+
const tokenUniverse = perpMetaAssets.find((u) => u.name === symbol);
|
|
1368
|
+
if (tokenUniverse === null || tokenUniverse === void 0 ? void 0 : tokenUniverse.maxLeverage)
|
|
1369
|
+
minLev = Math.min(minLev, tokenUniverse.maxLeverage);
|
|
1808
1370
|
});
|
|
1809
1371
|
return minLev === Infinity ? 0 : minLev;
|
|
1810
1372
|
})();
|
|
@@ -1816,10 +1378,7 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1816
1378
|
// Whether all tokens have matching leverage
|
|
1817
1379
|
const leverageMatched = (() => {
|
|
1818
1380
|
const allTokensArr = [...longTokens, ...shortTokens];
|
|
1819
|
-
const allMetadata = {
|
|
1820
|
-
...longTokensMetadata,
|
|
1821
|
-
...shortTokensMetadata,
|
|
1822
|
-
};
|
|
1381
|
+
const allMetadata = { ...longTokensMetadata, ...shortTokensMetadata };
|
|
1823
1382
|
if (allTokensArr.length === 0)
|
|
1824
1383
|
return true;
|
|
1825
1384
|
const tokensWithLev = allTokensArr.filter((token) => { var _a; return (_a = allMetadata[token.symbol]) === null || _a === void 0 ? void 0 : _a.leverage; });
|
|
@@ -6004,8 +5563,8 @@ function addAuthInterceptors(params) {
|
|
|
6004
5563
|
/**
|
|
6005
5564
|
* Fetch historical candle data from HyperLiquid API
|
|
6006
5565
|
*/
|
|
6007
|
-
const fetchHistoricalCandles = async (coin, startTime, endTime, interval,
|
|
6008
|
-
const backendCoin = toBackendSymbol(coin,
|
|
5566
|
+
const fetchHistoricalCandles = async (coin, startTime, endTime, interval, displayToFull) => {
|
|
5567
|
+
const backendCoin = toBackendSymbol(coin, displayToFull);
|
|
6009
5568
|
const request = {
|
|
6010
5569
|
req: { coin: backendCoin, startTime, endTime, interval },
|
|
6011
5570
|
type: 'candleSnapshot',
|
|
@@ -6164,10 +5723,10 @@ const useHistoricalPriceData = () => {
|
|
|
6164
5723
|
setTokenLoading(token.symbol, true);
|
|
6165
5724
|
});
|
|
6166
5725
|
try {
|
|
6167
|
-
const
|
|
5726
|
+
const displayToFull = useHyperliquidData.getState().hip3DisplayToFull;
|
|
6168
5727
|
const fetchPromises = tokensToFetch.map(async (token) => {
|
|
6169
5728
|
try {
|
|
6170
|
-
const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval,
|
|
5729
|
+
const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval, displayToFull);
|
|
6171
5730
|
addHistoricalPriceData(token.symbol, interval, response.data, { start: startTime, end: endTime });
|
|
6172
5731
|
return { symbol: token.symbol, candles: response.data, success: true };
|
|
6173
5732
|
}
|
|
@@ -6856,14 +6415,14 @@ function useAutoSyncFills(options) {
|
|
|
6856
6415
|
* @throws MinimumPositionSizeError if any asset has less than $11 USD value
|
|
6857
6416
|
* @throws MaxAssetsPerLegError if any leg exceeds the maximum allowed assets (15)
|
|
6858
6417
|
*/
|
|
6859
|
-
async function createPosition(baseUrl, payload,
|
|
6418
|
+
async function createPosition(baseUrl, payload, displayToFull) {
|
|
6860
6419
|
// Validate maximum assets per leg before creating position
|
|
6861
6420
|
validateMaxAssetsPerLeg(payload.longAssets, payload.shortAssets);
|
|
6862
6421
|
// Validate minimum asset size before creating position
|
|
6863
6422
|
validateMinimumAssetSize(payload.usdValue, payload.longAssets, payload.shortAssets);
|
|
6864
6423
|
const url = joinUrl(baseUrl, "/positions");
|
|
6865
6424
|
// Translate display symbols to backend format
|
|
6866
|
-
const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset,
|
|
6425
|
+
const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, displayToFull) }));
|
|
6867
6426
|
const translatedPayload = {
|
|
6868
6427
|
...payload,
|
|
6869
6428
|
longAssets: mapAssets(payload.longAssets),
|
|
@@ -6962,9 +6521,9 @@ async function adjustPosition(baseUrl, positionId, payload) {
|
|
|
6962
6521
|
throw toApiError(error);
|
|
6963
6522
|
}
|
|
6964
6523
|
}
|
|
6965
|
-
async function adjustAdvancePosition(baseUrl, positionId, payload,
|
|
6524
|
+
async function adjustAdvancePosition(baseUrl, positionId, payload, displayToFull) {
|
|
6966
6525
|
const url = joinUrl(baseUrl, `/positions/${positionId}/adjust-advance`);
|
|
6967
|
-
const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset,
|
|
6526
|
+
const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, displayToFull) }));
|
|
6968
6527
|
const translatedPayload = (payload || []).map((item) => ({
|
|
6969
6528
|
longAssets: mapAssets(item.longAssets),
|
|
6970
6529
|
shortAssets: mapAssets(item.shortAssets),
|
|
@@ -7027,9 +6586,6 @@ const calculatePositionAsset = (asset, currentPrice, totalInitialPositionSize, l
|
|
|
7027
6586
|
entryPositionValue: entryNotional,
|
|
7028
6587
|
initialWeight: totalInitialPositionSize > 0 ? entryNotional / totalInitialPositionSize : 0,
|
|
7029
6588
|
fundingPaid: (_a = asset.fundingPaid) !== null && _a !== void 0 ? _a : 0,
|
|
7030
|
-
// Preserve market metadata from raw asset (if provided by backend)
|
|
7031
|
-
marketPrefix: asset.marketPrefix,
|
|
7032
|
-
collateralToken: asset.collateralToken,
|
|
7033
6589
|
};
|
|
7034
6590
|
};
|
|
7035
6591
|
const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
|
|
@@ -7054,7 +6610,7 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
|
|
|
7054
6610
|
var _a, _b, _c;
|
|
7055
6611
|
const currentPrice = parseFloat(allMids.mids[longAsset.coin]);
|
|
7056
6612
|
const assetState = (_a = clearinghouseState.assetPositions.find(ap => toDisplaySymbol(ap.position.coin) === longAsset.coin)) === null || _a === void 0 ? void 0 : _a.position;
|
|
7057
|
-
const leverage = (_c = (_b = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c :
|
|
6613
|
+
const leverage = (_c = (_b = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : longAsset.leverage;
|
|
7058
6614
|
const mappedPositionAssets = calculatePositionAsset(longAsset, currentPrice, totalInitialPositionSize, leverage, true);
|
|
7059
6615
|
mappedPosition.entryPositionValue += mappedPositionAssets.entryPositionValue;
|
|
7060
6616
|
mappedPosition.unrealizedPnl += mappedPositionAssets.unrealizedPnl;
|
|
@@ -7068,7 +6624,7 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
|
|
|
7068
6624
|
var _a, _b, _c;
|
|
7069
6625
|
const currentPrice = parseFloat(allMids.mids[shortAsset.coin]);
|
|
7070
6626
|
const assetState = (_a = clearinghouseState.assetPositions.find(ap => toDisplaySymbol(ap.position.coin) === shortAsset.coin)) === null || _a === void 0 ? void 0 : _a.position;
|
|
7071
|
-
const leverage = (_c = (_b = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c :
|
|
6627
|
+
const leverage = (_c = (_b = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : shortAsset.leverage;
|
|
7072
6628
|
const mappedPositionAssets = calculatePositionAsset(shortAsset, currentPrice, totalInitialPositionSize, leverage, false);
|
|
7073
6629
|
mappedPosition.entryPositionValue += mappedPositionAssets.entryPositionValue;
|
|
7074
6630
|
mappedPosition.unrealizedPnl += mappedPositionAssets.unrealizedPnl;
|
|
@@ -7092,151 +6648,57 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
|
|
|
7092
6648
|
});
|
|
7093
6649
|
};
|
|
7094
6650
|
|
|
7095
|
-
function findAssetMeta$3(coinName, perpMetaAssets, knownPrefix, desiredCollateral) {
|
|
7096
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
7097
|
-
if (!perpMetaAssets) {
|
|
7098
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
7099
|
-
}
|
|
7100
|
-
if (desiredCollateral) {
|
|
7101
|
-
const collateralMatch = perpMetaAssets.find((a) => a.name === coinName && a.collateralToken === desiredCollateral);
|
|
7102
|
-
if (collateralMatch) {
|
|
7103
|
-
return {
|
|
7104
|
-
collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
|
|
7105
|
-
marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
|
|
7106
|
-
};
|
|
7107
|
-
}
|
|
7108
|
-
}
|
|
7109
|
-
if (coinName.includes(':')) {
|
|
7110
|
-
const [prefix, symbol] = coinName.split(':');
|
|
7111
|
-
const exactMatch = perpMetaAssets.find((a) => {
|
|
7112
|
-
var _a;
|
|
7113
|
-
return a.name === symbol &&
|
|
7114
|
-
((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
|
|
7115
|
-
});
|
|
7116
|
-
if (exactMatch) {
|
|
7117
|
-
return {
|
|
7118
|
-
collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
|
|
7119
|
-
marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
|
|
7120
|
-
};
|
|
7121
|
-
}
|
|
7122
|
-
}
|
|
7123
|
-
if (knownPrefix) {
|
|
7124
|
-
const exactMatch = perpMetaAssets.find((a) => {
|
|
7125
|
-
var _a;
|
|
7126
|
-
return a.name === coinName &&
|
|
7127
|
-
((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
|
|
7128
|
-
});
|
|
7129
|
-
if (exactMatch) {
|
|
7130
|
-
return {
|
|
7131
|
-
collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
|
|
7132
|
-
marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
|
|
7133
|
-
};
|
|
7134
|
-
}
|
|
7135
|
-
}
|
|
7136
|
-
const regularAsset = perpMetaAssets.find((a) => a.name === coinName && !a.marketPrefix);
|
|
7137
|
-
if (regularAsset) {
|
|
7138
|
-
return {
|
|
7139
|
-
collateralToken: (_g = regularAsset.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
|
|
7140
|
-
marketPrefix: null,
|
|
7141
|
-
};
|
|
7142
|
-
}
|
|
7143
|
-
const hip3Asset = perpMetaAssets.find((a) => a.name === coinName && a.marketPrefix);
|
|
7144
|
-
if (hip3Asset) {
|
|
7145
|
-
return {
|
|
7146
|
-
collateralToken: (_h = hip3Asset.collateralToken) !== null && _h !== void 0 ? _h : 'USDC',
|
|
7147
|
-
marketPrefix: (_j = hip3Asset.marketPrefix) !== null && _j !== void 0 ? _j : null,
|
|
7148
|
-
};
|
|
7149
|
-
}
|
|
7150
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
7151
|
-
}
|
|
7152
|
-
function enrichPositionAssets(assets, perpMetaAssets) {
|
|
7153
|
-
return assets.map((asset) => {
|
|
7154
|
-
var _a;
|
|
7155
|
-
if (asset.marketPrefix && asset.collateralToken) {
|
|
7156
|
-
return asset;
|
|
7157
|
-
}
|
|
7158
|
-
const meta = findAssetMeta$3(asset.coin, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
|
|
7159
|
-
return {
|
|
7160
|
-
...asset,
|
|
7161
|
-
marketPrefix: asset.marketPrefix || meta.marketPrefix,
|
|
7162
|
-
collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
|
|
7163
|
-
};
|
|
7164
|
-
});
|
|
7165
|
-
}
|
|
7166
|
-
function enrichPositions(positions, perpMetaAssets) {
|
|
7167
|
-
return positions.map((position) => ({
|
|
7168
|
-
...position,
|
|
7169
|
-
longAssets: enrichPositionAssets(position.longAssets, perpMetaAssets),
|
|
7170
|
-
shortAssets: enrichPositionAssets(position.shortAssets, perpMetaAssets),
|
|
7171
|
-
}));
|
|
7172
|
-
}
|
|
7173
6651
|
function usePosition() {
|
|
7174
6652
|
const context = useContext(PearHyperliquidContext);
|
|
7175
6653
|
if (!context) {
|
|
7176
6654
|
throw new Error('usePosition must be used within a PearHyperliquidProvider');
|
|
7177
6655
|
}
|
|
7178
6656
|
const { apiBaseUrl, isConnected } = context;
|
|
7179
|
-
const
|
|
6657
|
+
const displayToFull = useHyperliquidData((s) => s.hip3DisplayToFull);
|
|
6658
|
+
// Create position API action
|
|
7180
6659
|
const createPosition$1 = async (payload) => {
|
|
7181
|
-
return createPosition(apiBaseUrl, payload,
|
|
6660
|
+
return createPosition(apiBaseUrl, payload, displayToFull);
|
|
7182
6661
|
};
|
|
6662
|
+
// Update TP/SL risk parameters for a position
|
|
7183
6663
|
const updateRiskParameters$1 = async (positionId, payload) => {
|
|
7184
6664
|
return updateRiskParameters(apiBaseUrl, positionId, payload);
|
|
7185
6665
|
};
|
|
6666
|
+
// Close a position (MARKET or TWAP)
|
|
7186
6667
|
const closePosition$1 = async (positionId, payload) => {
|
|
7187
6668
|
return closePosition(apiBaseUrl, positionId, payload);
|
|
7188
6669
|
};
|
|
6670
|
+
// Close all positions (MARKET or TWAP)
|
|
7189
6671
|
const closeAllPositions$1 = async (payload) => {
|
|
7190
6672
|
return closeAllPositions(apiBaseUrl, payload);
|
|
7191
6673
|
};
|
|
6674
|
+
// Adjust a position (REDUCE/INCREASE by %; MARKET or LIMIT)
|
|
7192
6675
|
const adjustPosition$1 = async (positionId, payload) => {
|
|
7193
6676
|
return adjustPosition(apiBaseUrl, positionId, payload);
|
|
7194
6677
|
};
|
|
6678
|
+
// Adjust to absolute target sizes per asset, optionally adding new assets
|
|
7195
6679
|
const adjustAdvancePosition$1 = async (positionId, payload) => {
|
|
7196
|
-
return adjustAdvancePosition(apiBaseUrl, positionId, payload,
|
|
6680
|
+
return adjustAdvancePosition(apiBaseUrl, positionId, payload, displayToFull);
|
|
7197
6681
|
};
|
|
6682
|
+
// Open positions using WS data, with derived values
|
|
7198
6683
|
const userOpenPositions = useUserData((state) => state.rawOpenPositions);
|
|
7199
6684
|
const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
|
|
7200
6685
|
const allMids = useHyperliquidData((state) => state.allMids);
|
|
7201
|
-
const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
|
|
7202
6686
|
const isLoading = useMemo(() => {
|
|
7203
6687
|
return userOpenPositions === null && isConnected;
|
|
7204
6688
|
}, [userOpenPositions, isConnected]);
|
|
7205
6689
|
const openPositions = useMemo(() => {
|
|
7206
6690
|
if (!userOpenPositions || !aggregatedClearingHouseState || !allMids)
|
|
7207
6691
|
return null;
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
userOpenPositions,
|
|
7212
|
-
aggregatedClearingHouseState,
|
|
7213
|
-
allMids,
|
|
7214
|
-
allPerpMetaAssets,
|
|
7215
|
-
]);
|
|
7216
|
-
return {
|
|
7217
|
-
createPosition: createPosition$1,
|
|
7218
|
-
updateRiskParameters: updateRiskParameters$1,
|
|
7219
|
-
closePosition: closePosition$1,
|
|
7220
|
-
closeAllPositions: closeAllPositions$1,
|
|
7221
|
-
adjustPosition: adjustPosition$1,
|
|
7222
|
-
adjustAdvancePosition: adjustAdvancePosition$1,
|
|
7223
|
-
openPositions,
|
|
7224
|
-
isLoading,
|
|
7225
|
-
};
|
|
6692
|
+
return buildPositionValue(userOpenPositions, aggregatedClearingHouseState, allMids);
|
|
6693
|
+
}, [userOpenPositions, aggregatedClearingHouseState, allMids]);
|
|
6694
|
+
return { createPosition: createPosition$1, updateRiskParameters: updateRiskParameters$1, closePosition: closePosition$1, closeAllPositions: closeAllPositions$1, adjustPosition: adjustPosition$1, adjustAdvancePosition: adjustAdvancePosition$1, openPositions, isLoading };
|
|
7226
6695
|
}
|
|
7227
6696
|
|
|
7228
6697
|
async function adjustOrder(baseUrl, orderId, payload) {
|
|
7229
6698
|
const url = joinUrl(baseUrl, `/orders/${orderId}/adjust`);
|
|
7230
6699
|
try {
|
|
7231
|
-
const resp = await apiClient.put(url, payload, {
|
|
7232
|
-
|
|
7233
|
-
timeout: 60000,
|
|
7234
|
-
});
|
|
7235
|
-
return {
|
|
7236
|
-
data: resp.data,
|
|
7237
|
-
status: resp.status,
|
|
7238
|
-
headers: resp.headers,
|
|
7239
|
-
};
|
|
6700
|
+
const resp = await apiClient.put(url, payload, { headers: { 'Content-Type': 'application/json' }, timeout: 60000 });
|
|
6701
|
+
return { data: resp.data, status: resp.status, headers: resp.headers };
|
|
7240
6702
|
}
|
|
7241
6703
|
catch (error) {
|
|
7242
6704
|
throw toApiError(error);
|
|
@@ -7245,14 +6707,8 @@ async function adjustOrder(baseUrl, orderId, payload) {
|
|
|
7245
6707
|
async function cancelOrder(baseUrl, orderId) {
|
|
7246
6708
|
const url = joinUrl(baseUrl, `/orders/${orderId}/cancel`);
|
|
7247
6709
|
try {
|
|
7248
|
-
const resp = await apiClient.delete(url, {
|
|
7249
|
-
|
|
7250
|
-
});
|
|
7251
|
-
return {
|
|
7252
|
-
data: resp.data,
|
|
7253
|
-
status: resp.status,
|
|
7254
|
-
headers: resp.headers,
|
|
7255
|
-
};
|
|
6710
|
+
const resp = await apiClient.delete(url, { timeout: 60000 });
|
|
6711
|
+
return { data: resp.data, status: resp.status, headers: resp.headers };
|
|
7256
6712
|
}
|
|
7257
6713
|
catch (error) {
|
|
7258
6714
|
throw toApiError(error);
|
|
@@ -7262,129 +6718,19 @@ async function cancelTwapOrder(baseUrl, orderId) {
|
|
|
7262
6718
|
const url = joinUrl(baseUrl, `/orders/${orderId}/twap/cancel`);
|
|
7263
6719
|
try {
|
|
7264
6720
|
const resp = await apiClient.post(url, {}, { headers: { 'Content-Type': 'application/json' }, timeout: 60000 });
|
|
7265
|
-
return {
|
|
7266
|
-
data: resp.data,
|
|
7267
|
-
status: resp.status,
|
|
7268
|
-
headers: resp.headers,
|
|
7269
|
-
};
|
|
7270
|
-
}
|
|
7271
|
-
catch (error) {
|
|
7272
|
-
throw toApiError(error);
|
|
7273
|
-
}
|
|
7274
|
-
}
|
|
7275
|
-
/**
|
|
7276
|
-
* Execute a spot order (swap) using Pear Hyperliquid service
|
|
7277
|
-
* POST /orders/spot
|
|
7278
|
-
*/
|
|
7279
|
-
async function executeSpotOrder(baseUrl, payload) {
|
|
7280
|
-
const url = joinUrl(baseUrl, '/orders/spot');
|
|
7281
|
-
try {
|
|
7282
|
-
const resp = await apiClient.post(url, payload, {
|
|
7283
|
-
headers: { 'Content-Type': 'application/json' },
|
|
7284
|
-
timeout: 60000,
|
|
7285
|
-
});
|
|
7286
|
-
return {
|
|
7287
|
-
data: resp.data,
|
|
7288
|
-
status: resp.status,
|
|
7289
|
-
headers: resp.headers,
|
|
7290
|
-
};
|
|
6721
|
+
return { data: resp.data, status: resp.status, headers: resp.headers };
|
|
7291
6722
|
}
|
|
7292
6723
|
catch (error) {
|
|
7293
6724
|
throw toApiError(error);
|
|
7294
6725
|
}
|
|
7295
6726
|
}
|
|
7296
6727
|
|
|
7297
|
-
function findAssetMeta$2(assetName, perpMetaAssets, knownPrefix, desiredCollateral) {
|
|
7298
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
7299
|
-
if (!perpMetaAssets) {
|
|
7300
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
7301
|
-
}
|
|
7302
|
-
if (desiredCollateral) {
|
|
7303
|
-
const collateralMatch = perpMetaAssets.find((a) => a.name === assetName && a.collateralToken === desiredCollateral);
|
|
7304
|
-
if (collateralMatch) {
|
|
7305
|
-
return {
|
|
7306
|
-
collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
|
|
7307
|
-
marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
|
|
7308
|
-
};
|
|
7309
|
-
}
|
|
7310
|
-
}
|
|
7311
|
-
if (assetName.includes(':')) {
|
|
7312
|
-
const [prefix, symbol] = assetName.split(':');
|
|
7313
|
-
const exactMatch = perpMetaAssets.find((a) => {
|
|
7314
|
-
var _a;
|
|
7315
|
-
return a.name === symbol &&
|
|
7316
|
-
((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
|
|
7317
|
-
});
|
|
7318
|
-
if (exactMatch) {
|
|
7319
|
-
return {
|
|
7320
|
-
collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
|
|
7321
|
-
marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
|
|
7322
|
-
};
|
|
7323
|
-
}
|
|
7324
|
-
}
|
|
7325
|
-
if (knownPrefix) {
|
|
7326
|
-
const exactMatch = perpMetaAssets.find((a) => {
|
|
7327
|
-
var _a;
|
|
7328
|
-
return a.name === assetName &&
|
|
7329
|
-
((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
|
|
7330
|
-
});
|
|
7331
|
-
if (exactMatch) {
|
|
7332
|
-
return {
|
|
7333
|
-
collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
|
|
7334
|
-
marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
|
|
7335
|
-
};
|
|
7336
|
-
}
|
|
7337
|
-
}
|
|
7338
|
-
const regularAsset = perpMetaAssets.find((a) => a.name === assetName && !a.marketPrefix);
|
|
7339
|
-
if (regularAsset) {
|
|
7340
|
-
return {
|
|
7341
|
-
collateralToken: (_g = regularAsset.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
|
|
7342
|
-
marketPrefix: null,
|
|
7343
|
-
};
|
|
7344
|
-
}
|
|
7345
|
-
const hip3Assets = perpMetaAssets.filter((a) => a.name === assetName && a.marketPrefix);
|
|
7346
|
-
if (hip3Assets.length > 0) {
|
|
7347
|
-
if (desiredCollateral) {
|
|
7348
|
-
const collateralMatch = hip3Assets.find((a) => a.collateralToken === desiredCollateral);
|
|
7349
|
-
if (collateralMatch) {
|
|
7350
|
-
return {
|
|
7351
|
-
collateralToken: (_h = collateralMatch.collateralToken) !== null && _h !== void 0 ? _h : 'USDC',
|
|
7352
|
-
marketPrefix: (_j = collateralMatch.marketPrefix) !== null && _j !== void 0 ? _j : null,
|
|
7353
|
-
};
|
|
7354
|
-
}
|
|
7355
|
-
}
|
|
7356
|
-
const usdHMatch = hip3Assets.find((a) => a.collateralToken === 'USDH');
|
|
7357
|
-
const chosen = usdHMatch !== null && usdHMatch !== void 0 ? usdHMatch : hip3Assets[0];
|
|
7358
|
-
return {
|
|
7359
|
-
collateralToken: (_k = chosen.collateralToken) !== null && _k !== void 0 ? _k : 'USDC',
|
|
7360
|
-
marketPrefix: (_l = chosen.marketPrefix) !== null && _l !== void 0 ? _l : null,
|
|
7361
|
-
};
|
|
7362
|
-
}
|
|
7363
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
7364
|
-
}
|
|
7365
|
-
function enrichOrderAssets$1(assets, perpMetaAssets) {
|
|
7366
|
-
if (!assets)
|
|
7367
|
-
return [];
|
|
7368
|
-
return assets.map((asset) => {
|
|
7369
|
-
var _a;
|
|
7370
|
-
if (asset.marketPrefix && asset.collateralToken) {
|
|
7371
|
-
return asset;
|
|
7372
|
-
}
|
|
7373
|
-
const meta = findAssetMeta$2(asset.asset, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
|
|
7374
|
-
return {
|
|
7375
|
-
...asset,
|
|
7376
|
-
marketPrefix: asset.marketPrefix || meta.marketPrefix,
|
|
7377
|
-
collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
|
|
7378
|
-
};
|
|
7379
|
-
});
|
|
7380
|
-
}
|
|
7381
6728
|
function useOrders() {
|
|
7382
6729
|
const context = useContext(PearHyperliquidContext);
|
|
7383
6730
|
if (!context)
|
|
7384
6731
|
throw new Error('useOrders must be used within a PearHyperliquidProvider');
|
|
7385
6732
|
const { apiBaseUrl } = context;
|
|
7386
6733
|
const openOrders = useUserData((state) => state.openOrders);
|
|
7387
|
-
const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
|
|
7388
6734
|
const isLoading = useMemo(() => openOrders === null && context.isConnected, [openOrders, context.isConnected]);
|
|
7389
6735
|
const { openPositions } = usePosition();
|
|
7390
6736
|
const positionsById = useMemo(() => {
|
|
@@ -7403,27 +6749,19 @@ function useOrders() {
|
|
|
7403
6749
|
const isTpSl = ord.orderType === 'TP' || ord.orderType === 'SL';
|
|
7404
6750
|
const hasAssets = ((_b = (_a = ord.longAssets) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 || ((_d = (_c = ord.shortAssets) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) > 0;
|
|
7405
6751
|
const pos = positionsById.get((_e = ord.positionId) !== null && _e !== void 0 ? _e : '');
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
const mapAssets = (arr) => arr.map((a) => ({
|
|
7413
|
-
asset: a.coin,
|
|
7414
|
-
weight: a.initialWeight,
|
|
7415
|
-
marketPrefix: a.marketPrefix,
|
|
7416
|
-
collateralToken: a.collateralToken,
|
|
7417
|
-
}));
|
|
7418
|
-
enrichedOrd = {
|
|
7419
|
-
...enrichedOrd,
|
|
6752
|
+
if (!isTpSl || !pos)
|
|
6753
|
+
return ord;
|
|
6754
|
+
const mapAssets = (arr) => arr.map((a) => ({ asset: a.coin, weight: a.initialWeight }));
|
|
6755
|
+
if (!hasAssets) {
|
|
6756
|
+
return {
|
|
6757
|
+
...ord,
|
|
7420
6758
|
longAssets: mapAssets(pos.longAssets),
|
|
7421
6759
|
shortAssets: mapAssets(pos.shortAssets),
|
|
7422
6760
|
};
|
|
7423
6761
|
}
|
|
7424
|
-
return
|
|
6762
|
+
return ord;
|
|
7425
6763
|
});
|
|
7426
|
-
}, [openOrders, positionsById
|
|
6764
|
+
}, [openOrders, positionsById]);
|
|
7427
6765
|
const adjustOrder$1 = async (orderId, payload) => {
|
|
7428
6766
|
return adjustOrder(apiBaseUrl, orderId, payload);
|
|
7429
6767
|
};
|
|
@@ -7433,156 +6771,16 @@ function useOrders() {
|
|
|
7433
6771
|
const cancelTwapOrder$1 = async (orderId) => {
|
|
7434
6772
|
return cancelTwapOrder(apiBaseUrl, orderId);
|
|
7435
6773
|
};
|
|
7436
|
-
return {
|
|
7437
|
-
adjustOrder: adjustOrder$1,
|
|
7438
|
-
cancelOrder: cancelOrder$1,
|
|
7439
|
-
cancelTwapOrder: cancelTwapOrder$1,
|
|
7440
|
-
openOrders: enrichedOpenOrders,
|
|
7441
|
-
isLoading,
|
|
7442
|
-
};
|
|
6774
|
+
return { adjustOrder: adjustOrder$1, cancelOrder: cancelOrder$1, cancelTwapOrder: cancelTwapOrder$1, openOrders: enrichedOpenOrders, isLoading };
|
|
7443
6775
|
}
|
|
7444
6776
|
|
|
7445
|
-
/**
|
|
7446
|
-
* Hook for executing spot orders (swaps) on Hyperliquid
|
|
7447
|
-
* Use this to swap between USDC and USDH or other spot assets
|
|
7448
|
-
*/
|
|
7449
|
-
function useSpotOrder() {
|
|
7450
|
-
const context = useContext(PearHyperliquidContext);
|
|
7451
|
-
if (!context) {
|
|
7452
|
-
throw new Error('useSpotOrder must be used within a PearHyperliquidProvider');
|
|
7453
|
-
}
|
|
7454
|
-
const { apiBaseUrl } = context;
|
|
7455
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
7456
|
-
const [error, setError] = useState(null);
|
|
7457
|
-
const resetError = useCallback(() => {
|
|
7458
|
-
setError(null);
|
|
7459
|
-
}, []);
|
|
7460
|
-
const executeSpotOrder$1 = useCallback(async (payload) => {
|
|
7461
|
-
setIsLoading(true);
|
|
7462
|
-
setError(null);
|
|
7463
|
-
try {
|
|
7464
|
-
const response = await executeSpotOrder(apiBaseUrl, payload);
|
|
7465
|
-
return response;
|
|
7466
|
-
}
|
|
7467
|
-
catch (err) {
|
|
7468
|
-
const apiError = err;
|
|
7469
|
-
setError(apiError);
|
|
7470
|
-
throw apiError;
|
|
7471
|
-
}
|
|
7472
|
-
finally {
|
|
7473
|
-
setIsLoading(false);
|
|
7474
|
-
}
|
|
7475
|
-
}, [apiBaseUrl]);
|
|
7476
|
-
return {
|
|
7477
|
-
executeSpotOrder: executeSpotOrder$1,
|
|
7478
|
-
isLoading,
|
|
7479
|
-
error,
|
|
7480
|
-
resetError,
|
|
7481
|
-
};
|
|
7482
|
-
}
|
|
7483
|
-
|
|
7484
|
-
function findAssetMeta$1(assetName, perpMetaAssets, knownPrefix, desiredCollateral) {
|
|
7485
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
7486
|
-
if (!perpMetaAssets) {
|
|
7487
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
7488
|
-
}
|
|
7489
|
-
if (desiredCollateral) {
|
|
7490
|
-
const collateralMatch = perpMetaAssets.find((a) => a.name === assetName && a.collateralToken === desiredCollateral);
|
|
7491
|
-
if (collateralMatch) {
|
|
7492
|
-
return {
|
|
7493
|
-
collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
|
|
7494
|
-
marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
|
|
7495
|
-
};
|
|
7496
|
-
}
|
|
7497
|
-
}
|
|
7498
|
-
if (assetName.includes(':')) {
|
|
7499
|
-
const [prefix, symbol] = assetName.split(':');
|
|
7500
|
-
const exactMatch = perpMetaAssets.find((a) => {
|
|
7501
|
-
var _a;
|
|
7502
|
-
return a.name === symbol &&
|
|
7503
|
-
((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
|
|
7504
|
-
});
|
|
7505
|
-
if (exactMatch) {
|
|
7506
|
-
return {
|
|
7507
|
-
collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
|
|
7508
|
-
marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
|
|
7509
|
-
};
|
|
7510
|
-
}
|
|
7511
|
-
}
|
|
7512
|
-
if (knownPrefix) {
|
|
7513
|
-
const exactMatch = perpMetaAssets.find((a) => {
|
|
7514
|
-
var _a;
|
|
7515
|
-
return a.name === assetName &&
|
|
7516
|
-
((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
|
|
7517
|
-
});
|
|
7518
|
-
if (exactMatch) {
|
|
7519
|
-
return {
|
|
7520
|
-
collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
|
|
7521
|
-
marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
|
|
7522
|
-
};
|
|
7523
|
-
}
|
|
7524
|
-
}
|
|
7525
|
-
const regularAsset = perpMetaAssets.find((a) => a.name === assetName && !a.marketPrefix);
|
|
7526
|
-
if (regularAsset) {
|
|
7527
|
-
return {
|
|
7528
|
-
collateralToken: (_g = regularAsset.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
|
|
7529
|
-
marketPrefix: null,
|
|
7530
|
-
};
|
|
7531
|
-
}
|
|
7532
|
-
const hip3Assets = perpMetaAssets.filter((a) => a.name === assetName && a.marketPrefix);
|
|
7533
|
-
if (hip3Assets.length > 0) {
|
|
7534
|
-
if (desiredCollateral) {
|
|
7535
|
-
const collateralMatch = hip3Assets.find((a) => a.collateralToken === desiredCollateral);
|
|
7536
|
-
if (collateralMatch) {
|
|
7537
|
-
return {
|
|
7538
|
-
collateralToken: (_h = collateralMatch.collateralToken) !== null && _h !== void 0 ? _h : 'USDC',
|
|
7539
|
-
marketPrefix: (_j = collateralMatch.marketPrefix) !== null && _j !== void 0 ? _j : null,
|
|
7540
|
-
};
|
|
7541
|
-
}
|
|
7542
|
-
}
|
|
7543
|
-
const usdHMatch = hip3Assets.find((a) => a.collateralToken === 'USDH');
|
|
7544
|
-
const chosen = usdHMatch !== null && usdHMatch !== void 0 ? usdHMatch : hip3Assets[0];
|
|
7545
|
-
return {
|
|
7546
|
-
collateralToken: (_k = chosen.collateralToken) !== null && _k !== void 0 ? _k : 'USDC',
|
|
7547
|
-
marketPrefix: (_l = chosen.marketPrefix) !== null && _l !== void 0 ? _l : null,
|
|
7548
|
-
};
|
|
7549
|
-
}
|
|
7550
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
7551
|
-
}
|
|
7552
|
-
function enrichOrderAssets(assets, perpMetaAssets) {
|
|
7553
|
-
if (!assets)
|
|
7554
|
-
return [];
|
|
7555
|
-
return assets.map((asset) => {
|
|
7556
|
-
var _a;
|
|
7557
|
-
if (asset.marketPrefix && asset.collateralToken) {
|
|
7558
|
-
return asset;
|
|
7559
|
-
}
|
|
7560
|
-
const meta = findAssetMeta$1(asset.asset, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
|
|
7561
|
-
return {
|
|
7562
|
-
...asset,
|
|
7563
|
-
marketPrefix: asset.marketPrefix || meta.marketPrefix,
|
|
7564
|
-
collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
|
|
7565
|
-
};
|
|
7566
|
-
});
|
|
7567
|
-
}
|
|
7568
|
-
function enrichTwapOrders(orders, perpMetaAssets) {
|
|
7569
|
-
return orders.map((order) => ({
|
|
7570
|
-
...order,
|
|
7571
|
-
longAssets: enrichOrderAssets(order.longAssets, perpMetaAssets),
|
|
7572
|
-
shortAssets: enrichOrderAssets(order.shortAssets, perpMetaAssets),
|
|
7573
|
-
}));
|
|
7574
|
-
}
|
|
7575
6777
|
function useTwap() {
|
|
7576
|
-
const twapDetails = useUserData(
|
|
7577
|
-
const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
|
|
6778
|
+
const twapDetails = useUserData(state => state.twapDetails);
|
|
7578
6779
|
const context = useContext(PearHyperliquidContext);
|
|
7579
6780
|
if (!context)
|
|
7580
6781
|
throw new Error('useTwap must be used within a PearHyperliquidProvider');
|
|
7581
6782
|
const { apiBaseUrl } = context;
|
|
7582
|
-
const orders = useMemo(() =>
|
|
7583
|
-
const rawOrders = twapDetails !== null && twapDetails !== void 0 ? twapDetails : [];
|
|
7584
|
-
return enrichTwapOrders(rawOrders, allPerpMetaAssets);
|
|
7585
|
-
}, [twapDetails, allPerpMetaAssets]);
|
|
6783
|
+
const orders = useMemo(() => twapDetails !== null && twapDetails !== void 0 ? twapDetails : [], [twapDetails]);
|
|
7586
6784
|
const cancelTwap$1 = async (orderId) => {
|
|
7587
6785
|
return cancelTwap(apiBaseUrl, orderId);
|
|
7588
6786
|
};
|
|
@@ -7665,170 +6863,59 @@ function useNotifications() {
|
|
|
7665
6863
|
};
|
|
7666
6864
|
}
|
|
7667
6865
|
|
|
7668
|
-
//
|
|
7669
|
-
function findAssetMeta(assetName, perpMetaAssets) {
|
|
7670
|
-
var _a, _b, _c, _d;
|
|
7671
|
-
if (!perpMetaAssets) {
|
|
7672
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
7673
|
-
}
|
|
7674
|
-
// Try exact match first (for prefixed assets like "xyz:TSLA")
|
|
7675
|
-
const exactMatch = perpMetaAssets.find((a) => a.name === assetName);
|
|
7676
|
-
if (exactMatch) {
|
|
7677
|
-
return {
|
|
7678
|
-
collateralToken: (_a = exactMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
|
|
7679
|
-
marketPrefix: (_b = exactMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
|
|
7680
|
-
};
|
|
7681
|
-
}
|
|
7682
|
-
// Try matching by base symbol (for non-prefixed names in data)
|
|
7683
|
-
const baseMatch = perpMetaAssets.find((a) => {
|
|
7684
|
-
const baseName = a.name.includes(':') ? a.name.split(':')[1] : a.name;
|
|
7685
|
-
return baseName === assetName;
|
|
7686
|
-
});
|
|
7687
|
-
if (baseMatch) {
|
|
7688
|
-
return {
|
|
7689
|
-
collateralToken: (_c = baseMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
|
|
7690
|
-
marketPrefix: (_d = baseMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
|
|
7691
|
-
};
|
|
7692
|
-
}
|
|
7693
|
-
return { collateralToken: 'USDC', marketPrefix: null };
|
|
7694
|
-
}
|
|
7695
|
-
// Enrich a single asset with metadata
|
|
7696
|
-
function enrichAsset(asset, perpMetaAssets) {
|
|
7697
|
-
const meta = findAssetMeta(asset.asset, perpMetaAssets);
|
|
7698
|
-
return {
|
|
7699
|
-
...asset,
|
|
7700
|
-
collateralToken: meta.collateralToken,
|
|
7701
|
-
marketPrefix: meta.marketPrefix,
|
|
7702
|
-
};
|
|
7703
|
-
}
|
|
7704
|
-
// Enrich a basket item with collateral info
|
|
7705
|
-
function enrichBasketItem(item, perpMetaAssets) {
|
|
7706
|
-
const enrichedLongs = item.longAssets.map((a) => enrichAsset(a, perpMetaAssets));
|
|
7707
|
-
const enrichedShorts = item.shortAssets.map((a) => enrichAsset(a, perpMetaAssets));
|
|
7708
|
-
// Determine collateral type
|
|
7709
|
-
const allAssets = [...enrichedLongs, ...enrichedShorts];
|
|
7710
|
-
const hasUsdc = allAssets.some((a) => a.collateralToken === 'USDC');
|
|
7711
|
-
const hasUsdh = allAssets.some((a) => a.collateralToken === 'USDH');
|
|
7712
|
-
let collateralType = 'USDC';
|
|
7713
|
-
if (hasUsdc && hasUsdh) {
|
|
7714
|
-
collateralType = 'MIXED';
|
|
7715
|
-
}
|
|
7716
|
-
else if (hasUsdh) {
|
|
7717
|
-
collateralType = 'USDH';
|
|
7718
|
-
}
|
|
7719
|
-
return {
|
|
7720
|
-
...item,
|
|
7721
|
-
longAssets: enrichedLongs,
|
|
7722
|
-
shortAssets: enrichedShorts,
|
|
7723
|
-
collateralType,
|
|
7724
|
-
};
|
|
7725
|
-
}
|
|
7726
|
-
/**
|
|
7727
|
-
* Filter baskets by collateral type
|
|
7728
|
-
* - 'USDC': Only baskets where ALL assets use USDC (collateralType === 'USDC')
|
|
7729
|
-
* - 'USDH': Only baskets where ALL assets use USDH (collateralType === 'USDH')
|
|
7730
|
-
* - 'ALL' or undefined: No filtering, returns all baskets
|
|
7731
|
-
*/
|
|
7732
|
-
function filterByCollateral(baskets, filter) {
|
|
7733
|
-
if (!filter || filter === 'ALL') {
|
|
7734
|
-
return baskets;
|
|
7735
|
-
}
|
|
7736
|
-
return baskets.filter((basket) => {
|
|
7737
|
-
if (filter === 'USDC') {
|
|
7738
|
-
// Include baskets that are purely USDC or have USDC assets
|
|
7739
|
-
return (basket.collateralType === 'USDC' || basket.collateralType === 'MIXED');
|
|
7740
|
-
}
|
|
7741
|
-
if (filter === 'USDH') {
|
|
7742
|
-
// Include baskets that are purely USDH or have USDH assets
|
|
7743
|
-
return (basket.collateralType === 'USDH' || basket.collateralType === 'MIXED');
|
|
7744
|
-
}
|
|
7745
|
-
return true;
|
|
7746
|
-
});
|
|
7747
|
-
}
|
|
7748
|
-
// Base selector for the full market-data payload (raw from WS)
|
|
6866
|
+
// Base selector for the full market-data payload
|
|
7749
6867
|
const useMarketDataPayload = () => {
|
|
7750
6868
|
return useMarketData((s) => s.marketData);
|
|
7751
6869
|
};
|
|
7752
|
-
// Full payload for 'market-data-all' channel
|
|
6870
|
+
// Full payload for 'market-data-all' channel
|
|
7753
6871
|
const useMarketDataAllPayload = () => {
|
|
7754
6872
|
return useMarketData((s) => s.marketDataAll);
|
|
7755
6873
|
};
|
|
7756
|
-
//
|
|
7757
|
-
const
|
|
7758
|
-
|
|
7759
|
-
};
|
|
7760
|
-
// Active baskets (with collateral and market prefix info)
|
|
7761
|
-
const useActiveBaskets = (collateralFilter) => {
|
|
6874
|
+
// Active baskets
|
|
6875
|
+
const useActiveBaskets = () => {
|
|
6876
|
+
var _a;
|
|
7762
6877
|
const data = useMarketDataPayload();
|
|
7763
|
-
|
|
7764
|
-
return useMemo(() => {
|
|
7765
|
-
if (!(data === null || data === void 0 ? void 0 : data.active))
|
|
7766
|
-
return [];
|
|
7767
|
-
const enriched = data.active.map((item) => enrichBasketItem(item, perpMetaAssets));
|
|
7768
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7769
|
-
}, [data, perpMetaAssets, collateralFilter]);
|
|
6878
|
+
return (_a = data === null || data === void 0 ? void 0 : data.active) !== null && _a !== void 0 ? _a : [];
|
|
7770
6879
|
};
|
|
7771
|
-
// Top gainers (
|
|
7772
|
-
const useTopGainers = (limit
|
|
6880
|
+
// Top gainers (optional limit override)
|
|
6881
|
+
const useTopGainers = (limit) => {
|
|
7773
6882
|
const data = useMarketDataPayload();
|
|
7774
|
-
const perpMetaAssets = usePerpMetaAssets();
|
|
7775
6883
|
return useMemo(() => {
|
|
7776
6884
|
var _a;
|
|
7777
6885
|
const list = (_a = data === null || data === void 0 ? void 0 : data.topGainers) !== null && _a !== void 0 ? _a : [];
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7781
|
-
}, [data, perpMetaAssets, limit, collateralFilter]);
|
|
6886
|
+
return typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
|
|
6887
|
+
}, [data, limit]);
|
|
7782
6888
|
};
|
|
7783
|
-
// Top losers (
|
|
7784
|
-
const useTopLosers = (limit
|
|
6889
|
+
// Top losers (optional limit override)
|
|
6890
|
+
const useTopLosers = (limit) => {
|
|
7785
6891
|
const data = useMarketDataPayload();
|
|
7786
|
-
const perpMetaAssets = usePerpMetaAssets();
|
|
7787
6892
|
return useMemo(() => {
|
|
7788
6893
|
var _a;
|
|
7789
6894
|
const list = (_a = data === null || data === void 0 ? void 0 : data.topLosers) !== null && _a !== void 0 ? _a : [];
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7793
|
-
}, [data, perpMetaAssets, limit, collateralFilter]);
|
|
6895
|
+
return typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
|
|
6896
|
+
}, [data, limit]);
|
|
7794
6897
|
};
|
|
7795
|
-
// Highlighted baskets
|
|
7796
|
-
const useHighlightedBaskets = (
|
|
6898
|
+
// Highlighted baskets
|
|
6899
|
+
const useHighlightedBaskets = () => {
|
|
6900
|
+
var _a;
|
|
7797
6901
|
const data = useMarketDataPayload();
|
|
7798
|
-
|
|
7799
|
-
return useMemo(() => {
|
|
7800
|
-
if (!(data === null || data === void 0 ? void 0 : data.highlighted))
|
|
7801
|
-
return [];
|
|
7802
|
-
const enriched = data.highlighted.map((item) => enrichBasketItem(item, perpMetaAssets));
|
|
7803
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7804
|
-
}, [data, perpMetaAssets, collateralFilter]);
|
|
6902
|
+
return (_a = data === null || data === void 0 ? void 0 : data.highlighted) !== null && _a !== void 0 ? _a : [];
|
|
7805
6903
|
};
|
|
7806
|
-
// Watchlist baskets (
|
|
7807
|
-
const useWatchlistBaskets = (
|
|
6904
|
+
// Watchlist baskets (from market-data payload when subscribed with address)
|
|
6905
|
+
const useWatchlistBaskets = () => {
|
|
6906
|
+
var _a;
|
|
7808
6907
|
const data = useMarketDataPayload();
|
|
7809
|
-
|
|
7810
|
-
return useMemo(() => {
|
|
7811
|
-
if (!(data === null || data === void 0 ? void 0 : data.watchlist))
|
|
7812
|
-
return [];
|
|
7813
|
-
const enriched = data.watchlist.map((item) => enrichBasketItem(item, perpMetaAssets));
|
|
7814
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7815
|
-
}, [data, perpMetaAssets, collateralFilter]);
|
|
6908
|
+
return (_a = data === null || data === void 0 ? void 0 : data.watchlist) !== null && _a !== void 0 ? _a : [];
|
|
7816
6909
|
};
|
|
7817
|
-
// All baskets (
|
|
7818
|
-
const useAllBaskets = (
|
|
6910
|
+
// All baskets (from market-data-all)
|
|
6911
|
+
const useAllBaskets = () => {
|
|
6912
|
+
var _a;
|
|
7819
6913
|
const dataAll = useMarketDataAllPayload();
|
|
7820
|
-
|
|
7821
|
-
return useMemo(() => {
|
|
7822
|
-
if (!(dataAll === null || dataAll === void 0 ? void 0 : dataAll.all))
|
|
7823
|
-
return [];
|
|
7824
|
-
const enriched = dataAll.all.map((item) => enrichBasketItem(item, perpMetaAssets));
|
|
7825
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7826
|
-
}, [dataAll, perpMetaAssets, collateralFilter]);
|
|
6914
|
+
return (_a = dataAll === null || dataAll === void 0 ? void 0 : dataAll.all) !== null && _a !== void 0 ? _a : [];
|
|
7827
6915
|
};
|
|
7828
6916
|
// Find a basket by its exact asset composition (order-insensitive)
|
|
7829
6917
|
const useFindBasket = (longs, shorts) => {
|
|
7830
6918
|
const data = useMarketDataPayload();
|
|
7831
|
-
const perpMetaAssets = usePerpMetaAssets();
|
|
7832
6919
|
return useMemo(() => {
|
|
7833
6920
|
if (!data)
|
|
7834
6921
|
return undefined;
|
|
@@ -7842,28 +6929,17 @@ const useFindBasket = (longs, shorts) => {
|
|
|
7842
6929
|
: '';
|
|
7843
6930
|
const lKey = normalize(longs);
|
|
7844
6931
|
const sKey = normalize(shorts);
|
|
7845
|
-
const match = (item) => normalize(item.longAssets) === lKey &&
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
return found
|
|
7849
|
-
? enrichBasketItem(found, perpMetaAssets)
|
|
7850
|
-
: undefined;
|
|
7851
|
-
}, [data, longs, shorts, perpMetaAssets]);
|
|
6932
|
+
const match = (item) => normalize(item.longAssets) === lKey && normalize(item.shortAssets) === sKey;
|
|
6933
|
+
return data.active.find(match) || data.highlighted.find(match);
|
|
6934
|
+
}, [data, longs, shorts]);
|
|
7852
6935
|
};
|
|
7853
6936
|
|
|
7854
|
-
async function toggleWatchlist(baseUrl, longAssets, shortAssets,
|
|
6937
|
+
async function toggleWatchlist(baseUrl, longAssets, shortAssets, displayToFull) {
|
|
7855
6938
|
const url = joinUrl(baseUrl, '/watchlist');
|
|
7856
|
-
const mapAssets = (arr) => arr.map(
|
|
6939
|
+
const mapAssets = (arr) => arr.map(a => ({ ...a, asset: toBackendSymbol(a.asset, displayToFull) }));
|
|
7857
6940
|
try {
|
|
7858
|
-
const response = await apiClient.post(url, {
|
|
7859
|
-
|
|
7860
|
-
shortAssets: mapAssets(shortAssets),
|
|
7861
|
-
}, { headers: { 'Content-Type': 'application/json' } });
|
|
7862
|
-
return {
|
|
7863
|
-
data: response.data,
|
|
7864
|
-
status: response.status,
|
|
7865
|
-
headers: response.headers,
|
|
7866
|
-
};
|
|
6941
|
+
const response = await apiClient.post(url, { longAssets: mapAssets(longAssets), shortAssets: mapAssets(shortAssets) }, { headers: { 'Content-Type': 'application/json' } });
|
|
6942
|
+
return { data: response.data, status: response.status, headers: response.headers };
|
|
7867
6943
|
}
|
|
7868
6944
|
catch (error) {
|
|
7869
6945
|
throw toApiError(error);
|
|
@@ -7875,11 +6951,11 @@ function useWatchlist() {
|
|
|
7875
6951
|
if (!context)
|
|
7876
6952
|
throw new Error('useWatchlist must be used within a PearHyperliquidProvider');
|
|
7877
6953
|
const { apiBaseUrl, isConnected } = context;
|
|
7878
|
-
const
|
|
6954
|
+
const displayToFull = useHyperliquidData((s) => s.hip3DisplayToFull);
|
|
7879
6955
|
const marketData = useMarketDataPayload();
|
|
7880
6956
|
const isLoading = useMemo(() => !marketData && isConnected, [marketData, isConnected]);
|
|
7881
6957
|
const toggle = async (longAssets, shortAssets) => {
|
|
7882
|
-
const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets,
|
|
6958
|
+
const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets, displayToFull);
|
|
7883
6959
|
// Server will push updated market-data over WS; nothing to set here
|
|
7884
6960
|
return resp;
|
|
7885
6961
|
};
|
|
@@ -8133,48 +7209,16 @@ function useAuth() {
|
|
|
8133
7209
|
};
|
|
8134
7210
|
}
|
|
8135
7211
|
|
|
8136
|
-
const useSpotBalances = () => {
|
|
8137
|
-
const spotState = useUserData((state) => state.spotState);
|
|
8138
|
-
return useMemo(() => {
|
|
8139
|
-
if (!spotState) {
|
|
8140
|
-
return {
|
|
8141
|
-
usdhBalance: undefined,
|
|
8142
|
-
spotUsdcBalance: undefined,
|
|
8143
|
-
isLoading: true,
|
|
8144
|
-
};
|
|
8145
|
-
}
|
|
8146
|
-
const balances = spotState.balances || [];
|
|
8147
|
-
let usdhBal = 0;
|
|
8148
|
-
let spotUsdcBal = 0;
|
|
8149
|
-
for (const balance of balances) {
|
|
8150
|
-
const total = parseFloat(balance.total || '0');
|
|
8151
|
-
if (balance.coin === 'USDH') {
|
|
8152
|
-
usdhBal = total;
|
|
8153
|
-
}
|
|
8154
|
-
if (balance.coin === 'USDC') {
|
|
8155
|
-
spotUsdcBal = total;
|
|
8156
|
-
}
|
|
8157
|
-
}
|
|
8158
|
-
return {
|
|
8159
|
-
usdhBalance: usdhBal,
|
|
8160
|
-
spotUsdcBalance: spotUsdcBal,
|
|
8161
|
-
isLoading: false,
|
|
8162
|
-
};
|
|
8163
|
-
}, [spotState]);
|
|
8164
|
-
};
|
|
8165
|
-
|
|
8166
7212
|
const PearHyperliquidContext = createContext(undefined);
|
|
8167
7213
|
/**
|
|
8168
7214
|
* React Provider for PearHyperliquidClient
|
|
8169
7215
|
*/
|
|
8170
|
-
const PearHyperliquidProvider = ({ children, apiBaseUrl =
|
|
7216
|
+
const PearHyperliquidProvider = ({ children, apiBaseUrl = "https://hl-ui.pearprotocol.io", clientId = "PEARPROTOCOLUI", wsUrl = "wss://hl-ui.pearprotocol.io/ws", }) => {
|
|
8171
7217
|
const address = useUserData((s) => s.address);
|
|
8172
7218
|
const setAddress = useUserData((s) => s.setAddress);
|
|
8173
7219
|
const perpsMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
|
|
8174
7220
|
const setPerpMetaAssets = useHyperliquidData((state) => state.setPerpMetaAssets);
|
|
8175
|
-
const
|
|
8176
|
-
const setHip3Assets = useHyperliquidData((state) => state.setHip3Assets);
|
|
8177
|
-
const setHip3MarketPrefixes = useHyperliquidData((state) => state.setHip3MarketPrefixes);
|
|
7221
|
+
const setHip3DisplayToFull = useHyperliquidData((state) => state.setHip3DisplayToFull);
|
|
8178
7222
|
const websocketsEnabled = useMemo(() => Array.isArray(perpsMetaAssets) && perpsMetaAssets.length > 0, [perpsMetaAssets]);
|
|
8179
7223
|
const { isConnected, lastError } = useHyperliquidWebSocket({
|
|
8180
7224
|
wsUrl,
|
|
@@ -8189,65 +7233,32 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearpro
|
|
|
8189
7233
|
if (perpsMetaAssets === null) {
|
|
8190
7234
|
fetchAllPerpMetas()
|
|
8191
7235
|
.then((res) => {
|
|
8192
|
-
|
|
8193
|
-
const
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
const
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
assetToMarkets.set(displayName, [
|
|
8211
|
-
...existingMarkets,
|
|
8212
|
-
fullName,
|
|
8213
|
-
]);
|
|
8214
|
-
}
|
|
8215
|
-
}
|
|
8216
|
-
const assetWithMeta = {
|
|
8217
|
-
...asset,
|
|
8218
|
-
name: displayName,
|
|
8219
|
-
marketPrefix: prefix,
|
|
8220
|
-
collateralToken,
|
|
8221
|
-
};
|
|
8222
|
-
allPerpMetas.push(assetWithMeta);
|
|
8223
|
-
if (!FILTERED_PREFIXES.includes(prefix)) {
|
|
8224
|
-
cleanedPerpMetas.push(assetWithMeta);
|
|
8225
|
-
}
|
|
8226
|
-
}
|
|
8227
|
-
else {
|
|
8228
|
-
const assetWithMeta = {
|
|
8229
|
-
...asset,
|
|
8230
|
-
collateralToken,
|
|
8231
|
-
};
|
|
8232
|
-
cleanedPerpMetas.push(assetWithMeta);
|
|
8233
|
-
allPerpMetas.push(assetWithMeta);
|
|
8234
|
-
}
|
|
8235
|
-
});
|
|
7236
|
+
// Only show HL and XYZ for now as other are using USDH collateral and need more work
|
|
7237
|
+
const aggregatedPerpMetas = res.data
|
|
7238
|
+
.slice(0, 2)
|
|
7239
|
+
.flatMap((item) => item.universe);
|
|
7240
|
+
const hip3Map = new Map();
|
|
7241
|
+
const displayToFull = new Map();
|
|
7242
|
+
const cleanedPerpMetas = aggregatedPerpMetas.map((asset) => {
|
|
7243
|
+
var _a;
|
|
7244
|
+
const [maybePrefix, maybeMarket] = asset.name.split(":");
|
|
7245
|
+
if (maybeMarket) {
|
|
7246
|
+
const prefix = maybePrefix.toLowerCase();
|
|
7247
|
+
const market = maybeMarket;
|
|
7248
|
+
const existing = (_a = hip3Map.get(prefix)) !== null && _a !== void 0 ? _a : [];
|
|
7249
|
+
hip3Map.set(prefix, [...existing, market]);
|
|
7250
|
+
displayToFull.set(market, `${prefix}:${market}`);
|
|
7251
|
+
return { ...asset, name: market };
|
|
7252
|
+
}
|
|
7253
|
+
return asset;
|
|
8236
7254
|
});
|
|
8237
|
-
|
|
8238
|
-
setHip3MarketPrefixes(marketPrefixes);
|
|
7255
|
+
setHip3DisplayToFull(displayToFull);
|
|
8239
7256
|
setPerpMetaAssets(cleanedPerpMetas);
|
|
8240
|
-
setAllPerpMetaAssets(allPerpMetas);
|
|
8241
7257
|
})
|
|
8242
7258
|
.catch(() => { });
|
|
8243
7259
|
}
|
|
8244
|
-
}, [
|
|
8245
|
-
|
|
8246
|
-
setPerpMetaAssets,
|
|
8247
|
-
setAllPerpMetaAssets,
|
|
8248
|
-
setHip3Assets,
|
|
8249
|
-
setHip3MarketPrefixes,
|
|
8250
|
-
]);
|
|
7260
|
+
}, [perpsMetaAssets, setPerpMetaAssets, setHip3DisplayToFull]);
|
|
7261
|
+
// Auth methods now sourced from useAuth hook
|
|
8251
7262
|
useAutoSyncFills({
|
|
8252
7263
|
baseUrl: apiBaseUrl,
|
|
8253
7264
|
address,
|
|
@@ -8285,7 +7296,7 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearpro
|
|
|
8285
7296
|
function usePearHyperliquid() {
|
|
8286
7297
|
const ctx = useContext(PearHyperliquidContext);
|
|
8287
7298
|
if (!ctx)
|
|
8288
|
-
throw new Error(
|
|
7299
|
+
throw new Error("usePearHyperliquid must be used within a PearHyperliquidProvider");
|
|
8289
7300
|
return ctx;
|
|
8290
7301
|
}
|
|
8291
7302
|
|
|
@@ -8376,4 +7387,4 @@ function mapCandleIntervalToTradingViewInterval(interval) {
|
|
|
8376
7387
|
}
|
|
8377
7388
|
}
|
|
8378
7389
|
|
|
8379
|
-
export { AccountSummaryCalculator, ConflictDetector, MAX_ASSETS_PER_LEG, MINIMUM_ASSET_USD_VALUE, MaxAssetsPerLegError, MinimumPositionSizeError, PearHyperliquidProvider, TokenMetadataExtractor, adjustAdvancePosition, adjustOrder, adjustPosition, calculateMinimumPositionValue, calculateWeightedRatio, cancelOrder, cancelTwap, cancelTwapOrder, closeAllPositions, closePosition, computeBasketCandles, createCandleLookups, createPosition,
|
|
7390
|
+
export { AccountSummaryCalculator, ConflictDetector, MAX_ASSETS_PER_LEG, MINIMUM_ASSET_USD_VALUE, MaxAssetsPerLegError, MinimumPositionSizeError, PearHyperliquidProvider, TokenMetadataExtractor, adjustAdvancePosition, adjustOrder, adjustPosition, calculateMinimumPositionValue, calculateWeightedRatio, cancelOrder, cancelTwap, cancelTwapOrder, closeAllPositions, closePosition, computeBasketCandles, createCandleLookups, createPosition, getCompleteTimestamps, getPortfolio, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, toggleWatchlist, updateRiskParameters, useAccountSummary, useActiveBaskets, useAgentWallet, useAllBaskets, useAuth, useAutoSyncFills, useBasketCandles, useFindBasket, useHighlightedBaskets, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidNativeWebSocket, useHyperliquidWebSocket, useMarketData, useMarketDataAllPayload, useMarketDataPayload, useNotifications, useOpenOrders, useOrders, usePearHyperliquid, usePerformanceOverlays, usePortfolio, usePosition, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWatchlist, useWatchlistBaskets, useWebData, validateMaxAssetsPerLeg, validateMinimumAssetSize, validatePositionSize };
|