Skip to content

Commit

Permalink
bbo-banner: fix price status logic
Browse files Browse the repository at this point in the history
  • Loading branch information
sehyunc committed Feb 8, 2025
1 parent 451fd1e commit 6377f63
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 32 deletions.
34 changes: 12 additions & 22 deletions components/animated-price-status.tsx
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -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 (
<span className={cn("!text-muted-foreground", className)}>NO DATA</span>
)
}
if (!tokenSupported) {
content = "N/A"
} else if (stale) {
content = "STALE"
}

const { text, statusColor } = getPriceStatus({
price,
isStale,
mint,
exchange,
})

return (
<span
className={cn("transition-colors", className, {
"text-green-price": price,
"text-red-price": stale,
"text-muted": !tokenSupported,
})}
>
{content}
<span className={cn("transition-colors", className, statusColor)}>
{text}
</span>
)
}
16 changes: 7 additions & 9 deletions components/animated-price.tsx
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -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
Expand All @@ -36,17 +32,19 @@ export function AnimatedPrice({
}
}, [price])

// Temporary fix for Coinbase
if (exchange === "coinbase") {
return <span className={cn("text-muted-foreground", className)}>--</span>
}

const { priceColor } = getPriceStatus({ price, isStale, mint, exchange })

return (
<span
key={animationKey}
className={cn("transition-colors", className, {
className={cn("transition-colors", className, priceColor, {
"animate-price-green": price > prev.current,
"animate-price-red": price < prev.current,
"text-muted": !tokenSupported,
})}
>
{formatCurrency(price)}
Expand Down
4 changes: 3 additions & 1 deletion hooks/use-price-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -42,7 +44,7 @@ export function usePriceQuery(
return getPriceFromPriceReporter(topic)
},
initialData: 0,
staleTime: Infinity,
staleTime: STALE_TIME_MS,
retry: false,
})
}
52 changes: 52 additions & 0 deletions lib/price-status.ts
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 6377f63

Please sign in to comment.