Skip to content

Commit f9b2665

Browse files
committed
fix: PR fixes
1 parent 38f7eaf commit f9b2665

File tree

9 files changed

+111
-108
lines changed

9 files changed

+111
-108
lines changed
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
@use "@pythnetwork/component-library/theme";
2+
13
.conformanceReport {
24
display: flex;
3-
gap: 0.5rem;
5+
gap: theme.spacing(2);
46
}

apps/insights/src/components/ConformanceReport/conformance-report.tsx

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,30 @@
33
import { Download } from "@phosphor-icons/react/dist/ssr/Download";
44
import { Button } from "@pythnetwork/component-library/Button";
55
import { Select } from "@pythnetwork/component-library/Select";
6-
import { Skeleton } from "@pythnetwork/component-library/Skeleton";
76
import { useAlert } from "@pythnetwork/component-library/useAlert";
87
import { useLogger } from "@pythnetwork/component-library/useLogger";
9-
import { useState } from "react";
8+
import { useCallback, useState } from "react";
109

1110
import styles from "./conformance-report.module.scss";
1211
import type { Interval } from "./types";
1312
import { INTERVALS } from "./types";
14-
import { useDownloadReportForFeed } from "./use-download-report-for-feed";
15-
import { useDownloadReportForPublisher } from "./use-download-report-for-publisher";
16-
import { CLUSTER_NAMES } from "../../services/pyth";
1713

18-
type ConformanceReportProps =
19-
| { isLoading: true }
20-
| {
21-
isLoading?: false | undefined;
22-
symbol?: string;
23-
cluster: (typeof CLUSTER_NAMES)[number];
24-
publisher?: string;
25-
};
14+
type ConformanceReportProps = {
15+
onClick: (timeframe: Interval) => Promise<void>;
16+
};
2617

2718
const ConformanceReport = (props: ConformanceReportProps) => {
2819
const [timeframe, setTimeframe] = useState<Interval>(INTERVALS[0]);
2920
const [isGeneratingReport, setIsGeneratingReport] = useState(false);
3021
const { open } = useAlert();
31-
const downloadReportForFeed = useDownloadReportForFeed();
32-
const downloadReportForPublisher = useDownloadReportForPublisher();
3322
const logger = useLogger();
3423

3524
/**
3625
* Download the conformance report for the given symbol or publisher
3726
*/
38-
const downloadReport = async () => {
39-
if (props.isLoading) {
40-
return;
41-
}
42-
if (props.symbol && props.publisher) {
43-
return downloadReportForFeed({
44-
symbol: props.symbol,
45-
publisher: props.publisher,
46-
timeframe,
47-
cluster: props.cluster,
48-
});
49-
}
50-
51-
if (props.publisher) {
52-
return downloadReportForPublisher({
53-
publisher: props.publisher,
54-
cluster: props.cluster,
55-
interval: timeframe,
56-
});
57-
}
58-
};
27+
const downloadReport = useCallback(async () => {
28+
await props.onClick(timeframe);
29+
}, [props, timeframe]);
5930

6031
const handleReport = () => {
6132
setIsGeneratingReport(true);
@@ -72,10 +43,6 @@ const ConformanceReport = (props: ConformanceReportProps) => {
7243
});
7344
};
7445

