From e397245ec928aa48ebff552f06bcb2615d5e9a81 Mon Sep 17 00:00:00 2001 From: defiQUG Date: Thu, 30 Apr 2026 03:53:13 -0700 Subject: [PATCH] Add market evidence notes to explorer surfaces --- .../components/common/MarketEvidenceNote.tsx | 37 +++++++++++++++++++ .../explorer/LiquidityOperationsPage.tsx | 13 +++++++ frontend/src/components/home/HomePage.tsx | 2 + frontend/src/pages/search/index.tsx | 10 +++-- frontend/src/pages/tokens/[address].tsx | 6 +++ frontend/src/pages/tokens/index.tsx | 2 + 6 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 frontend/src/components/common/MarketEvidenceNote.tsx diff --git a/frontend/src/components/common/MarketEvidenceNote.tsx b/frontend/src/components/common/MarketEvidenceNote.tsx new file mode 100644 index 0000000..0a588ba --- /dev/null +++ b/frontend/src/components/common/MarketEvidenceNote.tsx @@ -0,0 +1,37 @@ +import { formatRelativeAge, formatTimestamp } from '@/utils/format' + +function formatSource(source?: string | null): string { + switch (source) { + case 'token-aggregation': + return 'token aggregation API' + case 'blockscout': + return 'Blockscout index' + case 'derived': + return 'derived from indexed supply and price inputs' + case 'mission-control': + return 'mission-control liquidity inventory' + default: + return source || 'source unavailable' + } +} + +export default function MarketEvidenceNote({ + source = 'token-aggregation', + lastUpdated, + method = 'DEX route and pool aggregation; visible liquidity only where indexed.', + compact = false, +}: { + source?: string | null + lastUpdated?: string | null + method?: string + compact?: boolean +}) { + const freshness = lastUpdated ? `${formatRelativeAge(lastUpdated)} (${formatTimestamp(lastUpdated)})` : 'timestamp unavailable' + const text = `Source: ${formatSource(source)}. Updated: ${freshness}. Method: ${method}` + + return ( +

+ {text} +

+ ) +} diff --git a/frontend/src/components/explorer/LiquidityOperationsPage.tsx b/frontend/src/components/explorer/LiquidityOperationsPage.tsx index beaab0a..a70d6c4 100644 --- a/frontend/src/components/explorer/LiquidityOperationsPage.tsx +++ b/frontend/src/components/explorer/LiquidityOperationsPage.tsx @@ -20,6 +20,7 @@ import { statsApi, type ExplorerStats } from '@/services/api/stats' import { summarizeChainActivity } from '@/utils/activityContext' import ActivityContextPanel from '@/components/common/ActivityContextPanel' import FreshnessTrustNote from '@/components/common/FreshnessTrustNote' +import MarketEvidenceNote from '@/components/common/MarketEvidenceNote' import SubsystemPosturePanel from '@/components/common/SubsystemPosturePanel' import { resolveEffectiveFreshness } from '@/utils/explorerFreshness' import { @@ -318,6 +319,12 @@ export default function LiquidityOperationsPage({
{formatNumber(dexCount)} DEX families in the current discovered pools.
+
Fallback posture
@@ -354,6 +361,12 @@ export default function LiquidityOperationsPage({
Seen from {pool.sourceSymbols.join(', ')}
+ ))} {aggregatedPools.length === 0 ? ( diff --git a/frontend/src/components/home/HomePage.tsx b/frontend/src/components/home/HomePage.tsx index 0c889f4..db9cf33 100644 --- a/frontend/src/components/home/HomePage.tsx +++ b/frontend/src/components/home/HomePage.tsx @@ -21,6 +21,7 @@ import { transactionsApi, type Transaction } from '@/services/api/transactions' import { summarizeChainActivity } from '@/utils/activityContext' import ActivityContextPanel from '@/components/common/ActivityContextPanel' import FreshnessTrustNote from '@/components/common/FreshnessTrustNote' +import MarketEvidenceNote from '@/components/common/MarketEvidenceNote' import { Explain, useUiMode } from '@/components/common/UiModeContext' import { resolveEffectiveFreshness, shouldExplainEmptyHeadBlocks } from '@/utils/explorerFreshness' import { tokenAggregationApi, type TokenAggregationTokenSnapshot } from '@/services/api/tokenAggregation' @@ -794,6 +795,7 @@ export default function Home({
{token.market?.lastUpdated ? `Updated ${formatRelativeAge(token.market.lastUpdated)}` : 'Update time unavailable'}
+ ))} diff --git a/frontend/src/pages/search/index.tsx b/frontend/src/pages/search/index.tsx index 95f73b1..85f30c5 100644 --- a/frontend/src/pages/search/index.tsx +++ b/frontend/src/pages/search/index.tsx @@ -16,6 +16,7 @@ import { import PageIntro from '@/components/common/PageIntro' import { fetchPublicJson } from '@/utils/publicExplorer' import { useUiMode } from '@/components/common/UiModeContext' +import MarketEvidenceNote from '@/components/common/MarketEvidenceNote' type SearchFilterMode = 'all' | 'gru' | 'x402' | 'wrapped' @@ -402,9 +403,12 @@ export default function SearchPage({
{market ? ( -
- Live price: {formatUsd(market.priceUsd)} - Visible liquidity: {formatUsd(market.liquidityUsd)} +
+
+ Live price: {formatUsd(market.priceUsd)} + Visible liquidity: {formatUsd(market.liquidityUsd)} +
+
) : null} diff --git a/frontend/src/pages/tokens/[address].tsx b/frontend/src/pages/tokens/[address].tsx index 23a5cee..adb2b0b 100644 --- a/frontend/src/pages/tokens/[address].tsx +++ b/frontend/src/pages/tokens/[address].tsx @@ -11,6 +11,7 @@ import PageIntro from '@/components/common/PageIntro' import { DetailRow } from '@/components/common/DetailRow' import EntityBadge from '@/components/common/EntityBadge' import GruStandardsCard from '@/components/common/GruStandardsCard' +import MarketEvidenceNote from '@/components/common/MarketEvidenceNote' import { formatTokenAmount, formatTimestamp } from '@/utils/format' import { getGruStandardsProfileSafe, type GruStandardsProfile } from '@/services/api/gru' import { getGruExplorerMetadata } from '@/services/api/gruExplorerData' @@ -352,6 +353,11 @@ export default function TokenDetailPage() {
Visible liquidity: {formatUsd(token.liquidity_usd)}
Valuation source: {token.price_source === 'token-aggregation' ? 'live token aggregation' : token.price_source || 'unavailable'}
Market snapshot: {token.market_updated_at ? formatTimestamp(token.market_updated_at) : 'Unavailable'}
+
diff --git a/frontend/src/pages/tokens/index.tsx b/frontend/src/pages/tokens/index.tsx index 0faae59..ad67f96 100644 --- a/frontend/src/pages/tokens/index.tsx +++ b/frontend/src/pages/tokens/index.tsx @@ -5,6 +5,7 @@ import { useEffect, useMemo, useState } from 'react' import { Card } from '@/libs/frontend-ui-primitives' import PageIntro from '@/components/common/PageIntro' import EntityBadge from '@/components/common/EntityBadge' +import MarketEvidenceNote from '@/components/common/MarketEvidenceNote' import { tokensApi } from '@/services/api/tokens' import type { TokenListToken } from '@/services/api/config' import { tokenAggregationApi, type TokenAggregationTokenSnapshot } from '@/services/api/tokenAggregation' @@ -203,6 +204,7 @@ export default function TokensPage({ initialCuratedTokens }: TokensPageProps) {
Live price: {formatUsd(market.priceUsd)}
Visible liquidity: {formatUsd(market.liquidityUsd)}
+
) : null} {token.tags && token.tags.length > 0 && (