@pear-protocol/hyperliquid-sdk 0.0.8 → 0.0.9
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/hooks/useCalculatedPositions.d.ts +2 -2
- package/dist/index.d.ts +32 -89
- package/dist/index.esm.js +152 -248
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +153 -250
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +2 -2
- package/dist/types.d.ts +29 -5
- package/dist/utils/position-processor.d.ts +22 -0
- package/dist/websocket.d.ts +2 -2
- package/package.json +1 -1
- package/dist/utils/aggregate-position-calculator.d.ts +0 -81
package/dist/index.esm.js
CHANGED
|
@@ -2743,8 +2743,8 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2743
2743
|
shouldReconnect: () => true,
|
|
2744
2744
|
reconnectAttempts: 5,
|
|
2745
2745
|
reconnectInterval: 3000,
|
|
2746
|
-
onOpen: () =>
|
|
2747
|
-
onClose: () =>
|
|
2746
|
+
onOpen: () => { },
|
|
2747
|
+
onClose: () => { },
|
|
2748
2748
|
onError: (event) => console.error('[HyperLiquid WS] Connection error:', event),
|
|
2749
2749
|
onReconnectStop: () => console.error('[HyperLiquid WS] Reconnection stopped after 5 attempts'),
|
|
2750
2750
|
});
|
|
@@ -2752,16 +2752,13 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2752
2752
|
// Setup ping mechanism
|
|
2753
2753
|
useEffect(() => {
|
|
2754
2754
|
if (isConnected) {
|
|
2755
|
-
console.log('[HyperLiquid WS] Setting up ping mechanism (30s interval)');
|
|
2756
2755
|
// Send ping every 30 seconds
|
|
2757
2756
|
pingIntervalRef.current = setInterval(() => {
|
|
2758
|
-
console.log('[HyperLiquid WS] Sending ping');
|
|
2759
2757
|
sendJsonMessage({ method: 'ping' });
|
|
2760
2758
|
}, 30000);
|
|
2761
2759
|
}
|
|
2762
2760
|
else {
|
|
2763
2761
|
if (pingIntervalRef.current) {
|
|
2764
|
-
console.log('[HyperLiquid WS] Clearing ping interval');
|
|
2765
2762
|
clearInterval(pingIntervalRef.current);
|
|
2766
2763
|
pingIntervalRef.current = null;
|
|
2767
2764
|
}
|
|
@@ -2783,7 +2780,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2783
2780
|
return;
|
|
2784
2781
|
// Unsubscribe from previous address if exists
|
|
2785
2782
|
if (subscribedAddress) {
|
|
2786
|
-
console.log(`[HyperLiquid WS] Unsubscribing from webData2 for previous address: ${subscribedAddress}`);
|
|
2787
2783
|
const unsubscribeMessage = {
|
|
2788
2784
|
method: 'unsubscribe',
|
|
2789
2785
|
subscription: {
|
|
@@ -2794,7 +2790,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2794
2790
|
sendJsonMessage(unsubscribeMessage);
|
|
2795
2791
|
}
|
|
2796
2792
|
// Subscribe to webData2 with new address
|
|
2797
|
-
console.log(`[HyperLiquid WS] Subscribing to webData2 for address: ${userAddress}`);
|
|
2798
2793
|
const subscribeWebData2 = {
|
|
2799
2794
|
method: 'subscribe',
|
|
2800
2795
|
subscription: {
|
|
@@ -2803,7 +2798,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2803
2798
|
},
|
|
2804
2799
|
};
|
|
2805
2800
|
// Subscribe to allMids
|
|
2806
|
-
console.log('[HyperLiquid WS] Subscribing to allMids');
|
|
2807
2801
|
const subscribeAllMids = {
|
|
2808
2802
|
method: 'subscribe',
|
|
2809
2803
|
subscription: {
|
|
@@ -2815,7 +2809,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2815
2809
|
setSubscribedAddress(userAddress);
|
|
2816
2810
|
// Clear previous data when address changes
|
|
2817
2811
|
if (subscribedAddress && subscribedAddress !== userAddress) {
|
|
2818
|
-
console.log('[HyperLiquid WS] Address changed, clearing previous webData2');
|
|
2819
2812
|
setWebData2(null);
|
|
2820
2813
|
}
|
|
2821
2814
|
}, [isConnected, address, subscribedAddress, sendJsonMessage]);
|
|
@@ -2825,7 +2818,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2825
2818
|
return;
|
|
2826
2819
|
try {
|
|
2827
2820
|
const message = JSON.parse(lastMessage.data);
|
|
2828
|
-
console.log('[HyperLiquid WS] Received message:', message);
|
|
2829
2821
|
// Handle subscription responses
|
|
2830
2822
|
if ('success' in message || 'error' in message) {
|
|
2831
2823
|
if (message.error) {
|
|
@@ -2833,7 +2825,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2833
2825
|
setLastError(message.error);
|
|
2834
2826
|
}
|
|
2835
2827
|
else {
|
|
2836
|
-
console.log('[HyperLiquid WS] Subscription success:', message);
|
|
2837
2828
|
setLastError(null);
|
|
2838
2829
|
}
|
|
2839
2830
|
return;
|
|
@@ -2841,14 +2832,11 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2841
2832
|
// Handle channel data messages
|
|
2842
2833
|
if ('channel' in message && 'data' in message) {
|
|
2843
2834
|
const response = message;
|
|
2844
|
-
console.log(`[HyperLiquid WS] Received ${response.channel} data`);
|
|
2845
2835
|
switch (response.channel) {
|
|
2846
2836
|
case 'webData2':
|
|
2847
|
-
console.log('[HyperLiquid WS] Setting webData2:', response.data);
|
|
2848
2837
|
setWebData2(response.data);
|
|
2849
2838
|
break;
|
|
2850
2839
|
case 'allMids':
|
|
2851
|
-
console.log('[HyperLiquid WS] Setting allMids:', response.data);
|
|
2852
2840
|
setAllMids(response.data);
|
|
2853
2841
|
break;
|
|
2854
2842
|
default:
|
|
@@ -2949,84 +2937,76 @@ const useAddress = () => {
|
|
|
2949
2937
|
};
|
|
2950
2938
|
};
|
|
2951
2939
|
|
|
2952
|
-
/**
|
|
2953
|
-
* Position side enum for calculations
|
|
2954
|
-
*/
|
|
2955
2940
|
var PositionSide;
|
|
2956
2941
|
(function (PositionSide) {
|
|
2957
2942
|
PositionSide["LONG"] = "LONG";
|
|
2958
2943
|
PositionSide["SHORT"] = "SHORT";
|
|
2959
2944
|
})(PositionSide || (PositionSide = {}));
|
|
2960
|
-
|
|
2961
|
-
* Aggregate position calculation utility class that handles cross-position asset syncing
|
|
2962
|
-
*/
|
|
2963
|
-
class AggregatePositionCalculator {
|
|
2945
|
+
class PositionProcessor {
|
|
2964
2946
|
constructor(webData2, allMids) {
|
|
2965
2947
|
this.webData2 = webData2;
|
|
2966
2948
|
this.allMids = allMids;
|
|
2967
2949
|
}
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2950
|
+
execute(rawPositions) {
|
|
2951
|
+
if (!rawPositions || rawPositions.length === 0) {
|
|
2952
|
+
return [];
|
|
2953
|
+
}
|
|
2954
|
+
const userHyperliquidPositions = this.getUserPositions();
|
|
2955
|
+
const platformTotalsByAsset = this.calculatePlatformTotalsByAsset(rawPositions);
|
|
2956
|
+
const hlPositionsMap = new Map();
|
|
2957
|
+
(userHyperliquidPositions || []).forEach(assetPos => {
|
|
2958
|
+
var _a;
|
|
2959
|
+
if ((_a = assetPos.position) === null || _a === void 0 ? void 0 : _a.coin) {
|
|
2960
|
+
hlPositionsMap.set(assetPos.position.coin, assetPos);
|
|
2961
|
+
}
|
|
2962
|
+
});
|
|
2963
|
+
const openPositionDtos = [];
|
|
2964
|
+
for (const position of rawPositions) {
|
|
2965
|
+
const syncedPositionDto = this.syncPositionWithAggregateData(position, hlPositionsMap, platformTotalsByAsset);
|
|
2966
|
+
openPositionDtos.push(syncedPositionDto);
|
|
2967
|
+
}
|
|
2968
|
+
return openPositionDtos;
|
|
2969
|
+
}
|
|
2970
|
+
getUserPositions() {
|
|
2971
|
+
var _a, _b;
|
|
2972
|
+
return ((_b = (_a = this.webData2) === null || _a === void 0 ? void 0 : _a.clearinghouseState) === null || _b === void 0 ? void 0 : _b.assetPositions) || [];
|
|
2973
|
+
}
|
|
2971
2974
|
getMarketPrice(coin) {
|
|
2972
2975
|
var _a;
|
|
2973
2976
|
if (!((_a = this.allMids) === null || _a === void 0 ? void 0 : _a.mids))
|
|
2974
2977
|
return 0;
|
|
2975
|
-
// Try exact match first
|
|
2976
2978
|
const exactPrice = this.allMids.mids[coin];
|
|
2977
2979
|
if (exactPrice) {
|
|
2978
2980
|
return Number(exactPrice);
|
|
2979
2981
|
}
|
|
2980
|
-
|
|
2981
|
-
const baseCurrency = coin.split('/')[0];
|
|
2982
|
+
const baseCurrency = this.extractBaseCurrency(coin);
|
|
2982
2983
|
const basePrice = this.allMids.mids[baseCurrency];
|
|
2983
2984
|
if (basePrice) {
|
|
2984
2985
|
return Number(basePrice);
|
|
2985
2986
|
}
|
|
2986
|
-
console.warn(`[AggregatePositionCalculator] No market price found for coin: ${coin}`);
|
|
2987
2987
|
return 0;
|
|
2988
2988
|
}
|
|
2989
|
-
/**
|
|
2990
|
-
* Get user positions from webData2
|
|
2991
|
-
*/
|
|
2992
|
-
getUserPositions() {
|
|
2993
|
-
var _a, _b;
|
|
2994
|
-
return ((_b = (_a = this.webData2) === null || _a === void 0 ? void 0 : _a.clearinghouseState) === null || _b === void 0 ? void 0 : _b.assetPositions) || [];
|
|
2995
|
-
}
|
|
2996
|
-
/**
|
|
2997
|
-
* Calculate updated open positions by syncing platform positions with HyperLiquid data
|
|
2998
|
-
* Uses aggregate totals across all positions for accurate cross-position sync
|
|
2999
|
-
*/
|
|
3000
|
-
calculateOpenPositions(platformPositions) {
|
|
3001
|
-
if (!(platformPositions === null || platformPositions === void 0 ? void 0 : platformPositions.length)) {
|
|
3002
|
-
return [];
|
|
3003
|
-
}
|
|
3004
|
-
const hyperliquidPositions = this.getUserPositions();
|
|
3005
|
-
// Build a map of total platform sizes per asset across ALL positions
|
|
3006
|
-
const platformTotalsByAsset = this.calculatePlatformTotalsByAsset(platformPositions);
|
|
3007
|
-
// Create a map of HyperLiquid positions by coin
|
|
3008
|
-
const hlPositionsMap = new Map();
|
|
3009
|
-
hyperliquidPositions.forEach(assetPos => {
|
|
3010
|
-
var _a;
|
|
3011
|
-
if ((_a = assetPos.position) === null || _a === void 0 ? void 0 : _a.coin) {
|
|
3012
|
-
hlPositionsMap.set(assetPos.position.coin, assetPos);
|
|
3013
|
-
}
|
|
3014
|
-
});
|
|
3015
|
-
// Process each position with awareness of the aggregated totals
|
|
3016
|
-
return platformPositions.map(position => this.syncPositionWithAggregateData(position, hlPositionsMap, platformTotalsByAsset));
|
|
3017
|
-
}
|
|
3018
|
-
/**
|
|
3019
|
-
* Calculate total platform sizes per asset across all positions
|
|
3020
|
-
*/
|
|
3021
2989
|
calculatePlatformTotalsByAsset(positions) {
|
|
3022
2990
|
const totalsMap = new Map();
|
|
3023
2991
|
for (const position of positions) {
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
2992
|
+
for (const asset of position.longAssets || []) {
|
|
2993
|
+
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
2994
|
+
if (!totalsMap.has(baseCurrency)) {
|
|
2995
|
+
totalsMap.set(baseCurrency, {
|
|
2996
|
+
totalSize: 0,
|
|
2997
|
+
positions: []
|
|
2998
|
+
});
|
|
2999
|
+
}
|
|
3000
|
+
const totals = totalsMap.get(baseCurrency);
|
|
3001
|
+
const assetSize = Number(asset.size || 0);
|
|
3002
|
+
totals.totalSize += assetSize;
|
|
3003
|
+
totals.positions.push({
|
|
3004
|
+
positionId: position.positionId,
|
|
3005
|
+
asset: asset,
|
|
3006
|
+
size: assetSize
|
|
3007
|
+
});
|
|
3008
|
+
}
|
|
3009
|
+
for (const asset of position.shortAssets || []) {
|
|
3030
3010
|
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3031
3011
|
if (!totalsMap.has(baseCurrency)) {
|
|
3032
3012
|
totalsMap.set(baseCurrency, {
|
|
@@ -3035,7 +3015,7 @@ class AggregatePositionCalculator {
|
|
|
3035
3015
|
});
|
|
3036
3016
|
}
|
|
3037
3017
|
const totals = totalsMap.get(baseCurrency);
|
|
3038
|
-
const assetSize = asset.
|
|
3018
|
+
const assetSize = Number(asset.size || 0);
|
|
3039
3019
|
totals.totalSize += assetSize;
|
|
3040
3020
|
totals.positions.push({
|
|
3041
3021
|
positionId: position.positionId,
|
|
@@ -3046,47 +3026,44 @@ class AggregatePositionCalculator {
|
|
|
3046
3026
|
}
|
|
3047
3027
|
return totalsMap;
|
|
3048
3028
|
}
|
|
3049
|
-
/**
|
|
3050
|
-
* Extract base currency from asset name (handles "LINK/USD" -> "LINK")
|
|
3051
|
-
*/
|
|
3052
3029
|
extractBaseCurrency(assetName) {
|
|
3053
3030
|
return assetName.split('/')[0] || assetName;
|
|
3054
3031
|
}
|
|
3055
|
-
/**
|
|
3056
|
-
* Sync a single position with HyperLiquid data using aggregate totals
|
|
3057
|
-
*/
|
|
3058
3032
|
syncPositionWithAggregateData(position, hlPositionsMap, platformTotalsByAsset) {
|
|
3059
3033
|
const syncResults = [];
|
|
3060
3034
|
let hasExternalModification = false;
|
|
3061
3035
|
let allAssetsClosed = true;
|
|
3062
|
-
// Separate tracking for long and short sides
|
|
3063
3036
|
let longAssetStatuses = { total: 0, closed: 0 };
|
|
3064
3037
|
let shortAssetStatuses = { total: 0, closed: 0 };
|
|
3065
|
-
// Process
|
|
3066
|
-
const
|
|
3067
|
-
...position.longAssets.map(asset => ({ ...asset, side: PositionSide.LONG })),
|
|
3068
|
-
...position.shortAssets.map(asset => ({ ...asset, side: PositionSide.SHORT }))
|
|
3069
|
-
];
|
|
3070
|
-
for (const asset of allAssets) {
|
|
3038
|
+
// Process long assets
|
|
3039
|
+
for (const asset of position.longAssets || []) {
|
|
3071
3040
|
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3072
3041
|
const hlPosition = hlPositionsMap.get(baseCurrency);
|
|
3073
3042
|
const platformTotals = platformTotalsByAsset.get(baseCurrency);
|
|
3074
|
-
const syncResult = this.syncAssetWithAggregateData(asset, hlPosition, (platformTotals === null || platformTotals === void 0 ? void 0 : platformTotals.totalSize) || 0);
|
|
3043
|
+
const syncResult = this.syncAssetWithAggregateData({ ...asset, side: PositionSide.LONG }, hlPosition, (platformTotals === null || platformTotals === void 0 ? void 0 : platformTotals.totalSize) || 0);
|
|
3075
3044
|
syncResults.push(syncResult);
|
|
3076
|
-
|
|
3077
|
-
if (
|
|
3078
|
-
longAssetStatuses.
|
|
3079
|
-
if (syncResult.actualSize === 0) {
|
|
3080
|
-
longAssetStatuses.closed++;
|
|
3081
|
-
}
|
|
3045
|
+
longAssetStatuses.total++;
|
|
3046
|
+
if (syncResult.actualSize === 0) {
|
|
3047
|
+
longAssetStatuses.closed++;
|
|
3082
3048
|
}
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3049
|
+
if (syncResult.isExternallyModified) {
|
|
3050
|
+
hasExternalModification = true;
|
|
3051
|
+
}
|
|
3052
|
+
if (syncResult.actualSize !== 0) {
|
|
3053
|
+
allAssetsClosed = false;
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
// Process short assets
|
|
3057
|
+
for (const asset of position.shortAssets || []) {
|
|
3058
|
+
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3059
|
+
const hlPosition = hlPositionsMap.get(baseCurrency);
|
|
3060
|
+
const platformTotals = platformTotalsByAsset.get(baseCurrency);
|
|
3061
|
+
const syncResult = this.syncAssetWithAggregateData({ ...asset, side: PositionSide.SHORT }, hlPosition, (platformTotals === null || platformTotals === void 0 ? void 0 : platformTotals.totalSize) || 0);
|
|
3062
|
+
syncResults.push(syncResult);
|
|
3063
|
+
shortAssetStatuses.total++;
|
|
3064
|
+
if (syncResult.actualSize === 0) {
|
|
3065
|
+
shortAssetStatuses.closed++;
|
|
3088
3066
|
}
|
|
3089
|
-
// Update flags
|
|
3090
3067
|
if (syncResult.isExternallyModified) {
|
|
3091
3068
|
hasExternalModification = true;
|
|
3092
3069
|
}
|
|
@@ -3094,17 +3071,27 @@ class AggregatePositionCalculator {
|
|
|
3094
3071
|
allAssetsClosed = false;
|
|
3095
3072
|
}
|
|
3096
3073
|
}
|
|
3097
|
-
// Determine sync status
|
|
3098
3074
|
const syncStatus = this.determineSyncStatus(hasExternalModification, allAssetsClosed, longAssetStatuses, shortAssetStatuses);
|
|
3099
|
-
return this.
|
|
3075
|
+
return this.mapPositionToDtoWithSyncData(position, syncResults, syncStatus);
|
|
3076
|
+
}
|
|
3077
|
+
determineSyncStatus(hasExternalModification, allAssetsClosed, longAssetStatuses, shortAssetStatuses) {
|
|
3078
|
+
if (allAssetsClosed) {
|
|
3079
|
+
return 'EXTERNALLY_CLOSED';
|
|
3080
|
+
}
|
|
3081
|
+
const allLongsClosed = longAssetStatuses.total > 0 &&
|
|
3082
|
+
longAssetStatuses.closed === longAssetStatuses.total;
|
|
3083
|
+
const allShortsClosed = shortAssetStatuses.total > 0 &&
|
|
3084
|
+
shortAssetStatuses.closed === shortAssetStatuses.total;
|
|
3085
|
+
if ((allLongsClosed && !allShortsClosed) || (!allLongsClosed && allShortsClosed)) {
|
|
3086
|
+
return 'PAIR_BROKEN';
|
|
3087
|
+
}
|
|
3088
|
+
if (hasExternalModification) {
|
|
3089
|
+
return 'EXTERNALLY_MODIFIED';
|
|
3090
|
+
}
|
|
3091
|
+
return 'SYNCED';
|
|
3100
3092
|
}
|
|
3101
|
-
/**
|
|
3102
|
-
* Sync individual asset with aggregate data awareness
|
|
3103
|
-
*/
|
|
3104
3093
|
syncAssetWithAggregateData(asset, hlPosition, platformTotal) {
|
|
3105
|
-
|
|
3106
|
-
const platformSize = asset.platformSize;
|
|
3107
|
-
// No position on HyperLiquid - asset was closed
|
|
3094
|
+
const platformSize = Number(asset.size || 0);
|
|
3108
3095
|
if (!hlPosition || !hlPosition.position || !hlPosition.position.szi) {
|
|
3109
3096
|
return {
|
|
3110
3097
|
asset,
|
|
@@ -3112,27 +3099,23 @@ class AggregatePositionCalculator {
|
|
|
3112
3099
|
isExternallyModified: true,
|
|
3113
3100
|
cumFunding: { allTime: 0, sinceChange: 0, sinceOpen: 0 },
|
|
3114
3101
|
unrealizedPnl: 0,
|
|
3115
|
-
liquidationPrice: 0
|
|
3116
|
-
side: asset.side
|
|
3102
|
+
liquidationPrice: 0
|
|
3117
3103
|
};
|
|
3118
3104
|
}
|
|
3119
3105
|
const hlTotalSize = Math.abs(Number(hlPosition.position.szi || 0));
|
|
3120
|
-
// Check if the TOTAL platform size matches HyperLiquid total
|
|
3121
3106
|
const totalDifference = Math.abs(hlTotalSize - platformTotal);
|
|
3122
|
-
const tolerance = platformTotal * 0.001;
|
|
3107
|
+
const tolerance = platformTotal * 0.001;
|
|
3123
3108
|
const isExternallyModified = totalDifference > tolerance;
|
|
3124
|
-
// Calculate this position's proportional share of the HyperLiquid position
|
|
3125
3109
|
const proportion = platformTotal > 0 ? platformSize / platformTotal : 0;
|
|
3126
3110
|
const actualSize = hlTotalSize * proportion;
|
|
3127
|
-
//
|
|
3111
|
+
// Get cumFunding from hlPosition.position.cumFunding
|
|
3112
|
+
const rawCumFunding = hlPosition.position.cumFunding;
|
|
3128
3113
|
const cumFunding = {
|
|
3129
|
-
allTime: Number((
|
|
3130
|
-
sinceChange: Number((
|
|
3131
|
-
sinceOpen: Number((
|
|
3114
|
+
allTime: Number((rawCumFunding === null || rawCumFunding === void 0 ? void 0 : rawCumFunding.allTime) || 0),
|
|
3115
|
+
sinceChange: Number((rawCumFunding === null || rawCumFunding === void 0 ? void 0 : rawCumFunding.sinceChange) || 0) * proportion,
|
|
3116
|
+
sinceOpen: Number((rawCumFunding === null || rawCumFunding === void 0 ? void 0 : rawCumFunding.sinceOpen) || 0) * proportion
|
|
3132
3117
|
};
|
|
3133
|
-
// Distribute PnL proportionally
|
|
3134
3118
|
const unrealizedPnl = Number(hlPosition.position.unrealizedPnl || 0) * proportion;
|
|
3135
|
-
// Liquidation price is the same for all positions of the same asset
|
|
3136
3119
|
const liquidationPrice = Number(hlPosition.position.liquidationPx || 0);
|
|
3137
3120
|
return {
|
|
3138
3121
|
asset,
|
|
@@ -3140,46 +3123,27 @@ class AggregatePositionCalculator {
|
|
|
3140
3123
|
isExternallyModified,
|
|
3141
3124
|
cumFunding,
|
|
3142
3125
|
unrealizedPnl,
|
|
3143
|
-
liquidationPrice
|
|
3144
|
-
side: asset.side
|
|
3126
|
+
liquidationPrice
|
|
3145
3127
|
};
|
|
3146
3128
|
}
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
}
|
|
3155
|
-
// Check if pair is broken (one entire side closed)
|
|
3156
|
-
const allLongsClosed = longAssetStatuses.total > 0 &&
|
|
3157
|
-
longAssetStatuses.closed === longAssetStatuses.total;
|
|
3158
|
-
const allShortsClosed = shortAssetStatuses.total > 0 &&
|
|
3159
|
-
shortAssetStatuses.closed === shortAssetStatuses.total;
|
|
3160
|
-
if ((allLongsClosed && !allShortsClosed) || (!allLongsClosed && allShortsClosed)) {
|
|
3161
|
-
return 'PAIR_BROKEN';
|
|
3162
|
-
}
|
|
3163
|
-
// External modification detected
|
|
3164
|
-
if (hasExternalModification) {
|
|
3165
|
-
return 'EXTERNALLY_MODIFIED';
|
|
3166
|
-
}
|
|
3167
|
-
// Everything synced properly
|
|
3168
|
-
return 'SYNCED';
|
|
3169
|
-
}
|
|
3170
|
-
/**
|
|
3171
|
-
* Build updated position with synced data
|
|
3172
|
-
*/
|
|
3173
|
-
buildUpdatedPosition(originalPosition, syncResults, syncStatus) {
|
|
3174
|
-
const longSyncResults = syncResults.filter(result => result.side === PositionSide.LONG);
|
|
3175
|
-
const shortSyncResults = syncResults.filter(result => result.side === PositionSide.SHORT);
|
|
3176
|
-
// Calculate position metrics
|
|
3129
|
+
mapPositionToDtoWithSyncData(position, syncResults, syncStatus) {
|
|
3130
|
+
var _a, _b;
|
|
3131
|
+
const longAssets = ((_a = position.longAssets) === null || _a === void 0 ? void 0 : _a.filter(asset => asset)) || [];
|
|
3132
|
+
const shortAssets = ((_b = position.shortAssets) === null || _b === void 0 ? void 0 : _b.filter(asset => asset)) || [];
|
|
3133
|
+
const syncResultsMap = new Map();
|
|
3134
|
+
syncResults.forEach(result => {
|
|
3135
|
+
syncResultsMap.set(`${result.asset.coin}-${result.asset.side}`, result);
|
|
3136
|
+
});
|
|
3177
3137
|
const currentTotalPositionValue = this.calculateCurrentTotalPositionValue(syncResults);
|
|
3178
3138
|
const entryTotalPositionValue = this.calculateEntryTotalPositionValue(syncResults);
|
|
3179
|
-
const totalMarginUsed = entryTotalPositionValue /
|
|
3139
|
+
const totalMarginUsed = entryTotalPositionValue / position.leverage;
|
|
3180
3140
|
return {
|
|
3181
|
-
|
|
3182
|
-
|
|
3141
|
+
syncStatus: syncStatus,
|
|
3142
|
+
positionId: position.positionId,
|
|
3143
|
+
address: position.address,
|
|
3144
|
+
leverage: position.leverage,
|
|
3145
|
+
stopLoss: position.stopLoss,
|
|
3146
|
+
takeProfit: position.takeProfit,
|
|
3183
3147
|
entryRatio: this.calculateEntryRatio(syncResults),
|
|
3184
3148
|
markRatio: this.calculateMarkRatio(syncResults),
|
|
3185
3149
|
netFunding: this.calculateNetFundingFromSyncResults(syncResults),
|
|
@@ -3187,51 +3151,50 @@ class AggregatePositionCalculator {
|
|
|
3187
3151
|
marginUsed: totalMarginUsed,
|
|
3188
3152
|
unrealizedPnl: this.calculateTotalUnrealizedPnlFromSyncResults(syncResults),
|
|
3189
3153
|
lastSyncAt: new Date().toISOString(),
|
|
3190
|
-
longAssets:
|
|
3191
|
-
shortAssets:
|
|
3192
|
-
|
|
3154
|
+
longAssets: longAssets.map(asset => this.mapAssetToDetailDto(asset, syncResultsMap.get(`${asset.coin}-LONG`))),
|
|
3155
|
+
shortAssets: shortAssets.map(asset => this.mapAssetToDetailDto(asset, syncResultsMap.get(`${asset.coin}-SHORT`))),
|
|
3156
|
+
createdAt: position.createdAt,
|
|
3157
|
+
updatedAt: position.updatedAt
|
|
3193
3158
|
};
|
|
3194
3159
|
}
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
const
|
|
3200
|
-
const positionValue = syncResult.actualSize * currentPrice;
|
|
3201
|
-
const entryValue = syncResult.actualSize * syncResult.asset.entryPrice;
|
|
3160
|
+
mapAssetToDetailDto(asset, syncData) {
|
|
3161
|
+
const currentPrice = this.getMarketPrice(asset.coin);
|
|
3162
|
+
const actualSize = (syncData === null || syncData === void 0 ? void 0 : syncData.actualSize) || Number(asset.size || 0);
|
|
3163
|
+
const positionValue = actualSize * currentPrice;
|
|
3164
|
+
const entryValue = Number(asset.size || 0) * Number(asset.entryPrice || 0);
|
|
3202
3165
|
return {
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3166
|
+
coin: asset.coin,
|
|
3167
|
+
entryPrice: Number(asset.entryPrice || 0),
|
|
3168
|
+
platformSize: Number(asset.size || 0),
|
|
3169
|
+
actualSize: actualSize,
|
|
3170
|
+
isExternallyModified: (syncData === null || syncData === void 0 ? void 0 : syncData.isExternallyModified) || false,
|
|
3171
|
+
cumFunding: (syncData === null || syncData === void 0 ? void 0 : syncData.cumFunding) || {
|
|
3172
|
+
allTime: 0,
|
|
3173
|
+
sinceChange: 0,
|
|
3174
|
+
sinceOpen: 0
|
|
3175
|
+
},
|
|
3207
3176
|
marginUsed: entryValue,
|
|
3208
3177
|
positionValue: positionValue,
|
|
3209
|
-
unrealizedPnl:
|
|
3210
|
-
liquidationPrice:
|
|
3178
|
+
unrealizedPnl: (syncData === null || syncData === void 0 ? void 0 : syncData.unrealizedPnl) || 0,
|
|
3179
|
+
liquidationPrice: (syncData === null || syncData === void 0 ? void 0 : syncData.liquidationPrice) || 0
|
|
3211
3180
|
};
|
|
3212
3181
|
}
|
|
3213
|
-
/**
|
|
3214
|
-
* Calculate entry ratio using actual sizes from sync results
|
|
3215
|
-
*/
|
|
3216
3182
|
calculateEntryRatio(syncResults) {
|
|
3217
|
-
const longResults = syncResults.filter(result => result.side === PositionSide.LONG);
|
|
3218
|
-
const shortResults = syncResults.filter(result => result.side === PositionSide.SHORT);
|
|
3183
|
+
const longResults = syncResults.filter(result => result.asset.side === PositionSide.LONG);
|
|
3184
|
+
const shortResults = syncResults.filter(result => result.asset.side === PositionSide.SHORT);
|
|
3219
3185
|
if (longResults.length === 0 || shortResults.length === 0)
|
|
3220
3186
|
return 0;
|
|
3221
3187
|
const longValue = longResults.reduce((sum, result) => {
|
|
3222
|
-
return sum + (result.
|
|
3188
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3223
3189
|
}, 0);
|
|
3224
3190
|
const shortValue = shortResults.reduce((sum, result) => {
|
|
3225
|
-
return sum + (result.
|
|
3191
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3226
3192
|
}, 0);
|
|
3227
3193
|
return shortValue > 0 ? longValue / shortValue : 0;
|
|
3228
3194
|
}
|
|
3229
|
-
/**
|
|
3230
|
-
* Calculate mark ratio using actual sizes and current prices
|
|
3231
|
-
*/
|
|
3232
3195
|
calculateMarkRatio(syncResults) {
|
|
3233
|
-
const longResults = syncResults.filter(result => result.side === PositionSide.LONG);
|
|
3234
|
-
const shortResults = syncResults.filter(result => result.side === PositionSide.SHORT);
|
|
3196
|
+
const longResults = syncResults.filter(result => result.asset.side === PositionSide.LONG);
|
|
3197
|
+
const shortResults = syncResults.filter(result => result.asset.side === PositionSide.SHORT);
|
|
3235
3198
|
if (longResults.length === 0 || shortResults.length === 0)
|
|
3236
3199
|
return 0;
|
|
3237
3200
|
const longValue = longResults.reduce((sum, result) => {
|
|
@@ -3244,33 +3207,25 @@ class AggregatePositionCalculator {
|
|
|
3244
3207
|
}, 0);
|
|
3245
3208
|
return shortValue > 0 ? longValue / shortValue : 0;
|
|
3246
3209
|
}
|
|
3247
|
-
/**
|
|
3248
|
-
* Calculate net funding from sync results
|
|
3249
|
-
*/
|
|
3250
3210
|
calculateNetFundingFromSyncResults(syncResults) {
|
|
3251
|
-
|
|
3211
|
+
const netFunding = syncResults.reduce((sum, result) => {
|
|
3212
|
+
const funding = result.cumFunding.sinceOpen;
|
|
3213
|
+
return sum + funding;
|
|
3214
|
+
}, 0);
|
|
3215
|
+
return netFunding;
|
|
3252
3216
|
}
|
|
3253
|
-
/**
|
|
3254
|
-
* Calculate total unrealized PnL from sync results
|
|
3255
|
-
*/
|
|
3256
3217
|
calculateTotalUnrealizedPnlFromSyncResults(syncResults) {
|
|
3257
3218
|
return syncResults.reduce((sum, result) => sum + result.unrealizedPnl, 0);
|
|
3258
3219
|
}
|
|
3259
|
-
/**
|
|
3260
|
-
* Calculate current total position value using market prices
|
|
3261
|
-
*/
|
|
3262
3220
|
calculateCurrentTotalPositionValue(syncResults) {
|
|
3263
3221
|
return syncResults.reduce((sum, result) => {
|
|
3264
3222
|
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3265
3223
|
return sum + (result.actualSize * currentPrice);
|
|
3266
3224
|
}, 0);
|
|
3267
3225
|
}
|
|
3268
|
-
/**
|
|
3269
|
-
* Calculate entry total position value using entry prices
|
|
3270
|
-
*/
|
|
3271
3226
|
calculateEntryTotalPositionValue(syncResults) {
|
|
3272
3227
|
return syncResults.reduce((sum, result) => {
|
|
3273
|
-
return sum + (result.
|
|
3228
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3274
3229
|
}, 0);
|
|
3275
3230
|
}
|
|
3276
3231
|
}
|
|
@@ -3280,32 +3235,18 @@ class AggregatePositionCalculator {
|
|
|
3280
3235
|
*/
|
|
3281
3236
|
const useCalculatedOpenPositions = (platformPositions, webData2, allMids) => {
|
|
3282
3237
|
const calculatedPositions = useMemo(() => {
|
|
3283
|
-
var _a, _b;
|
|
3284
3238
|
// Return null if we don't have platform positions yet
|
|
3285
3239
|
if (!platformPositions) {
|
|
3286
|
-
console.log('[useCalculatedOpenPositions] No platform positions available');
|
|
3287
3240
|
return null;
|
|
3288
3241
|
}
|
|
3289
|
-
// If we don't have real-time data yet,
|
|
3242
|
+
// If we don't have real-time data yet, we can't calculate properly, return null
|
|
3290
3243
|
if (!webData2 || !allMids) {
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
hasAllMids: !!allMids,
|
|
3298
|
-
hyperliquidPositionsCount: ((_b = (_a = webData2.clearinghouseState) === null || _a === void 0 ? void 0 : _a.assetPositions) === null || _b === void 0 ? void 0 : _b.length) || 0,
|
|
3299
|
-
availableMids: Object.keys(allMids.mids || {}).length
|
|
3300
|
-
});
|
|
3301
|
-
// Create calculator and compute positions
|
|
3302
|
-
const calculator = new AggregatePositionCalculator(webData2, allMids);
|
|
3303
|
-
const calculated = calculator.calculateOpenPositions(platformPositions);
|
|
3304
|
-
console.log('[useCalculatedOpenPositions] Calculation completed', {
|
|
3305
|
-
inputCount: platformPositions.length,
|
|
3306
|
-
outputCount: calculated.length
|
|
3307
|
-
});
|
|
3308
|
-
return calculated;
|
|
3244
|
+
return null;
|
|
3245
|
+
}
|
|
3246
|
+
// Create processor and compute positions
|
|
3247
|
+
const processor = new PositionProcessor(webData2, allMids);
|
|
3248
|
+
const processed = processor.execute(platformPositions);
|
|
3249
|
+
return processed;
|
|
3309
3250
|
}, [platformPositions, webData2, allMids]);
|
|
3310
3251
|
return calculatedPositions;
|
|
3311
3252
|
};
|
|
@@ -3324,19 +3265,11 @@ class AccountSummaryCalculator {
|
|
|
3324
3265
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
3325
3266
|
// If we don't have webData2, return platform data as-is
|
|
3326
3267
|
if (!((_a = this.webData2) === null || _a === void 0 ? void 0 : _a.clearinghouseState)) {
|
|
3327
|
-
console.log('[AccountSummaryCalculator] No webData2 clearinghouseState available, returning platform data');
|
|
3328
3268
|
return platformAccountSummary;
|
|
3329
3269
|
}
|
|
3330
|
-
console.log('[AccountSummaryCalculator] Calculating account summary with real-time data', {
|
|
3331
|
-
hasPlatformSummary: !!platformAccountSummary,
|
|
3332
|
-
hasOpenOrders: !!platformOpenOrders,
|
|
3333
|
-
openOrdersCount: (platformOpenOrders === null || platformOpenOrders === void 0 ? void 0 : platformOpenOrders.length) || 0,
|
|
3334
|
-
hasAgentWallet: !!agentWalletAddress
|
|
3335
|
-
});
|
|
3336
3270
|
const clearinghouseState = this.webData2.clearinghouseState;
|
|
3337
3271
|
// Calculate total limit order value from platform orders
|
|
3338
3272
|
const totalLimitOrderValue = this.calculateTotalLimitOrderValue(platformOpenOrders || []);
|
|
3339
|
-
console.log('[AccountSummaryCalculator] Total limit order value:', totalLimitOrderValue);
|
|
3340
3273
|
// Use real-time data from webData2 clearinghouseState
|
|
3341
3274
|
const withdrawableAmount = parseFloat(clearinghouseState.withdrawable || '0');
|
|
3342
3275
|
const adjustedWithdrawable = Math.max(0, withdrawableAmount - totalLimitOrderValue);
|
|
@@ -3363,12 +3296,6 @@ class AccountSummaryCalculator {
|
|
|
3363
3296
|
status: agentWalletStatus || ((_l = platformAccountSummary === null || platformAccountSummary === void 0 ? void 0 : platformAccountSummary.agentWallet) === null || _l === void 0 ? void 0 : _l.status) || 'UNKNOWN'
|
|
3364
3297
|
}
|
|
3365
3298
|
};
|
|
3366
|
-
console.log('[AccountSummaryCalculator] Calculated account summary:', {
|
|
3367
|
-
accountValue: accountSummary.balanceSummary.crossMarginSummary.accountValue,
|
|
3368
|
-
withdrawable: accountSummary.balanceSummary.withdrawable,
|
|
3369
|
-
totalMarginUsed: accountSummary.balanceSummary.crossMarginSummary.totalMarginUsed,
|
|
3370
|
-
agentWalletAddress: accountSummary.agentWallet.address
|
|
3371
|
-
});
|
|
3372
3299
|
return accountSummary;
|
|
3373
3300
|
}
|
|
3374
3301
|
/**
|
|
@@ -3381,11 +3308,6 @@ class AccountSummaryCalculator {
|
|
|
3381
3308
|
const totalValue = openOrders
|
|
3382
3309
|
.filter(order => order.status === 'OPEN' || order.status === 'PROCESSING')
|
|
3383
3310
|
.reduce((sum, order) => sum + order.usdValue, 0);
|
|
3384
|
-
console.log('[AccountSummaryCalculator] Calculated limit order value:', {
|
|
3385
|
-
totalOrders: openOrders.length,
|
|
3386
|
-
openOrders: openOrders.filter(order => order.status === 'OPEN' || order.status === 'PROCESSING').length,
|
|
3387
|
-
totalValue
|
|
3388
|
-
});
|
|
3389
3311
|
return totalValue;
|
|
3390
3312
|
}
|
|
3391
3313
|
/**
|
|
@@ -3409,35 +3331,17 @@ class AccountSummaryCalculator {
|
|
|
3409
3331
|
*/
|
|
3410
3332
|
const useCalculatedAccountSummary = (platformAccountSummary, platformOpenOrders, webData2, agentWalletAddress, agentWalletStatus) => {
|
|
3411
3333
|
const calculatedAccountSummary = useMemo(() => {
|
|
3412
|
-
var _a, _b, _c;
|
|
3413
3334
|
// Return null if we don't have platform account summary yet
|
|
3414
3335
|
if (!platformAccountSummary) {
|
|
3415
|
-
console.log('[useCalculatedAccountSummary] No platform account summary available');
|
|
3416
3336
|
return null;
|
|
3417
3337
|
}
|
|
3418
3338
|
// If we don't have real-time data yet, return platform summary as-is
|
|
3419
3339
|
if (!(webData2 === null || webData2 === void 0 ? void 0 : webData2.clearinghouseState)) {
|
|
3420
|
-
console.log('[useCalculatedAccountSummary] Missing webData2 clearinghouseState, returning platform summary');
|
|
3421
3340
|
return platformAccountSummary;
|
|
3422
3341
|
}
|
|
3423
|
-
console.log('[useCalculatedAccountSummary] Calculating account summary with real-time data', {
|
|
3424
|
-
hasPlatformSummary: !!platformAccountSummary,
|
|
3425
|
-
hasWebData2: !!webData2,
|
|
3426
|
-
hasClearinghouseState: !!webData2.clearinghouseState,
|
|
3427
|
-
hasOpenOrders: !!platformOpenOrders,
|
|
3428
|
-
openOrdersCount: (platformOpenOrders === null || platformOpenOrders === void 0 ? void 0 : platformOpenOrders.length) || 0,
|
|
3429
|
-
agentWalletAddress,
|
|
3430
|
-
agentWalletStatus
|
|
3431
|
-
});
|
|
3432
3342
|
// Create calculator and compute account summary
|
|
3433
3343
|
const calculator = new AccountSummaryCalculator(webData2);
|
|
3434
3344
|
const calculated = calculator.calculateAccountSummary(platformAccountSummary, platformOpenOrders, agentWalletAddress, agentWalletStatus);
|
|
3435
|
-
console.log('[useCalculatedAccountSummary] Calculation completed', {
|
|
3436
|
-
hadPlatformSummary: !!platformAccountSummary,
|
|
3437
|
-
calculatedSummary: !!calculated,
|
|
3438
|
-
withdrawable: (_a = calculated === null || calculated === void 0 ? void 0 : calculated.balanceSummary) === null || _a === void 0 ? void 0 : _a.withdrawable,
|
|
3439
|
-
accountValue: (_c = (_b = calculated === null || calculated === void 0 ? void 0 : calculated.balanceSummary) === null || _b === void 0 ? void 0 : _b.crossMarginSummary) === null || _c === void 0 ? void 0 : _c.accountValue
|
|
3440
|
-
});
|
|
3441
3345
|
return calculated;
|
|
3442
3346
|
}, [platformAccountSummary, platformOpenOrders, webData2, agentWalletAddress, agentWalletStatus]);
|
|
3443
3347
|
return calculatedAccountSummary;
|
|
@@ -3489,5 +3393,5 @@ const useAccountSummary = () => {
|
|
|
3489
3393
|
return calculatedAccountSummary;
|
|
3490
3394
|
};
|
|
3491
3395
|
|
|
3492
|
-
export { AccountSummaryCalculator,
|
|
3396
|
+
export { AccountSummaryCalculator, PearHyperliquidClient, PearHyperliquidProvider, PearMigrationSDK, PearHyperliquidClient as default, useAccountSummary, useAddress, useCalculatedAccountSummary, useCalculatedOpenPositions, useHyperliquidNativeWebSocket, useHyperliquidWebSocket, useMigrationSDK, useOpenOrders, useOpenPositions, usePearHyperliquidClient, useTradeHistories };
|
|
3493
3397
|
//# sourceMappingURL=index.esm.js.map
|