75-
if (props.isLoading) {
76-
return <Skeleton width={100} />;
77-
}
78-
7946
return (
8047
<div className={styles.conformanceReport}>
8148
<Select

apps/insights/src/components/ConformanceReport/use-download-report-for-publisher.tsx

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { z } from "zod";
1515
import { WEB_API_BASE_URL } from "./constants";
1616
import type { Interval } from "./types";
1717
import { useDownloadBlob } from "../../hooks/use-download-blob";
18-
import { priceFeedsSchema } from "../../schemas/pyth";
18+
import { priceFeedsSchema } from "../../schemas/pyth/price-feeds-schema";
1919
import { CLUSTER_NAMES } from "../../services/pyth";
2020

2121
// If interval is 'daily', set interval_days=1
@@ -72,7 +72,7 @@ const getFeeds = async (cluster: (typeof CLUSTER_NAMES)[number]) => {
7272
return priceFeedsSchema.element.array().parse(parsedData);
7373
};
7474

75-
const PublisherQualityScoreSchema = z.object({
75+
const publisherQualityScoreSchema = z.object({
7676
symbol: z.string(),
7777
uptime_score: z.string(),
7878
deviation_penalty: z.string(),
@@ -82,7 +82,7 @@ const PublisherQualityScoreSchema = z.object({
8282
final_score: z.string(),
8383
});
8484

85-
const PublisherQuantityScoreSchema = z.object({
85+
const publisherQuantityScoreSchema = z.object({
8686
numSymbols: z.number(),
8787
rank: z.number(),
8888
symbols: z.array(z.string()),
@@ -98,10 +98,7 @@ const fetchRankingData = async (
9898
new Date(),
9999
interval,
100100
);
101-
const quantityRankUrl = new URL(
102-
`/publisher_ranking?publisher=${publisher}&cluster=${cluster}`,
103-
WEB_API_BASE_URL,
104-
);
101+
const quantityRankUrl = new URL(`/publisher_ranking`, WEB_API_BASE_URL);
105102
quantityRankUrl.searchParams.set("cluster", cluster);
106103
quantityRankUrl.searchParams.set("publisher", publisher);
107104
const qualityRankUrl = new URL(
@@ -119,12 +116,12 @@ const fetchRankingData = async (
119116
]);
120117

121118
return {
122-
quantityRankData: PublisherQuantityScoreSchema.array().parse(
123-
await quantityRankRes.json(),
124-
),
125-
qualityRankData: PublisherQualityScoreSchema.array().parse(
126-
await qualityRankRes.json(),
127-
),
119+
quantityRankData: publisherQuantityScoreSchema
120+
.array()
121+
.parse(await quantityRankRes.json()),
122+
qualityRankData: publisherQualityScoreSchema
123+
.array()
124+
.parse(await qualityRankRes.json()),
128125
};
129126
};
130127
const csvHeaders = [

apps/insights/src/components/PriceComponentDrawer/index.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ import { PriceName } from "../PriceName";
4242
import { Score } from "../Score";
4343
import { Status as StatusComponent } from "../Status";
4444
import styles from "./index.module.scss";
45+
import type { Interval } from "../ConformanceReport/types";
46+
import { useDownloadReportForFeed } from "../ConformanceReport/use-download-report-for-feed";
4547

4648
const LineChart = dynamic(
4749
() => import("recharts").then((recharts) => recharts.LineChart),
@@ -273,13 +275,23 @@ type HeadingExtraProps = {
273275
};
274276

275277
const HeadingExtra = ({ status, ...props }: HeadingExtraProps) => {
278+
const downloadReportForFeed = useDownloadReportForFeed();
279+
280+
const handleDownloadReport = useCallback(
281+
(timeframe: Interval) => {
282+
return downloadReportForFeed({
283+
symbol: props.symbol,
284+
publisher: props.publisherKey,
285+
timeframe,
286+
cluster: ClusterToName[props.cluster],
287+
});
288+
},
289+
[downloadReportForFeed, props.cluster, props.publisherKey, props.symbol],
290+
);
291+
276292
return (
277293
<>
278-
<ConformanceReport
279-
symbol={props.symbol}
280-
publisher={props.publisherKey}
281-
cluster={ClusterToName[props.cluster]}
282-
/>
294+
<ConformanceReport onClick={handleDownloadReport} />
283295
<div className={styles.bigScreenBadges}>
284296
<StatusComponent status={status} />
285297
</div>

apps/insights/src/components/Publisher/layout.tsx

Lines changed: 71 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { StatCard } from "@pythnetwork/component-library/StatCard";
1313
import { lookup } from "@pythnetwork/known-publishers";
1414
import { notFound } from "next/navigation";
1515
import type { ReactNode } from "react";
16-
import { Suspense } from "react";
16+
import { Suspense, useCallback } from "react";
1717

1818
import {
1919
getPublishers,
@@ -46,6 +46,8 @@ import { TabPanel, TabRoot, Tabs } from "../Tabs";
4646
import { TokenIcon } from "../TokenIcon";
4747
import { OisApyHistory } from "./ois-apy-history";
4848
import ConformanceReport from "../ConformanceReport/conformance-report";
49+
import type { Interval } from "../ConformanceReport/types";
50+
import { useDownloadReportForPublisher } from "../ConformanceReport/use-download-report-for-publisher";
4951

5052
type Props = {
5153
children: ReactNode;
@@ -62,53 +64,9 @@ export const PublisherLayout = async ({ children, params }: Props) => {
6264
if (parsedCluster === undefined) {
6365
notFound();
6466
} else {
65-
const knownPublisher = lookup(key);
6667
return (
6768
<div className={styles.publisherLayout}>
68-
<section className={styles.header}>
69-
<div className={styles.breadcrumbRow}>
70-
<Breadcrumbs
71-
className={styles.breadcrumbs ?? ""}
72-
label="Breadcrumbs"
73-
items={[
74-
{ href: "/", label: "Home" },
75-
{ href: "/publishers", label: "Publishers" },
76-
{ label: <PublisherKey publisherKey={key} /> },
77-
]}
78-
/>
79-
</div>
80-
<div className={styles.titleRow}>
81-
<PublisherTag
82-
cluster={parsedCluster}
83-
publisherKey={key}
84-
{...(knownPublisher && {
85-
name: knownPublisher.name,
86-
icon: <PublisherIcon knownPublisher={knownPublisher} />,
87-
})}
88-
/>
89-
<ConformanceReport
90-
publisher={key}
91-
cluster={ClusterToName[parsedCluster]}
92-
/>
93-
</div>
94-
95-
<Cards className={styles.stats ?? ""}>
96-
<Suspense fallback={<RankingCardImpl isLoading />}>
97-
<RankingCard cluster={parsedCluster} publisherKey={key} />
98-
</Suspense>
99-
<Suspense fallback={<ScoreCardImpl isLoading />}>
100-
<ScoreCard cluster={parsedCluster} publisherKey={key} />
101-
</Suspense>
102-
<Suspense fallback={<ActiveFeedsCardImpl isLoading />}>
103-
<ActiveFeedsCard cluster={parsedCluster} publisherKey={key} />
104-
</Suspense>
105-
{parsedCluster === Cluster.Pythnet && (
106-
<Suspense fallback={<OisPoolCardImpl isLoading />}>
107-
<OisPoolCard publisherKey={key} />
108-
</Suspense>
109-
)}
110-
</Cards>
111-
</section>
69+
<PublisherHeader cluster={parsedCluster} publisherKey={key} />
11270
<TabRoot>
11371
<Tabs
11472
label="Price Feed Navigation"
@@ -140,6 +98,73 @@ export const PublisherLayout = async ({ children, params }: Props) => {
14098
}
14199
};
142100

101+
const PublisherHeader = ({
102+
cluster,
103+
publisherKey,
104+
}: {
105+
cluster: Cluster;
106+
publisherKey: string;
107+
}) => {
108+
const knownPublisher = lookup(publisherKey);
109+
110+
const downloadReportForPublisher = useDownloadReportForPublisher();
111+
112+
const handleDownloadReport = useCallback(
113+
(interval: Interval) => {
114+
return downloadReportForPublisher({
115+
publisher: publisherKey,
116+
cluster: ClusterToName[cluster],
117+
interval,
118+
});
119+
},
120+
[publisherKey, cluster, downloadReportForPublisher],
121+
);
122+
123+
return (
124+
<section className={styles.header}>
125+
<div className={styles.breadcrumbRow}>
126+
<Breadcrumbs
127+
className={styles.breadcrumbs ?? ""}
128+
label="Breadcrumbs"
129+
items={[
130+
{ href: "/", label: "Home" },
131+
{ href: "/publishers", label: "Publishers" },
132+
{ label: <PublisherKey publisherKey={publisherKey} /> },
133+
]}
134+
/>
135+
</div>
136+
<div className={styles.titleRow}>
137+
<PublisherTag
138+
cluster={cluster}
139+
publisherKey={publisherKey}
140+
{...(knownPublisher && {
141+
name: knownPublisher.name,
142+
icon: <PublisherIcon knownPublisher={knownPublisher} />,
143+
})}
144+
/>
145+
<ConformanceReport onClick={handleDownloadReport} />
146+
</div>
147+
148+
<Cards className={styles.stats ?? ""}>
149+
<Suspense fallback={<RankingCardImpl isLoading />}>
150+
<RankingCard cluster={cluster} publisherKey={publisherKey} />
151+
</Suspense>
152+
<Suspense fallback={<ScoreCardImpl isLoading />}>
153+
<ScoreCard cluster={cluster} publisherKey={publisherKey} />
154+
</Suspense>
155+
<Suspense fallback={<ActiveFeedsCardImpl isLoading />}>
156+
<ActiveFeedsCard cluster={cluster} publisherKey={publisherKey} />
157+
</Suspense>
158+
{cluster === Cluster.Pythnet && (
159+
<Suspense fallback={<OisPoolCardImpl isLoading />}>
160+
<OisPoolCard publisherKey={publisherKey} />
161+
</Suspense>
162+
)}
163+
</Cards>
164+
</section>
165+
);
166+
};
167+
143168
const NumFeeds = async ({
144169
cluster,
145170
publisherKey,

apps/insights/src/components/PublisherTag/index.module.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
.name {
2929
color: theme.color("heading");
3030

31-
@include theme.text("lg", "medium");
31+
@include theme.text("base", "medium");
3232
}
3333

3434
.publisherKey,

apps/insights/src/server/pyth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { z } from "zod";
44
import { DEFAULT_CACHE_TTL } from "../cache";
55
import { VERCEL_REQUEST_HEADERS } from "../config/server";
66
import { getHost } from "../get-host";
7-
import { priceFeedsSchema } from "../schemas/pyth";
7+
import { priceFeedsSchema } from "../schemas/pyth/price-feeds-schema";
88
import { Cluster, ClusterToName } from "../services/pyth";
99

1010
export async function getPublishersForFeedRequest(

apps/insights/src/services/pyth/get-feeds.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Cluster } from ".";
22
import { getPythMetadata } from "./get-metadata";
33
import { redisCache } from "../../cache";
4-
import { priceFeedsSchema } from "../../schemas/pyth";
4+
import { priceFeedsSchema } from "../../schemas/pyth/price-feeds-schema";
55

66
const _getFeeds = async (cluster: Cluster) => {
77
const unfilteredData = await getPythMetadata(cluster);

0 commit comments

Comments
 (0)