Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit 7f3cc56

Browse files
feat: use reward state for reward components (#1492)
* chore(BABY): Keep the useRewardState to reward components --------- Co-authored-by: wjrjerome <[email protected]>
1 parent d00eca5 commit 7f3cc56

File tree

3 files changed

+57
-85
lines changed

3 files changed

+57
-85
lines changed

src/ui/baby/components/RewardPreviewModal/index.tsx

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import {
55
DialogHeader,
66
Text,
77
} from "@babylonlabs-io/core-ui";
8-
import { PropsWithChildren, useEffect, useState } from "react";
8+
import { useEffect, useState } from "react";
99

1010
import babylon from "@/infrastructure/babylon";
11+
import { useRewardState } from "@/ui/baby/state/RewardState";
1112
import { ResponsiveDialog } from "@/ui/common/components/Modals/ResponsiveDialog";
1213
import { getNetworkConfigBBN } from "@/ui/common/config/network/bbn";
1314
import { useCosmosWallet } from "@/ui/common/context/wallet/CosmosWalletProvider";
@@ -19,27 +20,17 @@ import { maxDecimals } from "@/ui/common/utils/maxDecimals";
1920

2021
const { coinSymbol, displayUSD } = getNetworkConfigBBN();
2122

22-
interface PreviewModalProps {
23-
open: boolean;
24-
processing?: boolean;
25-
title: string;
26-
onClose: () => void;
27-
onProceed: () => void;
28-
rewards: Array<{ validatorAddress: string }>;
29-
totalReward: bigint;
30-
}
31-
32-
export const RewardsPreviewModal = ({
33-
open,
34-
processing = false,
35-
title,
36-
onClose,
37-
onProceed,
38-
rewards,
39-
totalReward,
40-
}: PropsWithChildren<PreviewModalProps>) => {
23+
export const RewardsPreviewModal = () => {
4124
const { bech32Address } = useCosmosWallet();
4225
const { estimateBbnGasFee } = useBbnTransaction();
26+
const {
27+
totalReward,
28+
rewards,
29+
showClaimModal: open,
30+
loading: processing,
31+
closeClaimModal: onClose,
32+
claimAll: onProceed,
33+
} = useRewardState();
4334
const babyPrice = usePrice(coinSymbol);
4435
const [feeAmount, setFeeAmount] = useState<number>(0);
4536
const [feeLoading, setFeeLoading] = useState<boolean>(false);
@@ -51,7 +42,7 @@ export const RewardsPreviewModal = ({
5142

5243
setFeeLoading(true);
5344
try {
54-
const msgs = rewards.map((reward) =>
45+
const msgs = rewards.map((reward: { validatorAddress: string }) =>
5546
babylon.txs.baby.createClaimRewardMsg({
5647
validatorAddress: reward.validatorAddress,
5748
delegatorAddress: bech32Address,
@@ -85,7 +76,7 @@ export const RewardsPreviewModal = ({
8576
: undefined;
8677
return (
8778
<ResponsiveDialog open={open} onClose={onClose}>
88-
<DialogHeader title={title} className="text-accent-primary" />
79+
<DialogHeader title="Claim Rewards" className="text-accent-primary" />
8980

9081
<DialogBody className="no-scrollbar mb-[40px] mt-8 flex max-h-[calc(100vh-12rem)] flex-col gap-[40px] overflow-y-auto text-accent-primary">
9182
<div className="flex flex-col gap-4">
Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useQuery, useQueryClient } from "@tanstack/react-query";
1+
import { useQueryClient } from "@tanstack/react-query";
22
import { useEffect, useRef } from "react";
33

44
import babylon from "@/infrastructure/babylon";
@@ -9,54 +9,52 @@ import { usePendingOperationsService } from "../services/usePendingOperationsSer
99
import { BABY_DELEGATIONS_KEY } from "./useDelegations";
1010
import { BABY_UNBONDING_DELEGATIONS_KEY } from "./useUnbondingDelegations";
1111

12-
const BABYLON_CURRENT_EPOCH_KEY = "BABYLON_CURRENT_EPOCH";
13-
1412
export function useEpochPolling(address?: string) {
1513
const queryClient = useQueryClient();
1614
const previousEpochRef = useRef<number | undefined>(undefined);
1715
const { cleanupAllPendingOperationsFromStorage } =
1816
usePendingOperationsService();
19-
20-
const { data: currentEpoch } = useQuery<number, Error>({
21-
queryKey: [BABYLON_CURRENT_EPOCH_KEY],
22-
queryFn: async () => {
23-
const client = await babylon.client();
24-
const { currentEpoch } = await client.baby.getCurrentEpoch();
25-
return currentEpoch;
26-
},
27-
refetchInterval: ONE_MINUTE,
28-
// Only poll if we have an address (user is connected)
29-
enabled: Boolean(address),
30-
});
17+
const cleanupRef = useRef(cleanupAllPendingOperationsFromStorage);
18+
cleanupRef.current = cleanupAllPendingOperationsFromStorage;
3119

3220
useEffect(() => {
33-
if (currentEpoch === undefined) return;
34-
35-
if (previousEpochRef.current === undefined) {
36-
previousEpochRef.current = currentEpoch;
37-
return;
38-
}
39-
40-
if (currentEpoch !== previousEpochRef.current) {
41-
// Clean up all pending operations from localStorage (everything from
42-
// previous epochs is finalized)
43-
cleanupAllPendingOperationsFromStorage();
44-
45-
// Invalidate all delegation queries since epoch change affects entire
46-
// blockchain state
47-
queryClient.invalidateQueries({
48-
queryKey: [BABY_DELEGATIONS_KEY],
49-
});
50-
// Also invalidate unbonding delegations since they're epoch-dependent
51-
queryClient.invalidateQueries({
52-
queryKey: [BABY_UNBONDING_DELEGATIONS_KEY],
53-
});
54-
previousEpochRef.current = currentEpoch;
55-
}
56-
}, [
57-
currentEpoch,
58-
queryClient,
59-
address,
60-
cleanupAllPendingOperationsFromStorage,
61-
]);
21+
if (!address) return;
22+
23+
let cancelled = false;
24+
25+
const checkEpoch = async () => {
26+
try {
27+
const client = await babylon.client();
28+
const { currentEpoch } = await client.baby.getCurrentEpoch();
29+
30+
if (previousEpochRef.current === undefined) {
31+
previousEpochRef.current = currentEpoch;
32+
return;
33+
}
34+
35+
if (!cancelled && currentEpoch !== previousEpochRef.current) {
36+
cleanupRef.current?.();
37+
38+
queryClient.invalidateQueries({
39+
queryKey: [BABY_DELEGATIONS_KEY],
40+
refetchType: "active",
41+
});
42+
queryClient.invalidateQueries({
43+
queryKey: [BABY_UNBONDING_DELEGATIONS_KEY],
44+
refetchType: "active",
45+
});
46+
previousEpochRef.current = currentEpoch;
47+
}
48+
} catch {
49+
// ignore transient errors
50+
}
51+
};
52+
53+
checkEpoch();
54+
const id = setInterval(checkEpoch, ONE_MINUTE);
55+
return () => {
56+
cancelled = true;
57+
clearInterval(id);
58+
};
59+
}, [address, queryClient]);
6260
}

src/ui/baby/layout.tsx

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useWalletConnect } from "@babylonlabs-io/wallet-connector";
22
import { useEffect, useState } from "react";
33

44
import { DelegationState } from "@/ui/baby/state/DelegationState";
5-
import { RewardState, useRewardState } from "@/ui/baby/state/RewardState";
5+
import { RewardState } from "@/ui/baby/state/RewardState";
66
import { StakingState } from "@/ui/baby/state/StakingState";
77
import { ValidatorState } from "@/ui/baby/state/ValidatorState";
88
import { AuthGuard } from "@/ui/common/components/Common/AuthGuard";
@@ -53,28 +53,11 @@ function BabyLayoutContent() {
5353
useEpochPolling(bech32Address);
5454

5555
const RewardsTab: React.FC = () => {
56-
const {
57-
showClaimModal,
58-
closeClaimModal,
59-
claimAll,
60-
loading: rewardLoading,
61-
totalReward,
62-
rewards,
63-
} = useRewardState();
64-
6556
return (
6657
<Section>
6758
<div className="h-[500px]">
6859
<RewardCard />
69-
<RewardsPreviewModal
70-
open={showClaimModal}
71-
processing={rewardLoading}
72-
title="Claim Rewards"
73-
totalReward={totalReward}
74-
rewards={rewards}
75-
onClose={closeClaimModal}
76-
onProceed={claimAll}
77-
/>
60+
<RewardsPreviewModal />
7861
</div>
7962
</Section>
8063
);

0 commit comments

Comments
 (0)