index.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { AppShell } from "@pythnetwork/component-library/AppShell";
  2. import { lookup as lookupPublisher } from "@pythnetwork/known-publishers";
  3. import { NuqsAdapter } from "nuqs/adapters/next/app";
  4. import type { ReactNode } from "react";
  5. import {
  6. AMPLITUDE_API_KEY,
  7. ENABLE_ACCESSIBILITY_REPORTING,
  8. GOOGLE_ANALYTICS_ID,
  9. } from "../../config/server";
  10. import { LivePriceDataProvider } from "../../hooks/use-live-price-data";
  11. import { getPublishers } from "../../services/clickhouse";
  12. import { Cluster } from "../../services/pyth";
  13. import { getFeeds } from "../../services/pyth/get-feeds";
  14. import { PriceFeedIcon } from "../PriceFeedIcon";
  15. import { PublisherIcon } from "../PublisherIcon";
  16. import { SearchButton as SearchButtonImpl } from "./search-button";
  17. export const TABS = [
  18. { segment: "", children: "Overview" },
  19. { segment: "publishers", children: "Publishers" },
  20. { segment: "price-feeds", children: "Price Feeds" },
  21. ];
  22. type Props = {
  23. children: ReactNode;
  24. };
  25. export const Root = ({ children }: Props) => (
  26. <AppShell
  27. appName="Insights"
  28. amplitudeApiKey={AMPLITUDE_API_KEY}
  29. googleAnalyticsId={GOOGLE_ANALYTICS_ID}
  30. enableAccessibilityReporting={ENABLE_ACCESSIBILITY_REPORTING}
  31. providers={[NuqsAdapter, LivePriceDataProvider]}
  32. tabs={TABS}
  33. extraCta={<SearchButton />}
  34. >
  35. {children}
  36. </AppShell>
  37. );
  38. const SearchButton = async () => {
  39. const [publishers, feeds] = await Promise.all([
  40. Promise.all([
  41. getPublishersForSearchDialog(Cluster.Pythnet),
  42. getPublishersForSearchDialog(Cluster.PythtestConformance),
  43. ]),
  44. getFeedsForSearchDialog(Cluster.Pythnet),
  45. ]);
  46. return <SearchButtonImpl publishers={publishers.flat()} feeds={feeds} />;
  47. };
  48. const getPublishersForSearchDialog = async (cluster: Cluster) => {
  49. const publishers = await getPublishers(cluster);
  50. return publishers.map((publisher) => {
  51. const knownPublisher = lookupPublisher(publisher.key);
  52. return {
  53. publisherKey: publisher.key,
  54. averageScore: publisher.averageScore,
  55. cluster,
  56. ...(knownPublisher && {
  57. name: knownPublisher.name,
  58. icon: <PublisherIcon knownPublisher={knownPublisher} />,
  59. }),
  60. };
  61. });
  62. };
  63. const getFeedsForSearchDialog = async (cluster: Cluster) => {
  64. const feeds = await getFeeds(cluster);
  65. return feeds.map((feed) => ({
  66. symbol: feed.symbol,
  67. displaySymbol: feed.product.display_symbol,
  68. assetClass: feed.product.asset_type,
  69. description: feed.product.description,
  70. icon: (
  71. <PriceFeedIcon
  72. assetClass={feed.product.asset_type}
  73. symbol={feed.symbol}
  74. />
  75. ),
  76. }));
  77. };