From 1bc2d7f8c1ecbc230cc65d079598ffdfc6ddc9b7 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Tue, 17 Feb 2026 12:17:20 +0800 Subject: [PATCH 1/4] feat: tooltip --- .gitignore | 4 +-- .../shared/estimated-value-tooltip.tsx | 32 +++++++++++++++++++ src/config/dataSources.ts | 2 +- src/data-sources/subgraph/market.ts | 3 +- .../components/table/market-row-detail.tsx | 7 +++- .../components/table/market-table-body.tsx | 3 ++ .../components/table/market-table-utils.tsx | 7 +++- src/utils/urls.ts | 2 +- src/utils/warnings.ts | 18 +---------- 9 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 src/components/shared/estimated-value-tooltip.tsx diff --git a/.gitignore b/.gitignore index 33a7761f..bdaa4c5d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - +.codexrc # dependencies /node_modules @@ -54,4 +54,4 @@ next-env.d.ts CLAUDE.md FULLAUTO_CONTEXT.md -.claude/settings.local.json \ No newline at end of file +.claude/settings.local.json diff --git a/src/components/shared/estimated-value-tooltip.tsx b/src/components/shared/estimated-value-tooltip.tsx new file mode 100644 index 00000000..d9057771 --- /dev/null +++ b/src/components/shared/estimated-value-tooltip.tsx @@ -0,0 +1,32 @@ +import type { ReactNode } from 'react'; +import { Tooltip } from '@/components/ui/tooltip'; +import { TooltipContent } from '@/components/shared/tooltip-content'; +import { cn } from '@/utils/components'; + +type EstimatedValueTooltipProps = { + children: ReactNode; + isEstimated: boolean; + detail?: string; + className?: string; +}; + +const DEFAULT_DETAIL = 'This USD value is estimated using an hardcoded price.'; + +export function EstimatedValueTooltip({ children, isEstimated, detail = DEFAULT_DETAIL, className }: EstimatedValueTooltipProps) { + if (!isEstimated) { + return <>{children}; + } + + return ( + + } + > + {children} + + ); +} diff --git a/src/config/dataSources.ts b/src/config/dataSources.ts index f45fb93b..880ace82 100644 --- a/src/config/dataSources.ts +++ b/src/config/dataSources.ts @@ -12,7 +12,7 @@ export const supportsMorphoApi = (network: SupportedNetworks): boolean => { case SupportedNetworks.Arbitrum: case SupportedNetworks.HyperEVM: case SupportedNetworks.Monad: - return true; + return false; default: return false; diff --git a/src/data-sources/subgraph/market.ts b/src/data-sources/subgraph/market.ts index 4a9bb1d9..baf1d135 100644 --- a/src/data-sources/subgraph/market.ts +++ b/src/data-sources/subgraph/market.ts @@ -7,7 +7,7 @@ import { getSubgraphUrl } from '@/utils/subgraph-urls'; import { blacklistTokens, type ERC20Token, findToken, type UnknownERC20Token, TokenPeg } from '@/utils/tokens'; import { fetchMajorPrices, type MajorPrices } from '@/utils/majorPrices'; import type { Market, MarketWarning } from '@/utils/types'; -import { SUBGRAPH_NO_PRICE, UNRECOGNIZED_COLLATERAL, UNRECOGNIZED_LOAN } from '@/utils/warnings'; +import { UNRECOGNIZED_COLLATERAL, UNRECOGNIZED_LOAN } from '@/utils/warnings'; import { subgraphGraphqlFetcher } from './fetchers'; // Helper to safely parse BigDecimal/BigInt strings @@ -104,7 +104,6 @@ const transformSubgraphMarketToMarket = ( if (knownCollateralAsset) { collateralAssetPrice = getEstimateValue(knownCollateralAsset) ?? 0; } - warnings.push(SUBGRAPH_NO_PRICE); } const supplyAssetsUsd = formatBalance(supplyAssets, loanAsset.decimals) * loanAssetPrice; diff --git a/src/features/markets/components/table/market-row-detail.tsx b/src/features/markets/components/table/market-row-detail.tsx index b05cb46e..ab62053a 100644 --- a/src/features/markets/components/table/market-row-detail.tsx +++ b/src/features/markets/components/table/market-row-detail.tsx @@ -1,4 +1,5 @@ import { Info } from '@/components/Info/info'; +import { EstimatedValueTooltip } from '@/components/shared/estimated-value-tooltip'; import { OracleTypeInfo } from '@/features/markets/components/oracle'; import { useMarketWarnings } from '@/hooks/useMarketWarnings'; import { formatReadable } from '@/utils/balance'; @@ -30,7 +31,11 @@ export function ExpandedMarketDetail({ market }: { market: Market }) {

