Skip to content

Commit ef759b0

Browse files
authored
Tables: Temporary solution for parsing svr feed variants (#2877)
* temporary solution parsing svr feed variants * update * restored filter (mistakingly removed) * return filter * restore logic * shared->canonical for user display * created util to avoid duplicate regex filtering * updated svr-feeds page, updated links * nit * canonical-svr => svr * dynamic svr feed sourcing * lintfix * reorder
1 parent bea5bc2 commit ef759b0

File tree

4 files changed

+126
-36
lines changed

4 files changed

+126
-36
lines changed

src/content/data-feeds/svr-feeds/index.mdx

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ whatsnext:
1414
import { Aside, ClickToZoom, CodeSample, CopyText } from "@components"
1515
import { Tabs } from "@components/Tabs"
1616
import { CHAINS } from "@features/data/chains"
17+
import { isSharedSVR, isAaveSVR } from "~/features/feeds/utils/svrDetection.ts"
1718

1819
export async function getFeeds() {
1920
const ethereumMainnet = CHAINS.find((chain) => chain.page === "ethereum")?.networks.find(
@@ -30,27 +31,38 @@ try {
3031
const response = await fetch(rddUrl)
3132
const data = await response.json()
3233

33-
const targetFeeds = [
34-
"AAVE/USD-RefPrice-DF-Ethereum-001",
35-
"BTC/USD-RefPrice-DF-Ethereum-001",
36-
"ETH/USD-RefPrice-DF-Ethereum-001",
37-
"LINK/USD-RefPrice-DF-Ethereum-001",
38-
"USDC/USD-RefPrice-DF-Ethereum-001",
39-
"USDT/USD-RefPrice-DF-Ethereum-001",
40-
]
41-
34+
// Find all feeds that have SVR variants (either Aave or Shared SVR) and are not hidden
4235
const svrFeeds = data.filter(
43-
(feed) =>
44-
feed.secondaryProxyAddress && feed.docs?.clicProductName && targetFeeds.includes(feed.docs.clicProductName)
36+
(feed) => feed.secondaryProxyAddress && !feed.docs?.hidden && (isAaveSVR(feed) || isSharedSVR(feed))
4537
)
4638

47-
return svrFeeds
48-
.map((feed) => ({
49-
name: feed.name.replace(" / ", "/"),
50-
address: feed.contractAddress,
51-
}))
39+
// Group feeds by their base name (e.g., "BTC/USD", "ETH/USD")
40+
const feedGroups = {}
41+
42+
svrFeeds.forEach(feed => {
43+
const baseName = feed.name.replace(" / ", "/")
44+
45+
if (!feedGroups[baseName]) {
46+
feedGroups[baseName] = {
47+
name: baseName,
48+
aaveAddress: null,
49+
svrAddress: null
50+
}
51+
}
52+
53+
if (isAaveSVR(feed)) {
54+
feedGroups[baseName].aaveAddress = feed.contractAddress
55+
} else if (isSharedSVR(feed)) {
56+
feedGroups[baseName].svrAddress = feed.contractAddress
57+
}
58+
})
59+
60+
// Convert to array and sort
61+
const combinedFeeds = Object.values(feedGroups)
5262
.sort((a, b) => a.name.localeCompare(b.name))
5363

64+
return combinedFeeds
65+
5466
} catch (error) {
5567
return []
5668
}
@@ -132,6 +144,14 @@ Chainlink Smart Value Recapture (SVR) extends standard Chainlink Price Feeds wit
132144
**Fail-Safe Fallback Mechanism**
133145
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.
134146

147+
## SVR Feed Variants
148+
149+
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.
150+
151+
### Aave SVR Feeds
152+
153+
Aave SVR feeds are specifically tailored for the Aave protocol and are only intended for use by Aave.
154+
135155
## How Protocols Can Utilize SVR Feeds
136156

137157
### 1. Identify the SVR Feed Address
@@ -288,30 +308,44 @@ The following code samples demonstrate the complete decoding process, including
288308
</Fragment>
289309
</Tabs>
290310

291-
#### 4. Detect SVR-enabled Feeds for the Aave Protocol
311+
#### 4. Detect SVR-enabled Feeds
292312

293313
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:
294314

295315
<table>
296316
<thead>
297317
<tr>
298-
<th>Feed name</th>
299-
<th>Address</th>
318+
<th>Feed</th>
319+
<th>SVR Feed</th>
320+
<th>Aave Dedicated SVR Feed</th>
300321
</tr>
301322
</thead>
302323
<tbody>
303324
{feeds &&
304325
feeds.map((feed) => (
305-
<tr key={feed.address}>
306-
<td>{feed.name}</td>
326+
<tr key={feed.name}>
327+
<td>
328+
<strong>{feed.name}</strong>
329+
</td>
330+
<td>
331+
{feed.svrAddress ? (
332+
<CopyText text={feed.svrAddress} code />
333+
) : (
334+
<span style={{ color: "#888" }}>Not available</span>
335+
)}
336+
</td>
307337
<td>
308-
<CopyText text={feed.address} code />
338+
{feed.aaveAddress ? (
339+
<CopyText text={feed.aaveAddress} code />
340+
) : (
341+
<span style={{ color: "#888" }}>Not available</span>
342+
)}
309343
</td>
310344
</tr>
311345
))}
312346
{(!feeds || feeds.length === 0) && (
313347
<tr>
314-
<td colSpan="2">No SVR feeds found.</td>
348+
<td colSpan="3">No SVR feeds found.</td>
315349
</tr>
316350
)}
317351
</tbody>
@@ -383,7 +417,7 @@ For gas management, simulations, and other advanced usage, see the official [Fla
383417

384418
3. **Stay Updated**
385419
- Keep track of any updates to the SVR aggregator address, function signatures, or Flashbots MEV-Share changes.
386-
- Monitor for changes in Aave liquidation parameters (e.g., new assets, different collateral thresholds).
420+
- Monitor for changes in liquidation parameters (e.g., new assets, different collateral thresholds).
387421

388422
## Economics and Revenue Split
389423

src/features/feeds/components/Tables.module.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,19 @@
195195
text-align: left;
196196
}
197197

198+
.sharedCallout {
199+
background-color: #e6f3ff;
200+
border-radius: 4px;
201+
padding: 10px 12px;
202+
margin-top: 10px;
203+
margin-bottom: 10px;
204+
font-size: 0.9rem;
205+
color: #0066cc;
206+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
207+
width: 100%;
208+
text-align: left;
209+
}
210+
198211
.feedVariantBadge {
199212
display: inline-block;
200213
font-size: 0.75rem;

src/features/feeds/components/Tables.tsx

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import button from "@chainlink/design-system/button.module.css"
99
import { CheckHeartbeat } from "./pause-notice/CheckHeartbeat.tsx"
1010
import { monitoredFeeds, FeedDataItem } from "~/features/data/index.ts"
1111
import { StreamsNetworksData, type NetworkData } from "../data/StreamsNetworksData.ts"
12+
import { isSharedSVR, isAaveSVR } from "~/features/feeds/utils/svrDetection.ts"
1213

1314
const feedItems = monitoredFeeds.mainnet
1415
const feedCategories = {
@@ -228,12 +229,20 @@ const DefaultTr = ({ network, metadata, showExtraDetails, dataFeedType }) => {
228229
{metadata.secondaryProxyAddress && (
229230
<div style={{ marginTop: "5px" }}>
230231
<a
231-
href="/data-feeds/svr-feeds"
232+
href={
233+
isAaveSVR(metadata)
234+
? "/data-feeds/svr-feeds#aave-svr-feeds"
235+
: isSharedSVR(metadata)
236+
? "/data-feeds/svr-feeds"
237+
: "/data-feeds/svr-feeds"
238+
}
232239
target="_blank"
233240
className={tableStyles.feedVariantBadge}
234-
title="SVR-enabled Feed"
241+
title={
242+
isAaveSVR(metadata) ? "Aave Dedicated SVR Feed" : isSharedSVR(metadata) ? " SVR Feed" : "SVR Feed"
243+
}
235244
>
236-
SVR
245+
{isAaveSVR(metadata) ? "Aave SVR" : isSharedSVR(metadata) ? "SVR" : "SVR"}
237246
</a>
238247
</div>
239248
)}
@@ -328,7 +337,7 @@ const DefaultTr = ({ network, metadata, showExtraDetails, dataFeedType }) => {
328337
<div className={tableStyles.separator} />
329338
<div className={tableStyles.assetAddress}>
330339
<dt>
331-
<span className="label">AAVE SVR Proxy:</span>
340+
<span className="label">{isAaveSVR(metadata) ? "AAVE SVR Proxy:" : "SVR Proxy:"}</span>
332341
</dt>
333342
<dd>
334343
<button
@@ -355,14 +364,25 @@ const DefaultTr = ({ network, metadata, showExtraDetails, dataFeedType }) => {
355364
</a>
356365
</dd>
357366
</div>
358-
<div className={clsx(tableStyles.aaveCallout)}>
359-
<strong>⚠️ Aave Dedicated Feed:</strong> This SVR proxy feed is dedicated exclusively for use by the
360-
Aave protocol. Learn more about{" "}
361-
<a href="/data-feeds/svr-feeds" target="_blank">
362-
SVR-enabled Feeds
363-
</a>
364-
.
365-
</div>
367+
{isAaveSVR(metadata) && (
368+
<div className={clsx(tableStyles.aaveCallout)}>
369+
<strong>⚠️ Aave Dedicated Feed:</strong> This SVR proxy feed is dedicated exclusively for use by the
370+
Aave protocol. Learn more about{" "}
371+
<a href="/data-feeds/svr-feeds#aave-svr-feeds" target="_blank">
372+
Aave SVR Feeds
373+
</a>
374+
.
375+
</div>
376+
)}
377+
{isSharedSVR(metadata) && (
378+
<div className={clsx(tableStyles.sharedCallout)}>
379+
<strong>🔗 SVR Feed:</strong> This SVR proxy feed is usable by any protocol. Learn more about{" "}
380+
<a href="/data-feeds/svr-feeds" target="_blank">
381+
SVR Feeds
382+
</a>
383+
.
384+
</div>
385+
)}
366386
</>
367387
)}
368388
</dl>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { type ChainMetadata } from "~/features/data/api/index.ts"
2+
3+
// This file contains *temporary* functions to detect SVR feeds based on their metadata
4+
// These functions are used to identify specific types of SVR feeds based on their metadata properties
5+
6+
/**
7+
* Determines if a feed is a Shared SVR feed based on its path
8+
* @param metadata - The feed metadata object
9+
* @returns true if the feed is a shared SVR feed
10+
*/
11+
export const isSharedSVR = (metadata: ChainMetadata): boolean => {
12+
// Check the path field for feeds ending with "-shared-svr"
13+
return typeof metadata.path === "string" && /-shared-svr$/.test(metadata.path)
14+
}
15+
16+
/**
17+
* Determines if a feed is an Aave dedicated SVR feed
18+
* @param metadata - The feed metadata object
19+
* @returns true if the feed has a secondary proxy address but is not a shared SVR feed
20+
*/
21+
export const isAaveSVR = (metadata: ChainMetadata): boolean => {
22+
return !!metadata?.secondaryProxyAddress && !isSharedSVR(metadata)
23+
}

0 commit comments

Comments
 (0)