diff --git a/src/content/data-feeds/svr-feeds/index.mdx b/src/content/data-feeds/svr-feeds/index.mdx index ff0c311d046..3c21ab384c8 100644 --- a/src/content/data-feeds/svr-feeds/index.mdx +++ b/src/content/data-feeds/svr-feeds/index.mdx @@ -14,6 +14,7 @@ whatsnext: import { Aside, ClickToZoom, CodeSample, CopyText } from "@components" import { Tabs } from "@components/Tabs" import { CHAINS } from "@features/data/chains" +import { isSharedSVR, isAaveSVR } from "~/features/feeds/utils/svrDetection.ts" export async function getFeeds() { const ethereumMainnet = CHAINS.find((chain) => chain.page === "ethereum")?.networks.find( @@ -30,27 +31,38 @@ try { const response = await fetch(rddUrl) const data = await response.json() - const targetFeeds = [ - "AAVE/USD-RefPrice-DF-Ethereum-001", - "BTC/USD-RefPrice-DF-Ethereum-001", - "ETH/USD-RefPrice-DF-Ethereum-001", - "LINK/USD-RefPrice-DF-Ethereum-001", - "USDC/USD-RefPrice-DF-Ethereum-001", - "USDT/USD-RefPrice-DF-Ethereum-001", - ] - + // Find all feeds that have SVR variants (either Aave or Shared SVR) and are not hidden const svrFeeds = data.filter( - (feed) => - feed.secondaryProxyAddress && feed.docs?.clicProductName && targetFeeds.includes(feed.docs.clicProductName) + (feed) => feed.secondaryProxyAddress && !feed.docs?.hidden && (isAaveSVR(feed) || isSharedSVR(feed)) ) - return svrFeeds - .map((feed) => ({ - name: feed.name.replace(" / ", "/"), - address: feed.contractAddress, - })) + // Group feeds by their base name (e.g., "BTC/USD", "ETH/USD") + const feedGroups = {} + + svrFeeds.forEach(feed => { + const baseName = feed.name.replace(" / ", "/") + + if (!feedGroups[baseName]) { + feedGroups[baseName] = { + name: baseName, + aaveAddress: null, + svrAddress: null + } + } + + if (isAaveSVR(feed)) { + feedGroups[baseName].aaveAddress = feed.contractAddress + } else if (isSharedSVR(feed)) { + feedGroups[baseName].svrAddress = feed.contractAddress + } + }) + + // Convert to array and sort + const combinedFeeds = Object.values(feedGroups) .sort((a, b) => a.name.localeCompare(b.name)) + return combinedFeeds + } catch (error) { return [] } @@ -132,6 +144,14 @@ Chainlink Smart Value Recapture (SVR) extends standard Chainlink Price Feeds wit **Fail-Safe Fallback Mechanism** If the **private route** fails or times out, the SVR feed automatically **reverts** to the **Standard Feed price** after a configurable delay. This delay can be set to any amount of seconds. This helps ensures the feed doesn't stall and that price data is accessible through the public route if the private channel is unavailable. +## SVR Feed Variants + +Chainlink SVR Feeds are available as standard feeds for general use and specialized [Aave SVR Feeds](#aave-svr-feeds) for the Aave protocol. More specialized SVR feeds may be developed in the future for other protocols. + +### Aave SVR Feeds + +Aave SVR feeds are specifically tailored for the Aave protocol and are only intended for use by Aave. + ## How Protocols Can Utilize SVR Feeds ### 1. Identify the SVR Feed Address @@ -288,30 +308,44 @@ The following code samples demonstrate the complete decoding process, including -#### 4. Detect SVR-enabled Feeds for the Aave Protocol +#### 4. Detect SVR-enabled Feeds When processing forward calls, verify that the `to` address from the code sample above (the destination of the forward call) matches one of these feed addresses. This tells you which SVR data feed the price update is for: - - + + + {feeds && feeds.map((feed) => ( - - + + + ))} {(!feeds || feeds.length === 0) && ( - + )} @@ -383,7 +417,7 @@ For gas management, simulations, and other advanced usage, see the official [Fla 3. **Stay Updated** - Keep track of any updates to the SVR aggregator address, function signatures, or Flashbots MEV-Share changes. - - Monitor for changes in Aave liquidation parameters (e.g., new assets, different collateral thresholds). + - Monitor for changes in liquidation parameters (e.g., new assets, different collateral thresholds). ## Economics and Revenue Split diff --git a/src/features/feeds/components/Tables.module.css b/src/features/feeds/components/Tables.module.css index a8d5790e887..e3418ccc3b6 100644 --- a/src/features/feeds/components/Tables.module.css +++ b/src/features/feeds/components/Tables.module.css @@ -195,6 +195,19 @@ text-align: left; } +.sharedCallout { + background-color: #e6f3ff; + border-radius: 4px; + padding: 10px 12px; + margin-top: 10px; + margin-bottom: 10px; + font-size: 0.9rem; + color: #0066cc; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + width: 100%; + text-align: left; +} + .feedVariantBadge { display: inline-block; font-size: 0.75rem; diff --git a/src/features/feeds/components/Tables.tsx b/src/features/feeds/components/Tables.tsx index 94e622a37df..9909e78893f 100644 --- a/src/features/feeds/components/Tables.tsx +++ b/src/features/feeds/components/Tables.tsx @@ -9,6 +9,7 @@ import button from "@chainlink/design-system/button.module.css" import { CheckHeartbeat } from "./pause-notice/CheckHeartbeat.tsx" import { monitoredFeeds, FeedDataItem } from "~/features/data/index.ts" import { StreamsNetworksData, type NetworkData } from "../data/StreamsNetworksData.ts" +import { isSharedSVR, isAaveSVR } from "~/features/feeds/utils/svrDetection.ts" const feedItems = monitoredFeeds.mainnet const feedCategories = { @@ -228,12 +229,20 @@ const DefaultTr = ({ network, metadata, showExtraDetails, dataFeedType }) => { {metadata.secondaryProxyAddress && (
- SVR + {isAaveSVR(metadata) ? "Aave SVR" : isSharedSVR(metadata) ? "SVR" : "SVR"}
)} @@ -328,7 +337,7 @@ const DefaultTr = ({ network, metadata, showExtraDetails, dataFeedType }) => {
- AAVE SVR Proxy: + {isAaveSVR(metadata) ? "AAVE SVR Proxy:" : "SVR Proxy:"}
-
- ⚠️ Aave Dedicated Feed: This SVR proxy feed is dedicated exclusively for use by the - Aave protocol. Learn more about{" "} - - SVR-enabled Feeds - - . -
+ {isAaveSVR(metadata) && ( +
+ ⚠️ Aave Dedicated Feed: This SVR proxy feed is dedicated exclusively for use by the + Aave protocol. Learn more about{" "} + + Aave SVR Feeds + + . +
+ )} + {isSharedSVR(metadata) && ( +
+ 🔗 SVR Feed: This SVR proxy feed is usable by any protocol. Learn more about{" "} + + SVR Feeds + + . +
+ )} )} diff --git a/src/features/feeds/utils/svrDetection.ts b/src/features/feeds/utils/svrDetection.ts new file mode 100644 index 00000000000..c43e65bf466 --- /dev/null +++ b/src/features/feeds/utils/svrDetection.ts @@ -0,0 +1,23 @@ +import { type ChainMetadata } from "~/features/data/api/index.ts" + +// This file contains *temporary* functions to detect SVR feeds based on their metadata +// These functions are used to identify specific types of SVR feeds based on their metadata properties + +/** + * Determines if a feed is a Shared SVR feed based on its path + * @param metadata - The feed metadata object + * @returns true if the feed is a shared SVR feed + */ +export const isSharedSVR = (metadata: ChainMetadata): boolean => { + // Check the path field for feeds ending with "-shared-svr" + return typeof metadata.path === "string" && /-shared-svr$/.test(metadata.path) +} + +/** + * Determines if a feed is an Aave dedicated SVR feed + * @param metadata - The feed metadata object + * @returns true if the feed has a secondary proxy address but is not a shared SVR feed + */ +export const isAaveSVR = (metadata: ChainMetadata): boolean => { + return !!metadata?.secondaryProxyAddress && !isSharedSVR(metadata) +}
Feed nameAddressFeedSVR FeedAave Dedicated SVR Feed
{feed.name}
+ {feed.name} + + {feed.svrAddress ? ( + + ) : ( + Not available + )} + - + {feed.aaveAddress ? ( + + ) : ( + Not available + )}
No SVR feeds found.No SVR feeds found.