@pear-protocol/hyperliquid-sdk 0.0.7 → 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 -84
- package/dist/index.esm.js +212 -291
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +213 -293
- 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/position-calculator.d.ts +0 -76
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,193 +2937,213 @@ 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
|
-
* Position calculation utility class
|
|
2962
|
-
*/
|
|
2963
|
-
class PositionCalculator {
|
|
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(`[PositionCalculator] No market price found for coin: ${coin}`);
|
|
2987
2987
|
return 0;
|
|
2988
2988
|
}
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
2989
|
+
calculatePlatformTotalsByAsset(positions) {
|
|
2990
|
+
const totalsMap = new Map();
|
|
2991
|
+
for (const position of positions) {
|
|
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 || []) {
|
|
3010
|
+
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3011
|
+
if (!totalsMap.has(baseCurrency)) {
|
|
3012
|
+
totalsMap.set(baseCurrency, {
|
|
3013
|
+
totalSize: 0,
|
|
3014
|
+
positions: []
|
|
3015
|
+
});
|
|
3016
|
+
}
|
|
3017
|
+
const totals = totalsMap.get(baseCurrency);
|
|
3018
|
+
const assetSize = Number(asset.size || 0);
|
|
3019
|
+
totals.totalSize += assetSize;
|
|
3020
|
+
totals.positions.push({
|
|
3021
|
+
positionId: position.positionId,
|
|
3022
|
+
asset: asset,
|
|
3023
|
+
size: assetSize
|
|
3024
|
+
});
|
|
3025
|
+
}
|
|
3002
3026
|
}
|
|
3003
|
-
|
|
3004
|
-
return platformPositions.map(position => this.syncPositionWithHyperliquid(position, hyperliquidPositions));
|
|
3027
|
+
return totalsMap;
|
|
3005
3028
|
}
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
// Create a map of HyperLiquid positions by coin for quick lookup
|
|
3011
|
-
const hlPositionsMap = new Map();
|
|
3012
|
-
hyperliquidPositions.forEach(assetPos => {
|
|
3013
|
-
var _a;
|
|
3014
|
-
if ((_a = assetPos.position) === null || _a === void 0 ? void 0 : _a.coin) {
|
|
3015
|
-
hlPositionsMap.set(assetPos.position.coin, assetPos);
|
|
3016
|
-
}
|
|
3017
|
-
});
|
|
3018
|
-
// Combine all assets for processing
|
|
3019
|
-
const allAssets = [
|
|
3020
|
-
...position.longAssets.map(asset => ({ ...asset, side: PositionSide.LONG })),
|
|
3021
|
-
...position.shortAssets.map(asset => ({ ...asset, side: PositionSide.SHORT }))
|
|
3022
|
-
];
|
|
3023
|
-
// Group assets by base currency for multi-pair position handling
|
|
3024
|
-
const assetsByBaseCurrency = this.groupAssetsByBaseCurrency(allAssets);
|
|
3025
|
-
// Sync each asset group with HyperLiquid data
|
|
3029
|
+
extractBaseCurrency(assetName) {
|
|
3030
|
+
return assetName.split('/')[0] || assetName;
|
|
3031
|
+
}
|
|
3032
|
+
syncPositionWithAggregateData(position, hlPositionsMap, platformTotalsByAsset) {
|
|
3026
3033
|
const syncResults = [];
|
|
3027
|
-
|
|
3034
|
+
let hasExternalModification = false;
|
|
3035
|
+
let allAssetsClosed = true;
|
|
3036
|
+
let longAssetStatuses = { total: 0, closed: 0 };
|
|
3037
|
+
let shortAssetStatuses = { total: 0, closed: 0 };
|
|
3038
|
+
// Process long assets
|
|
3039
|
+
for (const asset of position.longAssets || []) {
|
|
3040
|
+
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3028
3041
|
const hlPosition = hlPositionsMap.get(baseCurrency);
|
|
3029
|
-
const
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
const grouped = new Map();
|
|
3042
|
-
for (const asset of assets) {
|
|
3043
|
-
const baseCurrency = asset.coin.split('/')[0] || asset.coin;
|
|
3044
|
-
if (!grouped.has(baseCurrency)) {
|
|
3045
|
-
grouped.set(baseCurrency, []);
|
|
3042
|
+
const platformTotals = platformTotalsByAsset.get(baseCurrency);
|
|
3043
|
+
const syncResult = this.syncAssetWithAggregateData({ ...asset, side: PositionSide.LONG }, hlPosition, (platformTotals === null || platformTotals === void 0 ? void 0 : platformTotals.totalSize) || 0);
|
|
3044
|
+
syncResults.push(syncResult);
|
|
3045
|
+
longAssetStatuses.total++;
|
|
3046
|
+
if (syncResult.actualSize === 0) {
|
|
3047
|
+
longAssetStatuses.closed++;
|
|
3048
|
+
}
|
|
3049
|
+
if (syncResult.isExternallyModified) {
|
|
3050
|
+
hasExternalModification = true;
|
|
3051
|
+
}
|
|
3052
|
+
if (syncResult.actualSize !== 0) {
|
|
3053
|
+
allAssetsClosed = false;
|
|
3046
3054
|
}
|
|
3047
|
-
grouped.get(baseCurrency).push(asset);
|
|
3048
3055
|
}
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
// Check if the total size matches (within tolerance)
|
|
3060
|
-
const sizeDifference = Math.abs(actualTotalSize - totalPlatformSize);
|
|
3061
|
-
const sizeDifferencePercentage = totalPlatformSize > 0
|
|
3062
|
-
? (sizeDifference / totalPlatformSize) * 100
|
|
3063
|
-
: (actualTotalSize > 0 ? 100 : 0);
|
|
3064
|
-
const isGroupExternallyModified = sizeDifferencePercentage > 0.1; // 0.1% tolerance
|
|
3065
|
-
for (const asset of assets) {
|
|
3066
|
-
const platformSize = asset.platformSize;
|
|
3067
|
-
let actualSize = platformSize;
|
|
3068
|
-
let isExternallyModified = isGroupExternallyModified;
|
|
3069
|
-
let cumFunding = {
|
|
3070
|
-
allTime: 0,
|
|
3071
|
-
sinceChange: 0,
|
|
3072
|
-
sinceOpen: 0
|
|
3073
|
-
};
|
|
3074
|
-
let unrealizedPnl = 0;
|
|
3075
|
-
let liquidationPrice = 0;
|
|
3076
|
-
if (hlPosition) {
|
|
3077
|
-
// Proportionally distribute the actual size based on asset's contribution
|
|
3078
|
-
const sizeRatio = totalPlatformSize > 0 ? platformSize / totalPlatformSize : 0;
|
|
3079
|
-
actualSize = actualTotalSize * sizeRatio;
|
|
3080
|
-
// Proportionally distribute funding and PnL based on asset's contribution
|
|
3081
|
-
if (hlPosition.cumFunding) {
|
|
3082
|
-
cumFunding = {
|
|
3083
|
-
allTime: Number(hlPosition.cumFunding.allTime || 0),
|
|
3084
|
-
sinceChange: Number(hlPosition.cumFunding.sinceChange || 0) * sizeRatio,
|
|
3085
|
-
sinceOpen: Number(hlPosition.cumFunding.sinceOpen || 0) * sizeRatio
|
|
3086
|
-
};
|
|
3087
|
-
}
|
|
3088
|
-
unrealizedPnl = Number(hlPosition.position.unrealizedPnl || 0) * sizeRatio;
|
|
3089
|
-
liquidationPrice = Number(hlPosition.position.liquidationPx || 0);
|
|
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++;
|
|
3090
3066
|
}
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3067
|
+
if (syncResult.isExternallyModified) {
|
|
3068
|
+
hasExternalModification = true;
|
|
3069
|
+
}
|
|
3070
|
+
if (syncResult.actualSize !== 0) {
|
|
3071
|
+
allAssetsClosed = false;
|
|
3095
3072
|
}
|
|
3096
|
-
results.push({
|
|
3097
|
-
asset,
|
|
3098
|
-
actualSize,
|
|
3099
|
-
isExternallyModified,
|
|
3100
|
-
cumFunding,
|
|
3101
|
-
unrealizedPnl,
|
|
3102
|
-
liquidationPrice,
|
|
3103
|
-
side: asset.side
|
|
3104
|
-
});
|
|
3105
3073
|
}
|
|
3106
|
-
|
|
3074
|
+
const syncStatus = this.determineSyncStatus(hasExternalModification, allAssetsClosed, longAssetStatuses, shortAssetStatuses);
|
|
3075
|
+
return this.mapPositionToDtoWithSyncData(position, syncResults, syncStatus);
|
|
3107
3076
|
}
|
|
3108
|
-
|
|
3109
|
-
* Determine sync status based on asset sync results
|
|
3110
|
-
*/
|
|
3111
|
-
determineSyncStatus(syncResults) {
|
|
3112
|
-
const hasExternalModifications = syncResults.some(result => result.isExternallyModified);
|
|
3113
|
-
const allAssetsClosed = syncResults.every(result => result.actualSize === 0);
|
|
3114
|
-
const someAssetsClosed = syncResults.some(result => result.actualSize === 0) && !allAssetsClosed;
|
|
3077
|
+
determineSyncStatus(hasExternalModification, allAssetsClosed, longAssetStatuses, shortAssetStatuses) {
|
|
3115
3078
|
if (allAssetsClosed) {
|
|
3116
3079
|
return 'EXTERNALLY_CLOSED';
|
|
3117
3080
|
}
|
|
3118
|
-
|
|
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)) {
|
|
3119
3086
|
return 'PAIR_BROKEN';
|
|
3120
3087
|
}
|
|
3121
|
-
|
|
3088
|
+
if (hasExternalModification) {
|
|
3122
3089
|
return 'EXTERNALLY_MODIFIED';
|
|
3123
3090
|
}
|
|
3124
3091
|
return 'SYNCED';
|
|
3125
3092
|
}
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3093
|
+
syncAssetWithAggregateData(asset, hlPosition, platformTotal) {
|
|
3094
|
+
const platformSize = Number(asset.size || 0);
|
|
3095
|
+
if (!hlPosition || !hlPosition.position || !hlPosition.position.szi) {
|
|
3096
|
+
return {
|
|
3097
|
+
asset,
|
|
3098
|
+
actualSize: 0,
|
|
3099
|
+
isExternallyModified: true,
|
|
3100
|
+
cumFunding: { allTime: 0, sinceChange: 0, sinceOpen: 0 },
|
|
3101
|
+
unrealizedPnl: 0,
|
|
3102
|
+
liquidationPrice: 0
|
|
3103
|
+
};
|
|
3104
|
+
}
|
|
3105
|
+
const hlTotalSize = Math.abs(Number(hlPosition.position.szi || 0));
|
|
3106
|
+
const totalDifference = Math.abs(hlTotalSize - platformTotal);
|
|
3107
|
+
const tolerance = platformTotal * 0.001;
|
|
3108
|
+
const isExternallyModified = totalDifference > tolerance;
|
|
3109
|
+
const proportion = platformTotal > 0 ? platformSize / platformTotal : 0;
|
|
3110
|
+
const actualSize = hlTotalSize * proportion;
|
|
3111
|
+
// Get cumFunding from hlPosition.position.cumFunding
|
|
3112
|
+
const rawCumFunding = hlPosition.position.cumFunding;
|
|
3113
|
+
const cumFunding = {
|
|
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
|
|
3117
|
+
};
|
|
3118
|
+
const unrealizedPnl = Number(hlPosition.position.unrealizedPnl || 0) * proportion;
|
|
3119
|
+
const liquidationPrice = Number(hlPosition.position.liquidationPx || 0);
|
|
3120
|
+
return {
|
|
3121
|
+
asset,
|
|
3122
|
+
actualSize,
|
|
3123
|
+
isExternallyModified,
|
|
3124
|
+
cumFunding,
|
|
3125
|
+
unrealizedPnl,
|
|
3126
|
+
liquidationPrice
|
|
3127
|
+
};
|
|
3128
|
+
}
|
|
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
|
+
});
|
|
3133
3137
|
const currentTotalPositionValue = this.calculateCurrentTotalPositionValue(syncResults);
|
|
3134
3138
|
const entryTotalPositionValue = this.calculateEntryTotalPositionValue(syncResults);
|
|
3135
|
-
const totalMarginUsed = entryTotalPositionValue /
|
|
3139
|
+
const totalMarginUsed = entryTotalPositionValue / position.leverage;
|
|
3136
3140
|
return {
|
|
3137
|
-
|
|
3138
|
-
|
|
3141
|
+
syncStatus: syncStatus,
|
|
3142
|
+
positionId: position.positionId,
|
|
3143
|
+
address: position.address,
|
|
3144
|
+
leverage: position.leverage,
|
|
3145
|
+
stopLoss: position.stopLoss,
|
|
3146
|
+
takeProfit: position.takeProfit,
|
|
3139
3147
|
entryRatio: this.calculateEntryRatio(syncResults),
|
|
3140
3148
|
markRatio: this.calculateMarkRatio(syncResults),
|
|
3141
3149
|
netFunding: this.calculateNetFundingFromSyncResults(syncResults),
|
|
@@ -3143,117 +3151,81 @@ class PositionCalculator {
|
|
|
3143
3151
|
marginUsed: totalMarginUsed,
|
|
3144
3152
|
unrealizedPnl: this.calculateTotalUnrealizedPnlFromSyncResults(syncResults),
|
|
3145
3153
|
lastSyncAt: new Date().toISOString(),
|
|
3146
|
-
longAssets:
|
|
3147
|
-
shortAssets:
|
|
3148
|
-
|
|
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
|
|
3149
3158
|
};
|
|
3150
3159
|
}
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
const
|
|
3156
|
-
const positionValue = syncResult.actualSize * currentPrice;
|
|
3157
|
-
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);
|
|
3158
3165
|
return {
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
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
|
+
},
|
|
3163
3176
|
marginUsed: entryValue,
|
|
3164
3177
|
positionValue: positionValue,
|
|
3165
|
-
unrealizedPnl:
|
|
3166
|
-
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
|
|
3167
3180
|
};
|
|
3168
3181
|
}
|
|
3169
|
-
/**
|
|
3170
|
-
* Calculate entry ratio (weighted long entry value / weighted short entry value)
|
|
3171
|
-
*/
|
|
3172
3182
|
calculateEntryRatio(syncResults) {
|
|
3173
|
-
const longResults = syncResults.filter(result => result.side === PositionSide.LONG);
|
|
3174
|
-
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);
|
|
3175
3185
|
if (longResults.length === 0 || shortResults.length === 0)
|
|
3176
3186
|
return 0;
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
return sum + (result.actualSize * result.asset.entryPrice);
|
|
3187
|
+
const longValue = longResults.reduce((sum, result) => {
|
|
3188
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3180
3189
|
}, 0);
|
|
3181
|
-
|
|
3182
|
-
return 0;
|
|
3183
|
-
// Calculate weighted long portfolio entry value
|
|
3184
|
-
const weightedLongValue = longResults.reduce((sum, result) => {
|
|
3185
|
-
const entryPrice = result.asset.entryPrice;
|
|
3186
|
-
const assetValue = result.actualSize * entryPrice;
|
|
3187
|
-
const weight = assetValue / totalPositionValue;
|
|
3188
|
-
return sum + (entryPrice * weight);
|
|
3189
|
-
}, 0);
|
|
3190
|
-
// Calculate weighted short portfolio entry value
|
|
3191
|
-
const weightedShortValue = shortResults.reduce((sum, result) => {
|
|
3192
|
-
const entryPrice = result.asset.entryPrice;
|
|
3193
|
-
const assetValue = result.actualSize * entryPrice;
|
|
3194
|
-
const weight = assetValue / totalPositionValue;
|
|
3195
|
-
return sum + (entryPrice * weight);
|
|
3190
|
+
const shortValue = shortResults.reduce((sum, result) => {
|
|
3191
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3196
3192
|
}, 0);
|
|
3197
|
-
return
|
|
3193
|
+
return shortValue > 0 ? longValue / shortValue : 0;
|
|
3198
3194
|
}
|
|
3199
|
-
/**
|
|
3200
|
-
* Calculate mark ratio (weighted long mark value / weighted short mark value)
|
|
3201
|
-
*/
|
|
3202
3195
|
calculateMarkRatio(syncResults) {
|
|
3203
|
-
const longResults = syncResults.filter(result => result.side === PositionSide.LONG);
|
|
3204
|
-
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);
|
|
3205
3198
|
if (longResults.length === 0 || shortResults.length === 0)
|
|
3206
3199
|
return 0;
|
|
3207
|
-
|
|
3208
|
-
const totalPositionValue = syncResults.reduce((sum, result) => {
|
|
3200
|
+
const longValue = longResults.reduce((sum, result) => {
|
|
3209
3201
|
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3210
3202
|
return sum + (result.actualSize * currentPrice);
|
|
3211
3203
|
}, 0);
|
|
3212
|
-
|
|
3213
|
-
return 0;
|
|
3214
|
-
// Calculate weighted long portfolio value
|
|
3215
|
-
const weightedLongValue = longResults.reduce((sum, result) => {
|
|
3216
|
-
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3217
|
-
const assetValue = result.actualSize * currentPrice;
|
|
3218
|
-
const weight = assetValue / totalPositionValue;
|
|
3219
|
-
return sum + (currentPrice * weight);
|
|
3220
|
-
}, 0);
|
|
3221
|
-
// Calculate weighted short portfolio value
|
|
3222
|
-
const weightedShortValue = shortResults.reduce((sum, result) => {
|
|
3204
|
+
const shortValue = shortResults.reduce((sum, result) => {
|
|
3223
3205
|
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3224
|
-
|
|
3225
|
-
const weight = assetValue / totalPositionValue;
|
|
3226
|
-
return sum + (currentPrice * weight);
|
|
3206
|
+
return sum + (result.actualSize * currentPrice);
|
|
3227
3207
|
}, 0);
|
|
3228
|
-
return
|
|
3208
|
+
return shortValue > 0 ? longValue / shortValue : 0;
|
|
3229
3209
|
}
|
|
3230
|
-
/**
|
|
3231
|
-
* Calculate net funding from sync results
|
|
3232
|
-
*/
|
|
3233
3210
|
calculateNetFundingFromSyncResults(syncResults) {
|
|
3234
|
-
|
|
3211
|
+
const netFunding = syncResults.reduce((sum, result) => {
|
|
3212
|
+
const funding = result.cumFunding.sinceOpen;
|
|
3213
|
+
return sum + funding;
|
|
3214
|
+
}, 0);
|
|
3215
|
+
return netFunding;
|
|
3235
3216
|
}
|
|
3236
|
-
/**
|
|
3237
|
-
* Calculate total unrealized PnL from sync results
|
|
3238
|
-
*/
|
|
3239
3217
|
calculateTotalUnrealizedPnlFromSyncResults(syncResults) {
|
|
3240
3218
|
return syncResults.reduce((sum, result) => sum + result.unrealizedPnl, 0);
|
|
3241
3219
|
}
|
|
3242
|
-
/**
|
|
3243
|
-
* Calculate current total position value using market prices
|
|
3244
|
-
*/
|
|
3245
3220
|
calculateCurrentTotalPositionValue(syncResults) {
|
|
3246
3221
|
return syncResults.reduce((sum, result) => {
|
|
3247
3222
|
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3248
3223
|
return sum + (result.actualSize * currentPrice);
|
|
3249
3224
|
}, 0);
|
|
3250
3225
|
}
|
|
3251
|
-
/**
|
|
3252
|
-
* Calculate entry total position value using entry prices
|
|
3253
|
-
*/
|
|
3254
3226
|
calculateEntryTotalPositionValue(syncResults) {
|
|
3255
3227
|
return syncResults.reduce((sum, result) => {
|
|
3256
|
-
return sum + (result.
|
|
3228
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3257
3229
|
}, 0);
|
|
3258
3230
|
}
|
|
3259
3231
|
}
|
|
@@ -3263,32 +3235,18 @@ class PositionCalculator {
|
|
|
3263
3235
|
*/
|
|
3264
3236
|
const useCalculatedOpenPositions = (platformPositions, webData2, allMids) => {
|
|
3265
3237
|
const calculatedPositions = useMemo(() => {
|
|
3266
|
-
var _a, _b;
|
|
3267
3238
|
// Return null if we don't have platform positions yet
|
|
3268
3239
|
if (!platformPositions) {
|
|
3269
|
-
console.log('[useCalculatedOpenPositions] No platform positions available');
|
|
3270
3240
|
return null;
|
|
3271
3241
|
}
|
|
3272
|
-
// 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
|
|
3273
3243
|
if (!webData2 || !allMids) {
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
hasAllMids: !!allMids,
|
|
3281
|
-
hyperliquidPositionsCount: ((_b = (_a = webData2.clearinghouseState) === null || _a === void 0 ? void 0 : _a.assetPositions) === null || _b === void 0 ? void 0 : _b.length) || 0,
|
|
3282
|
-
availableMids: Object.keys(allMids.mids || {}).length
|
|
3283
|
-
});
|
|
3284
|
-
// Create calculator and compute positions
|
|
3285
|
-
const calculator = new PositionCalculator(webData2, allMids);
|
|
3286
|
-
const calculated = calculator.calculateOpenPositions(platformPositions);
|
|
3287
|
-
console.log('[useCalculatedOpenPositions] Calculation completed', {
|
|
3288
|
-
inputCount: platformPositions.length,
|
|
3289
|
-
outputCount: calculated.length
|
|
3290
|
-
});
|
|
3291
|
-
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;
|
|
3292
3250
|
}, [platformPositions, webData2, allMids]);
|
|
3293
3251
|
return calculatedPositions;
|
|
3294
3252
|
};
|
|
@@ -3307,19 +3265,11 @@ class AccountSummaryCalculator {
|
|
|
3307
3265
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
3308
3266
|
// If we don't have webData2, return platform data as-is
|
|
3309
3267
|
if (!((_a = this.webData2) === null || _a === void 0 ? void 0 : _a.clearinghouseState)) {
|
|
3310
|
-
console.log('[AccountSummaryCalculator] No webData2 clearinghouseState available, returning platform data');
|
|
3311
3268
|
return platformAccountSummary;
|
|
3312
3269
|
}
|
|
3313
|
-
console.log('[AccountSummaryCalculator] Calculating account summary with real-time data', {
|
|
3314
|
-
hasPlatformSummary: !!platformAccountSummary,
|
|
3315
|
-
hasOpenOrders: !!platformOpenOrders,
|
|
3316
|
-
openOrdersCount: (platformOpenOrders === null || platformOpenOrders === void 0 ? void 0 : platformOpenOrders.length) || 0,
|
|
3317
|
-
hasAgentWallet: !!agentWalletAddress
|
|
3318
|
-
});
|
|
3319
3270
|
const clearinghouseState = this.webData2.clearinghouseState;
|
|
3320
3271
|
// Calculate total limit order value from platform orders
|
|
3321
3272
|
const totalLimitOrderValue = this.calculateTotalLimitOrderValue(platformOpenOrders || []);
|
|
3322
|
-
console.log('[AccountSummaryCalculator] Total limit order value:', totalLimitOrderValue);
|
|
3323
3273
|
// Use real-time data from webData2 clearinghouseState
|
|
3324
3274
|
const withdrawableAmount = parseFloat(clearinghouseState.withdrawable || '0');
|
|
3325
3275
|
const adjustedWithdrawable = Math.max(0, withdrawableAmount - totalLimitOrderValue);
|
|
@@ -3346,12 +3296,6 @@ class AccountSummaryCalculator {
|
|
|
3346
3296
|
status: agentWalletStatus || ((_l = platformAccountSummary === null || platformAccountSummary === void 0 ? void 0 : platformAccountSummary.agentWallet) === null || _l === void 0 ? void 0 : _l.status) || 'UNKNOWN'
|
|
3347
3297
|
}
|
|
3348
3298
|
};
|
|
3349
|
-
console.log('[AccountSummaryCalculator] Calculated account summary:', {
|
|
3350
|
-
accountValue: accountSummary.balanceSummary.crossMarginSummary.accountValue,
|
|
3351
|
-
withdrawable: accountSummary.balanceSummary.withdrawable,
|
|
3352
|
-
totalMarginUsed: accountSummary.balanceSummary.crossMarginSummary.totalMarginUsed,
|
|
3353
|
-
agentWalletAddress: accountSummary.agentWallet.address
|
|
3354
|
-
});
|
|
3355
3299
|
return accountSummary;
|
|
3356
3300
|
}
|
|
3357
3301
|
/**
|
|
@@ -3364,11 +3308,6 @@ class AccountSummaryCalculator {
|
|
|
3364
3308
|
const totalValue = openOrders
|
|
3365
3309
|
.filter(order => order.status === 'OPEN' || order.status === 'PROCESSING')
|
|
3366
3310
|
.reduce((sum, order) => sum + order.usdValue, 0);
|
|
3367
|
-
console.log('[AccountSummaryCalculator] Calculated limit order value:', {
|
|
3368
|
-
totalOrders: openOrders.length,
|
|
3369
|
-
openOrders: openOrders.filter(order => order.status === 'OPEN' || order.status === 'PROCESSING').length,
|
|
3370
|
-
totalValue
|
|
3371
|
-
});
|
|
3372
3311
|
return totalValue;
|
|
3373
3312
|
}
|
|
3374
3313
|
/**
|
|
@@ -3392,35 +3331,17 @@ class AccountSummaryCalculator {
|
|
|
3392
3331
|
*/
|
|
3393
3332
|
const useCalculatedAccountSummary = (platformAccountSummary, platformOpenOrders, webData2, agentWalletAddress, agentWalletStatus) => {
|
|
3394
3333
|
const calculatedAccountSummary = useMemo(() => {
|
|
3395
|
-
var _a, _b, _c;
|
|
3396
3334
|
// Return null if we don't have platform account summary yet
|
|
3397
3335
|
if (!platformAccountSummary) {
|
|
3398
|
-
console.log('[useCalculatedAccountSummary] No platform account summary available');
|
|
3399
3336
|
return null;
|
|
3400
3337
|
}
|
|
3401
3338
|
// If we don't have real-time data yet, return platform summary as-is
|
|
3402
3339
|
if (!(webData2 === null || webData2 === void 0 ? void 0 : webData2.clearinghouseState)) {
|
|
3403
|
-
console.log('[useCalculatedAccountSummary] Missing webData2 clearinghouseState, returning platform summary');
|
|
3404
3340
|
return platformAccountSummary;
|
|
3405
3341
|
}
|
|
3406
|
-
console.log('[useCalculatedAccountSummary] Calculating account summary with real-time data', {
|
|
3407
|
-
hasPlatformSummary: !!platformAccountSummary,
|
|
3408
|
-
hasWebData2: !!webData2,
|
|
3409
|
-
hasClearinghouseState: !!webData2.clearinghouseState,
|
|
3410
|
-
hasOpenOrders: !!platformOpenOrders,
|
|
3411
|
-
openOrdersCount: (platformOpenOrders === null || platformOpenOrders === void 0 ? void 0 : platformOpenOrders.length) || 0,
|
|
3412
|
-
agentWalletAddress,
|
|
3413
|
-
agentWalletStatus
|
|
3414
|
-
});
|
|
3415
3342
|
// Create calculator and compute account summary
|
|
3416
3343
|
const calculator = new AccountSummaryCalculator(webData2);
|
|
3417
3344
|
const calculated = calculator.calculateAccountSummary(platformAccountSummary, platformOpenOrders, agentWalletAddress, agentWalletStatus);
|
|
3418
|
-
console.log('[useCalculatedAccountSummary] Calculation completed', {
|
|
3419
|
-
hadPlatformSummary: !!platformAccountSummary,
|
|
3420
|
-
calculatedSummary: !!calculated,
|
|
3421
|
-
withdrawable: (_a = calculated === null || calculated === void 0 ? void 0 : calculated.balanceSummary) === null || _a === void 0 ? void 0 : _a.withdrawable,
|
|
3422
|
-
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
|
|
3423
|
-
});
|
|
3424
3345
|
return calculated;
|
|
3425
3346
|
}, [platformAccountSummary, platformOpenOrders, webData2, agentWalletAddress, agentWalletStatus]);
|
|
3426
3347
|
return calculatedAccountSummary;
|
|
@@ -3472,5 +3393,5 @@ const useAccountSummary = () => {
|
|
|
3472
3393
|
return calculatedAccountSummary;
|
|
3473
3394
|
};
|
|
3474
3395
|
|
|
3475
|
-
export { AccountSummaryCalculator, PearHyperliquidClient, PearHyperliquidProvider, PearMigrationSDK,
|
|
3396
|
+
export { AccountSummaryCalculator, PearHyperliquidClient, PearHyperliquidProvider, PearMigrationSDK, PearHyperliquidClient as default, useAccountSummary, useAddress, useCalculatedAccountSummary, useCalculatedOpenPositions, useHyperliquidNativeWebSocket, useHyperliquidWebSocket, useMigrationSDK, useOpenOrders, useOpenPositions, usePearHyperliquidClient, useTradeHistories };
|
|
3476
3397
|
//# sourceMappingURL=index.esm.js.map
|