Skip to content

Commit a916e1c

Browse files
committed
feat(dev-hub) Include feeds in the search
1 parent b54bea3 commit a916e1c

File tree

2 files changed

+121
-5
lines changed

2 files changed

+121
-5
lines changed
Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,121 @@
1-
import { createFromSource } from "fumadocs-core/search/server";
1+
import type { AdvancedIndex } from "fumadocs-core/search/server";
2+
import { createSearchAPI } from "fumadocs-core/search/server";
3+
import { z } from "zod";
24

35
import { source } from "../../../lib/source";
46

5-
export const { GET } = createFromSource(source);
7+
// Define schemas for type safety
8+
const hermesSchema = z.array(
9+
z.object({
10+
id: z.string(),
11+
attributes: z.object({ symbol: z.string() }),
12+
}),
13+
);
14+
15+
const lazerSchema = z.array(
16+
z.object({
17+
symbol: z.string(),
18+
name: z.string(),
19+
pyth_lazer_id: z.number(),
20+
description: z.string(),
21+
}),
22+
);
23+
24+
async function getHermesFeeds(): Promise<AdvancedIndex[]> {
25+
try {
26+
const endpoints = [
27+
"https://hermes.pyth.network",
28+
"https://hermes-beta.pyth.network",
29+
];
30+
const responses = await Promise.all(
31+
endpoints.map((url) =>
32+
fetch(`${url}/v2/price_feeds`, {
33+
next: { revalidate: 3600 },
34+
}).then((res) => res.json() as Promise<unknown>),
35+
),
36+
);
37+
38+
const allFeeds: AdvancedIndex[] = [];
39+
40+
for (const data of responses) {
41+
const parsed = hermesSchema.safeParse(data);
42+
if (parsed.success) {
43+
for (const feed of parsed.data) {
44+
allFeeds.push({
45+
title: feed.attributes.symbol,
46+
description: `Price Feed ID: ${feed.id}`,
47+
url: `/price-feeds/core/price-feeds/price-feed-ids?search=${feed.attributes.symbol}`,
48+
id: feed.id,
49+
tag: "price-feed-core",
50+
structuredData: {
51+
headings: [],
52+
contents: [
53+
{ heading: "Symbol", content: feed.attributes.symbol },
54+
{ heading: "ID", content: feed.id },
55+
],
56+
},
57+
});
58+
}
59+
}
60+
}
61+
62+
return allFeeds;
63+
} catch (error: unknown) {
64+
throw new Error("Failed to fetch Hermes feeds", { cause: error });
65+
}
66+
}
67+
68+
async function getLazerFeeds(): Promise<AdvancedIndex[]> {
69+
try {
70+
const res = await fetch(
71+
"https://history.pyth-lazer.dourolabs.app/history/v1/symbols",
72+
{ next: { revalidate: 3600 } },
73+
);
74+
const data = (await res.json()) as unknown;
75+
const parsed = lazerSchema.safeParse(data);
76+
77+
if (!parsed.success) {
78+
return [];
79+
}
80+
81+
return parsed.data.map((feed) => ({
82+
title: feed.name,
83+
description: `${feed.symbol} - ${feed.description} (ID: ${String(feed.pyth_lazer_id)})`,
84+
url: `/price-feeds/pro/price-feed-ids?search=${feed.symbol}`,
85+
id: `lazer-${String(feed.pyth_lazer_id)}`,
86+
tag: "price-feed-pro",
87+
structuredData: {
88+
headings: [],
89+
contents: [
90+
{ heading: "Symbol", content: feed.symbol },
91+
{ heading: "Name", content: feed.name },
92+
{ heading: "Description", content: feed.description },
93+
{ heading: "ID", content: String(feed.pyth_lazer_id) },
94+
],
95+
},
96+
}));
97+
} catch (error: unknown) {
98+
throw new Error("Failed to fetch Lazer feeds", { cause: error });
99+
}
100+
}
101+
102+
export const { GET } = createSearchAPI("advanced", {
103+
indexes: async () => {
104+
const staticPages = source.getPages().map((page) => ({
105+
title: page.data.title,
106+
description: page.data.description,
107+
url: page.url,
108+
id: page.url,
109+
structuredData: page.data.structuredData,
110+
})) as AdvancedIndex[];
111+
112+
// Added these two functions to get the price feeds from the Hermes and Pro APIs
113+
const [hermesFeeds, lazerFeeds] = await Promise.all([
114+
getHermesFeeds(),
115+
getLazerFeeds(),
116+
]);
117+
118+
// Combine the static pages, Hermes feeds, and Pro feeds
119+
return [...staticPages, ...hermesFeeds, ...lazerFeeds];
120+
},
121+
});

apps/developer-hub/src/components/Pages/Homepage/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,21 @@ export const Homepage = () => {
5151
title="Pyth Token"
5252
description="The native token powering governance and staking across the Pyth Network."
5353
url="/pyth-token"
54-
urlLabel="Link"
54+
urlLabel="Read more"
5555
image={<SignalImage />}
5656
/>
5757
<SectionCard
5858
title="Oracle Integrity Staking"
5959
description="Stake PYTH to support data publishers and secure the integrity of Pyth price feeds."
6060
url="/oracle-integrity-staking"
61-
urlLabel="Link"
61+
urlLabel="Read more"
6262
image={<SignalImage />}
6363
/>
6464
<SectionCard
6565
title="Pyth Metrics"
6666
description="Track network performance, feed activity, and ecosystem growth in real time."
6767
url="/metrics"
68-
urlLabel="Link"
68+
urlLabel="Read more"
6969
image={<SignalImage />}
7070
/>
7171
</SectionCards>

0 commit comments

Comments
 (0)