diff --git a/apps/web/src/features/earn/components/discover/discover-tab.tsx b/apps/web/src/features/earn/components/discover/discover-tab.tsx index 440f4c0..c158fa0 100644 --- a/apps/web/src/features/earn/components/discover/discover-tab.tsx +++ b/apps/web/src/features/earn/components/discover/discover-tab.tsx @@ -7,33 +7,11 @@ import { formatPct, formatUsd, formatToken } from "@/shared/lib/format" import { useMarketPoolAmounts } from "../../hooks/useMarketPoolAmounts" import { useGLVVaultData, useGMPoolData, useStakingInfo } from "../../queries" import { fromSorobanAmount } from "@/shared/lib/bignum" +import { TokenIcon } from "@/shared/components/TokenIcon" type Filter = "all" | "glv" | "gm" type SortKey = "apy" | "tvl" - - -const TOKEN_COLORS: Record = { - BTC: "bg-orange-500/10 text-orange-400 ring-orange-500/20", - ETH: "bg-indigo-500/10 text-indigo-400 ring-indigo-500/20", - XLM: "bg-sky-500/10 text-sky-400 ring-sky-500/20", - GLV: "bg-teal-500/10 text-teal-400 ring-teal-500/20", -} - -function TokenAvatar({ symbol }: { symbol: string }) { - const color = TOKEN_COLORS[symbol] ?? "bg-muted/60 text-muted-foreground ring-border" - return ( -
- {symbol.slice(0, 2)} -
- ) -} - function PoolCompositionBar({ longPct, shortPct }: { longPct: number; shortPct: number }) { return (
@@ -280,7 +258,7 @@ function DiscoverRow({
- + {row.name}
diff --git a/apps/web/src/features/trade/components/positions/PositionsList.tsx b/apps/web/src/features/trade/components/positions/PositionsList.tsx index 4413e99..7cfe763 100644 --- a/apps/web/src/features/trade/components/positions/PositionsList.tsx +++ b/apps/web/src/features/trade/components/positions/PositionsList.tsx @@ -12,6 +12,7 @@ import { formatPct, formatUsd } from "@/shared/lib/format" import { queryKeys } from "../../lib/query-keys" import { useWalletStore } from "@/features/wallet/store/wallet-store" import { CollateralDialog } from "./CollateralDialog" +import { TokenIcon } from "@/shared/components/TokenIcon" type Props = { onSelectPosition?: (position: Position) => void @@ -154,6 +155,7 @@ export function PositionsList({ onSelectPosition }: Props) { >
+ {p.marketName} setFromAmount(e.target.value)} className="pr-16 font-mono text-sm" /> - - {fromTokenAddress} + + + {fromTokenAddress}
{fromUsd > 0 && ( @@ -308,7 +310,10 @@ function TradeInputs({ trade, validationError }: { trade: ReturnType {tradeFlags.isSwap ? "Receive" : "Market"} - {toTokenAddress}/USD + + + {toTokenAddress}/USD +
) diff --git a/apps/web/src/shared/components/TokenIcon.tsx b/apps/web/src/shared/components/TokenIcon.tsx new file mode 100644 index 0000000..1fe5644 --- /dev/null +++ b/apps/web/src/shared/components/TokenIcon.tsx @@ -0,0 +1,64 @@ +import { useState } from "react" +import { cn } from "@workspace/ui/lib/utils" + +type Props = { + symbol: string + size?: number + className?: string +} + +const CDN_BASE = "https://cdn.jsdelivr.net/gh/spothq/cryptocurrency-icons@master/svg/color" + +const SYMBOL_TO_CDN: Record = { + BTC: `${CDN_BASE}/btc.svg`, + ETH: `${CDN_BASE}/eth.svg`, + XLM: `${CDN_BASE}/xlm.svg`, + USDC: `${CDN_BASE}/usdc.svg`, + USDT: `${CDN_BASE}/usdt.svg`, + SOL: `${CDN_BASE}/sol.svg`, + BNB: `${CDN_BASE}/bnb.svg`, +} + +const PLACEHOLDER_COLORS: Record = { + BTC: "bg-orange-500/15 text-orange-400 ring-orange-500/25", + ETH: "bg-indigo-500/15 text-indigo-400 ring-indigo-500/25", + XLM: "bg-sky-500/15 text-sky-400 ring-sky-500/25", + USDC: "bg-blue-500/15 text-blue-400 ring-blue-500/25", + GLV: "bg-teal-500/15 text-teal-400 ring-teal-500/25", +} + +export function TokenIcon({ symbol, size = 32, className }: Props) { + const [imgError, setImgError] = useState(false) + const upper = symbol.toUpperCase() + const cdnUrl = SYMBOL_TO_CDN[upper] + const showImg = !!cdnUrl && !imgError + const color = PLACEHOLDER_COLORS[upper] ?? "bg-muted/60 text-muted-foreground ring-border" + + return ( +
+ {showImg ? ( + {`${symbol} setImgError(true)} + className="h-full w-full object-contain p-0.5" + /> + ) : ( + + {upper.slice(0, 2)} + + )} +
+ ) +}