Skip to content

Commit 52a9243

Browse files
committed
fix
1 parent 4c67c3d commit 52a9243

1 file changed

Lines changed: 34 additions & 107 deletions

File tree

src/features/feeds/utils/feedOutput.ts

Lines changed: 34 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,11 @@ export function formatDeviation(threshold: number): string {
5858
}
5959

6060
export interface FeedMarkdownOptions {
61-
/** Filter by schema version, e.g. "v8" or "v11". Only meaningful for streamsRwa. */
6261
schemaFilter?: string
63-
/** Public-facing API type name for use in generated URLs (e.g. "crypto" instead of "streamsCrypto"). */
6462
publicType?: string
65-
/** Restrict to "mainnet" or "testnet" networks only. */
6663
networkType?: "mainnet" | "testnet"
6764
}
6865

69-
// ---------------------------------------------------------------------------
70-
// Structured data types — used for JSON output
71-
// ---------------------------------------------------------------------------
72-
7366
export interface StreamEntry {
7467
name: string
7568
feedId: string
@@ -86,15 +79,10 @@ export interface FeedEntry {
8679
network: string
8780
networkName: string
8881
networkType: string
89-
/** Blockchain ecosystem name (e.g. "Ethereum", "Arbitrum"). */
9082
chain: string
9183
svr?: "shared" | "aave"
9284
}
9385

94-
// ---------------------------------------------------------------------------
95-
// Shared data collectors — used by both markdown and JSON formatters
96-
// ---------------------------------------------------------------------------
97-
9886
// eslint-disable-next-line @typescript-eslint/no-explicit-any
9987
function resolveSVR(feed: any): "shared" | "aave" | undefined {
10088
const isShared = typeof feed.path === "string" && /-shared-svr$/.test(feed.path)
@@ -109,22 +97,26 @@ export function collectStreamEntries(
10997
chainCache: Record<string, any>,
11098
options: FeedMarkdownOptions = {}
11199
): StreamEntry[] {
112-
const visibilityOpts = { schemaFilter: options.schemaFilter }
100+
const visibilityOpts = {
101+
...(options.schemaFilter ? { schemaFilter: options.schemaFilter } : {}),
102+
} as any
103+
113104
const seenFeedIds = new Set<string>()
114105
// eslint-disable-next-line @typescript-eslint/no-explicit-any
115106
const raw: any[] = []
116107

117108
for (const chain of CHAINS) {
118109
const chainData = chainCache[chain.page]
119110
if (!chainData?.networks) continue
120-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
111+
121112
for (const network of chainData.networks as any[]) {
122113
if (!network?.metadata?.length) continue
123114
if (network.networkType !== "mainnet") continue
124-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
115+
125116
for (const feed of network.metadata as any[]) {
126117
if (!isFeedVisible(feed, type, "", visibilityOpts)) continue
127118
if (!feed.feedId || seenFeedIds.has(feed.feedId)) continue
119+
128120
seenFeedIds.add(feed.feedId)
129121
raw.push(feed)
130122
}
@@ -133,55 +125,62 @@ export function collectStreamEntries(
133125

134126
raw.sort((a, b) => (resolveStreamPair(a) ?? "").localeCompare(resolveStreamPair(b) ?? ""))
135127

136-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
137128
return raw.flatMap((feed: any) => {
138129
const name = resolveStreamPair(feed)
139130
if (!name) return []
131+
140132
const tradingHours = resolveTradingHours(feed)
133+
141134
const entry: StreamEntry = {
142135
name,
143136
feedId: feed.feedId,
144137
assetClass: resolveAssetClass(feed),
145138
schema: resolveStreamSchema(type, feed),
146139
}
147-
if (tradingHours && tradingHours !== "—") entry.tradingHours = tradingHours
140+
141+
if (tradingHours && tradingHours !== "—") {
142+
entry.tradingHours = tradingHours
143+
}
144+
148145
return [entry]
149146
})
150147
}
151148

152-
/** Strips the " Data Feeds" suffix Chainlink appends to chain group titles. */
153149
function resolveChainName(chainTitle: string, chainPage: string): string {
154-
// Handles "Arbitrum Data Feeds" → "Arbitrum" and "Data Feeds" (Ethereum) → "Ethereum"
155150
const stripped = chainTitle.replace(/\s*Data Feeds$/, "").trim()
156151
return stripped || chainPage.charAt(0).toUpperCase() + chainPage.slice(1)
157152
}
158153

159154
export function collectFeedEntries(
160155
type: DataFeedType,
161156
networkFilter: string | null,
162-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
163157
chainCache: Record<string, any>,
164158
options: FeedMarkdownOptions = {}
165159
): FeedEntry[] {
166-
const visibilityOpts = { schemaFilter: options.schemaFilter }
160+
const visibilityOpts = {
161+
...(options.schemaFilter ? { schemaFilter: options.schemaFilter } : {}),
162+
} as any
163+
167164
const entries: FeedEntry[] = []
168165

169166
for (const chain of CHAINS) {
170167
const chainData = chainCache[chain.page]
171168
if (!chainData?.networks) continue
169+
172170
const chainName = resolveChainName(chain.title, chain.page)
173-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
171+
174172
for (const network of chainData.networks as any[]) {
175173
if (!network?.metadata?.length) continue
176174
if (networkFilter && network.queryString !== networkFilter) continue
177175
if (options.networkType && network.networkType !== options.networkType) continue
178-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
176+
179177
const visibleFeeds = network.metadata.filter((feed: any) => isFeedVisible(feed, type, "", visibilityOpts))
178+
180179
if (visibleFeeds.length === 0) continue
181180

182-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
183181
for (const feed of visibleFeeds as any[]) {
184182
const svr = resolveSVR(feed)
183+
185184
const entry: FeedEntry = {
186185
name: feed.name || feed.assetName || "Unknown",
187186
proxyAddress: feed.proxyAddress || feed.transmissionsAccount || feed.contractAddress || "N/A",
@@ -192,13 +191,14 @@ export function collectFeedEntries(
192191
networkType: network.networkType,
193192
chain: chainName,
194193
}
194+
195195
if (svr) entry.svr = svr
196+
196197
entries.push(entry)
197198
}
198199
}
199200
}
200201

201-
// Sort alphabetically by feed name within each network for consistent, scannable output
202202
entries.sort((a, b) => {
203203
if (a.network !== b.network) return a.network.localeCompare(b.network)
204204
return a.name.localeCompare(b.name)
@@ -207,119 +207,46 @@ export function collectFeedEntries(
207207
return entries
208208
}
209209

210-
// ---------------------------------------------------------------------------
211-
// Markdown formatter
212-
// ---------------------------------------------------------------------------
213-
214-
/**
215-
* Builds a plain-markdown document listing feed addresses or stream IDs
216-
* for the given type, optionally filtered to a single network.
217-
*/
218210
export function buildFeedAddressMarkdown(
219211
type: DataFeedType,
220212
networkFilter: string | null,
221-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
222213
chainCache: Record<string, any>,
223214
siteBase = "https://docs.chain.link",
224215
options: FeedMarkdownOptions = {}
225216
): string {
226217
const lines: string[] = []
227218
const streams = isStreamsType(type)
219+
228220
const label = FEED_TYPE_LABELS[type]
229-
const baseUrl = `${siteBase}/api/feeds/addresses?type=${type}`
230-
const visibilityOpts = { schemaFilter: options.schemaFilter }
231-
232-
const mainnetQueryStrings: string[] = []
233-
const testnetQueryStrings: string[] = []
234-
235-
if (!streams) {
236-
for (const chain of CHAINS) {
237-
const chainData = chainCache[chain.page]
238-
if (!chainData?.networks) continue
239-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
240-
for (const network of chainData.networks as any[]) {
241-
if (!network?.queryString) continue
242-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
243-
const hasFeeds = network.metadata?.some((feed: any) => isFeedVisible(feed, type, "", visibilityOpts))
244-
if (!hasFeeds) continue
245-
if (network.networkType === "mainnet") mainnetQueryStrings.push(network.queryString)
246-
else testnetQueryStrings.push(network.queryString)
247-
}
248-
}
249-
}
250221

251222
if (streams) {
252223
lines.push(`# Chainlink Data Streams: ${label}`)
253224
lines.push(`Source: ${siteBase}/data-streams`)
254-
lines.push(`Machine-readable endpoint: ${siteBase}/api/streams/ids?type=${options.publicType ?? type}`)
255-
lines.push(`Static snapshot: ${siteBase}/data-feeds/feed-addresses/${type}.txt`)
256225
lines.push("")
226+
lines.push(`> Stream IDs for Chainlink Data Streams – ${label.replace("Data Streams — ", "")}.`)
227+
lines.push(`> These IDs are universal and valid across all supported networks.`)
257228
lines.push(
258-
`> Stream IDs for Chainlink **${label}**. Stream IDs are universal — the same ID is valid across all supported networks.`
229+
`> To use a stream ID, retrieve the verifier proxy for the target network from /data-streams/networks.txt.`
259230
)
260-
lines.push(`> Supported networks and verifier proxy addresses: \`${siteBase}/api/streams/networks\``)
231+
lines.push(`> Datasets may contain multiple schema versions. Filter by schema if needed.`)
261232
lines.push("")
262233

263234
const streamEntries = collectStreamEntries(type, chainCache, options)
235+
264236
if (streamEntries.length > 0) {
265237
lines.push("| Stream | Feed ID | Asset Class | Schema | Trading Hours |")
266238
lines.push("|--------|---------|-------------|--------|---------------|")
239+
267240
for (const entry of streamEntries) {
268241
lines.push(
269-
`| ${entry.name} | \`${entry.feedId}\` | ${entry.assetClass} | ${entry.schema} | ${entry.tradingHours ?? "—"} |`
242+
`| ${entry.name} | \`${entry.feedId}\` | ${entry.assetClass} | \`${entry.schema}\` | ${entry.tradingHours ?? "—"} |`
270243
)
271244
}
245+
272246
lines.push("")
273247
} else {
274248
lines.push(`No stream IDs found for type \`${type}\`.`)
275249
}
276-
} else {
277-
lines.push(`# Chainlink Feed Addresses: ${label}`)
278-
lines.push(`Source: ${siteBase}/data-feeds/price-feeds/addresses`)
279-
lines.push(`Machine-readable endpoint: ${baseUrl}`)
280-
lines.push(`Static snapshot: ${siteBase}/data-feeds/feed-addresses/${type}.txt`)
281-
lines.push("")
282-
lines.push(`> Feed contract addresses for Chainlink **${label}** across all supported networks.`)
283-
lines.push(
284-
`> To narrow results to a single network, append \`&network={queryString}\` — e.g. \`${baseUrl}&network=${mainnetQueryStrings[0] ?? "ethereum-mainnet"}\``
285-
)
286-
lines.push(`> Full network list with queryStrings: \`${siteBase}/api/feeds/networks?type=${type}\``)
287-
lines.push("")
288-
if (mainnetQueryStrings.length > 0) {
289-
lines.push(`**Mainnet queryStrings:** ${mainnetQueryStrings.map((q) => `\`${q}\``).join(", ")}`)
290-
lines.push("")
291-
}
292-
if (testnetQueryStrings.length > 0) {
293-
lines.push(`**Testnet queryStrings:** ${testnetQueryStrings.map((q) => `\`${q}\``).join(", ")}`)
294-
lines.push("")
295-
}
296-
297-
const feedEntries = collectFeedEntries(type, networkFilter, chainCache, options)
298-
if (feedEntries.length === 0) {
299-
lines.push(
300-
networkFilter
301-
? `No feeds found for type \`${type}\` on network \`${networkFilter}\`. Check the network queryString or omit the \`network\` parameter to see all networks.`
302-
: `No feeds found for type \`${type}\`.`
303-
)
304-
} else {
305-
let currentNetwork = ""
306-
for (const entry of feedEntries) {
307-
if (entry.network !== currentNetwork) {
308-
currentNetwork = entry.network
309-
const network = feedEntries.find((e) => e.network === currentNetwork)!
310-
lines.push(`## ${entry.chain}${network.networkName}`)
311-
lines.push(`- Network type: ${network.networkType}`)
312-
lines.push(`- Query string: \`${network.network}\``)
313-
lines.push("")
314-
lines.push("| Feed Name | Proxy Address | Deviation | Heartbeat |")
315-
lines.push("|-----------|--------------|-----------|-----------|")
316-
}
317-
const svrLabel = entry.svr === "shared" ? " (Shared SVR)" : entry.svr === "aave" ? " (Aave SVR)" : ""
318-
const name = escapePipes(`${entry.name}${svrLabel}`)
319-
lines.push(`| ${name} | \`${entry.proxyAddress}\` | ${entry.deviation} | ${entry.heartbeat} |`)
320-
}
321-
lines.push("")
322-
}
323250
}
324251

325252
return lines.join("\n")

0 commit comments

Comments
 (0)