From d661fa263d30600fa7f443afaff70b74ecc8d0ab Mon Sep 17 00:00:00 2001 From: antoncoding Date: Fri, 9 Jan 2026 17:00:26 +0800 Subject: [PATCH 1/3] feat: put warning in market indicators, include overridable warnings --- .../components/market-risk-indicators.tsx | 4 +- .../markets/components/risk-indicator.tsx | 43 +++++++++++--- src/hooks/useProcessedMarkets.ts | 18 +++--- src/utils/markets.ts | 59 +++++++++++++++++++ src/utils/warnings.ts | 13 +++- 5 files changed, 117 insertions(+), 20 deletions(-) diff --git a/src/features/markets/components/market-risk-indicators.tsx b/src/features/markets/components/market-risk-indicators.tsx index 98ef9acb..a4407b3d 100644 --- a/src/features/markets/components/market-risk-indicators.tsx +++ b/src/features/markets/components/market-risk-indicators.tsx @@ -1,5 +1,5 @@ import type { Market } from '@/utils/types'; -import { MarketAssetIndicator, MarketOracleIndicator, MarketDebtIndicator } from './risk-indicator'; +import { MarketAssetIndicator, MarketOracleIndicator, MarketStatusIndicator } from './risk-indicator'; type MarketRiskIndicatorsProps = { market: Market; @@ -24,7 +24,7 @@ export function MarketRiskIndicators({ market, isBatched = false, mode = 'simple isBatched={isBatched} mode={mode} /> - w.category === WarningCategory.debt || w.category === WarningCategory.general); + + if (warnings.length === 0) { + return ( + + ); + } + + if (warnings.some((warning) => warning.level === 'alert')) { + const alertWarning = warnings.find((w) => w.level === 'alert'); + return ( + + ); + } + return ( - ); } + +// Keep old name as alias for backward compatibility +export const MarketDebtIndicator = MarketStatusIndicator; diff --git a/src/hooks/useProcessedMarkets.ts b/src/hooks/useProcessedMarkets.ts index fa8d7a2d..64ffda84 100644 --- a/src/hooks/useProcessedMarkets.ts +++ b/src/hooks/useProcessedMarkets.ts @@ -3,6 +3,7 @@ import { useMarketsQuery } from '@/hooks/queries/useMarketsQuery'; import { useOracleDataQuery } from '@/hooks/queries/useOracleDataQuery'; import { useBlacklistedMarkets } from '@/stores/useBlacklistedMarkets'; import { useAppSettings } from '@/stores/useAppSettings'; +import { isForceUnwhitelisted } from '@/utils/markets'; /** * Processes raw markets data with blacklist filtering and oracle enrichment. @@ -49,17 +50,16 @@ export const useProcessedMarkets = () => { // Apply blacklist filter const blacklistFiltered = rawMarketsUnfiltered.filter((market) => !allBlacklistedMarketKeys.has(market.uniqueKey)); - // Enrich with oracle data + // Enrich with oracle data and apply force-unwhitelisted overrides const enriched = blacklistFiltered.map((market) => { const oracleData = getOracleData(market.oracleAddress, market.morphoBlue.chain.id); - return oracleData - ? { - ...market, - oracle: { - data: oracleData, - }, - } - : market; + const shouldForceUnwhitelist = isForceUnwhitelisted(market.uniqueKey); + + return { + ...market, + ...(oracleData && { oracle: { data: oracleData } }), + ...(shouldForceUnwhitelist && { whitelisted: false }), + }; }); // allMarkets: all markets (whitelisted + unwhitelisted, excluding blacklisted) diff --git a/src/utils/markets.ts b/src/utils/markets.ts index 2a48e891..543616f2 100644 --- a/src/utils/markets.ts +++ b/src/utils/markets.ts @@ -39,3 +39,62 @@ export const monarchWhitelistedMarkets: WhitelistMarketData[] = [ offsetWarnings: ['unrecognized_collateral_asset'], }, ]; + +// Market override rules - group multiple markets under the same rule +export type MarketOverrideWarning = { + code: string; + level: 'warning' | 'alert'; + description: string; + category: 'asset' | 'oracle' | 'debt' | 'general'; +}; + +export type MarketOverrideRule = { + // Markets this rule applies to (uniqueKey, lowercase) + marketIds: string[]; + + // Force these markets to appear as unwhitelisted + forceUnwhitelisted?: boolean; + + // Custom warnings to attach + warnings?: MarketOverrideWarning[]; +}; + +export const marketOverrideRules: MarketOverrideRule[] = [ + { + marketIds: [ + '0xdb2cf3ad3ef91c9bb673bf35744e7141bc2950b27a75c8d11b0ead9f6742d927', + '0xe0ede98b4425285a9c93d51f8ba27d9a09bc0033874e4a883d3f29d41f9f2e4a', + '0x2b62c4153d81d5b5a233d1d2b7ef899d3fca4076d458e215ff3a00176b415b0d', + '0x2b62c4153d81d5b5a233d1d2b7ef899d3fca4076d458e215ff3a00176b415b0d', + '0x216bd19960f140177a4a3fb9cf258edcbadb1f5d54740fc944503bff4a00e65e', + ], + forceUnwhitelisted: true, + warnings: [ + { + code: 'deprecated', + level: 'alert', + description: 'The loan asset (rUSDC) of this market is deprecating.', + category: 'general', + }, + ], + }, +]; + +// Helper functions to query the override rules +export const isForceUnwhitelisted = (marketId: string): boolean => { + const normalizedId = marketId.toLowerCase(); + return marketOverrideRules.some((rule) => rule.forceUnwhitelisted && rule.marketIds.includes(normalizedId)); +}; + +export const getMarketOverrideWarnings = (marketId: string): MarketOverrideWarning[] => { + const normalizedId = marketId.toLowerCase(); + const warnings: MarketOverrideWarning[] = []; + + for (const rule of marketOverrideRules) { + if (rule.marketIds.includes(normalizedId) && rule.warnings) { + warnings.push(...rule.warnings); + } + } + + return warnings; +}; diff --git a/src/utils/warnings.ts b/src/utils/warnings.ts index 4b0a7023..9296b78d 100644 --- a/src/utils/warnings.ts +++ b/src/utils/warnings.ts @@ -1,5 +1,5 @@ import type { Market, MarketWarning } from '@/utils/types'; -import { monarchWhitelistedMarkets } from './markets'; +import { monarchWhitelistedMarkets, getMarketOverrideWarnings } from './markets'; import { getOracleType, OracleType, parsePriceFeedVendors, checkFeedsPath } from './oracle'; import { WarningCategory, type WarningWithDetail } from './types'; @@ -227,5 +227,16 @@ export const getMarketWarningsWithDetail = (market: Market, considerWhitelist = } } + // Inject custom market warnings from override rules + const overrideWarnings = getMarketOverrideWarnings(market.uniqueKey); + for (const warning of overrideWarnings) { + result.push({ + code: warning.code, + level: warning.level, + description: warning.description, + category: warning.category as WarningCategory, + }); + } + return result; }; From e9e746ca0c0423715be1f33c63175c4fe9d1ca8c Mon Sep 17 00:00:00 2001 From: antoncoding Date: Fri, 9 Jan 2026 17:05:40 +0800 Subject: [PATCH 2/3] chore: cleanup --- src/utils/markets.ts | 14 ++++---------- src/utils/warnings.ts | 11 +---------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/utils/markets.ts b/src/utils/markets.ts index 543616f2..21ccdaac 100644 --- a/src/utils/markets.ts +++ b/src/utils/markets.ts @@ -65,8 +65,8 @@ export const marketOverrideRules: MarketOverrideRule[] = [ '0xdb2cf3ad3ef91c9bb673bf35744e7141bc2950b27a75c8d11b0ead9f6742d927', '0xe0ede98b4425285a9c93d51f8ba27d9a09bc0033874e4a883d3f29d41f9f2e4a', '0x2b62c4153d81d5b5a233d1d2b7ef899d3fca4076d458e215ff3a00176b415b0d', - '0x2b62c4153d81d5b5a233d1d2b7ef899d3fca4076d458e215ff3a00176b415b0d', '0x216bd19960f140177a4a3fb9cf258edcbadb1f5d54740fc944503bff4a00e65e', + '0xf474c9a0cbd8f2b65d9480d94b56880ca13f10fc3b3c717d47bdf3ac9c4417b7', ], forceUnwhitelisted: true, warnings: [ @@ -88,13 +88,7 @@ export const isForceUnwhitelisted = (marketId: string): boolean => { export const getMarketOverrideWarnings = (marketId: string): MarketOverrideWarning[] => { const normalizedId = marketId.toLowerCase(); - const warnings: MarketOverrideWarning[] = []; - - for (const rule of marketOverrideRules) { - if (rule.marketIds.includes(normalizedId) && rule.warnings) { - warnings.push(...rule.warnings); - } - } - - return warnings; + return marketOverrideRules + .filter((rule) => rule.marketIds.includes(normalizedId) && rule.warnings) + .flatMap((rule) => rule.warnings ?? []); }; diff --git a/src/utils/warnings.ts b/src/utils/warnings.ts index 9296b78d..7cd121ae 100644 --- a/src/utils/warnings.ts +++ b/src/utils/warnings.ts @@ -155,10 +155,6 @@ export const getMarketWarningsWithDetail = (market: Market, considerWhitelist = for (const warning of market.warnings) { const foundWarning = allDetails.find((w) => w.code === warning.type); - if (whitelistedMarketData) { - console.log('whitelistedMarketData', whitelistedMarketData); - } - // if this market is whitelisted, there might be warnings we want to "offset" const isOffset = whitelistedMarketData?.offsetWarnings.includes(warning.type); @@ -230,12 +226,7 @@ export const getMarketWarningsWithDetail = (market: Market, considerWhitelist = // Inject custom market warnings from override rules const overrideWarnings = getMarketOverrideWarnings(market.uniqueKey); for (const warning of overrideWarnings) { - result.push({ - code: warning.code, - level: warning.level, - description: warning.description, - category: warning.category as WarningCategory, - }); + result.push({ ...warning, category: warning.category as WarningCategory }); } return result; From 83a5e18b6e01adead0b923623ec2b1ceec9d7c39 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Fri, 9 Jan 2026 17:07:19 +0800 Subject: [PATCH 3/3] chore: default message --- src/features/markets/components/risk-indicator.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/markets/components/risk-indicator.tsx b/src/features/markets/components/risk-indicator.tsx index 85524969..3593c9f6 100644 --- a/src/features/markets/components/risk-indicator.tsx +++ b/src/features/markets/components/risk-indicator.tsx @@ -210,7 +210,7 @@ export function MarketStatusIndicator({ return ( );