Skip to content

Commit 92d6291

Browse files
committed
use yaml format for the sponsored feed data for evm
1 parent b1ff9e7 commit 92d6291

File tree

7 files changed

+927
-1467
lines changed

7 files changed

+927
-1467
lines changed

components/SponsoredFeedsTable.tsx renamed to components/SponsoredFeedsTableWithData.tsx

Lines changed: 81 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,79 @@
11
import { useState } from "react";
22
import CopyIcon from "./icons/CopyIcon";
33
import { mapValues } from "../utils/ObjectHelpers";
4+
// Direct YAML import with webpack yaml-loader
5+
import sponsoredFeedsData from "../pages/price-feeds/sponsored-feeds/data/sponsored_feeds_by_network.yaml";
46

5-
interface UpdateParameters {
6-
heartbeatLength: number;
7-
heartbeatUnit: "second" | "minute" | "hour";
8-
priceDeviation: number;
7+
interface SponsoredFeed {
8+
alias: string; // name of the feed
9+
id: string; // price feed id
10+
time_difference: number; // in seconds
11+
price_deviation: number;
12+
confidence_ratio: number;
913
}
1014

11-
interface SponsoredFeed {
12-
name: string;
13-
priceFeedId: string;
14-
updateParameters: UpdateParameters;
15+
interface SponsoredFeedsData {
16+
[networkKey: string]: SponsoredFeed[];
1517
}
1618

1719
interface SponsoredFeedsTableProps {
18-
feeds: SponsoredFeed[];
20+
networkKey: string;
1921
networkName: string;
2022
}
2123

2224
/**
2325
* Helper functions
2426
*/
27+
// Convert time_difference (seconds) to human readable format
28+
const formatTimeUnit = (seconds: number): { value: number; unit: string } => {
29+
if (seconds >= 3600) {
30+
return { value: seconds / 3600, unit: "hour" };
31+
} else if (seconds >= 60) {
32+
return { value: seconds / 60, unit: "minute" };
33+
} else {
34+
return { value: seconds, unit: "second" };
35+
}
36+
};
2537

2638
// Format update parameters as a string for grouping
27-
const formatUpdateParams = (params: UpdateParameters): string => {
28-
return `${params.heartbeatLength} ${params.heartbeatUnit} heartbeat / ${params.priceDeviation}% price deviation`;
39+
const formatUpdateParams = (feed: SponsoredFeed): string => {
40+
const timeFormat = formatTimeUnit(feed.time_difference);
41+
const timeStr = `${timeFormat.value} ${timeFormat.unit}${
42+
timeFormat.value !== 1 ? "s" : ""
43+
}`;
44+
return `${timeStr} heartbeat / ${feed.price_deviation}% price deviation`;
2945
};
3046

3147
// Render update parameters with proper styling
32-
const renderUpdateParams = (params: UpdateParameters, isDefault: boolean) => (
33-
<div className="flex items-start gap-1.5">
34-
<div
35-
className={`w-1.5 h-1.5 rounded-full mt-1 flex-shrink-0 ${
36-
isDefault ? "bg-green-500" : "bg-orange-500"
37-
}`}
38-
></div>
39-
<span
40-
className={`text-xs leading-relaxed font-medium ${
41-
isDefault
42-
? "text-gray-700 dark:text-gray-300"
43-
: "text-orange-600 dark:text-orange-400"
44-
}`}
45-
>
46-
<strong>{params.heartbeatLength}</strong> {params.heartbeatUnit} heartbeat
47-
<br />
48-
<strong>{params.priceDeviation}%</strong> price deviation
49-
</span>
50-
</div>
51-
);
48+
const renderUpdateParams = (feed: SponsoredFeed, isDefault: boolean) => {
49+
const timeFormat = formatTimeUnit(feed.time_difference);
50+
const timeStr =
51+
timeFormat.value === 1 ? timeFormat.unit : `${timeFormat.unit}s`;
52+
53+
return (
54+
<div className="flex items-start gap-1.5">
55+
<div
56+
className={`w-1.5 h-1.5 rounded-full mt-1 flex-shrink-0 ${
57+
isDefault ? "bg-green-500" : "bg-orange-500"
58+
}`}
59+
></div>
60+
<span
61+
className={`text-xs leading-relaxed font-medium ${
62+
isDefault
63+
? "text-gray-700 dark:text-gray-300"
64+
: "text-orange-600 dark:text-orange-400"
65+
}`}
66+
>
67+
<strong>{timeFormat.value}</strong> {timeStr} heartbeat
68+
<br />
69+
<strong>{feed.price_deviation}%</strong> price deviation
70+
</span>
71+
</div>
72+
);
73+
};
5274

5375
export const SponsoredFeedsTable = ({
54-
feeds,
76+
networkKey,
5577
networkName,
5678
}: SponsoredFeedsTableProps) => {
5779
const [copiedId, setCopiedId] = useState<string | null>(null);
@@ -63,15 +85,32 @@ export const SponsoredFeedsTable = ({
6385
});
6486
};
6587

88+
// Load feeds from YAML data
89+
const data = sponsoredFeedsData as SponsoredFeedsData;
90+
const feeds = data[networkKey] || [];
91+
92+
// Handle empty feeds
93+
if (!feeds || feeds.length === 0) {
94+
return (
95+
<div className="my-6">
96+
<p className="mb-3">
97+
No sponsored price feeds are currently available for{" "}
98+
<strong>{networkName}</strong>.
99+
</p>
100+
</div>
101+
);
102+
}
103+
66104
// Calculate parameter statistics
67105
const paramCounts = mapValues(
68-
Object.groupBy(feeds, (feed) => formatUpdateParams(feed.updateParameters)),
106+
Object.groupBy(feeds, (feed) => formatUpdateParams(feed)),
69107
(feeds: SponsoredFeed[]) => feeds.length
70108
);
71109

72-
const defaultParams = Object.entries(paramCounts).sort(
110+
const paramEntries = Object.entries(paramCounts).sort(
73111
([, a], [, b]) => b - a
74-
)[0][0];
112+
);
113+
const defaultParams = paramEntries.length > 0 ? paramEntries[0][0] : "";
75114

76115
return (
77116
<div className="my-6">
@@ -124,32 +163,30 @@ export const SponsoredFeedsTable = ({
124163
</thead>
125164
<tbody className="bg-white dark:bg-gray-900">
126165
{feeds.map((feed, index) => {
127-
const formattedParams = formatUpdateParams(
128-
feed.updateParameters
129-
);
166+
const formattedParams = formatUpdateParams(feed);
130167
const isDefault = formattedParams === defaultParams;
131168

132169
return (
133170
<tr
134-
key={feed.priceFeedId}
171+
key={feed.id}
135172
className="border-b border-gray-100 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800/30"
136173
>
137174
<td className="px-3 py-2 align-top">
138175
<span className="font-medium text-gray-900 dark:text-gray-100">
139-
{feed.name}
176+
{feed.alias}
140177
</span>
141178
</td>
142179
<td className="px-3 py-2 align-top">
143180
<div className="flex items-start gap-2">
144181
<code className="text-xs font-mono text-gray-600 dark:text-gray-400 flex-1 break-all leading-relaxed">
145-
{feed.priceFeedId}
182+
{feed.id}
146183
</code>
147184
<button
148-
onClick={() => copyToClipboard(feed.priceFeedId)}
185+
onClick={() => copyToClipboard(feed.id)}
149186
className="p-1 hover:bg-gray-200 dark:hover:bg-gray-600 rounded flex-shrink-0 mt-0.5"
150187
title="Copy Price Feed ID"
151188
>
152-
{copiedId === feed.priceFeedId ? (
189+
{copiedId === feed.id ? (
153190
<span className="text-green-500 text-xs font-bold">
154191
155192
</span>
@@ -160,7 +197,7 @@ export const SponsoredFeedsTable = ({
160197
</div>
161198
</td>
162199
<td className="px-3 py-2 align-top">
163-
{renderUpdateParams(feed.updateParameters, isDefault)}
200+
{renderUpdateParams(feed, isDefault)}
164201
</td>
165202
</tr>
166203
);

next.config.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ const nextConfig = {
143143
},
144144
webpack: (config) => {
145145
config.resolve.fallback = { fs: false, net: false, tls: false };
146+
147+
// Add YAML loader
148+
config.module.rules.push({
149+
test: /\.ya?ml$/,
150+
use: "yaml-loader",
151+
});
152+
146153
return config;
147154
},
148155

0 commit comments

Comments
 (0)