diff --git a/app/api/oracle-metadata/[chainId]/route.ts b/app/api/oracle-metadata/[chainId]/route.ts index 9aabc59d..61de9d40 100644 --- a/app/api/oracle-metadata/[chainId]/route.ts +++ b/app/api/oracle-metadata/[chainId]/route.ts @@ -17,7 +17,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ chai try { const url = `${ORACLE_GIST_BASE_URL}/oracles.${chainId}.json`; const response = await fetch(url, { - next: { revalidate: 1800 }, // Cache for 30 minutes + cache: 'no-store', }); if (!response.ok) { @@ -29,11 +29,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ chai const data = await response.json(); - return NextResponse.json(data, { - headers: { - 'Cache-Control': 'public, s-maxage=1800, stale-while-revalidate=3600', - }, - }); + return NextResponse.json(data); } catch (error) { console.error('Failed to fetch oracle metadata:', error); return NextResponse.json({ error: 'Failed to fetch oracle metadata' }, { status: 500 }); diff --git a/src/features/markets/components/oracle/MarketOracle/FeedEntry.tsx b/src/features/markets/components/oracle/MarketOracle/FeedEntry.tsx index a328e478..388aabab 100644 --- a/src/features/markets/components/oracle/MarketOracle/FeedEntry.tsx +++ b/src/features/markets/components/oracle/MarketOracle/FeedEntry.tsx @@ -10,6 +10,7 @@ import type { OracleFeed } from '@/utils/types'; import { ChainlinkFeedTooltip } from './ChainlinkFeedTooltip'; import { CompoundFeedTooltip } from './CompoundFeedTooltip'; import { GeneralFeedTooltip } from './GeneralFeedTooltip'; +import { PendleFeedTooltip } from './PendleFeedTooltip'; import { RedstoneFeedTooltip } from './RedstoneFeedTooltip'; import { UnknownFeedTooltip } from './UnknownFeedTooltip'; @@ -56,6 +57,7 @@ export function FeedEntry({ feed, chainId, oracleAddress, oracleMetadataMap }: F const isChainlink = vendor === PriceFeedVendors.Chainlink; const isCompound = vendor === PriceFeedVendors.Compound; const isRedstone = vendor === PriceFeedVendors.Redstone; + const isPendle = vendor === PriceFeedVendors.Pendle; const getTooltipContent = () => { switch (vendor) { @@ -86,6 +88,15 @@ export function FeedEntry({ feed, chainId, oracleAddress, oracleMetadataMap }: F /> ); + case PriceFeedVendors.Pendle: + return ( + + ); + case PriceFeedVendors.PythNetwork: case PriceFeedVendors.Oval: case PriceFeedVendors.Lido: @@ -143,7 +154,7 @@ export function FeedEntry({ feed, chainId, oracleAddress, oracleMetadataMap }: F )}
- {(isChainlink || isCompound || isRedstone) && vendorIcon ? ( + {(isChainlink || isCompound || isRedstone || isPendle) && vendorIcon ? ( Oracle + {/* Header with icon and title */} +
+ {vendorIcon && ( +
+ Pendle +
+ )} +
Pendle Feed Details
+
+ + {/* Feed pair name */} +
+
+ {baseAsset} / {quoteAsset} +
+
+ + {/* Pendle Specific Data */} + {(feedData?.ptSymbol != null || feedData?.baseDiscountPerYear != null) && ( +
+ {feedData?.ptSymbol != null && ( +
+ PT Token: + {feedData.ptSymbol} +
+ )} + {feedData?.baseDiscountPerYear != null && ( +
+ Base Discount / Year: + {formatDiscountPerYear(feedData.baseDiscountPerYear)} +
+ )} +
+ )} + + {/* External Links */} +
+
View on:
+
+ + Etherscan + Etherscan + +
+
+
+ ); +} diff --git a/src/hooks/useOracleMetadata.ts b/src/hooks/useOracleMetadata.ts index a95aef45..b3ec81bf 100644 --- a/src/hooks/useOracleMetadata.ts +++ b/src/hooks/useOracleMetadata.ts @@ -29,6 +29,10 @@ export type EnrichedFeed = { deviationThreshold?: number; ens?: string; // Chainlink ENS name for feed URL (e.g. "eth-usd") feedType?: string; // Redstone feed type: "market" or "fundamental" + baseDiscountPerYear?: string; // Pendle base discount per year (raw 18-decimal value) + innerOracle?: string; // Pendle inner oracle address + pt?: string; // Pendle PT token address + ptSymbol?: string; // Pendle PT token symbol }; export type OracleOutputData = { diff --git a/src/imgs/oracles/pendle.png b/src/imgs/oracles/pendle.png new file mode 100644 index 00000000..27586919 Binary files /dev/null and b/src/imgs/oracles/pendle.png differ diff --git a/src/utils/oracle.ts b/src/utils/oracle.ts index bec1237a..5c5467de 100644 --- a/src/utils/oracle.ts +++ b/src/utils/oracle.ts @@ -48,6 +48,7 @@ export enum PriceFeedVendors { Oval = 'Oval', Compound = 'Compound', Lido = 'Lido', + Pendle = 'Pendle', Unknown = 'Unknown', } @@ -58,6 +59,7 @@ export const OracleVendorIcons: Record = { [PriceFeedVendors.Oval]: require('../imgs/oracles/uma.png') as string, [PriceFeedVendors.Compound]: require('../imgs/oracles/compound.webp') as string, [PriceFeedVendors.Lido]: require('../imgs/oracles/lido.png') as string, + [PriceFeedVendors.Pendle]: require('../imgs/oracles/pendle.png') as string, [PriceFeedVendors.Unknown]: '', }; @@ -74,6 +76,7 @@ export function mapProviderToVendor(provider: OracleFeedProvider): PriceFeedVend Lido: PriceFeedVendors.Lido, Oval: PriceFeedVendors.Oval, Pyth: PriceFeedVendors.PythNetwork, + Pendle: PriceFeedVendors.Pendle, }; return mapping[provider] ?? PriceFeedVendors.Unknown; @@ -110,6 +113,10 @@ export type FeedData = { deviationThreshold?: number; ens?: string; // Chainlink ENS name for feed URL (e.g. "eth-usd") feedType?: string; // Redstone feed type: "market" or "fundamental" + baseDiscountPerYear?: string; // Pendle base discount per year (raw 18-decimal value) + innerOracle?: string; // Pendle inner oracle address + pt?: string; // Pendle PT token address + ptSymbol?: string; // Pendle PT token symbol }; export type FeedVendorResult = { @@ -175,6 +182,10 @@ export function detectFeedVendorFromMetadata(feed: EnrichedFeed | null | undefin deviationThreshold: feed.deviationThreshold, ens: feed.ens, feedType: feed.feedType, + baseDiscountPerYear: feed.baseDiscountPerYear, + innerOracle: feed.innerOracle, + pt: feed.pt, + ptSymbol: feed.ptSymbol, }; return {