Available Liquidity

-

{formatReadable(Number(market.state.liquidityAssetsUsd))}

+

+ + {formatReadable(Number(market.state.liquidityAssetsUsd))} + +

Utilization Rate

diff --git a/src/features/markets/components/table/market-table-body.tsx b/src/features/markets/components/table/market-table-body.tsx index e86f16a6..bc70cafc 100644 --- a/src/features/markets/components/table/market-table-body.tsx +++ b/src/features/markets/components/table/market-table-body.tsx @@ -182,6 +182,7 @@ export function MarketTableBody({ currentEntries, expandedRowId, setExpandedRowI assets={item.state.supplyAssets} decimals={item.loanAsset.decimals} symbol={item.loanAsset.symbol} + isEstimated={!item.hasUSDPrice} /> )} {columnVisibility.totalBorrow && ( @@ -191,6 +192,7 @@ export function MarketTableBody({ currentEntries, expandedRowId, setExpandedRowI assets={item.state.borrowAssets} decimals={item.loanAsset.decimals} symbol={item.loanAsset.symbol} + isEstimated={!item.hasUSDPrice} /> )} {columnVisibility.liquidity && ( @@ -200,6 +202,7 @@ export function MarketTableBody({ currentEntries, expandedRowId, setExpandedRowI assets={item.state.liquidityAssets} decimals={item.loanAsset.decimals} symbol={item.loanAsset.symbol} + isEstimated={!item.hasUSDPrice} /> )} {columnVisibility.supplyAPY && ( diff --git a/src/features/markets/components/table/market-table-utils.tsx b/src/features/markets/components/table/market-table-utils.tsx index 51e090c1..9c2a547b 100644 --- a/src/features/markets/components/table/market-table-utils.tsx +++ b/src/features/markets/components/table/market-table-utils.tsx @@ -1,6 +1,7 @@ import { ArrowDownIcon, ArrowUpIcon, ExternalLinkIcon } from '@radix-ui/react-icons'; import { TableHead, TableCell } from '@/components/ui/table'; import { TokenIcon } from '@/components/shared/token-icon'; +import { EstimatedValueTooltip } from '@/components/shared/estimated-value-tooltip'; import { formatBalance, formatReadable } from '@/utils/balance'; import { getAssetURL } from '@/utils/external'; import type { SortColumn } from '../constants'; @@ -68,12 +69,14 @@ export function TDTotalSupplyOrBorrow({ assets, decimals, symbol, + isEstimated = false, }: { dataLabel: string; assetsUSD: number; assets: string; decimals: number; symbol: string; + isEstimated?: boolean; }) { return ( -

${`${formatReadable(Number(assetsUSD))} `}

+

+ ${formatReadable(Number(assetsUSD))} +

{`${formatReadable(formatBalance(assets, decimals))} ${symbol}`}

); diff --git a/src/utils/urls.ts b/src/utils/urls.ts index 252158c6..3a9d2c5e 100644 --- a/src/utils/urls.ts +++ b/src/utils/urls.ts @@ -1,7 +1,7 @@ import { SupportedNetworks } from './networks'; export const URLS = { - MORPHO_BLUE_API: 'https://blue-api.morpho.org/graphql', + MORPHO_BLUE_API: 'https://blue-api.morpho.org/graphql/', // only returns morpho reward, won't include merkl rewards MORPHO_REWARDS_API: 'https://rewards.morpho.org/v1', diff --git a/src/utils/warnings.ts b/src/utils/warnings.ts index 16fc01ea..2eb0654d 100644 --- a/src/utils/warnings.ts +++ b/src/utils/warnings.ts @@ -13,13 +13,6 @@ export const SUBGRAPH_NO_ORACLE = { __typename: 'OracleWarning_MonarchAttached', }; -// Most subgraph markets has no price data -export const SUBGRAPH_NO_PRICE = { - type: 'subgraph_no_price', - level: 'warning', - __typename: 'MarketWarning_SubgraphNoPrice', -}; - export const subgraphDefaultWarnings: MarketWarning[] = [SUBGRAPH_NO_ORACLE]; export const UNRECOGNIZED_LOAN = { @@ -90,15 +83,6 @@ const morphoOfficialWarnings: WarningWithDetail[] = [ }, ]; -const subgraphWarnings: WarningWithDetail[] = [ - { - code: 'subgraph_no_price', - level: 'warning', - description: 'The USD value of the market is estimated with an offchain price source.', - category: WarningCategory.general, - }, -]; - const BAD_DEBT: WarningWithDetail = { code: 'bad_debt_realized', level: 'warning', @@ -155,7 +139,7 @@ export const getMarketWarningsWithDetail = (market: Market, optionsOrWhitelist?: const { considerWhitelist = false, oracleMetadataMap } = options; const result = []; - const allDetails = [...morphoOfficialWarnings, ...subgraphWarnings]; + const allDetails = [...morphoOfficialWarnings]; const whitelistedMarketData = considerWhitelist ? monarchWhitelistedMarkets.find((m) => m.id === market.uniqueKey.toLowerCase()) From a90c60314fecccff56bd25f0ceefb2790c4d9d29 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Tue, 17 Feb 2026 12:18:00 +0800 Subject: [PATCH 2/4] chore: remove hardcoded --- src/config/dataSources.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/dataSources.ts b/src/config/dataSources.ts index 880ace82..f45fb93b 100644 --- a/src/config/dataSources.ts +++ b/src/config/dataSources.ts @@ -12,7 +12,7 @@ export const supportsMorphoApi = (network: SupportedNetworks): boolean => { case SupportedNetworks.Arbitrum: case SupportedNetworks.HyperEVM: case SupportedNetworks.Monad: - return false; + return true; default: return false; From 56116e63187186d1c2e8b3d412ca563fa1154af0 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Tue, 17 Feb 2026 12:21:58 +0800 Subject: [PATCH 3/4] fix: url --- src/utils/urls.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/urls.ts b/src/utils/urls.ts index 3a9d2c5e..252158c6 100644 --- a/src/utils/urls.ts +++ b/src/utils/urls.ts @@ -1,7 +1,7 @@ import { SupportedNetworks } from './networks'; export const URLS = { - MORPHO_BLUE_API: 'https://blue-api.morpho.org/graphql/', + MORPHO_BLUE_API: 'https://blue-api.morpho.org/graphql', // only returns morpho reward, won't include merkl rewards MORPHO_REWARDS_API: 'https://rewards.morpho.org/v1', From 366012adcedc3801a170333fd1366f5910ed3e70 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Tue, 17 Feb 2026 12:22:38 +0800 Subject: [PATCH 4/4] chore: wording --- src/components/shared/estimated-value-tooltip.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/shared/estimated-value-tooltip.tsx b/src/components/shared/estimated-value-tooltip.tsx index d9057771..b7e28256 100644 --- a/src/components/shared/estimated-value-tooltip.tsx +++ b/src/components/shared/estimated-value-tooltip.tsx @@ -10,7 +10,7 @@ type EstimatedValueTooltipProps = { className?: string; }; -const DEFAULT_DETAIL = 'This USD value is estimated using an hardcoded price.'; +const DEFAULT_DETAIL = 'This USD value is estimated using a hardcoded price.'; export function EstimatedValueTooltip({ children, isEstimated, detail = DEFAULT_DETAIL, className }: EstimatedValueTooltipProps) { if (!isEstimated) {