Skip to content

Commit 1306817

Browse files
authored
Merge pull request #2167 from cprussin/finish-publishers-index-page
feat(insights): mostly finish publishers index page
2 parents 59f3f6f + fd7c6e4 commit 1306817

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1954
-1133
lines changed

apps/insights/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
"@pythnetwork/client": "catalog:",
2727
"@pythnetwork/component-library": "workspace:*",
2828
"@pythnetwork/fonts": "workspace:*",
29+
"@pythnetwork/hermes-client": "workspace:*",
2930
"@pythnetwork/known-publishers": "workspace:*",
3031
"@pythnetwork/next-root": "workspace:*",
3132
"@react-hookz/web": "catalog:",
3233
"@solana/web3.js": "catalog:",
3334
"bs58": "catalog:",
3435
"clsx": "catalog:",
3536
"cryptocurrency-icons": "catalog:",
37+
"dnum": "catalog:",
3638
"framer-motion": "catalog:",
3739
"next": "catalog:",
3840
"next-themes": "catalog:",
@@ -41,6 +43,7 @@
4143
"react-aria": "catalog:",
4244
"react-aria-components": "catalog:",
4345
"react-dom": "catalog:",
46+
"recharts": "catalog:",
4447
"swr": "catalog:",
4548
"zod": "catalog:"
4649
},
@@ -49,6 +52,7 @@
4952
"@cprussin/jest-config": "catalog:",
5053
"@cprussin/prettier-config": "catalog:",
5154
"@cprussin/tsconfig": "catalog:",
55+
"@pythnetwork/staking-sdk": "workspace:",
5256
"@svgr/webpack": "catalog:",
5357
"@types/jest": "catalog:",
5458
"@types/node": "catalog:",
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
"use client";
22

3+
import { LoggerProvider } from "@pythnetwork/app-logger/provider";
34
import type { ComponentProps } from "react";
45

56
import { Error } from "../components/Error";
67

78
const GlobalError = (props: ComponentProps<typeof Error>) => (
8-
<html lang="en" dir="ltr">
9-
<body>
10-
<Error {...props} />
11-
</body>
12-
</html>
9+
<LoggerProvider>
10+
<html lang="en" dir="ltr">
11+
<body>
12+
<Error {...props} />
13+
</body>
14+
</html>
15+
</LoggerProvider>
1316
);
1417
export default GlobalError;

apps/insights/src/app/publishers/layout.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

apps/insights/src/app/publishers/loading.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

apps/insights/src/app/yesterdays-prices/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import type { NextRequest } from "next/server";
22
import { z } from "zod";
33

4-
import { client } from "../../clickhouse";
4+
import { client } from "../../services/clickhouse";
55

