diff --git a/components/animated-price-status.tsx b/components/animated-price-status.tsx index 14227c24..9fde896c 100644 --- a/components/animated-price-status.tsx +++ b/components/animated-price-status.tsx @@ -1,8 +1,7 @@ -import * as React from "react" - -import { Exchange, Token } from "@renegade-fi/react" +import { Exchange } from "@renegade-fi/react" import { usePriceQuery } from "@/hooks/use-price-query" +import { getPriceStatus } from "@/lib/price-status" import { cn } from "@/lib/utils" export function AnimatedPriceStatus({ @@ -14,34 +13,25 @@ export function AnimatedPriceStatus({ exchange?: Exchange mint: `0x${string}` }) { - const { data: price, dataUpdatedAt } = usePriceQuery(mint, exchange) - - const stale = Date.now() - dataUpdatedAt > 60000 + const { data: price, isStale } = usePriceQuery(mint, exchange) - const token = Token.findByAddress(mint) - const tokenSupported = token.supportedExchanges.has(exchange) - let content = "LIVE" // Temporary fix for Coinbase if (exchange === "coinbase") { return ( NO DATA ) } - if (!tokenSupported) { - content = "N/A" - } else if (stale) { - content = "STALE" - } + + const { text, statusColor } = getPriceStatus({ + price, + isStale, + mint, + exchange, + }) return ( - - {content} + + {text} ) } diff --git a/components/animated-price.tsx b/components/animated-price.tsx index 5b6ddee1..cf533be6 100644 --- a/components/animated-price.tsx +++ b/components/animated-price.tsx @@ -1,11 +1,10 @@ -"use client" - import * as React from "react" -import { Exchange, Token } from "@renegade-fi/react" +import { Exchange } from "@renegade-fi/react" import { usePriceQuery } from "@/hooks/use-price-query" import { formatCurrency } from "@/lib/format" +import { getPriceStatus } from "@/lib/price-status" import { cn } from "@/lib/utils" export function AnimatedPrice({ @@ -17,13 +16,10 @@ export function AnimatedPrice({ exchange?: Exchange mint: `0x${string}` }) { - const { data: price } = usePriceQuery(mint, exchange) + const { data: price, isStale } = usePriceQuery(mint, exchange) const prev = React.useRef(price) const [animationKey, setAnimationKey] = React.useState(0) - const token = Token.findByAddress(mint) - const tokenSupported = token.supportedExchanges.has(exchange) - React.useEffect(() => { if (price !== prev.current) { // Use requestAnimationFrame to batch DOM updates @@ -36,17 +32,19 @@ export function AnimatedPrice({ } }, [price]) + // Temporary fix for Coinbase if (exchange === "coinbase") { return -- } + const { priceColor } = getPriceStatus({ price, isStale, mint, exchange }) + return ( prev.current, "animate-price-red": price < prev.current, - "text-muted": !tokenSupported, })} > {formatCurrency(price)} diff --git a/hooks/use-price-query.ts b/hooks/use-price-query.ts index 07090ac2..b099b5d7 100644 --- a/hooks/use-price-query.ts +++ b/hooks/use-price-query.ts @@ -11,6 +11,8 @@ import { import { usePriceWebSocket } from "./use-price-websocket" +const STALE_TIME_MS = 60_000 + export function usePriceQuery( baseMint: `0x${string}`, exchange: Exchange = "binance", @@ -42,7 +44,7 @@ export function usePriceQuery( return getPriceFromPriceReporter(topic) }, initialData: 0, - staleTime: Infinity, + staleTime: STALE_TIME_MS, retry: false, }) } diff --git a/lib/price-status.ts b/lib/price-status.ts new file mode 100644 index 00000000..e7a8c6f3 --- /dev/null +++ b/lib/price-status.ts @@ -0,0 +1,52 @@ +import { Exchange, Token } from "@renegade-fi/react" + +/** Mapping of token price statuses with text, statusColor, and priceColor. */ +export const PRICE_STATUSES = { + live: { + text: "LIVE", + statusColor: "text-green-price", + priceColor: "price-green", + }, + stale: { + text: "STALE", + statusColor: "text-red-price", + priceColor: "price-red", + }, + noData: { + text: "NO DATA", + statusColor: "text-muted", + priceColor: "text-muted", + }, + unsupported: { + text: "N/A", + statusColor: "text-muted", + priceColor: "text-muted", + }, +} as const + +/** Returns the price status based on price, staleness, mint, and exchange. */ +export function getPriceStatus({ + price, + isStale, + mint, + exchange = "binance", +}: { + price: number | undefined + isStale: boolean + mint: `0x${string}` + exchange?: Exchange +}) { + const token = Token.findByAddress(mint) + const tokenSupported = token.supportedExchanges.has(exchange) + + if (!tokenSupported) { + return PRICE_STATUSES.unsupported + } + if (isStale) { + if (!price) { + return PRICE_STATUSES.noData + } + return PRICE_STATUSES.stale + } + return PRICE_STATUSES.live +}