Skip to content

Commit

Permalink
Merge pull request #604 from valory-xyz/tanya/fix-flickering
Browse files Browse the repository at this point in the history
fix: start agent button and earned tag flickering
  • Loading branch information
Tanya-atatakai authored Dec 19, 2024
2 parents 6650ba3 + a524d62 commit 817e045
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 62 deletions.
15 changes: 9 additions & 6 deletions frontend/components/MainPage/header/AgentButton/AgentButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ import { AgentStartingButton } from './AgentStartingButton';
import { AgentStoppingButton } from './AgentStoppingButton';

export const AgentButton = () => {
const { selectedService, isFetched, selectedServiceStatusOverride } =
useServices();
const {
selectedService,
isLoading: isServicesLoading,
selectedServiceStatusOverride,
} = useServices();

const {
isEligibleForStaking,
isAgentEvicted,
isSelectedStakingContractDetailsLoaded,
isSelectedStakingContractDetailsLoading,
} = useActiveStakingContractDetails();

const button = useMemo(() => {
if (!isFetched || !isSelectedStakingContractDetailsLoaded) {
if (isServicesLoading || isSelectedStakingContractDetailsLoading) {
return (
<Button type="primary" size="large" disabled loading>
Loading...
Expand Down Expand Up @@ -65,8 +68,8 @@ export const AgentButton = () => {

return <CannotStartAgentDueToUnexpectedError />;
}, [
isFetched,
isSelectedStakingContractDetailsLoaded,
isServicesLoading,
isSelectedStakingContractDetailsLoading,
selectedServiceStatusOverride,
selectedService,
isEligibleForStaking,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,15 @@ export const NoAvailableSlotsOnTheContract = () => {
selectedStakingProgramMeta,
} = useStakingProgram();

const {
isServiceStaked,
isSelectedStakingContractDetailsLoaded:
isActiveStakingContractDetailsLoaded,
} = useActiveStakingContractDetails();
const { isServiceStaked, isSelectedStakingContractDetailsLoading } =
useActiveStakingContractDetails();

const { hasEnoughServiceSlots } = useStakingContractDetails(
selectedStakingProgramId,
);

if (!isActiveStakingProgramLoaded) return null;
if (!isActiveStakingContractDetailsLoaded) return null;
if (isSelectedStakingContractDetailsLoading) return null;

if (hasEnoughServiceSlots) return null;
if (isServiceStaked) return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const useEpochEndTime = () => {
return { data, isLoading };
};

/**
* Staking rewards for the current epoch
*/
export const StakingRewardsThisEpoch = () => {
const { data: epochEndTimeInMs } = useEpochEndTime();

Expand Down
19 changes: 13 additions & 6 deletions frontend/components/MainPage/sections/RewardsSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,25 @@ const DisplayRewards = () => {
const {
availableRewardsForEpochEth,
isEligibleForRewards,
isStakingRewardsDetailsFetched,
isStakingRewardsDetailsLoading,
isStakingRewardsDetailsError,
} = useReward();
const { isLoaded: isBalancesLoaded } = useBalanceContext();
const reward = getFormattedReward(availableRewardsForEpochEth);

const earnedTag = useMemo(() => {
if (!isStakingRewardsDetailsFetched) return <Skeleton.Input size="small" />;
if (!isEligibleForRewards) {
return <Tag color="processing">Not yet earned</Tag>;
if (isStakingRewardsDetailsLoading && !isStakingRewardsDetailsError) {
return <Skeleton.Input size="small" />;
}
return <Tag color="success">Earned</Tag>;
}, [isEligibleForRewards, isStakingRewardsDetailsFetched]);
if (isEligibleForRewards) {
return <Tag color="success">Earned</Tag>;
}
return <Tag color="processing">Not yet earned</Tag>;
}, [
isEligibleForRewards,
isStakingRewardsDetailsLoading,
isStakingRewardsDetailsError,
]);

return (
<CardSection vertical gap={8} padding="16px 24px" align="start">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,19 @@ export const MigrateButton = ({
useStakingProgram();
const {
selectedStakingContractDetails,
isSelectedStakingContractDetailsLoaded,
isSelectedStakingContractDetailsLoading,
} = useActiveStakingContractDetails();
const { stakingContractInfo: defaultStakingContractInfo } =
useStakingContractDetails(defaultStakingProgramId);

const currentStakingContractInfo = useMemo(() => {
if (!isSelectedStakingContractDetailsLoaded) return;
if (isSelectedStakingContractDetailsLoading) return;
if (selectedStakingContractDetails) return selectedStakingContractDetails;
return defaultStakingContractInfo;
}, [
selectedStakingContractDetails,
defaultStakingContractInfo,
isSelectedStakingContractDetailsLoaded,
isSelectedStakingContractDetailsLoading,
]);

const { setMigrationModalOpen } = useModals();
Expand Down
28 changes: 16 additions & 12 deletions frontend/context/RewardProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export const RewardContext = createContext<{
optimisticRewardsEarnedForEpoch?: number;
minimumStakedAmountRequired?: number;
updateRewards: () => Promise<void>;
isStakingRewardsDetailsFetched?: boolean;
isStakingRewardsDetailsLoading?: boolean;
isStakingRewardsDetailsError?: boolean;
}>({
updateRewards: async () => {},
});
Expand Down Expand Up @@ -62,23 +63,24 @@ const useStakingRewardsDetails = () => {
token!,
),
queryFn: async () => {
if (!multisig || !token || !selectedStakingProgramId) return null;
const response =
await selectedAgentConfig.serviceApi.getAgentStakingRewardsInfo({
agentMultisigAddress: multisig,
serviceId: token,
stakingProgramId: selectedStakingProgramId,
chainId: currentChainId,
});
try {
const response =
await selectedAgentConfig.serviceApi.getAgentStakingRewardsInfo({
agentMultisigAddress: multisig!,
serviceId: token!,
stakingProgramId: selectedStakingProgramId!,
chainId: currentChainId,
});

if (!response) return null;
if (!response) return null;

try {
const parsed = StakingRewardsInfoSchema.parse(response);
return parsed;
} catch (e) {
console.error('Error parsing staking rewards info', e);
}

return null;
},
enabled:
!!isOnline &&
Expand Down Expand Up @@ -137,6 +139,7 @@ export const RewardProvider = ({ children }: PropsWithChildren) => {
data: stakingRewardsDetails,
refetch: refetchStakingRewardsDetails,
isLoading: isStakingRewardsDetailsLoading,
isError: isStakingRewardsDetailsError,
} = useStakingRewardsDetails();

const {
Expand Down Expand Up @@ -187,7 +190,8 @@ export const RewardProvider = ({ children }: PropsWithChildren) => {
isEligibleForRewards,
optimisticRewardsEarnedForEpoch,
updateRewards,
isStakingRewardsDetailsFetched: !isStakingRewardsDetailsLoading,
isStakingRewardsDetailsLoading,
isStakingRewardsDetailsError,
}}
>
{children}
Expand Down
10 changes: 5 additions & 5 deletions frontend/context/StakingContractDetailsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ const useStakingContractDetailsByStakingProgram = ({
return Promise.allSettled(promises).then((results) => {
const [stakingContractDetails, serviceStakingDetails] = results;
return {
...(stakingContractDetails.status === 'fulfilled'
...(stakingContractDetails?.status === 'fulfilled'
? (stakingContractDetails.value as StakingContractDetails)
: {}),
...(serviceStakingDetails.status === 'fulfilled'
...(serviceStakingDetails?.status === 'fulfilled'
? (serviceStakingDetails.value as ServiceStakingDetails)
: {}),
};
Expand All @@ -141,7 +141,7 @@ type StakingContractDetailsContextProps = {
selectedStakingContractDetails: Maybe<
Partial<StakingContractDetails & ServiceStakingDetails>
>;
isSelectedStakingContractDetailsLoaded: boolean;
isSelectedStakingContractDetailsLoading: boolean;
isPaused: boolean;
allStakingContractDetailsRecord?: Record<
StakingProgramId,
Expand All @@ -160,7 +160,7 @@ export const StakingContractDetailsContext =
selectedStakingContractDetails: null,
isPaused: false,
isAllStakingContractDetailsRecordLoaded: false,
isSelectedStakingContractDetailsLoaded: false,
isSelectedStakingContractDetailsLoading: false,
refetchSelectedStakingContractDetails: async () => {},
setIsPaused: () => {},
});
Expand Down Expand Up @@ -196,7 +196,7 @@ export const StakingContractDetailsProvider = ({
<StakingContractDetailsContext.Provider
value={{
selectedStakingContractDetails,
isSelectedStakingContractDetailsLoaded: !isLoading,
isSelectedStakingContractDetailsLoading: isLoading,
isAllStakingContractDetailsRecordLoaded:
isAllStakingContractDetailsLoaded,
allStakingContractDetailsRecord,
Expand Down
14 changes: 7 additions & 7 deletions frontend/context/StakingProgramProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ const useGetActiveStakingProgramId = (serviceNftTokenId: Maybe<number>) => {

const { serviceApi, evmHomeChainId } = selectedAgentConfig;

const isQueryEnabled =
!isNil(evmHomeChainId) && isServicesLoaded && !!serviceNftTokenId;

const response = useQuery({
queryKey: REACT_QUERY_KEYS.STAKING_PROGRAM_KEY(evmHomeChainId),
queryKey: REACT_QUERY_KEYS.STAKING_PROGRAM_KEY(
evmHomeChainId,
serviceNftTokenId!,
),
queryFn: async () => {
if (!serviceNftTokenId) return null;
if (!Number(serviceNftTokenId)) return null;
Expand All @@ -56,8 +56,8 @@ const useGetActiveStakingProgramId = (serviceNftTokenId: Maybe<number>) => {
DEFAULT_STAKING_PROGRAM_IDS[selectedAgentConfig.evmHomeChainId]
);
},
// enabled: isQueryEnabled,
refetchInterval: isQueryEnabled ? FIVE_SECONDS_INTERVAL : false,
enabled: !isNil(evmHomeChainId) && isServicesLoaded && !!serviceNftTokenId,
refetchInterval: FIVE_SECONDS_INTERVAL,
});

const setActiveStakingProgramId = useCallback(
Expand All @@ -80,7 +80,7 @@ const useGetActiveStakingProgramId = (serviceNftTokenId: Maybe<number>) => {
[queryClient, evmHomeChainId, serviceNftTokenId],
);

return { ...response, isEnabled: isQueryEnabled, setActiveStakingProgramId };
return { ...response, setActiveStakingProgramId };
};

/**
Expand Down
9 changes: 4 additions & 5 deletions frontend/hooks/useNotifyOnNewEpoch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@ export const useNotifyOnNewEpoch = () => {

const {
selectedStakingContractDetails: activeStakingContractDetails,
isSelectedStakingContractDetailsLoaded:
isActiveStakingContractDetailsLoaded,
isSelectedStakingContractDetailsLoading,
} = useActiveStakingContractDetails();
const epoch = activeStakingContractDetails?.epochCounter;

const [epochStatusNotification, setEpochStatusNotification] =
useState<EpochStatusNotification | null>(null);

useEffect(() => {
// if active staking contract info is not loaded yet, return
if (!isActiveStakingContractDetailsLoaded) return;
// if active staking contract info is still loading, return
if (isSelectedStakingContractDetailsLoading) return;

// if agent is running, no need to show notification
if (isServiceRunning) return;
Expand Down Expand Up @@ -60,7 +59,7 @@ export const useNotifyOnNewEpoch = () => {
}, [
epochStatusNotification,
epoch,
isActiveStakingContractDetailsLoaded,
isSelectedStakingContractDetailsLoading,
showNotification,
isServiceRunning,
]);
Expand Down
6 changes: 4 additions & 2 deletions frontend/hooks/useReward.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ export const useReward = () => {
availableRewardsForEpochEth,
isEligibleForRewards,
accruedServiceStakingRewards,
isStakingRewardsDetailsFetched,
isStakingRewardsDetailsLoading,
isStakingRewardsDetailsError,
} = useContext(RewardContext);

return {
availableRewardsForEpoch,
availableRewardsForEpochEth,
isEligibleForRewards,
accruedServiceStakingRewards,
isStakingRewardsDetailsFetched,
isStakingRewardsDetailsLoading,
isStakingRewardsDetailsError,
};
};
4 changes: 2 additions & 2 deletions frontend/hooks/useStakingContractDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const useStakingContractContext = () =>
export const useActiveStakingContractDetails = () => {
const {
selectedStakingContractDetails,
isSelectedStakingContractDetailsLoaded,
isSelectedStakingContractDetailsLoading,
// allStakingContractDetailsRecord,
// refetchActiveStakingContractDetails,
// isPaused,
Expand Down Expand Up @@ -93,7 +93,7 @@ export const useActiveStakingContractDetails = () => {
isServiceStakedForMinimumDuration,
isServiceStaked,
evictionExpiresAt,
isSelectedStakingContractDetailsLoaded,
isSelectedStakingContractDetailsLoading,
selectedStakingContractDetails,
hasEnoughRewardsAndSlots,
hasEnoughServiceSlots,
Expand Down
20 changes: 12 additions & 8 deletions frontend/service/agents/Memeooor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export abstract class MemeooorBaseService extends StakedAgentService {
stakingTokenProxyContract.minStakingDeposit(),
stakingTokenProxyContract.tsCheckpoint(),
activityChecker.livenessRatio(),
activityChecker.getMultisigNonces(),
activityChecker.getMultisigNonces(agentMultisigAddress),
];
const multicallResponse = await provider.all(contractCalls);

Expand Down Expand Up @@ -82,13 +82,17 @@ export abstract class MemeooorBaseService extends StakedAgentService {
const lastMultisigNonces = serviceInfo[2];
const nowInSeconds = Math.floor(Date.now() / 1000);

const [isEligibleForRewards] = await provider.all([
activityChecker.isRatioPass(
currentMultisigNonces,
lastMultisigNonces,
Math.ceil(nowInSeconds - tsCheckpoint),
),
]);
const isServiceStaked = serviceInfo[2].length > 0;

const [isEligibleForRewards] = isServiceStaked
? await provider.all([
activityChecker.isRatioPass(
currentMultisigNonces,
lastMultisigNonces,
Math.ceil(nowInSeconds - tsCheckpoint),
),
])
: [false];

const availableRewardsForEpoch = Math.max(
rewardsPerSecond * livenessPeriod, // expected rewards for the epoch
Expand Down

0 comments on commit 817e045

Please sign in to comment.