66
export async function GET(req: NextRequest) {
77
const symbols = req.nextUrl.searchParams.getAll("symbols");
88
const rows = await client.query({
99
query:
10-
"select * from insights_yesterdays_prices(symbols={symbols: Array(String)})",
10+
"select symbol, price from insights_yesterdays_prices(symbols={symbols: Array(String)})",
1111
query_params: { symbols },
1212
});
1313
const result = await rows.json();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use client";
2+
3+
import { Skeleton } from "@pythnetwork/component-library/Skeleton";
4+
import { Suspense, use } from "react";
5+
6+
type Props<T> = {
7+
placeholderWidth: number;
8+
valuePromise: Promise<T>;
9+
};
10+
11+
export const AsyncValue = <T,>({
12+
placeholderWidth,
13+
valuePromise,
14+
}: Props<T>) => (
15+
<Suspense fallback={<Skeleton width={placeholderWidth} />}>
16+
<ResolvedValue valuePromise={valuePromise} />
17+
</Suspense>
18+
);
19+
20+
const ResolvedValue = <T,>({ valuePromise }: Pick<Props<T>, "valuePromise">) =>
21+
use(valuePromise);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"use client";
2+
3+
import * as dnum from "dnum";
4+
import { useMemo } from "react";
5+
import { useLocale } from "react-aria";
6+
7+
const DECIMALS = 6;
8+
9+
type Props = {
10+
mode?: "compact" | "wholePart" | "full";
11+
children: bigint;
12+
};
13+
14+
export const FormattedTokens = ({ children, mode = "compact" }: Props) => {
15+
const { locale } = useLocale();
16+
const value = useMemo(
17+
() =>
18+
dnum.format([children, DECIMALS], {
19+
compact: mode === "compact",
20+
locale,
21+
}),
22+
[children, locale, mode],
23+
);
24+
25+
return mode === "wholePart" ? value.split(".")[0] : value;
26+
};

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

Lines changed: 0 additions & 7 deletions
This file was deleted.

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

Lines changed: 0 additions & 10 deletions
This file was deleted.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
import { useNumberFormatter } from "react-aria";
1717

1818
import styles from "./index.module.scss";
19-
import { client, subscribe } from "../../pyth";
19+
import { client, subscribe } from "../../services/pyth";
2020

2121
export const SKELETON_WIDTH = 20;
2222

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

Lines changed: 0 additions & 5 deletions
This file was deleted.

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

Lines changed: 0 additions & 12 deletions
This file was deleted.

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,12 @@
22

33
.overview {
44
@include theme.max-width;
5+
6+
.header {
7+
@include theme.h3;
8+
9+
color: theme.color("heading");
10+
font-weight: theme.font-weight("semibold");
11+
margin: theme.spacing(6) 0;
12+
}
513
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import styles from "./index.module.scss";
2-
import { H1 } from "../H1";
32

43
export const Overview = () => (
54
<div className={styles.overview}>
6-
<H1>Overview</H1>
5+
<h1 className={styles.header}>Overview</h1>
76
</div>
87
);

apps/insights/src/components/PriceFeeds/asset-classes-card.module.scss

Lines changed: 0 additions & 7 deletions
This file was deleted.

apps/insights/src/components/PriceFeeds/asset-classes-card.tsx renamed to apps/insights/src/components/PriceFeeds/asset-classes-drawer.tsx

Lines changed: 27 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,49 +6,36 @@ import {
66
Drawer,
77
DrawerTrigger,
88
} from "@pythnetwork/component-library/Drawer";
9-
import { Skeleton } from "@pythnetwork/component-library/Skeleton";
10-
import { StatCard } from "@pythnetwork/component-library/StatCard";
119
import { Table } from "@pythnetwork/component-library/Table";
1210
import { usePathname } from "next/navigation";
13-
import { createSerializer } from "nuqs";
14-
import { Suspense, use, useMemo } from "react";
11+
import { type ReactNode, useMemo } from "react";
1512
import { useCollator } from "react-aria";
1613

17-
import styles from "./asset-classes-card.module.scss";
18-
import { queryParams, useQuery } from "./use-query";
14+
import { serialize, useQueryParams } from "./query-params";
1915

2016
type Props = {
21-
numFeedsByAssetClassPromise: Promise<Record<string, number>>;
17+
numFeedsByAssetClass: Record<string, number>;
18+
children: ReactNode;
2219
};
2320

24-
export const AssetClassesCard = ({ numFeedsByAssetClassPromise }: Props) => (
25-
<Suspense
26-
fallback={
27-
<StatCard stat={<Skeleton width={10} />} {...sharedStatCardProps} />
28-
}
29-
>
30-
<ResolvedAssetClassesCard
31-
numFeedsByAssetClassPromise={numFeedsByAssetClassPromise}
32-
/>
33-
</Suspense>
34-
);
35-
36-
const ResolvedAssetClassesCard = ({ numFeedsByAssetClassPromise }: Props) => {
37-
const numFeedsByAssetClass = use(numFeedsByAssetClassPromise);
21+
export const AssetClassesDrawer = ({
22+
numFeedsByAssetClass,
23+
children,
24+
}: Props) => {
3825
const numAssetClasses = useMemo(
3926
() => Object.keys(numFeedsByAssetClass).length,
4027
[numFeedsByAssetClass],
4128
);
4229

4330
return (
4431
<DrawerTrigger>
45-
<StatCard stat={numAssetClasses} {...sharedStatCardProps} />
32+
{children}
4633
<Drawer
4734
title={
48-
<div className={styles.drawerTitle}>
35+
<>
4936
<span>Asset Classes</span>
5037
<Badge>{numAssetClasses}</Badge>
51-
</div>
38+
</>
5239
}
5340
>
5441
{({ close }) => (
@@ -62,10 +49,6 @@ const ResolvedAssetClassesCard = ({ numFeedsByAssetClassPromise }: Props) => {
6249
);
6350
};
6451

65-
const sharedStatCardProps = {
66-
header: "Asset Classes",
67-
};
68-
6952
type AssetClassTableProps = {
7053
numFeedsByAssetClass: Record<string, number>;
7154
closeDrawer: () => void;
@@ -77,28 +60,26 @@ const AssetClassTable = ({
7760
}: AssetClassTableProps) => {
7861
const collator = useCollator();
7962
const pathname = usePathname();
80-
const { updateAssetClass } = useQuery();
63+
const { updateAssetClass, updateSearch } = useQueryParams();
8164
const assetClassRows = useMemo(
8265
() =>
8366
Object.entries(numFeedsByAssetClass)
8467
.sort(([a], [b]) => collator.compare(a, b))
85-
.map(([assetClass, count]) => {
86-
const serialize = createSerializer(queryParams);
87-
return {
88-
id: assetClass,
89-
href: `${pathname}${serialize({ assetClass })}`,
90-
onAction: () => {
91-
closeDrawer();
92-
setTimeout(() => {
93-
updateAssetClass(assetClass);
94-
}, CLOSE_DURATION_IN_MS);
95-
},
96-
data: {
97-
assetClass,
98-
count: <Badge style="outline">{count}</Badge>,
99-
},
100-
};
101-
}),
68+
.map(([assetClass, count]) => ({
69+
id: assetClass,
70+
href: `${pathname}${serialize({ assetClass })}`,
71+
onAction: () => {
72+
closeDrawer();
73+
setTimeout(() => {
74+
updateAssetClass(assetClass);
75+
updateSearch("");
76+
}, CLOSE_DURATION_IN_MS);
77+
},
78+
data: {
79+
assetClass,
80+
count: <Badge style="outline">{count}</Badge>,
81+
},
82+
})),
10283
[numFeedsByAssetClass, collator, closeDrawer, pathname, updateAssetClass],
10384
);
10485
return (
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@use "@pythnetwork/component-library/theme";
2+
3+
.searchBar {
4+
width: 100%;
5+
padding: theme.spacing(3);
6+
display: flex;
7+
flex-flow: row nowrap;
8+
gap: theme.spacing(3);
9+
flex: none;
10+
}
11+
12+
.priceFeeds {
13+
overflow: auto;
14+
flex-grow: 1;
15+
}

0 commit comments

Comments
 (0)