diff --git a/src/hooks/useKeyTwap.ts b/src/hooks/useKeyTwap.ts new file mode 100644 index 00000000..6dd8f504 --- /dev/null +++ b/src/hooks/useKeyTwap.ts @@ -0,0 +1,13 @@ +import { useQuery } from '@tanstack/react-query'; +import { queryKeys } from '@/lib/queryKeys'; +import { courseService } from '@/services/course.service'; + +export function useKeyTwap(keyId: string) { + return useQuery({ + queryKey: queryKeys.creators.twap(keyId), + queryFn: () => courseService.getKeyTwap(keyId), + enabled: !!keyId, + staleTime: 60_000, + retry: false, + }); +} diff --git a/src/lib/queryKeys.ts b/src/lib/queryKeys.ts index fa3def57..a09d09d6 100644 --- a/src/lib/queryKeys.ts +++ b/src/lib/queryKeys.ts @@ -25,6 +25,8 @@ export const queryKeys = { ['creators', creatorId, 'holders'] as const, activity: (creatorId: string) => ['creators', creatorId, 'activity'] as const, + twap: (creatorId: string) => + ['creators', creatorId, 'twap', '24h'] as const, }, wallet: { holdings: (address: string) => ['wallet', address, 'holdings'] as const, diff --git a/src/pages/CreatorDetailPage.tsx b/src/pages/CreatorDetailPage.tsx index 3edaf068..596833c8 100644 --- a/src/pages/CreatorDetailPage.tsx +++ b/src/pages/CreatorDetailPage.tsx @@ -29,6 +29,9 @@ import { useWalletHoldings } from '@/hooks/useWallet'; import CoCreatorSection from '@/components/creator/CoCreatorSection'; import ShareTwitterButton from '@/components/common/ShareTwitterButton'; import { useDocumentTitle } from '@/hooks/useDocumentTitle'; +import { useKeyTwap } from '@/hooks/useKeyTwap'; +import Skeleton from '@/components/ui/skeleton'; +import { Tooltip } from '@/components/ui/tooltip'; function CreatorDetailPageContent() { const { id } = useParams<{ id: string }>(); @@ -63,6 +66,7 @@ function CreatorDetailPageContent() { // return a per-user one. Only shown for authenticated users. const nextBuyAllowedAt = userPosition?.nextBuyAllowedAt ?? creator?.nextBuyAllowedAt ?? null; + const { data: twap, isLoading: isTwapLoading } = useKeyTwap(id || ''); // Track stale data indicator const { shouldShowBadge, handleRefetch } = useCreatorProfileStaleIndicator( @@ -146,6 +150,9 @@ function CreatorDetailPageContent() { supply: (index + 1) * 20, priceXLM: priceStroops / 10_000_000, })); + const spotPrice = resolveCreatorKeyPriceStroops(creator); + const twapPrice = twap?.priceStroops ?? null; + const twapDelta = twapPrice != null && spotPrice != null ? twapPrice - spotPrice : null; const hasRealStakingData = creator.stakingPoolBalance != null || @@ -216,6 +223,27 @@ function CreatorDetailPageContent() { /> + {isTwapLoading ? ( +