diff --git a/apps/comps/components/nfl/brier-score-chart.tsx b/apps/comps/components/nfl/brier-score-chart.tsx index 9136f5b94..effe3cac7 100644 --- a/apps/comps/components/nfl/brier-score-chart.tsx +++ b/apps/comps/components/nfl/brier-score-chart.tsx @@ -103,7 +103,7 @@ export function BrierScoreChart({ } = useNflPredictions(gameId ? competitionId : undefined, gameId); const { chartData, agentIds, agentLabels } = useMemo(() => { - if (!game || !predictionsData?.predictions?.length) { + if (!game || !predictionsData?.length) { return { chartData: [] as TimelinePoint[], agentIds: [] as string[], @@ -112,7 +112,7 @@ export function BrierScoreChart({ } const agentLabelsMap = new Map(); - predictionsData.predictions.forEach((prediction) => { + predictionsData.forEach((prediction) => { if (!agentLabelsMap.has(prediction.agentId)) { agentLabelsMap.set( prediction.agentId, @@ -121,10 +121,10 @@ export function BrierScoreChart({ } }); - const predictionsWithTimestamps = predictionsData.predictions + const predictionsWithTimestamps = predictionsData .map((prediction) => ({ ...prediction, - timestamp: new Date(prediction.createdAt).getTime(), + timestamp: prediction.createdAt.getTime(), })) .sort((a, b) => a.timestamp - b.timestamp); diff --git a/apps/comps/components/nfl/nfl-standings-table.tsx b/apps/comps/components/nfl/nfl-standings-table.tsx index 3fcff9d7a..6e08cb8b5 100644 --- a/apps/comps/components/nfl/nfl-standings-table.tsx +++ b/apps/comps/components/nfl/nfl-standings-table.tsx @@ -138,7 +138,7 @@ export function NflStandingsTable({ games.forEach((game, index) => { const predictionResult = predictionQueries[index]; - const predictions = predictionResult?.data?.predictions ?? []; + const predictions = predictionResult?.data ?? []; const agentPredictionMap = new Map< string, { predictedWinner: string; confidence: number } diff --git a/apps/comps/components/nfl/predictions-table.tsx b/apps/comps/components/nfl/predictions-table.tsx index ae6a81f16..00d30618b 100644 --- a/apps/comps/components/nfl/predictions-table.tsx +++ b/apps/comps/components/nfl/predictions-table.tsx @@ -46,7 +46,7 @@ export function PredictionsTable({ if (error) { return
Failed to load predictions
; } - if (!data?.predictions || data.predictions.length === 0) { + if (!data || data.length === 0) { return (

@@ -66,7 +66,7 @@ export function PredictionsTable({

Reason
- {data.predictions.map((prediction: NflPrediction) => { + {data.map((prediction: NflPrediction) => { const agentLabel = prediction.agentName ?? `${prediction.agentId.slice(0, 8)}...`; diff --git a/apps/comps/hooks/useNextSeasonEligibility.ts b/apps/comps/hooks/useNextSeasonEligibility.ts index 738d0d447..f2e2f8c6b 100644 --- a/apps/comps/hooks/useNextSeasonEligibility.ts +++ b/apps/comps/hooks/useNextSeasonEligibility.ts @@ -5,75 +5,14 @@ import { useAccount } from "wagmi"; import { attoValueToNumberValue } from "@recallnet/conversions/atto-conversions"; import { tanstackClient } from "@/rpc/clients/tanstack-query"; +import type { RouterOutputs } from "@/rpc/router"; import { formatAmount } from "@/utils/format"; /** * Response type from the getNextAirdropEligibility RPC */ -export interface NextAirdropEligibilityResponse { - isEligible: boolean; - airdrop: number; - activitySeason: { - number: number; - name: string; - startDate: string; - endDate: string; - }; - activeStake: string; - potentialReward: string; - eligibilityReasons: { - hasBoostedAgents: boolean; - hasCompetedInCompetitions: boolean; - boostedCompetitionIds: string[]; - competedCompetitionIds: string[]; - totalUniqueCompetitions: number; - }; - poolStats: { - totalActiveStakes: string; - availableRewardsPool: string; - totalForfeited: string; - totalAlreadyClaimed: string; - }; - minCompetitionsRequired: number; -} - -/** - * Formatted eligibility data for UI display - */ -export interface FormattedEligibilityData { - isEligible: boolean; - isAlmostEligible: boolean; - airdrop: number; - activitySeasonNumber: number; - activitySeasonName: string; - activitySeasonStartDate: Date; - activitySeasonEndDate: Date; - daysRemainingInActivitySeason: number; - activeStake: bigint; - activeStakeFormatted: string; - potentialReward: bigint; - potentialRewardFormatted: string; - hasStaked: boolean; - hasBoostedOrCompeted: boolean; - hasBoostedAgents: boolean; - hasCompetedInCompetitions: boolean; - /** Competition IDs where the user boosted agents */ - boostedCompetitionIds: string[]; - /** Competition IDs where the user's agents competed */ - competedCompetitionIds: string[]; - /** Total count of unique competitions (boosted + competed combined) */ - totalUniqueCompetitions: number; - /** Minimum number of competitions required for eligibility */ - minCompetitionsRequired: number; - /** How many more competitions are needed to become eligible */ - competitionsRemaining: number; - totalActiveStakes: bigint; - totalActiveStakesFormatted: string; - availableRewardsPool: bigint; - availableRewardsPoolFormatted: string; - totalForfeited: bigint; - totalForfeitedFormatted: string; -} +type NextAirdropEligibilityResponse = + RouterOutputs["airdrop"]["getNextAirdropEligibility"]; /** * Calculate whole days remaining until a target date. @@ -90,21 +29,10 @@ function getDaysRemaining(endDate: Date, now: Date = new Date()): number { } /** - * Hook result type + * Format bigint value to display format */ -export interface UseNextSeasonEligibilityResult { - data: FormattedEligibilityData | null; - isLoading: boolean; - error: Error | null; - refetch: () => void; -} - -/** - * Format bigint value from string to display format - */ -function formatBigintString(value: string, compact: boolean = true): string { - const bigintValue = BigInt(value); - const numberValue = attoValueToNumberValue(bigintValue); +function formatBigintValue(value: bigint, compact: boolean = true): string { + const numberValue = attoValueToNumberValue(value); if (!numberValue || numberValue === 0) { return "0"; } @@ -114,7 +42,7 @@ function formatBigintString(value: string, compact: boolean = true): string { /** * Hook for fetching and formatting next season eligibility data */ -export function useNextSeasonEligibility(): UseNextSeasonEligibilityResult { +export function useNextSeasonEligibility() { const { address } = useAccount(); const { @@ -129,25 +57,21 @@ export function useNextSeasonEligibility(): UseNextSeasonEligibilityResult { }), ); - const formattedData = useMemo(() => { + const formattedData = useMemo(() => { if (!rawData) return null; - const activitySeasonStartDate = new Date(rawData.activitySeason.startDate); - const activitySeasonEndDate = new Date(rawData.activitySeason.endDate); - - const activeStake = BigInt(rawData.activeStake); - const potentialReward = BigInt(rawData.potentialReward); - const totalActiveStakes = BigInt(rawData.poolStats.totalActiveStakes); - const availableRewardsPool = BigInt(rawData.poolStats.availableRewardsPool); - const totalForfeited = BigInt(rawData.poolStats.totalForfeited); + const { activeStake, potentialReward, poolStats, eligibilityReasons } = + rawData; + const { totalActiveStakes, availableRewardsPool, totalForfeited } = + poolStats; + const { totalUniqueCompetitions } = eligibilityReasons; + const { minCompetitionsRequired } = rawData; const hasStaked = activeStake > 0n; const hasBoostedOrCompeted = - rawData.eligibilityReasons.hasBoostedAgents || - rawData.eligibilityReasons.hasCompetedInCompetitions; + eligibilityReasons.hasBoostedAgents || + eligibilityReasons.hasCompetedInCompetitions; - const { totalUniqueCompetitions } = rawData.eligibilityReasons; - const { minCompetitionsRequired } = rawData; const competitionsRemaining = Math.max( 0, minCompetitionsRequired - totalUniqueCompetitions, @@ -167,35 +91,30 @@ export function useNextSeasonEligibility(): UseNextSeasonEligibilityResult { airdrop: rawData.airdrop, activitySeasonNumber: rawData.activitySeason.number, activitySeasonName: rawData.activitySeason.name, - activitySeasonStartDate, - activitySeasonEndDate, + activitySeasonStartDate: rawData.activitySeason.startDate, + activitySeasonEndDate: rawData.activitySeason.endDate, activeStake, - activeStakeFormatted: formatBigintString(rawData.activeStake), + activeStakeFormatted: formatBigintValue(activeStake), potentialReward, - potentialRewardFormatted: formatBigintString(rawData.potentialReward), + potentialRewardFormatted: formatBigintValue(potentialReward), hasStaked, hasBoostedOrCompeted, - hasBoostedAgents: rawData.eligibilityReasons.hasBoostedAgents, - hasCompetedInCompetitions: - rawData.eligibilityReasons.hasCompetedInCompetitions, - boostedCompetitionIds: rawData.eligibilityReasons.boostedCompetitionIds, - competedCompetitionIds: rawData.eligibilityReasons.competedCompetitionIds, + hasBoostedAgents: eligibilityReasons.hasBoostedAgents, + hasCompetedInCompetitions: eligibilityReasons.hasCompetedInCompetitions, + boostedCompetitionIds: eligibilityReasons.boostedCompetitionIds, + competedCompetitionIds: eligibilityReasons.competedCompetitionIds, totalUniqueCompetitions, minCompetitionsRequired, competitionsRemaining, totalActiveStakes, - totalActiveStakesFormatted: formatBigintString( - rawData.poolStats.totalActiveStakes, - ), + totalActiveStakesFormatted: formatBigintValue(totalActiveStakes), availableRewardsPool, - availableRewardsPoolFormatted: formatBigintString( - rawData.poolStats.availableRewardsPool, - ), + availableRewardsPoolFormatted: formatBigintValue(availableRewardsPool), totalForfeited, - totalForfeitedFormatted: formatBigintString( - rawData.poolStats.totalForfeited, + totalForfeitedFormatted: formatBigintValue(totalForfeited), + daysRemainingInActivitySeason: getDaysRemaining( + rawData.activitySeason.endDate, ), - daysRemainingInActivitySeason: getDaysRemaining(activitySeasonEndDate), }; }, [rawData]); diff --git a/apps/comps/rpc/router/admin/bonus-boost/revoke.ts b/apps/comps/rpc/router/admin/bonus-boost/revoke.ts index dd418a84b..2d093d406 100644 --- a/apps/comps/rpc/router/admin/bonus-boost/revoke.ts +++ b/apps/comps/rpc/router/admin/bonus-boost/revoke.ts @@ -33,7 +33,7 @@ export const revokeBonusBoost = adminBase keptCount: result.keptInCompetitions.length, id: result.boostBonusId, revoked: result.revoked, - revokedAt: result.revokedAt.toISOString(), + revokedAt: result.revokedAt, removedFromCompetitions: result.removedFromCompetitions, keptInCompetitions: result.keptInCompetitions, })); diff --git a/apps/comps/rpc/router/airdrop/get-next-season-eligibility.ts b/apps/comps/rpc/router/airdrop/get-next-season-eligibility.ts index 881577f89..69674a637 100644 --- a/apps/comps/rpc/router/airdrop/get-next-season-eligibility.ts +++ b/apps/comps/rpc/router/airdrop/get-next-season-eligibility.ts @@ -34,37 +34,8 @@ export const getNextAirdropEligibility = base input.airdrop, ); - // Convert bigint values to strings for JSON serialization return { - isEligible: eligibility.isEligible, - airdrop: eligibility.airdrop, - activitySeason: { - number: eligibility.activitySeason.number, - name: eligibility.activitySeason.name, - startDate: eligibility.activitySeason.startDate.toISOString(), - endDate: eligibility.activitySeason.endDate.toISOString(), - }, - activeStake: eligibility.activeStake.toString(), - potentialReward: eligibility.potentialReward.toString(), - eligibilityReasons: { - hasBoostedAgents: eligibility.eligibilityReasons.hasBoostedAgents, - hasCompetedInCompetitions: - eligibility.eligibilityReasons.hasCompetedInCompetitions, - boostedCompetitionIds: - eligibility.eligibilityReasons.boostedCompetitionIds, - competedCompetitionIds: - eligibility.eligibilityReasons.competedCompetitionIds, - totalUniqueCompetitions: - eligibility.eligibilityReasons.totalUniqueCompetitions, - }, - poolStats: { - totalActiveStakes: eligibility.poolStats.totalActiveStakes.toString(), - availableRewardsPool: - eligibility.poolStats.availableRewardsPool.toString(), - totalForfeited: eligibility.poolStats.totalForfeited.toString(), - totalAlreadyClaimed: - eligibility.poolStats.totalAlreadyClaimed.toString(), - }, + ...eligibility, minCompetitionsRequired: config.airdrop.minCompetitionsForEligibility, }; } catch (error) { diff --git a/apps/comps/rpc/router/nfl/get-game-info.ts b/apps/comps/rpc/router/nfl/get-game-info.ts index 12659012e..6bd7f7459 100644 --- a/apps/comps/rpc/router/nfl/get-game-info.ts +++ b/apps/comps/rpc/router/nfl/get-game-info.ts @@ -29,25 +29,7 @@ export const getGameInfo = base throw errors.NOT_FOUND({ message: "Game not found" }); } - return { - game: { - id: game.id, - globalGameId: game.providerGameId, - season: game.season, - week: game.week, - startTime: game.startTime.toISOString(), - endTime: game.endTime?.toISOString() || null, - homeTeam: game.homeTeam, - awayTeam: game.awayTeam, - spread: game.spread, - overUnder: game.overUnder, - awayTeamMoneyLine: game.awayTeamMoneyLine, - homeTeamMoneyLine: game.homeTeamMoneyLine, - venue: game.venue, - status: game.status, - winner: game.winner, - }, - }; + return game; } catch (error) { if (error instanceof ORPCError) { throw error; diff --git a/apps/comps/rpc/router/nfl/get-predictions.ts b/apps/comps/rpc/router/nfl/get-predictions.ts index 6874c877b..13a5e871e 100644 --- a/apps/comps/rpc/router/nfl/get-predictions.ts +++ b/apps/comps/rpc/router/nfl/get-predictions.ts @@ -39,17 +39,7 @@ export const getPredictions = base input.competitionId, ); - return { - predictions: predictions.map((p) => ({ - id: p.id, - agentId: p.agentId, - agentName: p.agentName ?? null, - predictedWinner: p.predictedWinner, - confidence: p.confidence, - reason: p.reason, - createdAt: p.createdAt.toISOString(), - })), - }; + return predictions; } catch (error) { if (error instanceof ORPCError) { throw error; diff --git a/apps/comps/types/nfl.ts b/apps/comps/types/nfl.ts index 04c6b0e2e..ee084043c 100644 --- a/apps/comps/types/nfl.ts +++ b/apps/comps/types/nfl.ts @@ -32,7 +32,7 @@ export interface NflPrediction SelectGamePrediction, "id" | "agentId" | "predictedWinner" | "confidence" > { - createdAt: string; + createdAt: Date; reason?: string | null; agentName?: string | null; }