Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: nextBlockTimestamp refactor #2405

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/src/hooks/helpers/use-resource-arrivals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { getEntityIdFromKeys } from "@dojoengine/utils";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useDojo } from "../context/DojoContext";
import useUIStore from "../store/useUIStore";
import useNextBlockTimestamp from "../useNextBlockTimestamp";

export type ArrivalInfo = {
entityId: ID;
Expand Down Expand Up @@ -168,7 +168,7 @@ export const usePlayerArrivalsNotifications = () => {

const arrivals = usePlayerArrivals();

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

useEffect(() => {
const arrivedCount = arrivals.filter(
Expand Down
3 changes: 2 additions & 1 deletion client/src/hooks/helpers/useResources.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ResourceManager } from "../../dojo/modelManager/ResourceManager";
import { getEntityIdFromKeys } from "../../ui/utils/utils";
import { useDojo } from "../context/DojoContext";
import useUIStore from "../store/useUIStore";
import useNextBlockTimestamp from "../useNextBlockTimestamp";

export function useResourcesUtils() {
const { setup } = useDojo();
Expand All @@ -27,7 +28,7 @@ export function useResourcesUtils() {
}, []);

const useResourcesFromBalance = (entityId: ID) => {
const currentDefaultTick = useUIStore((state) => state.currentDefaultTick);
const { currentDefaultTick } = useNextBlockTimestamp();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Inconsistent timestamp retrieval methods detected

Several functions still use useUIStore.getState().currentDefaultTick while others have been updated to use useNextBlockTimestamp. This inconsistency could lead to synchronization issues in timestamp values.

Consider updating these instances to use the new hook:

- const currentDefaultTick = useUIStore.getState().currentDefaultTick;
+ const { currentDefaultTick } = useNextBlockTimestamp();

Affected functions:

  • getResourcesFromBalance
  • getRealmsWithSpecificResource
  • getFoodResources
  • getBalance
  • useBalance

Also applies to: 49-49, 89-89, 126-126, 147-147

const weight = useComponentValue(Weight, getEntityIdFromKeys([BigInt(entityId)]));
const capacityCategory = useComponentValue(CapacityCategory, getEntityIdFromKeys([BigInt(entityId)]));

Expand Down
4 changes: 2 additions & 2 deletions client/src/hooks/helpers/useStructures.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getEntityIdFromKeys } from "@dojoengine/utils";
import { useMemo } from "react";
import { shortString } from "starknet";
import { useDojo } from "../context/DojoContext";
import useUIStore from "../store/useUIStore";
import useNextBlockTimestamp from "../useNextBlockTimestamp";
import { ArmyInfo, getArmyByEntityId } from "./useArmies";
import { useEntitiesUtils } from "./useEntities";

Expand Down Expand Up @@ -245,7 +245,7 @@ export const useStructureImmunityTimer = (structure: Structure | undefined, next

export const useIsResourcesLocked = (structureEntityId: ID) => {
const dojo = useDojo();
const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const { getStructureByEntityId } = useStructures();
const structure = getStructureByEntityId(structureEntityId);
Expand Down
5 changes: 3 additions & 2 deletions client/src/hooks/helpers/useTrade.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { shortString } from "starknet";
import { getEntityIdFromKeys } from "../../ui/utils/utils";
import { useDojo } from "../context/DojoContext";
import useUIStore from "../store/useUIStore";
import useNextBlockTimestamp from "../useNextBlockTimestamp";
import { useEntities } from "./useEntities";

type TradeResourcesFromViewpoint = {
Expand Down Expand Up @@ -141,7 +142,7 @@ export function useGetMyOffers(): MarketInterface[] {
const { computeTrades } = useTrade();

const structureEntityId = useUIStore((state) => state.structureEntityId);
const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const [myOffers, setMyOffers] = useState<MarketInterface[]>([]);

Expand All @@ -166,7 +167,7 @@ export function useSetMarket() {

const { playerRealms } = useEntities();
const realmEntityIds = playerRealms().map((realm: any) => realm.entity_id);
const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const { computeTrades } = useTrade();

Expand Down
16 changes: 9 additions & 7 deletions client/src/hooks/store/useBlockchainStore.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { configManager } from "@/dojo/setup";
import { TickIds } from "@bibliothecadao/eternum";
import { useEffect } from "react";
import { useEffect, useTransition } from "react";
import useUIStore from "./useUIStore";

export interface BlockchainStore {
Expand All @@ -22,9 +22,7 @@ export const createBlockchainStore = (set: any) => ({
});

export const useFetchBlockchainData = () => {
const setNextBlockTimestamp = useUIStore((state) => state.setNextBlockTimestamp);
const setCurrentDefaultTick = useUIStore((state) => state.setCurrentDefaultTick);
const setCurrentArmiesTick = useUIStore((state) => state.setCurrentArmiesTick);
const [isPending, startTransition] = useTransition();

useEffect(() => {
const tickConfigArmies = configManager.getTick(TickIds.Armies);
Expand All @@ -34,9 +32,13 @@ export const useFetchBlockchainData = () => {
const timestamp = Math.floor(Date.now() / 1000);

if (timestamp) {
setNextBlockTimestamp(timestamp);
setCurrentDefaultTick(Math.floor(timestamp / Number(tickConfigDefault)));
setCurrentArmiesTick(Math.floor(timestamp / Number(tickConfigArmies)));
startTransition(() => {
useUIStore.setState({
nextBlockTimestamp: timestamp,
currentDefaultTick: Math.floor(timestamp / Number(tickConfigDefault)),
currentArmiesTick: Math.floor(timestamp / Number(tickConfigArmies)),
});
});
}
};

Expand Down
4 changes: 2 additions & 2 deletions client/src/hooks/store/useLeaderBoardStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useCallback } from "react";
import { create } from "zustand";
import { useDojo } from "../context/DojoContext";
import { useGuilds } from "../helpers/useGuilds";
import useUIStore from "./useUIStore";
import useNextBlockTimestamp from "../useNextBlockTimestamp";

interface LeaderboardStore {
playersByRank: [ContractAddress, number][];
Expand All @@ -27,7 +27,7 @@ export const useHyperstructureData = () => {

const { getGuildFromPlayerAddress } = useGuilds();

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const setPlayersByRank = useLeaderBoardStore((state) => state.setPlayersByRank);
const setGuildsByRank = useLeaderBoardStore((state) => state.setGuildsByRank);
Expand Down
34 changes: 34 additions & 0 deletions client/src/hooks/useNextBlockTimestamp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { configManager } from "@/dojo/setup";
import { TickIds } from "@bibliothecadao/eternum";
import { startTransition, useEffect, useState } from "react";

const useNextBlockTimestamp = () => {
const [nextBlockTimestamp, setNextBlockTimestamp] = useState<number>(Math.floor(Date.now() / 1000));
const [currentDefaultTick, setCurrentDefaultTick] = useState<number>(0);
const [currentArmiesTick, setCurrentArmiesTick] = useState<number>(0);

useEffect(() => {
const tickConfigArmies = configManager.getTick(TickIds.Armies);
const tickConfigDefault = configManager.getTick(TickIds.Default);

const updateTimestamp = () => {
const timestamp = Math.floor(Date.now() / 1000);
startTransition(() => {
setNextBlockTimestamp(timestamp);
setCurrentDefaultTick(Math.floor(timestamp / Number(tickConfigDefault)));
setCurrentArmiesTick(Math.floor(timestamp / Number(tickConfigArmies)));
});
};

// Create a unique interval for each hook instance
const intervalId = setInterval(updateTimestamp, 10000);

return () => {
clearInterval(intervalId);
};
}, []);

return { nextBlockTimestamp, currentDefaultTick, currentArmiesTick };
};

export default useNextBlockTimestamp;
3 changes: 2 additions & 1 deletion client/src/ui/components/battles/BattleListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { BattleInfo } from "@/hooks/helpers/battles/useBattles";
import { ArmyInfo } from "@/hooks/helpers/useArmies";
import { useEntitiesUtils } from "@/hooks/helpers/useEntities";
import useUIStore from "@/hooks/store/useUIStore";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import { getComponentValue, HasValue, runQuery } from "@dojoengine/recs";
import React, { useMemo, useState } from "react";
import { ViewOnMapIcon } from "../military/ArmyManagementCard";
Expand All @@ -24,7 +25,7 @@ export const BattleListItem = ({ battle, ownArmySelected, showCompass = false }:

const { getAddressNameFromEntity } = useEntitiesUtils();

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const [showInventory, setShowInventory] = useState(false);

Expand Down
3 changes: 2 additions & 1 deletion client/src/ui/components/hyperstructures/CoOwners.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useGetAllPlayers } from "@/hooks/helpers/use-get-all-players";
import { useRealm } from "@/hooks/helpers/useRealm";
import { useStructureByEntityId } from "@/hooks/helpers/useStructures";
import useUIStore from "@/hooks/store/useUIStore";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import Button from "@/ui/elements/Button";
import { NumberInput } from "@/ui/elements/NumberInput";
import { SelectAddress } from "@/ui/elements/SelectAddress";
Expand Down Expand Up @@ -59,7 +60,7 @@ const CoOwnersRows = ({
} = useDojo();
const setTooltip = useUIStore((state) => state.setTooltip);

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const hyperstructureConfig = useMemo(() => {
return getComponentValue(HyperstructureConfig, getEntityIdFromKeys([HYPERSTRUCTURE_CONFIG_ID]));
Expand Down
4 changes: 2 additions & 2 deletions client/src/ui/components/hyperstructures/Leaderboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { LeaderboardManager } from "@/dojo/modelManager/LeaderboardManager";
import { useDojo } from "@/hooks/context/DojoContext";
import { useHyperstructureUpdates } from "@/hooks/helpers/useHyperstructures";
import { useRealm } from "@/hooks/helpers/useRealm";
import useUIStore from "@/hooks/store/useUIStore";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import Button from "@/ui/elements/Button";
import { SortButton, SortInterface } from "@/ui/elements/SortButton";
import { SortPanel } from "@/ui/elements/SortPanel";
Expand All @@ -26,7 +26,7 @@ export const Leaderboard = ({
},
} = dojo;

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const { getAddressName } = useRealm();

Expand Down
3 changes: 2 additions & 1 deletion client/src/ui/components/military/ArmyChip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useDojo } from "@/hooks/context/DojoContext";
import { ArmyInfo, getArmiesByPosition } from "@/hooks/helpers/useArmies";
import { armyHasTroops } from "@/hooks/helpers/useQuests";
import useUIStore from "@/hooks/store/useUIStore";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import { Position as PositionInterface } from "@/types/Position";
import { ArmyCapacity } from "@/ui/elements/ArmyCapacity";
import Button from "@/ui/elements/Button";
Expand Down Expand Up @@ -71,7 +72,7 @@ export const ArmyChip = ({
const [showInventory, setShowInventory] = useState(false);
const [showTroopSwap, setShowTroopSwap] = useState(false);

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const [editMode, setEditMode] = useState(false);

Expand Down
4 changes: 2 additions & 2 deletions client/src/ui/components/resources/EntityResourceTable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { configManager } from "@/dojo/setup";
import { useDojo } from "@/hooks/context/DojoContext";
import useUIStore from "@/hooks/store/useUIStore";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import { getEntityIdFromKeys, gramToKg, multiplyByPrecision } from "@/ui/utils/utils";
import { BuildingType, CapacityConfigCategory, ID, RESOURCE_TIERS } from "@bibliothecadao/eternum";
import { useComponentValue } from "@dojoengine/react";
Expand All @@ -10,7 +10,7 @@ import { ResourceChip } from "./ResourceChip";
export const EntityResourceTable = ({ entityId }: { entityId: ID | undefined }) => {
const dojo = useDojo();

const tick = useUIStore((state) => state.currentDefaultTick);
const { currentDefaultTick: tick } = useNextBlockTimestamp();

const quantity =
useComponentValue(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useGuilds } from "@/hooks/helpers/useGuilds";
import { useQuery } from "@/hooks/helpers/useQuery";
import { useIsStructureImmune, useStructureAtPosition, useStructureImmunityTimer } from "@/hooks/helpers/useStructures";
import useUIStore from "@/hooks/store/useUIStore";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import { Position } from "@/types/Position";
import { ArmyCapacity } from "@/ui/elements/ArmyCapacity";
import Button from "@/ui/elements/Button";
Expand Down Expand Up @@ -35,7 +36,7 @@ export const StructureCard = ({
}) => {
const [showMergeTroopsPopup, setShowMergeTroopsPopup] = useState<boolean>(false);

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const { handleUrlChange } = useQuery();

Expand Down
12 changes: 7 additions & 5 deletions client/src/ui/components/trading/MarketOrderPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useRealm } from "@/hooks/helpers/useRealm";
import { useResourceManager } from "@/hooks/helpers/useResources";
import { useIsResourcesLocked } from "@/hooks/helpers/useStructures";
import { useTravel } from "@/hooks/helpers/useTravel";
import useUIStore from "@/hooks/store/useUIStore";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import { soundSelector, useUiSounds } from "@/hooks/useUISound";
import Button from "@/ui/elements/Button";
import { NumberInput } from "@/ui/elements/NumberInput";
Expand Down Expand Up @@ -47,7 +47,7 @@ export const MarketResource = ({
bidPrice: number;
ammPrice: number;
}) => {
const currentDefaultTick = useUIStore((state) => state.currentDefaultTick);
const { currentDefaultTick } = useNextBlockTimestamp();
const resourceManager = useResourceManager(entityId, resourceId);

const production = useMemo(() => {
Expand Down Expand Up @@ -293,7 +293,7 @@ const OrderRow = ({
return isBuy ? offer.takerGets[0].amount : offer.makerGets[0].amount;
}, [entityId, offer.makerId, offer.tradeId, offer]);

const currentDefaultTick = useUIStore((state) => state.currentDefaultTick);
const { currentDefaultTick } = useNextBlockTimestamp();

const resourceBalanceRatio = useMemo(
() => (resourceBalance < getsDisplayNumber ? resourceBalance / getsDisplayNumber : 1),
Expand Down Expand Up @@ -497,7 +497,8 @@ const OrderCreation = ({
const [resource, setResource] = useState(1000);
const [lords, setLords] = useState(100);
const [bid, setBid] = useState(String(lords / resource));
const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const { play: playLordsSound } = useUiSounds(soundSelector.addLords);

const {
Expand Down Expand Up @@ -558,7 +559,8 @@ const OrderCreation = ({
return calculateDonkeysNeeded(orderWeight);
}, [orderWeight]);

const currentDefaultTick = useUIStore((state) => state.currentDefaultTick);
const { currentDefaultTick } = useNextBlockTimestamp();

const donkeyProductionManager = useResourceManager(entityId, ResourcesIds.Donkey);

const donkeyProduction = useMemo(() => {
Expand Down
3 changes: 2 additions & 1 deletion client/src/ui/components/worldmap/armies/ArmyInfoLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
useStructureImmunityTimer,
useStructures,
} from "@/hooks/helpers/useStructures";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import { ArmyCapacity } from "@/ui/elements/ArmyCapacity";
import { BaseThreeTooltip, Position } from "@/ui/elements/BaseThreeTooltip";
import { Headline } from "@/ui/elements/Headline";
Expand Down Expand Up @@ -56,7 +57,7 @@ const RaiderInfo = ({ army }: ArmyInfoLabelProps) => {
}
}, [entityOwner.entity_owner_id]);

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const isImmune = useIsStructureImmune(structure, nextBlockTimestamp || 0);
const timer = useStructureImmunityTimer(structure as Structure, nextBlockTimestamp || 0);
Comment on lines +60 to 63
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Consider handling undefined nextBlockTimestamp more gracefully

Using 0 as a fallback for nextBlockTimestamp could lead to incorrect immunity and timer calculations. Consider showing a loading state or error message when the timestamp is not available.

Here's a suggested improvement:

-  const { nextBlockTimestamp } = useNextBlockTimestamp();
+  const { nextBlockTimestamp } = useNextBlockTimestamp();
+  
+  if (!nextBlockTimestamp) {
+    return (
+      <BaseThreeTooltip position={Position.CLEAN} className="pointer-events-none w-[250px]">
+        <div>Loading...</div>
+      </BaseThreeTooltip>
+    );
+  }

-  const isImmune = useIsStructureImmune(structure, nextBlockTimestamp || 0);
-  const timer = useStructureImmunityTimer(structure as Structure, nextBlockTimestamp || 0);
+  const isImmune = useIsStructureImmune(structure, nextBlockTimestamp);
+  const timer = useStructureImmunityTimer(structure as Structure, nextBlockTimestamp);

Committable suggestion skipped: line range outside the PR's diff.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
useStructureImmunityTimer,
useStructures,
} from "@/hooks/helpers/useStructures";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import { BaseThreeTooltip, Position } from "@/ui/elements/BaseThreeTooltip";
import { Headline } from "@/ui/elements/Headline";
import { formatTime } from "@/ui/utils/utils";
Expand Down Expand Up @@ -49,7 +50,7 @@ export const StructureInfoLabel = memo(() => {

const playerGuild = getGuildFromPlayerAddress(ContractAddress(structure?.owner.address || 0n));

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const isImmune = useIsStructureImmune(structure, nextBlockTimestamp || 0);
const timer = useStructureImmunityTimer(structure as Structure, nextBlockTimestamp || 0);
Expand Down Expand Up @@ -83,4 +84,4 @@ export const StructureInfoLabel = memo(() => {
);
});

StructureInfoLabel.displayName = "StructureInfoLabel";
StructureInfoLabel.displayName = "StructureInfoLabel";
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ArmyInfo, getUserArmyInBattle } from "@/hooks/helpers/useArmies";
import { useGetHyperstructureProgress } from "@/hooks/helpers/useHyperstructures";
import { Structure, useIsStructureImmune } from "@/hooks/helpers/useStructures";
import useUIStore from "@/hooks/store/useUIStore";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import { ResourcesIds, StructureType } from "@bibliothecadao/eternum";
import clsx from "clsx";
import { useMemo } from "react";
Expand Down Expand Up @@ -39,7 +40,8 @@ export const StructureListItem = ({
}: StructureListItemProps) => {
const dojo = useDojo();

const nextBlockTimestamp = useUIStore((state) => state.nextBlockTimestamp);
const { nextBlockTimestamp } = useNextBlockTimestamp();

const setTooltip = useUIStore((state) => state.setTooltip);
const setBattleView = useUIStore((state) => state.setBattleView);

Expand Down
4 changes: 3 additions & 1 deletion client/src/ui/elements/StaminaResource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { configManager } from "@/dojo/setup";
import { useDojo } from "@/hooks/context/DojoContext";
import { useStaminaManager } from "@/hooks/helpers/useStamina";
import useUIStore from "@/hooks/store/useUIStore";
import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp";
import { ID } from "@bibliothecadao/eternum";
import { getComponentValue } from "@dojoengine/recs";
import { getEntityIdFromKeys } from "@dojoengine/utils";
import { useMemo } from "react";

export const StaminaResource = ({ entityId, className }: { entityId: ID | undefined; className?: string }) => {
const { setup } = useDojo();
const currentArmiesTick = useUIStore((state) => state.currentArmiesTick);
const { currentArmiesTick } = useNextBlockTimestamp();

const staminaManager = useStaminaManager(entityId || 0);
const setTooltip = useUIStore((state) => state.setTooltip);

Expand Down
Loading
Loading