@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.js
CHANGED
|
@@ -2747,8 +2747,8 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2747
2747
|
shouldReconnect: () => true,
|
|
2748
2748
|
reconnectAttempts: 5,
|
|
2749
2749
|
reconnectInterval: 3000,
|
|
2750
|
-
onOpen: () =>
|
|
2751
|
-
onClose: () =>
|
|
2750
|
+
onOpen: () => { },
|
|
2751
|
+
onClose: () => { },
|
|
2752
2752
|
onError: (event) => console.error('[HyperLiquid WS] Connection error:', event),
|
|
2753
2753
|
onReconnectStop: () => console.error('[HyperLiquid WS] Reconnection stopped after 5 attempts'),
|
|
2754
2754
|
});
|
|
@@ -2756,16 +2756,13 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2756
2756
|
// Setup ping mechanism
|
|
2757
2757
|
require$$0.useEffect(() => {
|
|
2758
2758
|
if (isConnected) {
|
|
2759
|
-
console.log('[HyperLiquid WS] Setting up ping mechanism (30s interval)');
|
|
2760
2759
|
// Send ping every 30 seconds
|
|
2761
2760
|
pingIntervalRef.current = setInterval(() => {
|
|
2762
|
-
console.log('[HyperLiquid WS] Sending ping');
|
|
2763
2761
|
sendJsonMessage({ method: 'ping' });
|
|
2764
2762
|
}, 30000);
|
|
2765
2763
|
}
|
|
2766
2764
|
else {
|
|
2767
2765
|
if (pingIntervalRef.current) {
|
|
2768
|
-
console.log('[HyperLiquid WS] Clearing ping interval');
|
|
2769
2766
|
clearInterval(pingIntervalRef.current);
|
|
2770
2767
|
pingIntervalRef.current = null;
|
|
2771
2768
|
}
|
|
@@ -2787,7 +2784,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2787
2784
|
return;
|
|
2788
2785
|
// Unsubscribe from previous address if exists
|
|
2789
2786
|
if (subscribedAddress) {
|
|
2790
|
-
console.log(`[HyperLiquid WS] Unsubscribing from webData2 for previous address: ${subscribedAddress}`);
|
|
2791
2787
|
const unsubscribeMessage = {
|
|
2792
2788
|
method: 'unsubscribe',
|
|
2793
2789
|
subscription: {
|
|
@@ -2798,7 +2794,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2798
2794
|
sendJsonMessage(unsubscribeMessage);
|
|
2799
2795
|
}
|
|
2800
2796
|
// Subscribe to webData2 with new address
|
|
2801
|
-
console.log(`[HyperLiquid WS] Subscribing to webData2 for address: ${userAddress}`);
|
|
2802
2797
|
const subscribeWebData2 = {
|
|
2803
2798
|
method: 'subscribe',
|
|
2804
2799
|
subscription: {
|
|
@@ -2807,7 +2802,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2807
2802
|
},
|
|
2808
2803
|
};
|
|
2809
2804
|
// Subscribe to allMids
|
|
2810
|
-
console.log('[HyperLiquid WS] Subscribing to allMids');
|
|
2811
2805
|
const subscribeAllMids = {
|
|
2812
2806
|
method: 'subscribe',
|
|
2813
2807
|
subscription: {
|
|
@@ -2819,7 +2813,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2819
2813
|
setSubscribedAddress(userAddress);
|
|
2820
2814
|
// Clear previous data when address changes
|
|
2821
2815
|
if (subscribedAddress && subscribedAddress !== userAddress) {
|
|
2822
|
-
console.log('[HyperLiquid WS] Address changed, clearing previous webData2');
|
|
2823
2816
|
setWebData2(null);
|
|
2824
2817
|
}
|
|
2825
2818
|
}, [isConnected, address, subscribedAddress, sendJsonMessage]);
|
|
@@ -2829,7 +2822,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2829
2822
|
return;
|
|
2830
2823
|
try {
|
|
2831
2824
|
const message = JSON.parse(lastMessage.data);
|
|
2832
|
-
console.log('[HyperLiquid WS] Received message:', message);
|
|
2833
2825
|
// Handle subscription responses
|
|
2834
2826
|
if ('success' in message || 'error' in message) {
|
|
2835
2827
|
if (message.error) {
|
|
@@ -2837,7 +2829,6 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2837
2829
|
setLastError(message.error);
|
|
2838
2830
|
}
|
|
2839
2831
|
else {
|
|
2840
|
-
console.log('[HyperLiquid WS] Subscription success:', message);
|
|
2841
2832
|
setLastError(null);
|
|
2842
2833
|
}
|
|
2843
2834
|
return;
|
|
@@ -2845,14 +2836,11 @@ const useHyperliquidNativeWebSocket = ({ address }) => {
|
|
|
2845
2836
|
// Handle channel data messages
|
|
2846
2837
|
if ('channel' in message && 'data' in message) {
|
|
2847
2838
|
const response = message;
|
|
2848
|
-
console.log(`[HyperLiquid WS] Received ${response.channel} data`);
|
|
2849
2839
|
switch (response.channel) {
|
|
2850
2840
|
case 'webData2':
|
|
2851
|
-
console.log('[HyperLiquid WS] Setting webData2:', response.data);
|
|
2852
2841
|
setWebData2(response.data);
|
|
2853
2842
|
break;
|
|
2854
2843
|
case 'allMids':
|
|
2855
|
-
console.log('[HyperLiquid WS] Setting allMids:', response.data);
|
|
2856
2844
|
setAllMids(response.data);
|
|
2857
2845
|
break;
|
|
2858
2846
|
default:
|
|
@@ -2953,193 +2941,213 @@ const useAddress = () => {
|
|
|
2953
2941
|
};
|
|
2954
2942
|
};
|
|
2955
2943
|
|
|
2956
|
-
|
|
2957
|
-
* Position side enum for calculations
|
|
2958
|
-
*/
|
|
2959
|
-
exports.PositionSide = void 0;
|
|
2944
|
+
var PositionSide;
|
|
2960
2945
|
(function (PositionSide) {
|
|
2961
2946
|
PositionSide["LONG"] = "LONG";
|
|
2962
2947
|
PositionSide["SHORT"] = "SHORT";
|
|
2963
|
-
})(
|
|
2964
|
-
|
|
2965
|
-
* Position calculation utility class
|
|
2966
|
-
*/
|
|
2967
|
-
class PositionCalculator {
|
|
2948
|
+
})(PositionSide || (PositionSide = {}));
|
|
2949
|
+
class PositionProcessor {
|
|
2968
2950
|
constructor(webData2, allMids) {
|
|
2969
2951
|
this.webData2 = webData2;
|
|
2970
2952
|
this.allMids = allMids;
|
|
2971
2953
|
}
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2954
|
+
execute(rawPositions) {
|
|
2955
|
+
if (!rawPositions || rawPositions.length === 0) {
|
|
2956
|
+
return [];
|
|
2957
|
+
}
|
|
2958
|
+
const userHyperliquidPositions = this.getUserPositions();
|
|
2959
|
+
const platformTotalsByAsset = this.calculatePlatformTotalsByAsset(rawPositions);
|
|
2960
|
+
const hlPositionsMap = new Map();
|
|
2961
|
+
(userHyperliquidPositions || []).forEach(assetPos => {
|
|
2962
|
+
var _a;
|
|
2963
|
+
if ((_a = assetPos.position) === null || _a === void 0 ? void 0 : _a.coin) {
|
|
2964
|
+
hlPositionsMap.set(assetPos.position.coin, assetPos);
|
|
2965
|
+
}
|
|
2966
|
+
});
|
|
2967
|
+
const openPositionDtos = [];
|
|
2968
|
+
for (const position of rawPositions) {
|
|
2969
|
+
const syncedPositionDto = this.syncPositionWithAggregateData(position, hlPositionsMap, platformTotalsByAsset);
|
|
2970
|
+
openPositionDtos.push(syncedPositionDto);
|
|
2971
|
+
}
|
|
2972
|
+
return openPositionDtos;
|
|
2973
|
+
}
|
|
2974
|
+
getUserPositions() {
|
|
2975
|
+
var _a, _b;
|
|
2976
|
+
return ((_b = (_a = this.webData2) === null || _a === void 0 ? void 0 : _a.clearinghouseState) === null || _b === void 0 ? void 0 : _b.assetPositions) || [];
|
|
2977
|
+
}
|
|
2975
2978
|
getMarketPrice(coin) {
|
|
2976
2979
|
var _a;
|
|
2977
2980
|
if (!((_a = this.allMids) === null || _a === void 0 ? void 0 : _a.mids))
|
|
2978
2981
|
return 0;
|
|
2979
|
-
// Try exact match first
|
|
2980
2982
|
const exactPrice = this.allMids.mids[coin];
|
|
2981
2983
|
if (exactPrice) {
|
|
2982
2984
|
return Number(exactPrice);
|
|
2983
2985
|
}
|
|
2984
|
-
|
|
2985
|
-
const baseCurrency = coin.split('/')[0];
|
|
2986
|
+
const baseCurrency = this.extractBaseCurrency(coin);
|
|
2986
2987
|
const basePrice = this.allMids.mids[baseCurrency];
|
|
2987
2988
|
if (basePrice) {
|
|
2988
2989
|
return Number(basePrice);
|
|
2989
2990
|
}
|
|
2990
|
-
console.warn(`[PositionCalculator] No market price found for coin: ${coin}`);
|
|
2991
2991
|
return 0;
|
|
2992
2992
|
}
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
2993
|
+
calculatePlatformTotalsByAsset(positions) {
|
|
2994
|
+
const totalsMap = new Map();
|
|
2995
|
+
for (const position of positions) {
|
|
2996
|
+
for (const asset of position.longAssets || []) {
|
|
2997
|
+
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
2998
|
+
if (!totalsMap.has(baseCurrency)) {
|
|
2999
|
+
totalsMap.set(baseCurrency, {
|
|
3000
|
+
totalSize: 0,
|
|
3001
|
+
positions: []
|
|
3002
|
+
});
|
|
3003
|
+
}
|
|
3004
|
+
const totals = totalsMap.get(baseCurrency);
|
|
3005
|
+
const assetSize = Number(asset.size || 0);
|
|
3006
|
+
totals.totalSize += assetSize;
|
|
3007
|
+
totals.positions.push({
|
|
3008
|
+
positionId: position.positionId,
|
|
3009
|
+
asset: asset,
|
|
3010
|
+
size: assetSize
|
|
3011
|
+
});
|
|
3012
|
+
}
|
|
3013
|
+
for (const asset of position.shortAssets || []) {
|
|
3014
|
+
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3015
|
+
if (!totalsMap.has(baseCurrency)) {
|
|
3016
|
+
totalsMap.set(baseCurrency, {
|
|
3017
|
+
totalSize: 0,
|
|
3018
|
+
positions: []
|
|
3019
|
+
});
|
|
3020
|
+
}
|
|
3021
|
+
const totals = totalsMap.get(baseCurrency);
|
|
3022
|
+
const assetSize = Number(asset.size || 0);
|
|
3023
|
+
totals.totalSize += assetSize;
|
|
3024
|
+
totals.positions.push({
|
|
3025
|
+
positionId: position.positionId,
|
|
3026
|
+
asset: asset,
|
|
3027
|
+
size: assetSize
|
|
3028
|
+
});
|
|
3029
|
+
}
|
|
3006
3030
|
}
|
|
3007
|
-
|
|
3008
|
-
return platformPositions.map(position => this.syncPositionWithHyperliquid(position, hyperliquidPositions));
|
|
3031
|
+
return totalsMap;
|
|
3009
3032
|
}
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
// Create a map of HyperLiquid positions by coin for quick lookup
|
|
3015
|
-
const hlPositionsMap = new Map();
|
|
3016
|
-
hyperliquidPositions.forEach(assetPos => {
|
|
3017
|
-
var _a;
|
|
3018
|
-
if ((_a = assetPos.position) === null || _a === void 0 ? void 0 : _a.coin) {
|
|
3019
|
-
hlPositionsMap.set(assetPos.position.coin, assetPos);
|
|
3020
|
-
}
|
|
3021
|
-
});
|
|
3022
|
-
// Combine all assets for processing
|
|
3023
|
-
const allAssets = [
|
|
3024
|
-
...position.longAssets.map(asset => ({ ...asset, side: exports.PositionSide.LONG })),
|
|
3025
|
-
...position.shortAssets.map(asset => ({ ...asset, side: exports.PositionSide.SHORT }))
|
|
3026
|
-
];
|
|
3027
|
-
// Group assets by base currency for multi-pair position handling
|
|
3028
|
-
const assetsByBaseCurrency = this.groupAssetsByBaseCurrency(allAssets);
|
|
3029
|
-
// Sync each asset group with HyperLiquid data
|
|
3033
|
+
extractBaseCurrency(assetName) {
|
|
3034
|
+
return assetName.split('/')[0] || assetName;
|
|
3035
|
+
}
|
|
3036
|
+
syncPositionWithAggregateData(position, hlPositionsMap, platformTotalsByAsset) {
|
|
3030
3037
|
const syncResults = [];
|
|
3031
|
-
|
|
3038
|
+
let hasExternalModification = false;
|
|
3039
|
+
let allAssetsClosed = true;
|
|
3040
|
+
let longAssetStatuses = { total: 0, closed: 0 };
|
|
3041
|
+
let shortAssetStatuses = { total: 0, closed: 0 };
|
|
3042
|
+
// Process long assets
|
|
3043
|
+
for (const asset of position.longAssets || []) {
|
|
3044
|
+
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3032
3045
|
const hlPosition = hlPositionsMap.get(baseCurrency);
|
|
3033
|
-
const
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
const grouped = new Map();
|
|
3046
|
-
for (const asset of assets) {
|
|
3047
|
-
const baseCurrency = asset.coin.split('/')[0] || asset.coin;
|
|
3048
|
-
if (!grouped.has(baseCurrency)) {
|
|
3049
|
-
grouped.set(baseCurrency, []);
|
|
3046
|
+
const platformTotals = platformTotalsByAsset.get(baseCurrency);
|
|
3047
|
+
const syncResult = this.syncAssetWithAggregateData({ ...asset, side: PositionSide.LONG }, hlPosition, (platformTotals === null || platformTotals === void 0 ? void 0 : platformTotals.totalSize) || 0);
|
|
3048
|
+
syncResults.push(syncResult);
|
|
3049
|
+
longAssetStatuses.total++;
|
|
3050
|
+
if (syncResult.actualSize === 0) {
|
|
3051
|
+
longAssetStatuses.closed++;
|
|
3052
|
+
}
|
|
3053
|
+
if (syncResult.isExternallyModified) {
|
|
3054
|
+
hasExternalModification = true;
|
|
3055
|
+
}
|
|
3056
|
+
if (syncResult.actualSize !== 0) {
|
|
3057
|
+
allAssetsClosed = false;
|
|
3050
3058
|
}
|
|
3051
|
-
grouped.get(baseCurrency).push(asset);
|
|
3052
3059
|
}
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
// Check if the total size matches (within tolerance)
|
|
3064
|
-
const sizeDifference = Math.abs(actualTotalSize - totalPlatformSize);
|
|
3065
|
-
const sizeDifferencePercentage = totalPlatformSize > 0
|
|
3066
|
-
? (sizeDifference / totalPlatformSize) * 100
|
|
3067
|
-
: (actualTotalSize > 0 ? 100 : 0);
|
|
3068
|
-
const isGroupExternallyModified = sizeDifferencePercentage > 0.1; // 0.1% tolerance
|
|
3069
|
-
for (const asset of assets) {
|
|
3070
|
-
const platformSize = asset.platformSize;
|
|
3071
|
-
let actualSize = platformSize;
|
|
3072
|
-
let isExternallyModified = isGroupExternallyModified;
|
|
3073
|
-
let cumFunding = {
|
|
3074
|
-
allTime: 0,
|
|
3075
|
-
sinceChange: 0,
|
|
3076
|
-
sinceOpen: 0
|
|
3077
|
-
};
|
|
3078
|
-
let unrealizedPnl = 0;
|
|
3079
|
-
let liquidationPrice = 0;
|
|
3080
|
-
if (hlPosition) {
|
|
3081
|
-
// Proportionally distribute the actual size based on asset's contribution
|
|
3082
|
-
const sizeRatio = totalPlatformSize > 0 ? platformSize / totalPlatformSize : 0;
|
|
3083
|
-
actualSize = actualTotalSize * sizeRatio;
|
|
3084
|
-
// Proportionally distribute funding and PnL based on asset's contribution
|
|
3085
|
-
if (hlPosition.cumFunding) {
|
|
3086
|
-
cumFunding = {
|
|
3087
|
-
allTime: Number(hlPosition.cumFunding.allTime || 0),
|
|
3088
|
-
sinceChange: Number(hlPosition.cumFunding.sinceChange || 0) * sizeRatio,
|
|
3089
|
-
sinceOpen: Number(hlPosition.cumFunding.sinceOpen || 0) * sizeRatio
|
|
3090
|
-
};
|
|
3091
|
-
}
|
|
3092
|
-
unrealizedPnl = Number(hlPosition.position.unrealizedPnl || 0) * sizeRatio;
|
|
3093
|
-
liquidationPrice = Number(hlPosition.position.liquidationPx || 0);
|
|
3060
|
+
// Process short assets
|
|
3061
|
+
for (const asset of position.shortAssets || []) {
|
|
3062
|
+
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3063
|
+
const hlPosition = hlPositionsMap.get(baseCurrency);
|
|
3064
|
+
const platformTotals = platformTotalsByAsset.get(baseCurrency);
|
|
3065
|
+
const syncResult = this.syncAssetWithAggregateData({ ...asset, side: PositionSide.SHORT }, hlPosition, (platformTotals === null || platformTotals === void 0 ? void 0 : platformTotals.totalSize) || 0);
|
|
3066
|
+
syncResults.push(syncResult);
|
|
3067
|
+
shortAssetStatuses.total++;
|
|
3068
|
+
if (syncResult.actualSize === 0) {
|
|
3069
|
+
shortAssetStatuses.closed++;
|
|
3094
3070
|
}
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3071
|
+
if (syncResult.isExternallyModified) {
|
|
3072
|
+
hasExternalModification = true;
|
|
3073
|
+
}
|
|
3074
|
+
if (syncResult.actualSize !== 0) {
|
|
3075
|
+
allAssetsClosed = false;
|
|
3099
3076
|
}
|
|
3100
|
-
results.push({
|
|
3101
|
-
asset,
|
|
3102
|
-
actualSize,
|
|
3103
|
-
isExternallyModified,
|
|
3104
|
-
cumFunding,
|
|
3105
|
-
unrealizedPnl,
|
|
3106
|
-
liquidationPrice,
|
|
3107
|
-
side: asset.side
|
|
3108
|
-
});
|
|
3109
3077
|
}
|
|
3110
|
-
|
|
3078
|
+
const syncStatus = this.determineSyncStatus(hasExternalModification, allAssetsClosed, longAssetStatuses, shortAssetStatuses);
|
|
3079
|
+
return this.mapPositionToDtoWithSyncData(position, syncResults, syncStatus);
|
|
3111
3080
|
}
|
|
3112
|
-
|
|
3113
|
-
* Determine sync status based on asset sync results
|
|
3114
|
-
*/
|
|
3115
|
-
determineSyncStatus(syncResults) {
|
|
3116
|
-
const hasExternalModifications = syncResults.some(result => result.isExternallyModified);
|
|
3117
|
-
const allAssetsClosed = syncResults.every(result => result.actualSize === 0);
|
|
3118
|
-
const someAssetsClosed = syncResults.some(result => result.actualSize === 0) && !allAssetsClosed;
|
|
3081
|
+
determineSyncStatus(hasExternalModification, allAssetsClosed, longAssetStatuses, shortAssetStatuses) {
|
|
3119
3082
|
if (allAssetsClosed) {
|
|
3120
3083
|
return 'EXTERNALLY_CLOSED';
|
|
3121
3084
|
}
|
|
3122
|
-
|
|
3085
|
+
const allLongsClosed = longAssetStatuses.total > 0 &&
|
|
3086
|
+
longAssetStatuses.closed === longAssetStatuses.total;
|
|
3087
|
+
const allShortsClosed = shortAssetStatuses.total > 0 &&
|
|
3088
|
+
shortAssetStatuses.closed === shortAssetStatuses.total;
|
|
3089
|
+
if ((allLongsClosed && !allShortsClosed) || (!allLongsClosed && allShortsClosed)) {
|
|
3123
3090
|
return 'PAIR_BROKEN';
|
|
3124
3091
|
}
|
|
3125
|
-
|
|
3092
|
+
if (hasExternalModification) {
|
|
3126
3093
|
return 'EXTERNALLY_MODIFIED';
|
|
3127
3094
|
}
|
|
3128
3095
|
return 'SYNCED';
|
|
3129
3096
|
}
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3097
|
+
syncAssetWithAggregateData(asset, hlPosition, platformTotal) {
|
|
3098
|
+
const platformSize = Number(asset.size || 0);
|
|
3099
|
+
if (!hlPosition || !hlPosition.position || !hlPosition.position.szi) {
|
|
3100
|
+
return {
|
|
3101
|
+
asset,
|
|
3102
|
+
actualSize: 0,
|
|
3103
|
+
isExternallyModified: true,
|
|
3104
|
+
cumFunding: { allTime: 0, sinceChange: 0, sinceOpen: 0 },
|
|
3105
|
+
unrealizedPnl: 0,
|
|
3106
|
+
liquidationPrice: 0
|
|
3107
|
+
};
|
|
3108
|
+
}
|
|
3109
|
+
const hlTotalSize = Math.abs(Number(hlPosition.position.szi || 0));
|
|
3110
|
+
const totalDifference = Math.abs(hlTotalSize - platformTotal);
|
|
3111
|
+
const tolerance = platformTotal * 0.001;
|
|
3112
|
+
const isExternallyModified = totalDifference > tolerance;
|
|
3113
|
+
const proportion = platformTotal > 0 ? platformSize / platformTotal : 0;
|
|
3114
|
+
const actualSize = hlTotalSize * proportion;
|
|
3115
|
+
// Get cumFunding from hlPosition.position.cumFunding
|
|
3116
|
+
const rawCumFunding = hlPosition.position.cumFunding;
|
|
3117
|
+
const cumFunding = {
|
|
3118
|
+
allTime: Number((rawCumFunding === null || rawCumFunding === void 0 ? void 0 : rawCumFunding.allTime) || 0),
|
|
3119
|
+
sinceChange: Number((rawCumFunding === null || rawCumFunding === void 0 ? void 0 : rawCumFunding.sinceChange) || 0) * proportion,
|
|
3120
|
+
sinceOpen: Number((rawCumFunding === null || rawCumFunding === void 0 ? void 0 : rawCumFunding.sinceOpen) || 0) * proportion
|
|
3121
|
+
};
|
|
3122
|
+
const unrealizedPnl = Number(hlPosition.position.unrealizedPnl || 0) * proportion;
|
|
3123
|
+
const liquidationPrice = Number(hlPosition.position.liquidationPx || 0);
|
|
3124
|
+
return {
|
|
3125
|
+
asset,
|
|
3126
|
+
actualSize,
|
|
3127
|
+
isExternallyModified,
|
|
3128
|
+
cumFunding,
|
|
3129
|
+
unrealizedPnl,
|
|
3130
|
+
liquidationPrice
|
|
3131
|
+
};
|
|
3132
|
+
}
|
|
3133
|
+
mapPositionToDtoWithSyncData(position, syncResults, syncStatus) {
|
|
3134
|
+
var _a, _b;
|
|
3135
|
+
const longAssets = ((_a = position.longAssets) === null || _a === void 0 ? void 0 : _a.filter(asset => asset)) || [];
|
|
3136
|
+
const shortAssets = ((_b = position.shortAssets) === null || _b === void 0 ? void 0 : _b.filter(asset => asset)) || [];
|
|
3137
|
+
const syncResultsMap = new Map();
|
|
3138
|
+
syncResults.forEach(result => {
|
|
3139
|
+
syncResultsMap.set(`${result.asset.coin}-${result.asset.side}`, result);
|
|
3140
|
+
});
|
|
3137
3141
|
const currentTotalPositionValue = this.calculateCurrentTotalPositionValue(syncResults);
|
|
3138
3142
|
const entryTotalPositionValue = this.calculateEntryTotalPositionValue(syncResults);
|
|
3139
|
-
const totalMarginUsed = entryTotalPositionValue /
|
|
3143
|
+
const totalMarginUsed = entryTotalPositionValue / position.leverage;
|
|
3140
3144
|
return {
|
|
3141
|
-
|
|
3142
|
-
|
|
3145
|
+
syncStatus: syncStatus,
|
|
3146
|
+
positionId: position.positionId,
|
|
3147
|
+
address: position.address,
|
|
3148
|
+
leverage: position.leverage,
|
|
3149
|
+
stopLoss: position.stopLoss,
|
|
3150
|
+
takeProfit: position.takeProfit,
|
|
3143
3151
|
entryRatio: this.calculateEntryRatio(syncResults),
|
|
3144
3152
|
markRatio: this.calculateMarkRatio(syncResults),
|
|
3145
3153
|
netFunding: this.calculateNetFundingFromSyncResults(syncResults),
|
|
@@ -3147,117 +3155,81 @@ class PositionCalculator {
|
|
|
3147
3155
|
marginUsed: totalMarginUsed,
|
|
3148
3156
|
unrealizedPnl: this.calculateTotalUnrealizedPnlFromSyncResults(syncResults),
|
|
3149
3157
|
lastSyncAt: new Date().toISOString(),
|
|
3150
|
-
longAssets:
|
|
3151
|
-
shortAssets:
|
|
3152
|
-
|
|
3158
|
+
longAssets: longAssets.map(asset => this.mapAssetToDetailDto(asset, syncResultsMap.get(`${asset.coin}-LONG`))),
|
|
3159
|
+
shortAssets: shortAssets.map(asset => this.mapAssetToDetailDto(asset, syncResultsMap.get(`${asset.coin}-SHORT`))),
|
|
3160
|
+
createdAt: position.createdAt,
|
|
3161
|
+
updatedAt: position.updatedAt
|
|
3153
3162
|
};
|
|
3154
3163
|
}
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
const
|
|
3160
|
-
const positionValue = syncResult.actualSize * currentPrice;
|
|
3161
|
-
const entryValue = syncResult.actualSize * syncResult.asset.entryPrice;
|
|
3164
|
+
mapAssetToDetailDto(asset, syncData) {
|
|
3165
|
+
const currentPrice = this.getMarketPrice(asset.coin);
|
|
3166
|
+
const actualSize = (syncData === null || syncData === void 0 ? void 0 : syncData.actualSize) || Number(asset.size || 0);
|
|
3167
|
+
const positionValue = actualSize * currentPrice;
|
|
3168
|
+
const entryValue = Number(asset.size || 0) * Number(asset.entryPrice || 0);
|
|
3162
3169
|
return {
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3170
|
+
coin: asset.coin,
|
|
3171
|
+
entryPrice: Number(asset.entryPrice || 0),
|
|
3172
|
+
platformSize: Number(asset.size || 0),
|
|
3173
|
+
actualSize: actualSize,
|
|
3174
|
+
isExternallyModified: (syncData === null || syncData === void 0 ? void 0 : syncData.isExternallyModified) || false,
|
|
3175
|
+
cumFunding: (syncData === null || syncData === void 0 ? void 0 : syncData.cumFunding) || {
|
|
3176
|
+
allTime: 0,
|
|
3177
|
+
sinceChange: 0,
|
|
3178
|
+
sinceOpen: 0
|
|
3179
|
+
},
|
|
3167
3180
|
marginUsed: entryValue,
|
|
3168
3181
|
positionValue: positionValue,
|
|
3169
|
-
unrealizedPnl:
|
|
3170
|
-
liquidationPrice:
|
|
3182
|
+
unrealizedPnl: (syncData === null || syncData === void 0 ? void 0 : syncData.unrealizedPnl) || 0,
|
|
3183
|
+
liquidationPrice: (syncData === null || syncData === void 0 ? void 0 : syncData.liquidationPrice) || 0
|
|
3171
3184
|
};
|
|
3172
3185
|
}
|
|
3173
|
-
/**
|
|
3174
|
-
* Calculate entry ratio (weighted long entry value / weighted short entry value)
|
|
3175
|
-
*/
|
|
3176
3186
|
calculateEntryRatio(syncResults) {
|
|
3177
|
-
const longResults = syncResults.filter(result => result.side ===
|
|
3178
|
-
const shortResults = syncResults.filter(result => result.side ===
|
|
3187
|
+
const longResults = syncResults.filter(result => result.asset.side === PositionSide.LONG);
|
|
3188
|
+
const shortResults = syncResults.filter(result => result.asset.side === PositionSide.SHORT);
|
|
3179
3189
|
if (longResults.length === 0 || shortResults.length === 0)
|
|
3180
3190
|
return 0;
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
return sum + (result.actualSize * result.asset.entryPrice);
|
|
3191
|
+
const longValue = longResults.reduce((sum, result) => {
|
|
3192
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3184
3193
|
}, 0);
|
|
3185
|
-
|
|
3186
|
-
return 0;
|
|
3187
|
-
// Calculate weighted long portfolio entry value
|
|
3188
|
-
const weightedLongValue = longResults.reduce((sum, result) => {
|
|
3189
|
-
const entryPrice = result.asset.entryPrice;
|
|
3190
|
-
const assetValue = result.actualSize * entryPrice;
|
|
3191
|
-
const weight = assetValue / totalPositionValue;
|
|
3192
|
-
return sum + (entryPrice * weight);
|
|
3193
|
-
}, 0);
|
|
3194
|
-
// Calculate weighted short portfolio entry value
|
|
3195
|
-
const weightedShortValue = shortResults.reduce((sum, result) => {
|
|
3196
|
-
const entryPrice = result.asset.entryPrice;
|
|
3197
|
-
const assetValue = result.actualSize * entryPrice;
|
|
3198
|
-
const weight = assetValue / totalPositionValue;
|
|
3199
|
-
return sum + (entryPrice * weight);
|
|
3194
|
+
const shortValue = shortResults.reduce((sum, result) => {
|
|
3195
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3200
3196
|
}, 0);
|
|
3201
|
-
return
|
|
3197
|
+
return shortValue > 0 ? longValue / shortValue : 0;
|
|
3202
3198
|
}
|
|
3203
|
-
/**
|
|
3204
|
-
* Calculate mark ratio (weighted long mark value / weighted short mark value)
|
|
3205
|
-
*/
|
|
3206
3199
|
calculateMarkRatio(syncResults) {
|
|
3207
|
-
const longResults = syncResults.filter(result => result.side ===
|
|
3208
|
-
const shortResults = syncResults.filter(result => result.side ===
|
|
3200
|
+
const longResults = syncResults.filter(result => result.asset.side === PositionSide.LONG);
|
|
3201
|
+
const shortResults = syncResults.filter(result => result.asset.side === PositionSide.SHORT);
|
|
3209
3202
|
if (longResults.length === 0 || shortResults.length === 0)
|
|
3210
3203
|
return 0;
|
|
3211
|
-
|
|
3212
|
-
const totalPositionValue = syncResults.reduce((sum, result) => {
|
|
3204
|
+
const longValue = longResults.reduce((sum, result) => {
|
|
3213
3205
|
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3214
3206
|
return sum + (result.actualSize * currentPrice);
|
|
3215
3207
|
}, 0);
|
|
3216
|
-
|
|
3217
|
-
return 0;
|
|
3218
|
-
// Calculate weighted long portfolio value
|
|
3219
|
-
const weightedLongValue = longResults.reduce((sum, result) => {
|
|
3220
|
-
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3221
|
-
const assetValue = result.actualSize * currentPrice;
|
|
3222
|
-
const weight = assetValue / totalPositionValue;
|
|
3223
|
-
return sum + (currentPrice * weight);
|
|
3224
|
-
}, 0);
|
|
3225
|
-
// Calculate weighted short portfolio value
|
|
3226
|
-
const weightedShortValue = shortResults.reduce((sum, result) => {
|
|
3208
|
+
const shortValue = shortResults.reduce((sum, result) => {
|
|
3227
3209
|
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3228
|
-
|
|
3229
|
-
const weight = assetValue / totalPositionValue;
|
|
3230
|
-
return sum + (currentPrice * weight);
|
|
3210
|
+
return sum + (result.actualSize * currentPrice);
|
|
3231
3211
|
}, 0);
|
|
3232
|
-
return
|
|
3212
|
+
return shortValue > 0 ? longValue / shortValue : 0;
|
|
3233
3213
|
}
|
|
3234
|
-
/**
|
|
3235
|
-
* Calculate net funding from sync results
|
|
3236
|
-
*/
|
|
3237
3214
|
calculateNetFundingFromSyncResults(syncResults) {
|
|
3238
|
-
|
|
3215
|
+
const netFunding = syncResults.reduce((sum, result) => {
|
|
3216
|
+
const funding = result.cumFunding.sinceOpen;
|
|
3217
|
+
return sum + funding;
|
|
3218
|
+
}, 0);
|
|
3219
|
+
return netFunding;
|
|
3239
3220
|
}
|
|
3240
|
-
/**
|
|
3241
|
-
* Calculate total unrealized PnL from sync results
|
|
3242
|
-
*/
|
|
3243
3221
|
calculateTotalUnrealizedPnlFromSyncResults(syncResults) {
|
|
3244
3222
|
return syncResults.reduce((sum, result) => sum + result.unrealizedPnl, 0);
|
|
3245
3223
|
}
|
|
3246
|
-
/**
|
|
3247
|
-
* Calculate current total position value using market prices
|
|
3248
|
-
*/
|
|
3249
3224
|
calculateCurrentTotalPositionValue(syncResults) {
|
|
3250
3225
|
return syncResults.reduce((sum, result) => {
|
|
3251
3226
|
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3252
3227
|
return sum + (result.actualSize * currentPrice);
|
|
3253
3228
|
}, 0);
|
|
3254
3229
|
}
|
|
3255
|
-
/**
|
|
3256
|
-
* Calculate entry total position value using entry prices
|
|
3257
|
-
*/
|
|
3258
3230
|
calculateEntryTotalPositionValue(syncResults) {
|
|
3259
3231
|
return syncResults.reduce((sum, result) => {
|
|
3260
|
-
return sum + (result.
|
|
3232
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3261
3233
|
}, 0);
|
|
3262
3234
|
}
|
|
3263
3235
|
}
|
|
@@ -3267,32 +3239,18 @@ class PositionCalculator {
|
|
|
3267
3239
|
*/
|
|
3268
3240
|
const useCalculatedOpenPositions = (platformPositions, webData2, allMids) => {
|
|
3269
3241
|
const calculatedPositions = require$$0.useMemo(() => {
|
|
3270
|
-
var _a, _b;
|
|
3271
3242
|
// Return null if we don't have platform positions yet
|
|
3272
3243
|
if (!platformPositions) {
|
|
3273
|
-
console.log('[useCalculatedOpenPositions] No platform positions available');
|
|
3274
3244
|
return null;
|
|
3275
3245
|
}
|
|
3276
|
-
// If we don't have real-time data yet,
|
|
3246
|
+
// If we don't have real-time data yet, we can't calculate properly, return null
|
|
3277
3247
|
if (!webData2 || !allMids) {
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
hasAllMids: !!allMids,
|
|
3285
|
-
hyperliquidPositionsCount: ((_b = (_a = webData2.clearinghouseState) === null || _a === void 0 ? void 0 : _a.assetPositions) === null || _b === void 0 ? void 0 : _b.length) || 0,
|
|
3286
|
-
availableMids: Object.keys(allMids.mids || {}).length
|
|
3287
|
-
});
|
|
3288
|
-
// Create calculator and compute positions
|
|
3289
|
-
const calculator = new PositionCalculator(webData2, allMids);
|
|
3290
|
-
const calculated = calculator.calculateOpenPositions(platformPositions);
|
|
3291
|
-
console.log('[useCalculatedOpenPositions] Calculation completed', {
|
|
3292
|
-
inputCount: platformPositions.length,
|
|
3293
|
-
outputCount: calculated.length
|
|
3294
|
-
});
|
|
3295
|
-
return calculated;
|
|
3248
|
+
return null;
|
|
3249
|
+
}
|
|
3250
|
+
// Create processor and compute positions
|
|
3251
|
+
const processor = new PositionProcessor(webData2, allMids);
|
|
3252
|
+
const processed = processor.execute(platformPositions);
|
|
3253
|
+
return processed;
|
|
3296
3254
|
}, [platformPositions, webData2, allMids]);
|
|
3297
3255
|
return calculatedPositions;
|
|
3298
3256
|
};
|
|
@@ -3311,19 +3269,11 @@ class AccountSummaryCalculator {
|
|
|
3311
3269
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
3312
3270
|
// If we don't have webData2, return platform data as-is
|
|
3313
3271
|
if (!((_a = this.webData2) === null || _a === void 0 ? void 0 : _a.clearinghouseState)) {
|
|
3314
|
-
console.log('[AccountSummaryCalculator] No webData2 clearinghouseState available, returning platform data');
|
|
3315
3272
|
return platformAccountSummary;
|
|
3316
3273
|
}
|
|
3317
|
-
console.log('[AccountSummaryCalculator] Calculating account summary with real-time data', {
|
|
3318
|
-
hasPlatformSummary: !!platformAccountSummary,
|
|
3319
|
-
hasOpenOrders: !!platformOpenOrders,
|
|
3320
|
-
openOrdersCount: (platformOpenOrders === null || platformOpenOrders === void 0 ? void 0 : platformOpenOrders.length) || 0,
|
|
3321
|
-
hasAgentWallet: !!agentWalletAddress
|
|
3322
|
-
});
|
|
3323
3274
|
const clearinghouseState = this.webData2.clearinghouseState;
|
|
3324
3275
|
// Calculate total limit order value from platform orders
|
|
3325
3276
|
const totalLimitOrderValue = this.calculateTotalLimitOrderValue(platformOpenOrders || []);
|
|
3326
|
-
console.log('[AccountSummaryCalculator] Total limit order value:', totalLimitOrderValue);
|
|
3327
3277
|
// Use real-time data from webData2 clearinghouseState
|
|
3328
3278
|
const withdrawableAmount = parseFloat(clearinghouseState.withdrawable || '0');
|
|
3329
3279
|
const adjustedWithdrawable = Math.max(0, withdrawableAmount - totalLimitOrderValue);
|
|
@@ -3350,12 +3300,6 @@ class AccountSummaryCalculator {
|
|
|
3350
3300
|
status: agentWalletStatus || ((_l = platformAccountSummary === null || platformAccountSummary === void 0 ? void 0 : platformAccountSummary.agentWallet) === null || _l === void 0 ? void 0 : _l.status) || 'UNKNOWN'
|
|
3351
3301
|
}
|
|
3352
3302
|
};
|
|
3353
|
-
console.log('[AccountSummaryCalculator] Calculated account summary:', {
|
|
3354
|
-
accountValue: accountSummary.balanceSummary.crossMarginSummary.accountValue,
|
|
3355
|
-
withdrawable: accountSummary.balanceSummary.withdrawable,
|
|
3356
|
-
totalMarginUsed: accountSummary.balanceSummary.crossMarginSummary.totalMarginUsed,
|
|
3357
|
-
agentWalletAddress: accountSummary.agentWallet.address
|
|
3358
|
-
});
|
|
3359
3303
|
return accountSummary;
|
|
3360
3304
|
}
|
|
3361
3305
|
/**
|
|
@@ -3368,11 +3312,6 @@ class AccountSummaryCalculator {
|
|
|
3368
3312
|
const totalValue = openOrders
|
|
3369
3313
|
.filter(order => order.status === 'OPEN' || order.status === 'PROCESSING')
|
|
3370
3314
|
.reduce((sum, order) => sum + order.usdValue, 0);
|
|
3371
|
-
console.log('[AccountSummaryCalculator] Calculated limit order value:', {
|
|
3372
|
-
totalOrders: openOrders.length,
|
|
3373
|
-
openOrders: openOrders.filter(order => order.status === 'OPEN' || order.status === 'PROCESSING').length,
|
|
3374
|
-
totalValue
|
|
3375
|
-
});
|
|
3376
3315
|
return totalValue;
|
|
3377
3316
|
}
|
|
3378
3317
|
/**
|
|
@@ -3396,35 +3335,17 @@ class AccountSummaryCalculator {
|
|
|
3396
3335
|
*/
|
|
3397
3336
|
const useCalculatedAccountSummary = (platformAccountSummary, platformOpenOrders, webData2, agentWalletAddress, agentWalletStatus) => {
|
|
3398
3337
|
const calculatedAccountSummary = require$$0.useMemo(() => {
|
|
3399
|
-
var _a, _b, _c;
|
|
3400
3338
|
// Return null if we don't have platform account summary yet
|
|
3401
3339
|
if (!platformAccountSummary) {
|
|
3402
|
-
console.log('[useCalculatedAccountSummary] No platform account summary available');
|
|
3403
3340
|
return null;
|
|
3404
3341
|
}
|
|
3405
3342
|
// If we don't have real-time data yet, return platform summary as-is
|
|
3406
3343
|
if (!(webData2 === null || webData2 === void 0 ? void 0 : webData2.clearinghouseState)) {
|
|
3407
|
-
console.log('[useCalculatedAccountSummary] Missing webData2 clearinghouseState, returning platform summary');
|
|
3408
3344
|
return platformAccountSummary;
|
|
3409
3345
|
}
|
|
3410
|
-
console.log('[useCalculatedAccountSummary] Calculating account summary with real-time data', {
|
|
3411
|
-
hasPlatformSummary: !!platformAccountSummary,
|
|
3412
|
-
hasWebData2: !!webData2,
|
|
3413
|
-
hasClearinghouseState: !!webData2.clearinghouseState,
|
|
3414
|
-
hasOpenOrders: !!platformOpenOrders,
|
|
3415
|
-
openOrdersCount: (platformOpenOrders === null || platformOpenOrders === void 0 ? void 0 : platformOpenOrders.length) || 0,
|
|
3416
|
-
agentWalletAddress,
|
|
3417
|
-
agentWalletStatus
|
|
3418
|
-
});
|
|
3419
3346
|
// Create calculator and compute account summary
|
|
3420
3347
|
const calculator = new AccountSummaryCalculator(webData2);
|
|
3421
3348
|
const calculated = calculator.calculateAccountSummary(platformAccountSummary, platformOpenOrders, agentWalletAddress, agentWalletStatus);
|
|
3422
|
-
console.log('[useCalculatedAccountSummary] Calculation completed', {
|
|
3423
|
-
hadPlatformSummary: !!platformAccountSummary,
|
|
3424
|
-
calculatedSummary: !!calculated,
|
|
3425
|
-
withdrawable: (_a = calculated === null || calculated === void 0 ? void 0 : calculated.balanceSummary) === null || _a === void 0 ? void 0 : _a.withdrawable,
|
|
3426
|
-
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
|
|
3427
|
-
});
|
|
3428
3349
|
return calculated;
|
|
3429
3350
|
}, [platformAccountSummary, platformOpenOrders, webData2, agentWalletAddress, agentWalletStatus]);
|
|
3430
3351
|
return calculatedAccountSummary;
|
|
@@ -3480,7 +3401,6 @@ exports.AccountSummaryCalculator = AccountSummaryCalculator;
|
|
|
3480
3401
|
exports.PearHyperliquidClient = PearHyperliquidClient;
|
|
3481
3402
|
exports.PearHyperliquidProvider = PearHyperliquidProvider;
|
|
3482
3403
|
exports.PearMigrationSDK = PearMigrationSDK;
|
|
3483
|
-
exports.PositionCalculator = PositionCalculator;
|
|
3484
3404
|
exports.default = PearHyperliquidClient;
|
|
3485
3405
|
exports.useAccountSummary = useAccountSummary;
|
|
3486
3406
|
exports.useAddress = useAddress;
|