@pear-protocol/hyperliquid-sdk 0.1.27 → 0.1.29
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/index.d.ts +1 -0
- package/dist/index.js +181 -40
- package/dist/store/userSelection.d.ts +1 -1
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -820,22 +820,13 @@ function validateClosePositionRequest(payload) {
|
|
|
820
820
|
}
|
|
821
821
|
|
|
822
822
|
const DEFAULT_STATE = {
|
|
823
|
-
longTokens: [
|
|
824
|
-
|
|
825
|
-
{ symbol: "BTC", weight: 25 },
|
|
826
|
-
],
|
|
827
|
-
shortTokens: [
|
|
828
|
-
{ symbol: "AVAX", weight: 10 },
|
|
829
|
-
{ symbol: "SEI", weight: 10 },
|
|
830
|
-
{ symbol: "ADA", weight: 10 },
|
|
831
|
-
{ symbol: "TRUMP", weight: 10 },
|
|
832
|
-
{ symbol: "SUI", weight: 10 },
|
|
833
|
-
],
|
|
823
|
+
longTokens: [],
|
|
824
|
+
shortTokens: [],
|
|
834
825
|
openTokenSelector: false,
|
|
835
826
|
selectorConfig: null,
|
|
836
827
|
openConflictModal: false,
|
|
837
828
|
conflicts: [],
|
|
838
|
-
candleInterval:
|
|
829
|
+
candleInterval: '1h',
|
|
839
830
|
isWeightBalanced: true,
|
|
840
831
|
};
|
|
841
832
|
const useUserSelection$1 = create((set, get) => ({
|
|
@@ -855,7 +846,11 @@ const useUserSelection$1 = create((set, get) => ({
|
|
|
855
846
|
const longTotal = updated.reduce((sum, t) => sum + t.weight, 0);
|
|
856
847
|
const shortTotal = prev.shortTokens.reduce((sum, t) => sum + t.weight, 0);
|
|
857
848
|
const isWeightBalanced = longTotal + shortTotal === 100;
|
|
858
|
-
return {
|
|
849
|
+
return {
|
|
850
|
+
...prev,
|
|
851
|
+
longTokens: updated,
|
|
852
|
+
isWeightBalanced,
|
|
853
|
+
};
|
|
859
854
|
}
|
|
860
855
|
else {
|
|
861
856
|
const updated = [...prev.shortTokens];
|
|
@@ -863,7 +858,11 @@ const useUserSelection$1 = create((set, get) => ({
|
|
|
863
858
|
const longTotal = prev.longTokens.reduce((sum, t) => sum + t.weight, 0);
|
|
864
859
|
const shortTotal = updated.reduce((sum, t) => sum + t.weight, 0);
|
|
865
860
|
const isWeightBalanced = longTotal + shortTotal === 100;
|
|
866
|
-
return {
|
|
861
|
+
return {
|
|
862
|
+
...prev,
|
|
863
|
+
shortTokens: updated,
|
|
864
|
+
isWeightBalanced,
|
|
865
|
+
};
|
|
867
866
|
}
|
|
868
867
|
});
|
|
869
868
|
},
|
|
@@ -892,14 +891,22 @@ const useUserSelection$1 = create((set, get) => ({
|
|
|
892
891
|
const longTotal = updated.reduce((sum, t) => sum + t.weight, 0);
|
|
893
892
|
const shortTotal = prev.shortTokens.reduce((sum, t) => sum + t.weight, 0);
|
|
894
893
|
const isWeightBalanced = longTotal + shortTotal === 100;
|
|
895
|
-
return {
|
|
894
|
+
return {
|
|
895
|
+
...prev,
|
|
896
|
+
longTokens: updated,
|
|
897
|
+
isWeightBalanced,
|
|
898
|
+
};
|
|
896
899
|
}
|
|
897
900
|
else {
|
|
898
901
|
const updated = prev.shortTokens.filter((_, i) => i !== index);
|
|
899
902
|
const longTotal = prev.longTokens.reduce((sum, t) => sum + t.weight, 0);
|
|
900
903
|
const shortTotal = updated.reduce((sum, t) => sum + t.weight, 0);
|
|
901
904
|
const isWeightBalanced = longTotal + shortTotal === 100;
|
|
902
|
-
return {
|
|
905
|
+
return {
|
|
906
|
+
...prev,
|
|
907
|
+
shortTokens: updated,
|
|
908
|
+
isWeightBalanced,
|
|
909
|
+
};
|
|
903
910
|
}
|
|
904
911
|
});
|
|
905
912
|
},
|
|
@@ -965,6 +972,20 @@ const useUserSelection$1 = create((set, get) => ({
|
|
|
965
972
|
resetToDefaults: () => set((prev) => ({ ...prev, ...DEFAULT_STATE })),
|
|
966
973
|
}));
|
|
967
974
|
|
|
975
|
+
const CANDLE_STALE_WARNING_MS = 90000;
|
|
976
|
+
const getCandleSubscriptionKey = (coin, interval) => `${coin}:${interval}`;
|
|
977
|
+
const debugHyperliquidWs = (message, payload) => {
|
|
978
|
+
if (typeof window === "undefined")
|
|
979
|
+
return;
|
|
980
|
+
if (window.localStorage.getItem("pear:debug:hl-ws") !== "1")
|
|
981
|
+
return;
|
|
982
|
+
if (payload === undefined) {
|
|
983
|
+
console.debug(`[HyperLiquid WS] ${message}`);
|
|
984
|
+
}
|
|
985
|
+
else {
|
|
986
|
+
console.debug(`[HyperLiquid WS] ${message}`, payload);
|
|
987
|
+
}
|
|
988
|
+
};
|
|
968
989
|
const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }) => {
|
|
969
990
|
const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAtOICaps, setAggregatedClearingHouseState, setRawClearinghouseStates, setAssetContextsByDex, } = useHyperliquidData();
|
|
970
991
|
const { setSpotState, setUserAbstractionMode } = useUserData();
|
|
@@ -979,7 +1000,10 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
979
1000
|
const [subscribedCandleTokens, setSubscribedCandleTokens] = useState([]);
|
|
980
1001
|
const [clearinghouseStateReceived, setClearinghouseStateReceived] = useState(false);
|
|
981
1002
|
const prevCandleIntervalRef = useRef(null);
|
|
1003
|
+
const currentCandleIntervalRef = useRef(candleInterval);
|
|
982
1004
|
const prevActiveAssetAddressRef = useRef(null);
|
|
1005
|
+
const lastCandleMessageAtRef = useRef(null);
|
|
1006
|
+
const lastCandleBySubscriptionRef = useRef(new Map());
|
|
983
1007
|
const pingIntervalRef = useRef(null);
|
|
984
1008
|
const wsRef = useRef(null);
|
|
985
1009
|
const reconnectAttemptsRef = useRef(0);
|
|
@@ -991,8 +1015,11 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
991
1015
|
useEffect(() => {
|
|
992
1016
|
onUserFillsRef.current = onUserFills;
|
|
993
1017
|
}, [onUserFills]);
|
|
1018
|
+
useEffect(() => {
|
|
1019
|
+
currentCandleIntervalRef.current = candleInterval;
|
|
1020
|
+
}, [candleInterval]);
|
|
994
1021
|
const handleMessage = useCallback((event) => {
|
|
995
|
-
var _a;
|
|
1022
|
+
var _a, _b;
|
|
996
1023
|
try {
|
|
997
1024
|
const message = JSON.parse(event.data);
|
|
998
1025
|
// Handle subscription responses
|
|
@@ -1090,7 +1117,27 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1090
1117
|
{
|
|
1091
1118
|
const candleDataItem = response.data;
|
|
1092
1119
|
const symbol = candleDataItem.s || "";
|
|
1120
|
+
const messageInterval = (_b = candleDataItem.i) !== null && _b !== void 0 ? _b : currentCandleIntervalRef.current;
|
|
1121
|
+
if (messageInterval !== currentCandleIntervalRef.current) {
|
|
1122
|
+
debugHyperliquidWs("ignoring stale candle interval", {
|
|
1123
|
+
symbol,
|
|
1124
|
+
messageInterval,
|
|
1125
|
+
currentInterval: currentCandleIntervalRef.current,
|
|
1126
|
+
t: candleDataItem.t,
|
|
1127
|
+
T: candleDataItem.T,
|
|
1128
|
+
});
|
|
1129
|
+
break;
|
|
1130
|
+
}
|
|
1093
1131
|
addCandleData(symbol, candleDataItem);
|
|
1132
|
+
const now = Date.now();
|
|
1133
|
+
lastCandleMessageAtRef.current = now;
|
|
1134
|
+
lastCandleBySubscriptionRef.current.set(getCandleSubscriptionKey(symbol, messageInterval), now);
|
|
1135
|
+
debugHyperliquidWs("candle received", {
|
|
1136
|
+
symbol,
|
|
1137
|
+
interval: messageInterval,
|
|
1138
|
+
t: candleDataItem.t,
|
|
1139
|
+
T: candleDataItem.T,
|
|
1140
|
+
});
|
|
1094
1141
|
}
|
|
1095
1142
|
break;
|
|
1096
1143
|
case "spotState":
|
|
@@ -1159,6 +1206,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1159
1206
|
setSubscribedAddress(null);
|
|
1160
1207
|
setSubscribedTokens([]);
|
|
1161
1208
|
setSubscribedCandleTokens([]);
|
|
1209
|
+
lastCandleBySubscriptionRef.current.clear();
|
|
1162
1210
|
setClearinghouseStateReceived(false);
|
|
1163
1211
|
if (!manualCloseRef.current) {
|
|
1164
1212
|
reconnectAttemptsRef.current += 1;
|
|
@@ -1190,6 +1238,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1190
1238
|
setSubscribedAddress(null);
|
|
1191
1239
|
setSubscribedTokens([]);
|
|
1192
1240
|
setSubscribedCandleTokens([]);
|
|
1241
|
+
lastCandleBySubscriptionRef.current.clear();
|
|
1193
1242
|
setClearinghouseStateReceived(false);
|
|
1194
1243
|
// Close existing socket if in a bad state
|
|
1195
1244
|
if (wsRef.current &&
|
|
@@ -1479,9 +1528,13 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1479
1528
|
if (!isConnected)
|
|
1480
1529
|
return;
|
|
1481
1530
|
const effectiveTokens = selectedTokenSymbols;
|
|
1482
|
-
// Unsubscribe from previous candle subscriptions if interval changed
|
|
1483
1531
|
const prevInterval = prevCandleIntervalRef.current;
|
|
1484
|
-
|
|
1532
|
+
const intervalChanged = prevInterval !== null && prevInterval !== candleInterval;
|
|
1533
|
+
const activeSubscribedCandleTokens = intervalChanged
|
|
1534
|
+
? []
|
|
1535
|
+
: subscribedCandleTokens;
|
|
1536
|
+
// Unsubscribe from previous candle subscriptions if interval changed
|
|
1537
|
+
if (intervalChanged && prevInterval !== null) {
|
|
1485
1538
|
subscribedCandleTokens.forEach((token) => {
|
|
1486
1539
|
const unsubscribeMessage = {
|
|
1487
1540
|
method: "unsubscribe",
|
|
@@ -1492,12 +1545,17 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1492
1545
|
},
|
|
1493
1546
|
};
|
|
1494
1547
|
sendJsonMessage(unsubscribeMessage);
|
|
1548
|
+
lastCandleBySubscriptionRef.current.delete(getCandleSubscriptionKey(token, prevInterval));
|
|
1549
|
+
debugHyperliquidWs("candle unsubscribe", {
|
|
1550
|
+
token,
|
|
1551
|
+
interval: prevInterval,
|
|
1552
|
+
reason: "interval-change",
|
|
1553
|
+
});
|
|
1495
1554
|
});
|
|
1496
1555
|
setCandleData(new Map());
|
|
1497
|
-
setSubscribedCandleTokens([]);
|
|
1498
1556
|
}
|
|
1499
|
-
const tokensToSubscribe = effectiveTokens.filter((token) => token && !
|
|
1500
|
-
const tokensToUnsubscribe =
|
|
1557
|
+
const tokensToSubscribe = effectiveTokens.filter((token) => token && !activeSubscribedCandleTokens.includes(token));
|
|
1558
|
+
const tokensToUnsubscribe = activeSubscribedCandleTokens.filter((token) => !effectiveTokens.includes(token));
|
|
1501
1559
|
// Unsubscribe from tokens no longer in the list
|
|
1502
1560
|
tokensToUnsubscribe.forEach((token) => {
|
|
1503
1561
|
const unsubscribeMessage = {
|
|
@@ -1509,6 +1567,12 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1509
1567
|
},
|
|
1510
1568
|
};
|
|
1511
1569
|
sendJsonMessage(unsubscribeMessage);
|
|
1570
|
+
lastCandleBySubscriptionRef.current.delete(getCandleSubscriptionKey(token, candleInterval));
|
|
1571
|
+
debugHyperliquidWs("candle unsubscribe", {
|
|
1572
|
+
token,
|
|
1573
|
+
interval: candleInterval,
|
|
1574
|
+
reason: "token-removed",
|
|
1575
|
+
});
|
|
1512
1576
|
});
|
|
1513
1577
|
// Subscribe to new tokens
|
|
1514
1578
|
tokensToSubscribe.forEach((token) => {
|
|
@@ -1521,6 +1585,11 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1521
1585
|
},
|
|
1522
1586
|
};
|
|
1523
1587
|
sendJsonMessage(subscribeMessage);
|
|
1588
|
+
lastCandleBySubscriptionRef.current.delete(getCandleSubscriptionKey(token, candleInterval));
|
|
1589
|
+
debugHyperliquidWs("candle subscribe", {
|
|
1590
|
+
token,
|
|
1591
|
+
interval: candleInterval,
|
|
1592
|
+
});
|
|
1524
1593
|
});
|
|
1525
1594
|
// Update subscribed state
|
|
1526
1595
|
if (tokensToSubscribe.length > 0 ||
|
|
@@ -1537,7 +1606,48 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1537
1606
|
subscribedCandleTokens,
|
|
1538
1607
|
sendJsonMessage,
|
|
1539
1608
|
setCandleData,
|
|
1609
|
+
deleteCandleSymbol,
|
|
1540
1610
|
]);
|
|
1611
|
+
useEffect(() => {
|
|
1612
|
+
if (!isConnected)
|
|
1613
|
+
return;
|
|
1614
|
+
const checkCandleSubscriptionHealth = () => {
|
|
1615
|
+
const effectiveTokens = selectedTokenSymbols.filter((token) => token);
|
|
1616
|
+
if (effectiveTokens.length === 0)
|
|
1617
|
+
return;
|
|
1618
|
+
const now = Date.now();
|
|
1619
|
+
const missingSubscriptionState = effectiveTokens.filter((token) => !subscribedCandleTokens.includes(token));
|
|
1620
|
+
const missingCandles = effectiveTokens.filter((token) => {
|
|
1621
|
+
const key = getCandleSubscriptionKey(token, candleInterval);
|
|
1622
|
+
return !lastCandleBySubscriptionRef.current.has(key);
|
|
1623
|
+
});
|
|
1624
|
+
const staleCandles = effectiveTokens.filter((token) => {
|
|
1625
|
+
const key = getCandleSubscriptionKey(token, candleInterval);
|
|
1626
|
+
const lastSeenAt = lastCandleBySubscriptionRef.current.get(key);
|
|
1627
|
+
return (lastSeenAt !== undefined &&
|
|
1628
|
+
now - lastSeenAt > CANDLE_STALE_WARNING_MS);
|
|
1629
|
+
});
|
|
1630
|
+
if (missingSubscriptionState.length === 0 &&
|
|
1631
|
+
missingCandles.length === 0 &&
|
|
1632
|
+
staleCandles.length === 0) {
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
debugHyperliquidWs("candle subscription health", {
|
|
1636
|
+
interval: candleInterval,
|
|
1637
|
+
selectedTokens: effectiveTokens,
|
|
1638
|
+
subscribedTokens: subscribedCandleTokens,
|
|
1639
|
+
missingSubscriptionState,
|
|
1640
|
+
missingCandles,
|
|
1641
|
+
staleCandles,
|
|
1642
|
+
lastAnyCandleAgeMs: lastCandleMessageAtRef.current === null
|
|
1643
|
+
? null
|
|
1644
|
+
: now - lastCandleMessageAtRef.current,
|
|
1645
|
+
});
|
|
1646
|
+
};
|
|
1647
|
+
checkCandleSubscriptionHealth();
|
|
1648
|
+
const healthInterval = setInterval(checkCandleSubscriptionHealth, 30000);
|
|
1649
|
+
return () => clearInterval(healthInterval);
|
|
1650
|
+
}, [isConnected, selectedTokenSymbols, candleInterval, subscribedCandleTokens]);
|
|
1541
1651
|
return {
|
|
1542
1652
|
isConnected,
|
|
1543
1653
|
lastError,
|
|
@@ -6626,6 +6736,22 @@ const computeBasketCandles = (longTokens, shortTokens, tokenCandles) => {
|
|
|
6626
6736
|
return basketCandles;
|
|
6627
6737
|
};
|
|
6628
6738
|
|
|
6739
|
+
const CANDLE_INTERVAL_MS = {
|
|
6740
|
+
'1m': 60 * 1000,
|
|
6741
|
+
'3m': 3 * 60 * 1000,
|
|
6742
|
+
'5m': 5 * 60 * 1000,
|
|
6743
|
+
'15m': 15 * 60 * 1000,
|
|
6744
|
+
'30m': 30 * 60 * 1000,
|
|
6745
|
+
'1h': 60 * 60 * 1000,
|
|
6746
|
+
'2h': 2 * 60 * 60 * 1000,
|
|
6747
|
+
'4h': 4 * 60 * 60 * 1000,
|
|
6748
|
+
'8h': 8 * 60 * 60 * 1000,
|
|
6749
|
+
'12h': 12 * 60 * 60 * 1000,
|
|
6750
|
+
'1d': 24 * 60 * 60 * 1000,
|
|
6751
|
+
'3d': 3 * 24 * 60 * 60 * 1000,
|
|
6752
|
+
'1w': 7 * 24 * 60 * 60 * 1000,
|
|
6753
|
+
'1M': 30 * 24 * 60 * 60 * 1000,
|
|
6754
|
+
};
|
|
6629
6755
|
/**
|
|
6630
6756
|
* Composes historical price fetching with basket candle computation.
|
|
6631
6757
|
* - Listens to `longTokens` and `shortTokens` from user selection.
|
|
@@ -6635,6 +6761,7 @@ const computeBasketCandles = (longTokens, shortTokens, tokenCandles) => {
|
|
|
6635
6761
|
const useBasketCandles = () => {
|
|
6636
6762
|
const longTokens = useUserSelection$1((state) => state.longTokens);
|
|
6637
6763
|
const shortTokens = useUserSelection$1((state) => state.shortTokens);
|
|
6764
|
+
const candleInterval = useUserSelection$1((state) => state.candleInterval);
|
|
6638
6765
|
const candleData = useHyperliquidData((s) => s.candleData);
|
|
6639
6766
|
const { fetchHistoricalPriceData, isLoading: tokenLoading, getAllHistoricalPriceData, getEffectiveDataBoundary } = useHistoricalPriceData();
|
|
6640
6767
|
const fetchBasketCandles = useCallback(async (startTime, endTime, interval) => {
|
|
@@ -6740,40 +6867,56 @@ const useBasketCandles = () => {
|
|
|
6740
6867
|
const removeRealtimeListener = useCallback((id) => {
|
|
6741
6868
|
listenersRef.current.delete(id);
|
|
6742
6869
|
}, []);
|
|
6743
|
-
// Helper: compute weighted bar from latest snapshot
|
|
6870
|
+
// Helper: compute weighted bar from latest snapshot, carrying forward lagging
|
|
6871
|
+
// symbols so one sparse feed does not suppress every realtime chart update.
|
|
6744
6872
|
const computeRealtimeBar = useCallback(() => {
|
|
6745
6873
|
if (!candleData)
|
|
6746
6874
|
return null;
|
|
6747
6875
|
const allTokens = [...longTokens, ...shortTokens];
|
|
6748
6876
|
if (allTokens.length === 0)
|
|
6749
6877
|
return null;
|
|
6750
|
-
// Collect candles, ensure presence and alignment
|
|
6751
6878
|
const symbolSet = new Set(allTokens.map((t) => t.symbol));
|
|
6752
6879
|
const snapshot = {};
|
|
6880
|
+
let t = null;
|
|
6881
|
+
let T = null;
|
|
6753
6882
|
for (const symbol of symbolSet) {
|
|
6754
6883
|
const c = candleData.get(symbol);
|
|
6755
6884
|
if (!c)
|
|
6756
6885
|
return null; // missing latest candle for symbol
|
|
6757
6886
|
snapshot[symbol] = c;
|
|
6758
|
-
|
|
6759
|
-
// Verify same interval window (t and T match across symbols)
|
|
6760
|
-
let t = null;
|
|
6761
|
-
let T = null;
|
|
6762
|
-
for (const symbol of symbolSet) {
|
|
6763
|
-
const c = snapshot[symbol];
|
|
6764
|
-
if (t === null) {
|
|
6887
|
+
if (t === null || c.t > t) {
|
|
6765
6888
|
t = c.t;
|
|
6766
6889
|
T = c.T;
|
|
6767
6890
|
}
|
|
6768
|
-
else if (c.t !== t || c.T !== T) {
|
|
6769
|
-
return null; // not aligned yet
|
|
6770
|
-
}
|
|
6771
6891
|
}
|
|
6892
|
+
if (t === null || T === null)
|
|
6893
|
+
return null;
|
|
6894
|
+
const intervalMs = CANDLE_INTERVAL_MS[candleInterval];
|
|
6895
|
+
const maxCarryForwardMs = intervalMs * 2;
|
|
6896
|
+
const getCandleForTargetWindow = (symbol) => {
|
|
6897
|
+
const c = snapshot[symbol];
|
|
6898
|
+
if (c.t === t)
|
|
6899
|
+
return c;
|
|
6900
|
+
if (c.t > t || t - c.t > maxCarryForwardMs)
|
|
6901
|
+
return null;
|
|
6902
|
+
const price = c.c;
|
|
6903
|
+
if (!(price > 0))
|
|
6904
|
+
return null;
|
|
6905
|
+
return {
|
|
6906
|
+
s: c.s,
|
|
6907
|
+
t,
|
|
6908
|
+
T,
|
|
6909
|
+
o: price,
|
|
6910
|
+
h: price,
|
|
6911
|
+
l: price,
|
|
6912
|
+
c: price,
|
|
6913
|
+
};
|
|
6914
|
+
};
|
|
6772
6915
|
// Compute weighted OHLC similar to computeBasketCandles
|
|
6773
6916
|
let longOpen = 1, longHigh = 1, longLow = 1, longClose = 1;
|
|
6774
6917
|
let shortOpen = 1, shortHigh = 1, shortLow = 1, shortClose = 1;
|
|
6775
6918
|
for (const token of longTokens) {
|
|
6776
|
-
const c =
|
|
6919
|
+
const c = getCandleForTargetWindow(token.symbol);
|
|
6777
6920
|
if (!c)
|
|
6778
6921
|
return null;
|
|
6779
6922
|
const w = token.weight / 100;
|
|
@@ -6786,7 +6929,7 @@ const useBasketCandles = () => {
|
|
|
6786
6929
|
longClose *= Math.pow(cl, w);
|
|
6787
6930
|
}
|
|
6788
6931
|
for (const token of shortTokens) {
|
|
6789
|
-
const c =
|
|
6932
|
+
const c = getCandleForTargetWindow(token.symbol);
|
|
6790
6933
|
if (!c)
|
|
6791
6934
|
return null;
|
|
6792
6935
|
const w = -(token.weight / 100);
|
|
@@ -6798,8 +6941,6 @@ const useBasketCandles = () => {
|
|
|
6798
6941
|
shortLow *= Math.pow(l, w);
|
|
6799
6942
|
shortClose *= Math.pow(cl, w);
|
|
6800
6943
|
}
|
|
6801
|
-
if (t === null || T === null)
|
|
6802
|
-
return null;
|
|
6803
6944
|
const weighted = {
|
|
6804
6945
|
t,
|
|
6805
6946
|
T,
|
|
@@ -6809,8 +6950,8 @@ const useBasketCandles = () => {
|
|
|
6809
6950
|
c: longClose * shortClose,
|
|
6810
6951
|
};
|
|
6811
6952
|
return weighted;
|
|
6812
|
-
}, [candleData, longTokens, shortTokens]);
|
|
6813
|
-
// Emit realtime bars when
|
|
6953
|
+
}, [candleData, candleInterval, longTokens, shortTokens]);
|
|
6954
|
+
// Emit realtime bars when the latest snapshot can produce a valid bar.
|
|
6814
6955
|
useEffect(() => {
|
|
6815
6956
|
if (listenersRef.current.size === 0)
|
|
6816
6957
|
return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CandleInterval, TokenConflict, TokenSelection, TokenSelectorConfig } from
|
|
1
|
+
import type { CandleInterval, TokenConflict, TokenSelection, TokenSelectorConfig } from '../types';
|
|
2
2
|
interface UserSelectionState {
|
|
3
3
|
longTokens: TokenSelection[];
|
|
4
4
|
shortTokens: TokenSelection[];
|
package/dist/types.d.ts
CHANGED