@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.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,84 +2941,76 @@ 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
|
-
* Aggregate position calculation utility class that handles cross-position asset syncing
|
|
2966
|
-
*/
|
|
2967
|
-
class AggregatePositionCalculator {
|
|
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(`[AggregatePositionCalculator] No market price found for coin: ${coin}`);
|
|
2991
2991
|
return 0;
|
|
2992
2992
|
}
|
|
2993
|
-
/**
|
|
2994
|
-
* Get user positions from webData2
|
|
2995
|
-
*/
|
|
2996
|
-
getUserPositions() {
|
|
2997
|
-
var _a, _b;
|
|
2998
|
-
return ((_b = (_a = this.webData2) === null || _a === void 0 ? void 0 : _a.clearinghouseState) === null || _b === void 0 ? void 0 : _b.assetPositions) || [];
|
|
2999
|
-
}
|
|
3000
|
-
/**
|
|
3001
|
-
* Calculate updated open positions by syncing platform positions with HyperLiquid data
|
|
3002
|
-
* Uses aggregate totals across all positions for accurate cross-position sync
|
|
3003
|
-
*/
|
|
3004
|
-
calculateOpenPositions(platformPositions) {
|
|
3005
|
-
if (!(platformPositions === null || platformPositions === void 0 ? void 0 : platformPositions.length)) {
|
|
3006
|
-
return [];
|
|
3007
|
-
}
|
|
3008
|
-
const hyperliquidPositions = this.getUserPositions();
|
|
3009
|
-
// Build a map of total platform sizes per asset across ALL positions
|
|
3010
|
-
const platformTotalsByAsset = this.calculatePlatformTotalsByAsset(platformPositions);
|
|
3011
|
-
// Create a map of HyperLiquid positions by coin
|
|
3012
|
-
const hlPositionsMap = new Map();
|
|
3013
|
-
hyperliquidPositions.forEach(assetPos => {
|
|
3014
|
-
var _a;
|
|
3015
|
-
if ((_a = assetPos.position) === null || _a === void 0 ? void 0 : _a.coin) {
|
|
3016
|
-
hlPositionsMap.set(assetPos.position.coin, assetPos);
|
|
3017
|
-
}
|
|
3018
|
-
});
|
|
3019
|
-
// Process each position with awareness of the aggregated totals
|
|
3020
|
-
return platformPositions.map(position => this.syncPositionWithAggregateData(position, hlPositionsMap, platformTotalsByAsset));
|
|
3021
|
-
}
|
|
3022
|
-
/**
|
|
3023
|
-
* Calculate total platform sizes per asset across all positions
|
|
3024
|
-
*/
|
|
3025
2993
|
calculatePlatformTotalsByAsset(positions) {
|
|
3026
2994
|
const totalsMap = new Map();
|
|
3027
2995
|
for (const position of positions) {
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
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 || []) {
|
|
3034
3014
|
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3035
3015
|
if (!totalsMap.has(baseCurrency)) {
|
|
3036
3016
|
totalsMap.set(baseCurrency, {
|
|
@@ -3039,7 +3019,7 @@ class AggregatePositionCalculator {
|
|
|
3039
3019
|
});
|
|
3040
3020
|
}
|
|
3041
3021
|
const totals = totalsMap.get(baseCurrency);
|
|
3042
|
-
const assetSize = asset.
|
|
3022
|
+
const assetSize = Number(asset.size || 0);
|
|
3043
3023
|
totals.totalSize += assetSize;
|
|
3044
3024
|
totals.positions.push({
|
|
3045
3025
|
positionId: position.positionId,
|
|
@@ -3050,47 +3030,44 @@ class AggregatePositionCalculator {
|
|
|
3050
3030
|
}
|
|
3051
3031
|
return totalsMap;
|
|
3052
3032
|
}
|
|
3053
|
-
/**
|
|
3054
|
-
* Extract base currency from asset name (handles "LINK/USD" -> "LINK")
|
|
3055
|
-
*/
|
|
3056
3033
|
extractBaseCurrency(assetName) {
|
|
3057
3034
|
return assetName.split('/')[0] || assetName;
|
|
3058
3035
|
}
|
|
3059
|
-
/**
|
|
3060
|
-
* Sync a single position with HyperLiquid data using aggregate totals
|
|
3061
|
-
*/
|
|
3062
3036
|
syncPositionWithAggregateData(position, hlPositionsMap, platformTotalsByAsset) {
|
|
3063
3037
|
const syncResults = [];
|
|
3064
3038
|
let hasExternalModification = false;
|
|
3065
3039
|
let allAssetsClosed = true;
|
|
3066
|
-
// Separate tracking for long and short sides
|
|
3067
3040
|
let longAssetStatuses = { total: 0, closed: 0 };
|
|
3068
3041
|
let shortAssetStatuses = { total: 0, closed: 0 };
|
|
3069
|
-
// Process
|
|
3070
|
-
const
|
|
3071
|
-
...position.longAssets.map(asset => ({ ...asset, side: exports.PositionSide.LONG })),
|
|
3072
|
-
...position.shortAssets.map(asset => ({ ...asset, side: exports.PositionSide.SHORT }))
|
|
3073
|
-
];
|
|
3074
|
-
for (const asset of allAssets) {
|
|
3042
|
+
// Process long assets
|
|
3043
|
+
for (const asset of position.longAssets || []) {
|
|
3075
3044
|
const baseCurrency = this.extractBaseCurrency(asset.coin);
|
|
3076
3045
|
const hlPosition = hlPositionsMap.get(baseCurrency);
|
|
3077
3046
|
const platformTotals = platformTotalsByAsset.get(baseCurrency);
|
|
3078
|
-
const syncResult = this.syncAssetWithAggregateData(asset, hlPosition, (platformTotals === null || platformTotals === void 0 ? void 0 : platformTotals.totalSize) || 0);
|
|
3047
|
+
const syncResult = this.syncAssetWithAggregateData({ ...asset, side: PositionSide.LONG }, hlPosition, (platformTotals === null || platformTotals === void 0 ? void 0 : platformTotals.totalSize) || 0);
|
|
3079
3048
|
syncResults.push(syncResult);
|
|
3080
|
-
|
|
3081
|
-
if (
|
|
3082
|
-
longAssetStatuses.
|
|
3083
|
-
if (syncResult.actualSize === 0) {
|
|
3084
|
-
longAssetStatuses.closed++;
|
|
3085
|
-
}
|
|
3049
|
+
longAssetStatuses.total++;
|
|
3050
|
+
if (syncResult.actualSize === 0) {
|
|
3051
|
+
longAssetStatuses.closed++;
|
|
3086
3052
|
}
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3053
|
+
if (syncResult.isExternallyModified) {
|
|
3054
|
+
hasExternalModification = true;
|
|
3055
|
+
}
|
|
3056
|
+
if (syncResult.actualSize !== 0) {
|
|
3057
|
+
allAssetsClosed = false;
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
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++;
|
|
3092
3070
|
}
|
|
3093
|
-
// Update flags
|
|
3094
3071
|
if (syncResult.isExternallyModified) {
|
|
3095
3072
|
hasExternalModification = true;
|
|
3096
3073
|
}
|
|
@@ -3098,17 +3075,27 @@ class AggregatePositionCalculator {
|
|
|
3098
3075
|
allAssetsClosed = false;
|
|
3099
3076
|
}
|
|
3100
3077
|
}
|
|
3101
|
-
// Determine sync status
|
|
3102
3078
|
const syncStatus = this.determineSyncStatus(hasExternalModification, allAssetsClosed, longAssetStatuses, shortAssetStatuses);
|
|
3103
|
-
return this.
|
|
3079
|
+
return this.mapPositionToDtoWithSyncData(position, syncResults, syncStatus);
|
|
3080
|
+
}
|
|
3081
|
+
determineSyncStatus(hasExternalModification, allAssetsClosed, longAssetStatuses, shortAssetStatuses) {
|
|
3082
|
+
if (allAssetsClosed) {
|
|
3083
|
+
return 'EXTERNALLY_CLOSED';
|
|
3084
|
+
}
|
|
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)) {
|
|
3090
|
+
return 'PAIR_BROKEN';
|
|
3091
|
+
}
|
|
3092
|
+
if (hasExternalModification) {
|
|
3093
|
+
return 'EXTERNALLY_MODIFIED';
|
|
3094
|
+
}
|
|
3095
|
+
return 'SYNCED';
|
|
3104
3096
|
}
|
|
3105
|
-
/**
|
|
3106
|
-
* Sync individual asset with aggregate data awareness
|
|
3107
|
-
*/
|
|
3108
3097
|
syncAssetWithAggregateData(asset, hlPosition, platformTotal) {
|
|
3109
|
-
|
|
3110
|
-
const platformSize = asset.platformSize;
|
|
3111
|
-
// No position on HyperLiquid - asset was closed
|
|
3098
|
+
const platformSize = Number(asset.size || 0);
|
|
3112
3099
|
if (!hlPosition || !hlPosition.position || !hlPosition.position.szi) {
|
|
3113
3100
|
return {
|
|
3114
3101
|
asset,
|
|
@@ -3116,27 +3103,23 @@ class AggregatePositionCalculator {
|
|
|
3116
3103
|
isExternallyModified: true,
|
|
3117
3104
|
cumFunding: { allTime: 0, sinceChange: 0, sinceOpen: 0 },
|
|
3118
3105
|
unrealizedPnl: 0,
|
|
3119
|
-
liquidationPrice: 0
|
|
3120
|
-
side: asset.side
|
|
3106
|
+
liquidationPrice: 0
|
|
3121
3107
|
};
|
|
3122
3108
|
}
|
|
3123
3109
|
const hlTotalSize = Math.abs(Number(hlPosition.position.szi || 0));
|
|
3124
|
-
// Check if the TOTAL platform size matches HyperLiquid total
|
|
3125
3110
|
const totalDifference = Math.abs(hlTotalSize - platformTotal);
|
|
3126
|
-
const tolerance = platformTotal * 0.001;
|
|
3111
|
+
const tolerance = platformTotal * 0.001;
|
|
3127
3112
|
const isExternallyModified = totalDifference > tolerance;
|
|
3128
|
-
// Calculate this position's proportional share of the HyperLiquid position
|
|
3129
3113
|
const proportion = platformTotal > 0 ? platformSize / platformTotal : 0;
|
|
3130
3114
|
const actualSize = hlTotalSize * proportion;
|
|
3131
|
-
//
|
|
3115
|
+
// Get cumFunding from hlPosition.position.cumFunding
|
|
3116
|
+
const rawCumFunding = hlPosition.position.cumFunding;
|
|
3132
3117
|
const cumFunding = {
|
|
3133
|
-
allTime: Number((
|
|
3134
|
-
sinceChange: Number((
|
|
3135
|
-
sinceOpen: Number((
|
|
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
|
|
3136
3121
|
};
|
|
3137
|
-
// Distribute PnL proportionally
|
|
3138
3122
|
const unrealizedPnl = Number(hlPosition.position.unrealizedPnl || 0) * proportion;
|
|
3139
|
-
// Liquidation price is the same for all positions of the same asset
|
|
3140
3123
|
const liquidationPrice = Number(hlPosition.position.liquidationPx || 0);
|
|
3141
3124
|
return {
|
|
3142
3125
|
asset,
|
|
@@ -3144,46 +3127,27 @@ class AggregatePositionCalculator {
|
|
|
3144
3127
|
isExternallyModified,
|
|
3145
3128
|
cumFunding,
|
|
3146
3129
|
unrealizedPnl,
|
|
3147
|
-
liquidationPrice
|
|
3148
|
-
side: asset.side
|
|
3130
|
+
liquidationPrice
|
|
3149
3131
|
};
|
|
3150
3132
|
}
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
}
|
|
3159
|
-
// Check if pair is broken (one entire side closed)
|
|
3160
|
-
const allLongsClosed = longAssetStatuses.total > 0 &&
|
|
3161
|
-
longAssetStatuses.closed === longAssetStatuses.total;
|
|
3162
|
-
const allShortsClosed = shortAssetStatuses.total > 0 &&
|
|
3163
|
-
shortAssetStatuses.closed === shortAssetStatuses.total;
|
|
3164
|
-
if ((allLongsClosed && !allShortsClosed) || (!allLongsClosed && allShortsClosed)) {
|
|
3165
|
-
return 'PAIR_BROKEN';
|
|
3166
|
-
}
|
|
3167
|
-
// External modification detected
|
|
3168
|
-
if (hasExternalModification) {
|
|
3169
|
-
return 'EXTERNALLY_MODIFIED';
|
|
3170
|
-
}
|
|
3171
|
-
// Everything synced properly
|
|
3172
|
-
return 'SYNCED';
|
|
3173
|
-
}
|
|
3174
|
-
/**
|
|
3175
|
-
* Build updated position with synced data
|
|
3176
|
-
*/
|
|
3177
|
-
buildUpdatedPosition(originalPosition, syncResults, syncStatus) {
|
|
3178
|
-
const longSyncResults = syncResults.filter(result => result.side === exports.PositionSide.LONG);
|
|
3179
|
-
const shortSyncResults = syncResults.filter(result => result.side === exports.PositionSide.SHORT);
|
|
3180
|
-
// Calculate position metrics
|
|
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
|
+
});
|
|
3181
3141
|
const currentTotalPositionValue = this.calculateCurrentTotalPositionValue(syncResults);
|
|
3182
3142
|
const entryTotalPositionValue = this.calculateEntryTotalPositionValue(syncResults);
|
|
3183
|
-
const totalMarginUsed = entryTotalPositionValue /
|
|
3143
|
+
const totalMarginUsed = entryTotalPositionValue / position.leverage;
|
|
3184
3144
|
return {
|
|
3185
|
-
|
|
3186
|
-
|
|
3145
|
+
syncStatus: syncStatus,
|
|
3146
|
+
positionId: position.positionId,
|
|
3147
|
+
address: position.address,
|
|
3148
|
+
leverage: position.leverage,
|
|
3149
|
+
stopLoss: position.stopLoss,
|
|
3150
|
+
takeProfit: position.takeProfit,
|
|
3187
3151
|
entryRatio: this.calculateEntryRatio(syncResults),
|
|
3188
3152
|
markRatio: this.calculateMarkRatio(syncResults),
|
|
3189
3153
|
netFunding: this.calculateNetFundingFromSyncResults(syncResults),
|
|
@@ -3191,51 +3155,50 @@ class AggregatePositionCalculator {
|
|
|
3191
3155
|
marginUsed: totalMarginUsed,
|
|
3192
3156
|
unrealizedPnl: this.calculateTotalUnrealizedPnlFromSyncResults(syncResults),
|
|
3193
3157
|
lastSyncAt: new Date().toISOString(),
|
|
3194
|
-
longAssets:
|
|
3195
|
-
shortAssets:
|
|
3196
|
-
|
|
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
|
|
3197
3162
|
};
|
|
3198
3163
|
}
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
const
|
|
3204
|
-
const positionValue = syncResult.actualSize * currentPrice;
|
|
3205
|
-
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);
|
|
3206
3169
|
return {
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
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
|
+
},
|
|
3211
3180
|
marginUsed: entryValue,
|
|
3212
3181
|
positionValue: positionValue,
|
|
3213
|
-
unrealizedPnl:
|
|
3214
|
-
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
|
|
3215
3184
|
};
|
|
3216
3185
|
}
|
|
3217
|
-
/**
|
|
3218
|
-
* Calculate entry ratio using actual sizes from sync results
|
|
3219
|
-
*/
|
|
3220
3186
|
calculateEntryRatio(syncResults) {
|
|
3221
|
-
const longResults = syncResults.filter(result => result.side ===
|
|
3222
|
-
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);
|
|
3223
3189
|
if (longResults.length === 0 || shortResults.length === 0)
|
|
3224
3190
|
return 0;
|
|
3225
3191
|
const longValue = longResults.reduce((sum, result) => {
|
|
3226
|
-
return sum + (result.
|
|
3192
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3227
3193
|
}, 0);
|
|
3228
3194
|
const shortValue = shortResults.reduce((sum, result) => {
|
|
3229
|
-
return sum + (result.
|
|
3195
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3230
3196
|
}, 0);
|
|
3231
3197
|
return shortValue > 0 ? longValue / shortValue : 0;
|
|
3232
3198
|
}
|
|
3233
|
-
/**
|
|
3234
|
-
* Calculate mark ratio using actual sizes and current prices
|
|
3235
|
-
*/
|
|
3236
3199
|
calculateMarkRatio(syncResults) {
|
|
3237
|
-
const longResults = syncResults.filter(result => result.side ===
|
|
3238
|
-
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);
|
|
3239
3202
|
if (longResults.length === 0 || shortResults.length === 0)
|
|
3240
3203
|
return 0;
|
|
3241
3204
|
const longValue = longResults.reduce((sum, result) => {
|
|
@@ -3248,33 +3211,25 @@ class AggregatePositionCalculator {
|
|
|
3248
3211
|
}, 0);
|
|
3249
3212
|
return shortValue > 0 ? longValue / shortValue : 0;
|
|
3250
3213
|
}
|
|
3251
|
-
/**
|
|
3252
|
-
* Calculate net funding from sync results
|
|
3253
|
-
*/
|
|
3254
3214
|
calculateNetFundingFromSyncResults(syncResults) {
|
|
3255
|
-
|
|
3215
|
+
const netFunding = syncResults.reduce((sum, result) => {
|
|
3216
|
+
const funding = result.cumFunding.sinceOpen;
|
|
3217
|
+
return sum + funding;
|
|
3218
|
+
}, 0);
|
|
3219
|
+
return netFunding;
|
|
3256
3220
|
}
|
|
3257
|
-
/**
|
|
3258
|
-
* Calculate total unrealized PnL from sync results
|
|
3259
|
-
*/
|
|
3260
3221
|
calculateTotalUnrealizedPnlFromSyncResults(syncResults) {
|
|
3261
3222
|
return syncResults.reduce((sum, result) => sum + result.unrealizedPnl, 0);
|
|
3262
3223
|
}
|
|
3263
|
-
/**
|
|
3264
|
-
* Calculate current total position value using market prices
|
|
3265
|
-
*/
|
|
3266
3224
|
calculateCurrentTotalPositionValue(syncResults) {
|
|
3267
3225
|
return syncResults.reduce((sum, result) => {
|
|
3268
3226
|
const currentPrice = this.getMarketPrice(result.asset.coin);
|
|
3269
3227
|
return sum + (result.actualSize * currentPrice);
|
|
3270
3228
|
}, 0);
|
|
3271
3229
|
}
|
|
3272
|
-
/**
|
|
3273
|
-
* Calculate entry total position value using entry prices
|
|
3274
|
-
*/
|
|
3275
3230
|
calculateEntryTotalPositionValue(syncResults) {
|
|
3276
3231
|
return syncResults.reduce((sum, result) => {
|
|
3277
|
-
return sum + (result.
|
|
3232
|
+
return sum + (Number(result.asset.size || 0) * Number(result.asset.entryPrice || 0));
|
|
3278
3233
|
}, 0);
|
|
3279
3234
|
}
|
|
3280
3235
|
}
|
|
@@ -3284,32 +3239,18 @@ class AggregatePositionCalculator {
|
|
|
3284
3239
|
*/
|
|
3285
3240
|
const useCalculatedOpenPositions = (platformPositions, webData2, allMids) => {
|
|
3286
3241
|
const calculatedPositions = require$$0.useMemo(() => {
|
|
3287
|
-
var _a, _b;
|
|
3288
3242
|
// Return null if we don't have platform positions yet
|
|
3289
3243
|
if (!platformPositions) {
|
|
3290
|
-
console.log('[useCalculatedOpenPositions] No platform positions available');
|
|
3291
3244
|
return null;
|
|
3292
3245
|
}
|
|
3293
|
-
// 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
|
|
3294
3247
|
if (!webData2 || !allMids) {
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
hasAllMids: !!allMids,
|
|
3302
|
-
hyperliquidPositionsCount: ((_b = (_a = webData2.clearinghouseState) === null || _a === void 0 ? void 0 : _a.assetPositions) === null || _b === void 0 ? void 0 : _b.length) || 0,
|
|
3303
|
-
availableMids: Object.keys(allMids.mids || {}).length
|
|
3304
|
-
});
|
|
3305
|
-
// Create calculator and compute positions
|
|
3306
|
-
const calculator = new AggregatePositionCalculator(webData2, allMids);
|
|
3307
|
-
const calculated = calculator.calculateOpenPositions(platformPositions);
|
|
3308
|
-
console.log('[useCalculatedOpenPositions] Calculation completed', {
|
|
3309
|
-
inputCount: platformPositions.length,
|
|
3310
|
-
outputCount: calculated.length
|
|
3311
|
-
});
|
|
3312
|
-
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;
|
|
3313
3254
|
}, [platformPositions, webData2, allMids]);
|
|
3314
3255
|
return calculatedPositions;
|
|
3315
3256
|
};
|
|
@@ -3328,19 +3269,11 @@ class AccountSummaryCalculator {
|
|
|
3328
3269
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
3329
3270
|
// If we don't have webData2, return platform data as-is
|
|
3330
3271
|
if (!((_a = this.webData2) === null || _a === void 0 ? void 0 : _a.clearinghouseState)) {
|
|
3331
|
-
console.log('[AccountSummaryCalculator] No webData2 clearinghouseState available, returning platform data');
|
|
3332
3272
|
return platformAccountSummary;
|
|
3333
3273
|
}
|
|
3334
|
-
console.log('[AccountSummaryCalculator] Calculating account summary with real-time data', {
|
|
3335
|
-
hasPlatformSummary: !!platformAccountSummary,
|
|
3336
|
-
hasOpenOrders: !!platformOpenOrders,
|
|
3337
|
-
openOrdersCount: (platformOpenOrders === null || platformOpenOrders === void 0 ? void 0 : platformOpenOrders.length) || 0,
|
|
3338
|
-
hasAgentWallet: !!agentWalletAddress
|
|
3339
|
-
});
|
|
3340
3274
|
const clearinghouseState = this.webData2.clearinghouseState;
|
|
3341
3275
|
// Calculate total limit order value from platform orders
|
|
3342
3276
|
const totalLimitOrderValue = this.calculateTotalLimitOrderValue(platformOpenOrders || []);
|
|
3343
|
-
console.log('[AccountSummaryCalculator] Total limit order value:', totalLimitOrderValue);
|
|
3344
3277
|
// Use real-time data from webData2 clearinghouseState
|
|
3345
3278
|
const withdrawableAmount = parseFloat(clearinghouseState.withdrawable || '0');
|
|
3346
3279
|
const adjustedWithdrawable = Math.max(0, withdrawableAmount - totalLimitOrderValue);
|
|
@@ -3367,12 +3300,6 @@ class AccountSummaryCalculator {
|
|
|
3367
3300
|
status: agentWalletStatus || ((_l = platformAccountSummary === null || platformAccountSummary === void 0 ? void 0 : platformAccountSummary.agentWallet) === null || _l === void 0 ? void 0 : _l.status) || 'UNKNOWN'
|
|
3368
3301
|
}
|
|
3369
3302
|
};
|
|
3370
|
-
console.log('[AccountSummaryCalculator] Calculated account summary:', {
|
|
3371
|
-
accountValue: accountSummary.balanceSummary.crossMarginSummary.accountValue,
|
|
3372
|
-
withdrawable: accountSummary.balanceSummary.withdrawable,
|
|
3373
|
-
totalMarginUsed: accountSummary.balanceSummary.crossMarginSummary.totalMarginUsed,
|
|
3374
|
-
agentWalletAddress: accountSummary.agentWallet.address
|
|
3375
|
-
});
|
|
3376
3303
|
return accountSummary;
|
|
3377
3304
|
}
|
|
3378
3305
|
/**
|
|
@@ -3385,11 +3312,6 @@ class AccountSummaryCalculator {
|
|
|
3385
3312
|
const totalValue = openOrders
|
|
3386
3313
|
.filter(order => order.status === 'OPEN' || order.status === 'PROCESSING')
|
|
3387
3314
|
.reduce((sum, order) => sum + order.usdValue, 0);
|
|
3388
|
-
console.log('[AccountSummaryCalculator] Calculated limit order value:', {
|
|
3389
|
-
totalOrders: openOrders.length,
|
|
3390
|
-
openOrders: openOrders.filter(order => order.status === 'OPEN' || order.status === 'PROCESSING').length,
|
|
3391
|
-
totalValue
|
|
3392
|
-
});
|
|
3393
3315
|
return totalValue;
|
|
3394
3316
|
}
|
|
3395
3317
|
/**
|
|
@@ -3413,35 +3335,17 @@ class AccountSummaryCalculator {
|
|
|
3413
3335
|
*/
|
|
3414
3336
|
const useCalculatedAccountSummary = (platformAccountSummary, platformOpenOrders, webData2, agentWalletAddress, agentWalletStatus) => {
|
|
3415
3337
|
const calculatedAccountSummary = require$$0.useMemo(() => {
|
|
3416
|
-
var _a, _b, _c;
|
|
3417
3338
|
// Return null if we don't have platform account summary yet
|
|
3418
3339
|
if (!platformAccountSummary) {
|
|
3419
|
-
console.log('[useCalculatedAccountSummary] No platform account summary available');
|
|
3420
3340
|
return null;
|
|
3421
3341
|
}
|
|
3422
3342
|
// If we don't have real-time data yet, return platform summary as-is
|
|
3423
3343
|
if (!(webData2 === null || webData2 === void 0 ? void 0 : webData2.clearinghouseState)) {
|
|
3424
|
-
console.log('[useCalculatedAccountSummary] Missing webData2 clearinghouseState, returning platform summary');
|
|
3425
3344
|
return platformAccountSummary;
|
|
3426
3345
|
}
|
|
3427
|
-
console.log('[useCalculatedAccountSummary] Calculating account summary with real-time data', {
|
|
3428
|
-
hasPlatformSummary: !!platformAccountSummary,
|
|
3429
|
-
hasWebData2: !!webData2,
|
|
3430
|
-
hasClearinghouseState: !!webData2.clearinghouseState,
|
|
3431
|
-
hasOpenOrders: !!platformOpenOrders,
|
|
3432
|
-
openOrdersCount: (platformOpenOrders === null || platformOpenOrders === void 0 ? void 0 : platformOpenOrders.length) || 0,
|
|
3433
|
-
agentWalletAddress,
|
|
3434
|
-
agentWalletStatus
|
|
3435
|
-
});
|
|
3436
3346
|
// Create calculator and compute account summary
|
|
3437
3347
|
const calculator = new AccountSummaryCalculator(webData2);
|
|
3438
3348
|
const calculated = calculator.calculateAccountSummary(platformAccountSummary, platformOpenOrders, agentWalletAddress, agentWalletStatus);
|
|
3439
|
-
console.log('[useCalculatedAccountSummary] Calculation completed', {
|
|
3440
|
-
hadPlatformSummary: !!platformAccountSummary,
|
|
3441
|
-
calculatedSummary: !!calculated,
|
|
3442
|
-
withdrawable: (_a = calculated === null || calculated === void 0 ? void 0 : calculated.balanceSummary) === null || _a === void 0 ? void 0 : _a.withdrawable,
|
|
3443
|
-
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
|
|
3444
|
-
});
|
|
3445
3349
|
return calculated;
|
|
3446
3350
|
}, [platformAccountSummary, platformOpenOrders, webData2, agentWalletAddress, agentWalletStatus]);
|
|
3447
3351
|
return calculatedAccountSummary;
|
|
@@ -3494,7 +3398,6 @@ const useAccountSummary = () => {
|
|
|
3494
3398
|
};
|
|
3495
3399
|
|
|
3496
3400
|
exports.AccountSummaryCalculator = AccountSummaryCalculator;
|
|
3497
|
-
exports.AggregatePositionCalculator = AggregatePositionCalculator;
|
|
3498
3401
|
exports.PearHyperliquidClient = PearHyperliquidClient;
|
|
3499
3402
|
exports.PearHyperliquidProvider = PearHyperliquidProvider;
|
|
3500
3403
|
exports.PearMigrationSDK = PearMigrationSDK;
|