diff --git a/src/features/markets/components/oracle/MarketOracle/ChainlinkFeedTooltip.tsx b/src/features/markets/components/oracle/MarketOracle/ChainlinkFeedTooltip.tsx
index a66943fe..db8132e9 100644
--- a/src/features/markets/components/oracle/MarketOracle/ChainlinkFeedTooltip.tsx
+++ b/src/features/markets/components/oracle/MarketOracle/ChainlinkFeedTooltip.tsx
@@ -7,7 +7,14 @@ import { useGlobalModal } from '@/contexts/GlobalModalContext';
import type { EnrichedFeed } from '@/hooks/useOracleMetadata';
import etherscanLogo from '@/imgs/etherscan.png';
import { getExplorerURL } from '@/utils/external';
-import { getChainlinkFeedUrl, OracleVendorIcons, PriceFeedVendors, type FeedFreshnessStatus } from '@/utils/oracle';
+import {
+ detectFeedVendorFromMetadata,
+ getChainlinkFeedUrl,
+ getChronicleFeedUrl,
+ OracleVendorIcons,
+ PriceFeedVendors,
+ type FeedFreshnessStatus,
+} from '@/utils/oracle';
import { ChainlinkRiskTiersModal } from './ChainlinkRiskTiersModal';
import { FeedFreshnessSection } from './FeedFreshnessSection';
@@ -39,14 +46,22 @@ function getRiskTierBadge(category: string) {
export function ChainlinkFeedTooltip({ feed, chainId, feedFreshness }: ChainlinkFeedTooltipProps) {
const { toggleModal, closeModal } = useGlobalModal();
- const baseAsset = feed.pair[0] ?? 'Unknown';
- const quoteAsset = feed.pair[1] ?? 'Unknown';
+ const { vendor, assetPair } = detectFeedVendorFromMetadata(feed);
+ const baseAsset = assetPair.baseAsset;
+ const quoteAsset = assetPair.quoteAsset;
+ const isChronicle = vendor === PriceFeedVendors.Chronicle;
+ const feedTitle = isChronicle ? 'Chronicle Feed Details' : 'Chainlink Feed Details';
+ const vendorLabel = isChronicle ? 'Chronicle' : 'Chainlink';
+ const intervalValue = isChronicle ? (feed.updateInterval ?? feed.heartbeat) : (feed.heartbeat ?? null);
+ const deviationValue = isChronicle ? (feed.updateSpread ?? feed.deviationThreshold) : (feed.deviationThreshold ?? null);
+ const chronicleRiskTier = isChronicle ? feed.riskTier : null;
+ const chainlinkTier = isChronicle ? null : feed.tier;
- const vendorIcon = OracleVendorIcons[PriceFeedVendors.Chainlink];
+ const vendorIcon = OracleVendorIcons[vendor] || OracleVendorIcons[PriceFeedVendors.Chainlink];
- const chainlinkUrl = feed.ens ? getChainlinkFeedUrl(chainId, feed.ens) : '';
+ const vendorUrl = isChronicle ? getChronicleFeedUrl(baseAsset, quoteAsset) : feed.ens ? getChainlinkFeedUrl(chainId, feed.ens) : '';
- const hasDetails = feed.heartbeat != null || feed.tier != null || feed.deviationThreshold != null;
+ const hasDetails = intervalValue != null || chainlinkTier != null || chronicleRiskTier != null || deviationValue != null;
return (
@@ -56,13 +71,13 @@ export function ChainlinkFeedTooltip({ feed, chainId, feedFreshness }: Chainlink
)}
-
Chainlink Feed Details
+
{feedTitle}
{/* Feed pair name */}
@@ -72,20 +87,20 @@ export function ChainlinkFeedTooltip({ feed, chainId, feedFreshness }: Chainlink
- {/* Chainlink Specific Data */}
+ {/* Vendor specific data */}
{hasDetails && (
- {feed.heartbeat != null && (
+ {intervalValue != null && (
- Heartbeat:
- {feed.heartbeat}s
+ {isChronicle ? 'Update Interval:' : 'Heartbeat:'}
+ {intervalValue}s
)}
- {feed.tier != null && (
+ {chainlinkTier != null && (
Risk Tier:
- {getRiskTierBadge(feed.tier)}
+ {getRiskTierBadge(chainlinkTier)}
)}
- {feed.deviationThreshold != null && (
+ {chronicleRiskTier != null && (
- Deviation Threshold:
- {feed.deviationThreshold}%
+ Risk Tier:
+ {chronicleRiskTier}
+
+ )}
+ {deviationValue != null && (
+
+ {isChronicle ? 'Update Spread:' : 'Deviation Threshold:'}
+ {deviationValue}%
)}
@@ -135,9 +156,9 @@ export function ChainlinkFeedTooltip({ feed, chainId, feedFreshness }: Chainlink
/>
Etherscan
- {chainlinkUrl && (
+ {vendorUrl && (
)}
- Chainlink
+ {vendorLabel}
)}
diff --git a/src/features/markets/components/oracle/MarketOracle/FeedEntry.tsx b/src/features/markets/components/oracle/MarketOracle/FeedEntry.tsx
index 27801731..df27d11b 100644
--- a/src/features/markets/components/oracle/MarketOracle/FeedEntry.tsx
+++ b/src/features/markets/components/oracle/MarketOracle/FeedEntry.tsx
@@ -109,6 +109,7 @@ export function FeedEntry({ feed, chainId, feedSnapshotsByAddress }: FeedEntryPr
const getTooltipContent = () => {
switch (vendor) {
case PriceFeedVendors.Chainlink:
+ case PriceFeedVendors.Chronicle:
return (
+
+
diff --git a/src/utils/oracle.ts b/src/utils/oracle.ts
index 3bee975a..a9fb9186 100644
--- a/src/utils/oracle.ts
+++ b/src/utils/oracle.ts
@@ -39,6 +39,7 @@ export enum OracleType {
export enum PriceFeedVendors {
Chainlink = 'Chainlink',
+ Chronicle = 'Chronicle',
PythNetwork = 'Pyth Network',
Redstone = 'Redstone',
Oval = 'Oval',
@@ -52,6 +53,7 @@ export enum PriceFeedVendors {
export const OracleVendorIcons: Record = {
[PriceFeedVendors.Chainlink]: require('../imgs/oracles/chainlink.png') as string,
+ [PriceFeedVendors.Chronicle]: require('../imgs/oracles/chronicle.svg') as string,
[PriceFeedVendors.PythNetwork]: require('../imgs/oracles/pyth.png') as string,
[PriceFeedVendors.Redstone]: require('../imgs/oracles/redstone.svg') as string,
[PriceFeedVendors.Oval]: require('../imgs/oracles/uma.png') as string,
@@ -71,11 +73,13 @@ export function mapProviderToVendor(provider: OracleFeedProvider): PriceFeedVend
const normalizedProvider = provider.trim().toLowerCase();
+ if (normalizedProvider.includes('chronicle')) return PriceFeedVendors.Chronicle;
if (normalizedProvider.includes('pendle')) return PriceFeedVendors.Pendle;
if (normalizedProvider.includes('midas')) return PriceFeedVendors.Midas;
const mapping: Record = {
chainlink: PriceFeedVendors.Chainlink,
+ chronicle: PriceFeedVendors.Chronicle,
redstone: PriceFeedVendors.Redstone,
compound: PriceFeedVendors.Compound,
lido: PriceFeedVendors.Lido,
@@ -108,6 +112,17 @@ export function getChainlinkFeedUrl(chainId: number, ens: string): string {
return `https://data.chain.link/feeds/${path}/${ens}`;
}
+/**
+ * Generate Chronicle dashboard URL from a feed pair.
+ */
+export function getChronicleFeedUrl(baseAsset: string, quoteAsset: string): string {
+ if (!baseAsset || !quoteAsset || baseAsset === 'Unknown' || quoteAsset === 'Unknown') {
+ return '';
+ }
+
+ return `https://chroniclelabs.org/dashboard/oracle/${encodeURIComponent(baseAsset)}/${encodeURIComponent(quoteAsset)}`;
+}
+
export type FeedVendorResult = {
vendor: PriceFeedVendors;
assetPair: {