Преглед на файлове

Merge pull request #2488 from pyth-network/cprussin/ui-24-update-dependencies

chore: update all app node dependencies
Connor Prussin преди 8 месеца
родител
ревизия
c905fbe1a8
променени са 100 файла, в които са добавени 451 реда и са изтрити 557 реда
  1. 0 6
      .envrc
  2. 1 1
      apps/api-reference/jest.config.js
  3. 33 33
      apps/api-reference/package.json
  4. 2 7
      apps/api-reference/src/apis/evm/common.ts
  5. 2 1
      apps/api-reference/src/app/price-feeds/[chain]/[method]/page.tsx
  6. 2 1
      apps/api-reference/src/browser-logger.ts
  7. 2 1
      apps/api-reference/src/components/Accordion/index.tsx
  8. 6 7
      apps/api-reference/src/components/Button/index.tsx
  9. 2 2
      apps/api-reference/src/components/Code/index.tsx
  10. 8 11
      apps/api-reference/src/components/Code/shiki.ts
  11. 2 3
      apps/api-reference/src/components/Code/use-highlighted-code.tsx
  12. 11 11
      apps/api-reference/src/components/EvmApi/index.tsx
  13. 4 11
      apps/api-reference/src/components/EvmApi/parameter-input.tsx
  14. 3 3
      apps/api-reference/src/components/EvmApi/parameter.ts
  15. 2 1
      apps/api-reference/src/components/EvmApi/run-button.tsx
  16. 2 1
      apps/api-reference/src/components/Header/nav-link.tsx
  17. 3 2
      apps/api-reference/src/components/Input/index.tsx
  18. 1 1
      apps/api-reference/src/components/Markdown/index.tsx
  19. 2 1
      apps/api-reference/src/components/Modal/index.tsx
  20. 2 7
      apps/api-reference/src/components/Select/index.tsx
  21. 2 6
      apps/api-reference/src/components/Sidebar/index.tsx
  22. 2 4
      apps/api-reference/src/components/Tooltip/index.tsx
  23. 2 7
      apps/api-reference/src/use-price-feed-list.tsx
  24. 2 1
      apps/api-reference/src/zod-utils.ts
  25. 1 1
      apps/entropy-debugger/jest.config.js
  26. 9 9
      apps/entropy-debugger/package.json
  27. 2 1
      apps/entropy-debugger/src/components/ui/button.tsx
  28. 2 4
      apps/entropy-debugger/src/lib/revelation.ts
  29. 2 1
      apps/entropy-debugger/src/lib/utils.ts
  30. 1 1
      apps/insights/jest.config.js
  31. 1 1
      apps/insights/package.json
  32. 2 9
      apps/insights/src/components/ChartCard/index.tsx
  33. 2 1
      apps/insights/src/components/CopyButton/index.tsx
  34. 2 1
      apps/insights/src/components/FeedKey/index.tsx
  35. 4 13
      apps/insights/src/components/LayoutTransition/index.tsx
  36. 14 6
      apps/insights/src/components/LivePrices/index.tsx
  37. 2 1
      apps/insights/src/components/Overview/tab-list.tsx
  38. 3 9
      apps/insights/src/components/PriceComponentDrawer/index.tsx
  39. 8 13
      apps/insights/src/components/PriceComponentsCard/index.tsx
  40. 8 12
      apps/insights/src/components/PriceFeed/chart.tsx
  41. 2 1
      apps/insights/src/components/PriceFeed/price-feed-select.tsx
  42. 2 1
      apps/insights/src/components/PriceFeed/publishers-card.tsx
  43. 3 2
      apps/insights/src/components/PriceFeedChangePercent/index.tsx
  44. 2 1
      apps/insights/src/components/PriceFeedTag/index.tsx
  45. 2 1
      apps/insights/src/components/PriceFeeds/asset-classes-drawer.tsx
  46. 2 4
      apps/insights/src/components/PriceFeeds/index.tsx
  47. 4 4
      apps/insights/src/components/PriceFeeds/price-feeds-card.tsx
  48. 1 1
      apps/insights/src/components/PriceName/index.tsx
  49. 2 5
      apps/insights/src/components/Publisher/get-price-feeds.tsx
  50. 2 1
      apps/insights/src/components/Publisher/performance.tsx
  51. 2 8
      apps/insights/src/components/Publisher/price-feed-drawer-provider.tsx
  52. 2 1
      apps/insights/src/components/Publisher/price-feeds-card.tsx
  53. 2 1
      apps/insights/src/components/Publisher/top-feeds-table.tsx
  54. 6 5
      apps/insights/src/components/Publishers/publishers-card.tsx
  55. 2 4
      apps/insights/src/components/Root/footer.tsx
  56. 2 1
      apps/insights/src/components/Root/mobile-nav-tabs.tsx
  57. 2 1
      apps/insights/src/components/Root/search-button.tsx
  58. 3 4
      apps/insights/src/components/Root/search-dialog.tsx
  59. 2 4
      apps/insights/src/components/Root/support-drawer.tsx
  60. 3 2
      apps/insights/src/components/Root/tabs.tsx
  61. 4 11
      apps/insights/src/components/Root/theme-switch.tsx
  62. 2 1
      apps/insights/src/components/SemicircleMeter/index.tsx
  63. 2 1
      apps/insights/src/components/Tabs/index.tsx
  64. 2 1
      apps/insights/src/components/ZoomLayoutTransition/index.tsx
  65. 2 1
      apps/insights/src/hooks/use-data.ts
  66. 1 1
      apps/insights/src/hooks/use-live-price-data.tsx
  67. 2 1
      apps/insights/src/hooks/use-price-feeds.tsx
  68. 5 7
      apps/insights/src/hooks/use-query-param-filter-pagination.ts
  69. 1 4
      apps/insights/src/omit-keys.ts
  70. 2 1
      apps/insights/src/services/clickhouse.ts
  71. 1 1
      apps/staking/jest.config.js
  72. 35 37
      apps/staking/package.json
  73. 2 2
      apps/staking/src/api.ts
  74. 4 8
      apps/staking/src/components/AccountSummary/index.tsx
  75. 2 1
      apps/staking/src/components/CopyButton/index.tsx
  76. 7 13
      apps/staking/src/components/Dashboard/index.tsx
  77. 4 2
      apps/staking/src/components/Date/index.tsx
  78. 0 3
      apps/staking/src/components/ErrorMessage/index.tsx
  79. 2 9
      apps/staking/src/components/Faq/index.tsx
  80. 2 1
      apps/staking/src/components/Governance/index.tsx
  81. 12 12
      apps/staking/src/components/Guide/index.tsx
  82. 1 1
      apps/staking/src/components/Header/current-stake-account.tsx
  83. 2 5
      apps/staking/src/components/Home/index.tsx
  84. 1 1
      apps/staking/src/components/Menu/index.tsx
  85. 7 14
      apps/staking/src/components/NoWalletHome/index.tsx
  86. 9 12
      apps/staking/src/components/OracleIntegrityStaking/index.tsx
  87. 3 2
      apps/staking/src/components/Root/i18n-provider.tsx
  88. 80 74
      apps/staking/src/components/Root/toast-region.tsx
  89. 2 1
      apps/staking/src/components/RouterProvider/index.tsx
  90. 2 1
      apps/staking/src/components/Tokens/index.tsx
  91. 2 8
      apps/staking/src/components/TransferButton/index.tsx
  92. 2 1
      apps/staking/src/components/TruncatedKey/index.tsx
  93. 4 12
      apps/staking/src/components/WalletButton/index.tsx
  94. 2 7
      apps/staking/src/components/WalletProvider/index.tsx
  95. 2 1
      apps/staking/src/hooks/use-api.tsx
  96. 2 1
      apps/staking/src/hooks/use-data.ts
  97. 4 2
      apps/staking/src/hooks/use-logger.tsx
  98. 2 7
      apps/staking/src/hooks/use-network.tsx
  99. 17 23
      apps/staking/src/hooks/use-toast.tsx
  100. 4 2
      apps/staking/src/middleware.ts

+ 0 - 6
.envrc

@@ -1,7 +1 @@
-#!/usr/bin/env bash
-# the shebang is ignored, but nice for editors
-
-if ! has nix_direnv_version || ! nix_direnv_version 3.0.5; then
-    source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.5/direnvrc" "sha256-RuwIS+QKFj/T9M2TFXScjBsLR6V3A17YVoEW/Q6AZ1w="
-fi
 use flake

+ 1 - 1
apps/api-reference/jest.config.js

@@ -1 +1 @@
-export { nextjs as default } from "@cprussin/jest-config";
+export { nextjs as default } from "@cprussin/jest-config/next";

+ 33 - 33
apps/api-reference/package.json

@@ -18,51 +18,51 @@
     "test:types": "tsc"
   },
   "dependencies": {
-    "@amplitude/analytics-browser": "^2.9.0",
-    "@amplitude/plugin-autocapture-browser": "^0.9.0",
-    "@floating-ui/react": "^0.26.17",
-    "@headlessui/react": "^2.2.0",
-    "@heroicons/react": "^2.1.4",
-    "@next/third-parties": "^14.2.4",
+    "@amplitude/analytics-browser": "catalog:",
+    "@amplitude/plugin-autocapture-browser": "catalog:",
+    "@floating-ui/react": "catalog:",
+    "@headlessui/react": "catalog:",
+    "@heroicons/react": "catalog:",
+    "@next/third-parties": "catalog:",
     "@pythnetwork/client": "catalog:",
-    "@pythnetwork/pyth-sdk-solidity": "workspace:^",
-    "@solana/web3.js": "^1.95.1",
-    "@tanstack/react-query": "^5.45.1",
-    "bs58": "^5.0.0",
-    "clsx": "^2.1.1",
-    "connectkit": "^1.8.2",
-    "cryptocurrency-icons": "^0.18.1",
-    "framer-motion": "^11.3.8",
+    "@pythnetwork/pyth-sdk-solidity": "workspace:*",
+    "@solana/web3.js": "catalog:",
+    "@tanstack/react-query": "catalog:",
+    "bs58": "catalog:",
+    "clsx": "catalog:",
+    "connectkit": "catalog:",
+    "cryptocurrency-icons": "catalog:",
+    "framer-motion": "catalog:",
     "next": "catalog:",
-    "next-themes": "^0.3.0",
-    "pino": "^9.2.0",
+    "next-themes": "catalog:",
+    "pino": "catalog:",
     "react": "catalog:",
     "react-dom": "catalog:",
-    "react-markdown": "^9.0.1",
-    "shiki": "^1.7.0",
-    "viem": "^2.22.23",
-    "wagmi": "^2.10.4",
-    "zod": "^3.23.8"
+    "react-markdown": "catalog:",
+    "shiki": "catalog:",
+    "viem": "catalog:",
+    "wagmi": "catalog:",
+    "zod": "catalog:"
   },
   "devDependencies": {
-    "@axe-core/react": "^4.9.1",
+    "@axe-core/react": "catalog:",
     "@cprussin/eslint-config": "catalog:",
     "@cprussin/jest-config": "catalog:",
     "@cprussin/prettier-config": "catalog:",
     "@cprussin/tsconfig": "catalog:",
-    "@svgr/webpack": "^8.1.0",
-    "@tailwindcss/forms": "^0.5.7",
-    "@types/jest": "^29.5.12",
-    "@types/node": "^20.14.6",
+    "@svgr/webpack": "catalog:",
+    "@tailwindcss/forms": "catalog:",
+    "@types/jest": "catalog:",
+    "@types/node": "catalog:",
     "@types/react": "catalog:",
     "@types/react-dom": "catalog:",
-    "autoprefixer": "^10.4.19",
-    "eslint": "^9.5.0",
-    "jest": "^29.7.0",
-    "postcss": "^8.4.38",
+    "autoprefixer": "catalog:",
+    "eslint": "catalog:",
+    "jest": "catalog:",
+    "postcss": "catalog:",
     "prettier": "catalog:",
-    "tailwindcss": "^3.4.4",
-    "typescript": "^5.5.2",
-    "vercel": "^34.2.7"
+    "tailwindcss": "catalog:",
+    "typescript": "catalog:",
+    "vercel": "catalog:"
   }
 }

+ 2 - 7
apps/api-reference/src/apis/evm/common.ts

@@ -1,12 +1,7 @@
 import { z } from "zod";
 
-import {
-  type ReadApi,
-  type WriteApi,
-  type NetworkInfo,
-  EvmApiType,
-  Language,
-} from "../../components/EvmApi";
+import type { ReadApi, WriteApi, NetworkInfo } from "../../components/EvmApi";
+import { EvmApiType, Language } from "../../components/EvmApi";
 import { singletonArray, safeFetch } from "../../zod-utils";
 
 export const readApi = <ParameterName extends string>(

+ 2 - 1
apps/api-reference/src/app/price-feeds/[chain]/[method]/page.tsx

@@ -1,7 +1,8 @@
 "use client";
 
 import { notFound } from "next/navigation";
-import { type ComponentProps, use } from "react";
+import type { ComponentProps } from "react";
+import { use } from "react";
 
 import * as apis from "../../../../apis";
 import { EvmApi } from "../../../../components/EvmApi";

+ 2 - 1
apps/api-reference/src/browser-logger.ts

@@ -1,4 +1,5 @@
-import pino, { type Logger } from "pino";
+import type { Logger } from "pino";
+import pino from "pino";
 
 import { IS_PRODUCTION_BUILD } from "./isomorphic-config";
 

+ 2 - 1
apps/api-reference/src/components/Accordion/index.tsx

@@ -1,6 +1,7 @@
 import { Disclosure, DisclosurePanel } from "@headlessui/react";
 import { LazyMotion, AnimatePresence, m, domAnimation } from "framer-motion";
-import { type ComponentProps, type Ref, forwardRef } from "react";
+import type { ComponentProps, Ref } from "react";
+import { forwardRef } from "react";
 
 export { DisclosureButton as AccordionButton } from "@headlessui/react";
 

+ 6 - 7
apps/api-reference/src/components/Button/index.tsx

@@ -1,14 +1,13 @@
 "use client";
 
 import clsx from "clsx";
-import {
-  type ComponentProps,
-  type ElementType,
-  type MouseEvent,
-  type CSSProperties,
-  useState,
-  useCallback,
+import type {
+  ComponentProps,
+  ElementType,
+  MouseEvent,
+  CSSProperties,
 } from "react";
+import { useState, useCallback } from "react";
 
 const DEFAULT_GRADIENT_SIZE = "30rem";
 

+ 2 - 2
apps/api-reference/src/components/Code/index.tsx

@@ -1,8 +1,8 @@
 import { Transition } from "@headlessui/react";
 import { ClipboardDocumentIcon, CheckIcon } from "@heroicons/react/24/outline";
 import clsx from "clsx";
-import { useMemo, useCallback, type HTMLAttributes } from "react";
-import { useEffect, useState } from "react";
+import type { HTMLAttributes } from "react";
+import { useMemo, useCallback, useEffect, useState } from "react";
 import type { OffsetOrPosition } from "shiki";
 
 import style from "./style.module.css";

+ 8 - 11
apps/api-reference/src/components/Code/shiki.ts

@@ -1,14 +1,11 @@
-import {
-  type HighlighterCore,
-  type DecorationItem,
-  getHighlighterCore as shikiGetHighlighterCore,
-} from "shiki/core";
+import type { HighlighterCore, DecorationItem } from "shiki/core";
+import { createHighlighterCore } from "shiki/core";
+import { createOnigurumaEngine } from "shiki/engine/oniguruma";
 import javascript from "shiki/langs/javascript.mjs";
 import json from "shiki/langs/json.mjs";
 import solidity from "shiki/langs/solidity.mjs";
 import darkPlus from "shiki/themes/dark-plus.mjs";
 import lightPlus from "shiki/themes/light-plus.mjs";
-import loadWasm from "shiki/wasm";
 
 import type { SupportedLanguage } from "./supported-language";
 
@@ -16,7 +13,7 @@ export type Highlighter = {
   highlight: (
     lang: SupportedLanguage | undefined,
     code: string,
-    options?: HighlightOptions | undefined,
+    options?: HighlightOptions,
   ) => string;
 };
 
@@ -25,17 +22,17 @@ export type HighlightOptions = {
 };
 
 export const getHighlighter = async (): Promise<Highlighter> => {
-  const highlighterCore = await shikiGetHighlighterCore({
+  const highlighterCore = await createHighlighterCore({
     langs: [javascript, solidity, json],
     themes: [darkPlus, lightPlus],
-    loadWasm,
+    engine: createOnigurumaEngine(() => import("shiki/wasm")),
   });
 
   return {
     highlight: (
       lang: SupportedLanguage | undefined,
       code: string,
-      options?: HighlightOptions | undefined,
+      options?: HighlightOptions,
     ) => highlight(highlighterCore, lang, code, options),
   };
 };
@@ -44,7 +41,7 @@ const highlight = (
   highlighter: HighlighterCore,
   lang: SupportedLanguage | undefined,
   code: string,
-  options?: HighlightOptions | undefined,
+  options?: HighlightOptions,
 ) =>
   highlighter.codeToHtml(code, {
     lang: lang ?? "text",

+ 2 - 3
apps/api-reference/src/components/Code/use-highlighted-code.tsx

@@ -1,8 +1,7 @@
 "use client";
 
+import type { ReactNode, RefObject } from "react";
 import {
-  type ReactNode,
-  type RefObject,
   createContext,
   useContext,
   useState,
@@ -48,7 +47,7 @@ const useHighlighter = () => {
 export const useHighlightedCode = (
   language: SupportedLanguage | undefined,
   code: string,
-  dimRange?: readonly [OffsetOrPosition, OffsetOrPosition] | undefined,
+  dimRange?: readonly [OffsetOrPosition, OffsetOrPosition],
 ) => {
   const highlighter = useHighlighter();
   const decorations = useMemo(

+ 11 - 11
apps/api-reference/src/components/EvmApi/index.tsx

@@ -13,26 +13,26 @@ import { ArrowPathIcon } from "@heroicons/react/24/outline";
 import PythAbi from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json";
 import PythErrorsAbi from "@pythnetwork/pyth-sdk-solidity/abis/PythErrors.json";
 import { ChainIcon } from "connectkit";
-import {
-  type Dispatch,
-  type SetStateAction,
-  type ComponentProps,
-  type ElementType,
-  type SVGAttributes,
-  useState,
-  useCallback,
-  useMemo,
+import type {
+  Dispatch,
+  SetStateAction,
+  ComponentProps,
+  ElementType,
+  SVGAttributes,
 } from "react";
+import { useState, useCallback, useMemo } from "react";
 import { useSwitchChain, useChainId, useConfig } from "wagmi";
 import { readContract } from "wagmi/actions";
 
 import type { Parameter } from "./parameter";
 import { ParameterInput } from "./parameter-input";
-import { type EvmApiType, RunButton } from "./run-button";
+import type { EvmApiType } from "./run-button";
+import { RunButton } from "./run-button";
 import { getLogger } from "../../browser-logger";
 import { getContractAddress } from "../../evm-networks";
 import { useIsMounted } from "../../use-is-mounted";
-import { type SupportedLanguage, Code } from "../Code";
+import type { SupportedLanguage } from "../Code";
+import { Code } from "../Code";
 import { ErrorTooltip } from "../ErrorTooltip";
 import { InlineLink } from "../InlineLink";
 import { Markdown } from "../Markdown";

+ 4 - 11
apps/api-reference/src/components/EvmApi/parameter-input.tsx

@@ -8,25 +8,18 @@ import { ArrowPathIcon } from "@heroicons/react/24/outline";
 import base58 from "bs58";
 import clsx from "clsx";
 import Image from "next/image";
-import {
-  type ChangeEvent,
-  type Dispatch,
-  type SetStateAction,
-  useState,
-  useCallback,
-  useMemo,
-  useEffect,
-} from "react";
+import type { ChangeEvent, Dispatch, SetStateAction } from "react";
+import { useState, useCallback, useMemo, useEffect } from "react";
 
+import type { Parameter } from "./parameter";
 import {
-  type Parameter,
   PLACEHOLDERS,
   isValid,
   getValidationError,
   ParameterType,
 } from "./parameter";
+import type { PriceFeed } from "../../use-price-feed-list";
 import {
-  type PriceFeed,
   PriceFeedListContextType,
   usePriceFeedList,
 } from "../../use-price-feed-list";

+ 3 - 3
apps/api-reference/src/components/EvmApi/parameter.ts

@@ -13,9 +13,9 @@ export enum ParameterType {
   IntArray,
 }
 
-export const TRANSFORMS: {
-  [paramType in ParameterType]?: (value: string) => unknown;
-} = {
+export const TRANSFORMS: Partial<
+  Record<ParameterType, (value: string) => unknown>
+> = {
   [ParameterType.PriceFeedIdArray]: (value) => [value],
   [ParameterType.HexArray]: (value) => [value],
   [ParameterType.IntArray]: (value) => [value],

+ 2 - 1
apps/api-reference/src/components/EvmApi/run-button.tsx

@@ -9,7 +9,8 @@ import { ContractFunctionExecutionError } from "viem";
 import { useAccount, useConfig } from "wagmi";
 import { readContract, simulateContract, writeContract } from "wagmi/actions";
 
-import { type Parameter, TRANSFORMS } from "./parameter";
+import type { Parameter } from "./parameter";
+import { TRANSFORMS } from "./parameter";
 import { getContractAddress } from "../../evm-networks";
 import { useIsMounted } from "../../use-is-mounted";
 import { Button } from "../Button";

+ 2 - 1
apps/api-reference/src/components/Header/nav-link.tsx

@@ -3,7 +3,8 @@
 import clsx from "clsx";
 import Link from "next/link";
 import { useSelectedLayoutSegment } from "next/navigation";
-import { type ComponentProps, useMemo } from "react";
+import type { ComponentProps } from "react";
+import { useMemo } from "react";
 
 const baseClasses = "font-semibold text-sm py-2 px-3";
 

+ 3 - 2
apps/api-reference/src/components/Input/index.tsx

@@ -1,12 +1,13 @@
+import type { InputProps } from "@headlessui/react";
 import {
   Field,
   Label,
   Description,
   Input as HeadlessUiInput,
-  type InputProps,
 } from "@headlessui/react";
 import clsx from "clsx";
-import { type Ref, type ReactNode, forwardRef } from "react";
+import type { Ref, ReactNode } from "react";
+import { forwardRef } from "react";
 
 import { ErrorTooltip } from "../ErrorTooltip";
 

+ 1 - 1
apps/api-reference/src/components/Markdown/index.tsx

@@ -1,4 +1,4 @@
-import { type ComponentProps } from "react";
+import type { ComponentProps } from "react";
 import MarkdownComponent from "react-markdown";
 
 import { MARKDOWN_COMPONENTS } from "../../markdown-components";

+ 2 - 1
apps/api-reference/src/components/Modal/index.tsx

@@ -8,7 +8,8 @@ import {
   CloseButton,
 } from "@headlessui/react";
 import { XMarkIcon } from "@heroicons/react/24/outline";
-import { type ReactNode, Fragment } from "react";
+import type { ReactNode } from "react";
+import { Fragment } from "react";
 
 import { Button } from "../Button";
 

+ 2 - 7
apps/api-reference/src/components/Select/index.tsx

@@ -11,13 +11,8 @@ import {
   ChevronRightIcon,
 } from "@heroicons/react/24/outline";
 import clsx from "clsx";
-import {
-  type ReactNode,
-  type ChangeEvent,
-  useState,
-  useCallback,
-  useMemo,
-} from "react";
+import type { ReactNode, ChangeEvent } from "react";
+import { useState, useCallback, useMemo } from "react";
 
 import { Accordion, AccordionButton, AccordionPanel } from "../Accordion";
 

+ 2 - 6
apps/api-reference/src/components/Sidebar/index.tsx

@@ -4,12 +4,8 @@ import { Field, Label } from "@headlessui/react";
 import clsx from "clsx";
 import Link from "next/link";
 import { useSelectedLayoutSegments } from "next/navigation";
-import {
-  type HTMLAttributes,
-  useState,
-  type ComponentProps,
-  type ElementType,
-} from "react";
+import type { HTMLAttributes, ComponentProps, ElementType } from "react";
+import { useState } from "react";
 
 import * as apis from "../../apis";
 import { Select } from "../Select";

+ 2 - 4
apps/api-reference/src/components/Tooltip/index.tsx

@@ -1,7 +1,7 @@
 "use client";
 
+import type { Placement } from "@floating-ui/react";
 import {
-  type Placement,
   FloatingArrow,
   FloatingPortal,
   useFloating,
@@ -20,10 +20,8 @@ import {
   flip,
   shift,
 } from "@floating-ui/react";
+import type { ComponentProps, ElementType, Ref } from "react";
 import {
-  type ComponentProps,
-  type ElementType,
-  type Ref,
   useState,
   useMemo,
   createContext,

+ 2 - 7
apps/api-reference/src/use-price-feed-list.tsx

@@ -2,13 +2,8 @@
 
 import { PythHttpClient } from "@pythnetwork/client";
 import { Connection, PublicKey } from "@solana/web3.js";
-import {
-  type ComponentProps,
-  createContext,
-  useContext,
-  useState,
-  useEffect,
-} from "react";
+import type { ComponentProps } from "react";
+import { createContext, useContext, useState, useEffect } from "react";
 import { z } from "zod";
 
 const PYTHNET_RPC_URL = "https://api2.pythnet.pyth.network";

+ 2 - 1
apps/api-reference/src/zod-utils.ts

@@ -1,4 +1,5 @@
-import { type ZodSchema, type ZodTypeDef, z } from "zod";
+import type { ZodSchema, ZodTypeDef } from "zod";
+import { z } from "zod";
 
 export const singletonArray = <Output, Def extends ZodTypeDef, Input>(
   schema: ZodSchema<Output, Def, Input>,

+ 1 - 1
apps/entropy-debugger/jest.config.js

@@ -1 +1 @@
-export { nextjs as default } from "@cprussin/jest-config";
+export { nextjs as default } from "@cprussin/jest-config/next";

+ 9 - 9
apps/entropy-debugger/package.json

@@ -17,19 +17,19 @@
     "test:types": "tsc"
   },
   "dependencies": {
-    "@radix-ui/react-select": "^2.1.2",
-    "@radix-ui/react-slot": "^1.1.0",
-    "@radix-ui/react-switch": "^1.1.1",
-    "class-variance-authority": "^0.7.1",
+    "@radix-ui/react-select": "catalog:",
+    "@radix-ui/react-slot": "catalog:",
+    "@radix-ui/react-switch": "catalog:",
+    "class-variance-authority": "catalog:",
     "clsx": "catalog:",
-    "highlight.js": "^11.10.0",
-    "lucide-react": "^0.465.0",
+    "highlight.js": "catalog:",
+    "lucide-react": "catalog:",
     "next": "catalog:",
     "react": "catalog:",
     "react-dom": "catalog:",
-    "tailwind-merge": "^2.5.5",
-    "tailwindcss-animate": "^1.0.7",
-    "viem": "^2.21.53",
+    "tailwind-merge": "catalog:",
+    "tailwindcss-animate": "catalog:",
+    "viem": "catalog:",
     "zod": "catalog:"
   },
   "devDependencies": {

+ 2 - 1
apps/entropy-debugger/src/components/ui/button.tsx

@@ -1,5 +1,6 @@
 import { Slot } from "@radix-ui/react-slot";
-import { cva, type VariantProps } from "class-variance-authority";
+import type { VariantProps } from "class-variance-authority";
+import { cva } from "class-variance-authority";
 import type { ComponentProps } from "react";
 
 import { cn } from "../../lib/utils";

+ 2 - 4
apps/entropy-debugger/src/lib/revelation.ts

@@ -2,10 +2,8 @@ import { createPublicClient, http, parseEventLogs, publicActions } from "viem";
 import { z } from "zod";
 
 import { EntropyAbi } from "./entropy-abi";
-import {
-  type EntropyDeployment,
-  EntropyDeployments,
-} from "../store/entropy-deployments";
+import type { EntropyDeployment } from "../store/entropy-deployments";
+import { EntropyDeployments } from "../store/entropy-deployments";
 
 export async function requestCallback(
   txHash: string,

+ 2 - 1
apps/entropy-debugger/src/lib/utils.ts

@@ -1,4 +1,5 @@
-import { clsx, type ClassValue } from "clsx";
+import type { ClassValue } from "clsx";
+import { clsx } from "clsx";
 import { twMerge } from "tailwind-merge";
 
 export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs));

+ 1 - 1
apps/insights/jest.config.js

@@ -1 +1 @@
-export { nextjs as default } from "@cprussin/jest-config";
+export { nextjs as default } from "@cprussin/jest-config/next";

+ 1 - 1
apps/insights/package.json

@@ -54,7 +54,7 @@
     "@cprussin/jest-config": "catalog:",
     "@cprussin/prettier-config": "catalog:",
     "@cprussin/tsconfig": "catalog:",
-    "@pythnetwork/staking-sdk": "workspace:",
+    "@pythnetwork/staking-sdk": "workspace:*",
     "@svgr/webpack": "catalog:",
     "@types/jest": "catalog:",
     "@types/node": "catalog:",

+ 2 - 9
apps/insights/src/components/ChartCard/index.tsx

@@ -3,15 +3,8 @@
 import { StatCard } from "@pythnetwork/component-library/StatCard";
 import clsx from "clsx";
 import dynamic from "next/dynamic";
-import {
-  type ElementType,
-  type ComponentProps,
-  type ReactNode,
-  Suspense,
-  useState,
-  useMemo,
-  useCallback,
-} from "react";
+import type { ElementType, ComponentProps, ReactNode } from "react";
+import { Suspense, useState, useMemo, useCallback } from "react";
 import { ResponsiveContainer, Tooltip, Line, XAxis, YAxis } from "recharts";
 import type { CategoricalChartState } from "recharts/types/chart/types";
 

+ 2 - 1
apps/insights/src/components/CopyButton/index.tsx

@@ -5,7 +5,8 @@ import { Copy } from "@phosphor-icons/react/dist/ssr/Copy";
 import { useLogger } from "@pythnetwork/app-logger";
 import { Button } from "@pythnetwork/component-library/unstyled/Button";
 import clsx from "clsx";
-import { type ComponentProps, useCallback, useEffect, useState } from "react";
+import type { ComponentProps } from "react";
+import { useCallback, useEffect, useState } from "react";
 
 import styles from "./index.module.scss";
 

+ 2 - 1
apps/insights/src/components/FeedKey/index.tsx

@@ -1,4 +1,5 @@
-import { useMemo, type ComponentProps } from "react";
+import type { ComponentProps } from "react";
+import { useMemo } from "react";
 
 import { toHex, truncateHex } from "../../hex";
 import { CopyButton } from "../CopyButton";

+ 4 - 13
apps/insights/src/components/LayoutTransition/index.tsx

@@ -1,20 +1,11 @@
 "use client";
 
-import {
-  type TargetAndTransition,
-  type Target,
-  AnimatePresence,
-  motion,
-} from "motion/react";
+import type { TargetAndTransition, Target } from "motion/react";
+import { AnimatePresence, motion } from "motion/react";
 import { LayoutRouterContext } from "next/dist/shared/lib/app-router-context.shared-runtime";
 import { useSelectedLayoutSegment } from "next/navigation";
-import {
-  type ReactNode,
-  type ComponentProps,
-  useContext,
-  useEffect,
-  useRef,
-} from "react";
+import type { ReactNode, ComponentProps } from "react";
+import { useContext, useEffect, useRef } from "react";
 
 type OwnProps = {
   children: ReactNode;

+ 14 - 6
apps/insights/src/components/LivePrices/index.tsx

@@ -3,7 +3,8 @@
 import { PlusMinus } from "@phosphor-icons/react/dist/ssr/PlusMinus";
 import type { PriceData, PriceComponent } from "@pythnetwork/client";
 import { Skeleton } from "@pythnetwork/component-library/Skeleton";
-import { type ReactNode, useMemo } from "react";
+import type { ReactNode } from "react";
+import { useMemo } from "react";
 import { useNumberFormatter, useDateFormatter } from "react-aria";
 
 import styles from "./index.module.scss";
@@ -177,11 +178,18 @@ export const LiveValue = <T extends keyof PriceData>({
 }: LiveValueProps<T>) => {
   const { current } = useLivePriceData(cluster, feedKey);
 
-  return current !== undefined || defaultValue !== undefined ? (
-    (current?.[field]?.toString() ?? defaultValue)
-  ) : (
-    <Skeleton width={SKELETON_WIDTH} />
-  );
+  if (current !== undefined || defaultValue !== undefined) {
+    const value = current?.[field];
+    if (typeof value === "string") {
+      return value;
+    } else if (typeof value === "number" || typeof value === "bigint") {
+      return value.toString();
+    } else {
+      return value ? JSON.stringify(value) : defaultValue;
+    }
+  } else {
+    return <Skeleton width={SKELETON_WIDTH} />;
+  }
 };
 
 type LiveComponentValueProps<T extends keyof PriceComponent["latest"]> = {

+ 2 - 1
apps/insights/src/components/Overview/tab-list.tsx

@@ -6,7 +6,8 @@ import {
 } from "@pythnetwork/component-library/unstyled/Tabs";
 import clsx from "clsx";
 import { motion } from "motion/react";
-import { type ComponentProps, useId } from "react";
+import type { ComponentProps } from "react";
+import { useId } from "react";
 
 import styles from "./tab-list.module.scss";
 

+ 3 - 9
apps/insights/src/components/PriceComponentDrawer/index.tsx

@@ -10,14 +10,8 @@ import { StatCard } from "@pythnetwork/component-library/StatCard";
 import { Table } from "@pythnetwork/component-library/Table";
 import dynamic from "next/dynamic";
 import { useRouter } from "next/navigation";
-import {
-  type ReactNode,
-  Suspense,
-  useState,
-  useRef,
-  useCallback,
-  useMemo,
-} from "react";
+import type { ReactNode } from "react";
+import { Suspense, useState, useRef, useCallback, useMemo } from "react";
 import {
   RouterProvider,
   useDateFormatter,
@@ -343,7 +337,7 @@ const getScoreHistory = async ([
   symbol,
   selectedPeriod,
 ]: [Cluster, string, string, EvaluationPeriod]) => {
-  const url = new URL("/component-score-history", window.location.origin);
+  const url = new URL("/component-score-history", globalThis.location.origin);
   url.searchParams.set("cluster", ClusterToName[cluster]);
   url.searchParams.set("publisherKey", publisherKey);
   url.searchParams.set("symbol", symbol);

+ 8 - 13
apps/insights/src/components/PriceComponentsCard/index.tsx

@@ -8,28 +8,23 @@ import { Paginator } from "@pythnetwork/component-library/Paginator";
 import { SearchInput } from "@pythnetwork/component-library/SearchInput";
 import { Select } from "@pythnetwork/component-library/Select";
 import { SingleToggleGroup } from "@pythnetwork/component-library/SingleToggleGroup";
-import {
-  type RowConfig,
-  type ColumnConfig,
-  type SortDescriptor,
-  Table,
+import type {
+  RowConfig,
+  ColumnConfig,
+  SortDescriptor,
 } from "@pythnetwork/component-library/Table";
+import { Table } from "@pythnetwork/component-library/Table";
 import clsx from "clsx";
 import { useQueryState, parseAsStringEnum, parseAsBoolean } from "nuqs";
-import {
-  type ReactNode,
-  Fragment,
-  Suspense,
-  useMemo,
-  useCallback,
-} from "react";
+import type { ReactNode } from "react";
+import { Fragment, Suspense, useMemo, useCallback } from "react";
 import { useFilter, useCollator } from "react-aria";
 
 import styles from "./index.module.scss";
 import { useQueryParamFilterPagination } from "../../hooks/use-query-param-filter-pagination";
 import { Cluster } from "../../services/pyth";
+import type { StatusName } from "../../status";
 import {
-  type StatusName,
   STATUS_NAMES,
   Status as StatusType,
   statusNameToStatus,

+ 8 - 12
apps/insights/src/components/PriceFeed/chart.tsx

@@ -2,15 +2,11 @@
 
 import { useLogger } from "@pythnetwork/app-logger";
 import { useResizeObserver } from "@react-hookz/web";
-import {
-  type IChartApi,
-  type ISeriesApi,
-  type UTCTimestamp,
-  LineStyle,
-  createChart,
-} from "lightweight-charts";
+import type { IChartApi, ISeriesApi, UTCTimestamp } from "lightweight-charts";
+import { LineSeries, LineStyle, createChart } from "lightweight-charts";
 import { useTheme } from "next-themes";
-import { type RefObject, useEffect, useRef, useCallback } from "react";
+import type { RefObject } from "react";
+import { useEffect, useRef, useCallback } from "react";
 import { z } from "zod";
 
 import theme from "./theme.module.scss";
@@ -48,7 +44,7 @@ const useChartElem = (symbol: string, feedId: string) => {
   const backfillData = useCallback(() => {
     if (!isBackfilling.current && earliestDateRef.current) {
       isBackfilling.current = true;
-      const url = new URL("/historical-prices", window.location.origin);
+      const url = new URL("/historical-prices", globalThis.location.origin);
       url.searchParams.set("symbol", symbol);
       url.searchParams.set("until", earliestDateRef.current.toString());
       fetch(url)
@@ -115,7 +111,7 @@ const useChartElem = (symbol: string, feedId: string) => {
         },
       });
 
-      const price = chart.addLineSeries({ priceFormat });
+      const price = chart.addSeries(LineSeries, { priceFormat });
 
       chart.timeScale().subscribeVisibleLogicalRangeChange((range) => {
         if (
@@ -133,8 +129,8 @@ const useChartElem = (symbol: string, feedId: string) => {
       chartRef.current = {
         resolution: Resolution.Tick,
         chart,
-        confidenceHigh: chart.addLineSeries(confidenceConfig),
-        confidenceLow: chart.addLineSeries(confidenceConfig),
+        confidenceHigh: chart.addSeries(LineSeries, confidenceConfig),
+        confidenceLow: chart.addSeries(LineSeries, confidenceConfig),
         price,
       };
       return () => {

+ 2 - 1
apps/insights/src/components/PriceFeed/price-feed-select.tsx

@@ -16,7 +16,8 @@ import { SearchField } from "@pythnetwork/component-library/unstyled/SearchField
 import { Select } from "@pythnetwork/component-library/unstyled/Select";
 import { Input } from "@pythnetwork/component-library/unstyled/TextField";
 import clsx from "clsx";
-import { type ReactNode, useMemo, useState } from "react";
+import type { ReactNode } from "react";
+import { useMemo, useState } from "react";
 import { useCollator, useFilter } from "react-aria";
 
 import styles from "./price-feed-select.module.scss";

+ 2 - 1
apps/insights/src/components/PriceFeed/publishers-card.tsx

@@ -3,7 +3,8 @@
 import { useLogger } from "@pythnetwork/app-logger";
 import { Switch } from "@pythnetwork/component-library/Switch";
 import { useQueryState, parseAsString, parseAsBoolean } from "nuqs";
-import { type ComponentProps, Suspense, useCallback, useMemo } from "react";
+import type { ComponentProps } from "react";
+import { Suspense, useCallback, useMemo } from "react";
 
 import { Cluster, ClusterToName } from "../../services/pyth";
 import { PriceComponentDrawer } from "../PriceComponentDrawer";

+ 3 - 2
apps/insights/src/components/PriceFeedChangePercent/index.tsx

@@ -1,6 +1,7 @@
 "use client";
 
-import { type ComponentProps, createContext, use } from "react";
+import type { ComponentProps } from "react";
+import { createContext, use } from "react";
 import { z } from "zod";
 
 import { StateType, useData } from "../../hooks/use-data";
@@ -42,7 +43,7 @@ export const YesterdaysPricesProvider = ({
 const getYesterdaysPrices = async (
   feeds: YesterdaysPricesProviderProps["feeds"],
 ): Promise<Map<string, number>> => {
-  const url = new URL("/yesterdays-prices", window.location.origin);
+  const url = new URL("/yesterdays-prices", globalThis.location.origin);
   for (const symbol of Object.keys(feeds)) {
     url.searchParams.append("symbols", symbol);
   }

+ 2 - 1
apps/insights/src/components/PriceFeedTag/index.tsx

@@ -2,7 +2,8 @@
 
 import { Skeleton } from "@pythnetwork/component-library/Skeleton";
 import clsx from "clsx";
-import { type ComponentProps, type ReactNode, Fragment } from "react";
+import type { ComponentProps, ReactNode } from "react";
+import { Fragment } from "react";
 
 import styles from "./index.module.scss";
 import { usePriceFeeds } from "../../hooks/use-price-feeds";

+ 2 - 1
apps/insights/src/components/PriceFeeds/asset-classes-drawer.tsx

@@ -15,7 +15,8 @@ import {
   useQueryStates,
   createSerializer,
 } from "nuqs";
-import { type ReactNode, useMemo } from "react";
+import type { ReactNode } from "react";
+import { useMemo } from "react";
 import { useCollator } from "react-aria";
 
 type Props = {

+ 2 - 4
apps/insights/src/components/PriceFeeds/index.tsx

@@ -5,10 +5,8 @@ import { ClockCountdown } from "@phosphor-icons/react/dist/ssr/ClockCountdown";
 import { Star } from "@phosphor-icons/react/dist/ssr/Star";
 import { Badge } from "@pythnetwork/component-library/Badge";
 import { Button } from "@pythnetwork/component-library/Button";
-import {
-  type Props as CardProps,
-  Card,
-} from "@pythnetwork/component-library/Card";
+import type { Props as CardProps } from "@pythnetwork/component-library/Card";
+import { Card } from "@pythnetwork/component-library/Card";
 import { Drawer, DrawerTrigger } from "@pythnetwork/component-library/Drawer";
 import { StatCard } from "@pythnetwork/component-library/StatCard";
 import { TabList } from "@pythnetwork/component-library/TabList";

+ 4 - 4
apps/insights/src/components/PriceFeeds/price-feeds-card.tsx

@@ -7,11 +7,11 @@ import { Card } from "@pythnetwork/component-library/Card";
 import { Paginator } from "@pythnetwork/component-library/Paginator";
 import { SearchInput } from "@pythnetwork/component-library/SearchInput";
 import { Select } from "@pythnetwork/component-library/Select";
-import {
-  type RowConfig,
-  type SortDescriptor,
-  Table,
+import type {
+  RowConfig,
+  SortDescriptor,
 } from "@pythnetwork/component-library/Table";
+import { Table } from "@pythnetwork/component-library/Table";
 import { useQueryState, parseAsString } from "nuqs";
 import { Suspense, useCallback, useMemo } from "react";
 import { useFilter, useCollator } from "react-aria";

+ 1 - 1
apps/insights/src/components/PriceName/index.tsx

@@ -9,7 +9,7 @@ export const PriceName = ({ assetClass, uppercase, plural }: Props) =>
     uppercase ? "upcase" : "title"
   ];
 
-const getLabels = (assetClass?: string | undefined) => {
+const getLabels = (assetClass?: string) => {
   if (assetClass === undefined) {
     return LABELS.ambiguous;
   } else {

+ 2 - 5
apps/insights/src/components/Publisher/get-price-feeds.tsx

@@ -1,9 +1,6 @@
 import { getRankingsByPublisher } from "../../services/clickhouse";
-import {
-  type Cluster,
-  ClusterToName,
-  getFeedsForPublisher,
-} from "../../services/pyth";
+import type { Cluster } from "../../services/pyth";
+import { ClusterToName, getFeedsForPublisher } from "../../services/pyth";
 import { getStatus } from "../../status";
 
 export const getPriceFeeds = async (cluster: Cluster, key: string) => {

+ 2 - 1
apps/insights/src/components/Publisher/performance.tsx

@@ -22,7 +22,8 @@ import {
   ExplainInactive,
   ExplainAverage,
 } from "../Explanations";
-import { type Variant as NoResultsVariant, NoResults } from "../NoResults";
+import type { Variant as NoResultsVariant } from "../NoResults";
+import { NoResults } from "../NoResults";
 import { PriceFeedTag } from "../PriceFeedTag";
 import { PublisherIcon } from "../PublisherIcon";
 import { PublisherTag } from "../PublisherTag";

+ 2 - 8
apps/insights/src/components/Publisher/price-feed-drawer-provider.tsx

@@ -2,14 +2,8 @@
 
 import { useLogger } from "@pythnetwork/app-logger";
 import { parseAsString, useQueryState } from "nuqs";
-import {
-  type ComponentProps,
-  Suspense,
-  createContext,
-  useMemo,
-  useCallback,
-  use,
-} from "react";
+import type { ComponentProps } from "react";
+import { Suspense, createContext, useMemo, useCallback, use } from "react";
 
 import { usePriceFeeds } from "../../hooks/use-price-feeds";
 import type { Cluster } from "../../services/pyth";

+ 2 - 1
apps/insights/src/components/Publisher/price-feeds-card.tsx

@@ -1,6 +1,7 @@
 "use client";
 
-import { type ComponentProps, useCallback } from "react";
+import type { ComponentProps } from "react";
+import { useCallback } from "react";
 
 import { useSelectPriceFeed } from "./price-feed-drawer-provider";
 import { usePriceFeeds } from "../../hooks/use-price-feeds";

+ 2 - 1
apps/insights/src/components/Publisher/top-feeds-table.tsx

@@ -1,6 +1,7 @@
 "use client";
 
-import { type RowConfig, Table } from "@pythnetwork/component-library/Table";
+import type { RowConfig } from "@pythnetwork/component-library/Table";
+import { Table } from "@pythnetwork/component-library/Table";
 import { useMemo } from "react";
 
 import { useSelectPriceFeed } from "./price-feed-drawer-provider";

+ 6 - 5
apps/insights/src/components/Publishers/publishers-card.tsx

@@ -9,14 +9,15 @@ import { Link } from "@pythnetwork/component-library/Link";
 import { Paginator } from "@pythnetwork/component-library/Paginator";
 import { SearchInput } from "@pythnetwork/component-library/SearchInput";
 import { Select } from "@pythnetwork/component-library/Select";
-import {
-  type RowConfig,
-  type SortDescriptor,
-  Table,
+import type {
+  RowConfig,
+  SortDescriptor,
 } from "@pythnetwork/component-library/Table";
+import { Table } from "@pythnetwork/component-library/Table";
 import clsx from "clsx";
 import { useQueryState, parseAsStringEnum } from "nuqs";
-import { type ReactNode, Suspense, useMemo, useCallback } from "react";
+import type { ReactNode } from "react";
+import { Suspense, useMemo, useCallback } from "react";
 import { useFilter, useCollator } from "react-aria";
 
 import styles from "./publishers-card.module.scss";

+ 2 - 4
apps/insights/src/components/Root/footer.tsx

@@ -1,7 +1,5 @@
-import {
-  type Props as ButtonProps,
-  Button,
-} from "@pythnetwork/component-library/Button";
+import type { Props as ButtonProps } from "@pythnetwork/component-library/Button";
+import { Button } from "@pythnetwork/component-library/Button";
 import { DrawerTrigger } from "@pythnetwork/component-library/Drawer";
 import { Link } from "@pythnetwork/component-library/Link";
 import type { ComponentProps, ElementType } from "react";

+ 2 - 1
apps/insights/src/components/Root/mobile-nav-tabs.tsx

@@ -4,7 +4,8 @@ import { Link } from "@pythnetwork/component-library/unstyled/Link";
 import clsx from "clsx";
 import { motion } from "motion/react";
 import { usePathname } from "next/navigation";
-import { type ReactNode, useId, useMemo } from "react";
+import type { ReactNode } from "react";
+import { useId, useMemo } from "react";
 
 import styles from "./mobile-nav-tabs.module.scss";
 

+ 2 - 1
apps/insights/src/components/Root/search-button.tsx

@@ -3,7 +3,8 @@
 import { MagnifyingGlass } from "@phosphor-icons/react/dist/ssr/MagnifyingGlass";
 import { Button } from "@pythnetwork/component-library/Button";
 import { Skeleton } from "@pythnetwork/component-library/Skeleton";
-import { type ComponentProps, useMemo } from "react";
+import type { ComponentProps } from "react";
+import { useMemo } from "react";
 import { useIsSSR } from "react-aria";
 
 import { useToggleSearchDialog } from "./search-dialog";

+ 3 - 4
apps/insights/src/components/Root/search-dialog.tsx

@@ -17,9 +17,8 @@ import {
 } from "@pythnetwork/component-library/unstyled/ListBox";
 import { useMediaQuery } from "@react-hookz/web";
 import { useRouter } from "next/navigation";
+import type { ReactNode, ComponentProps } from "react";
 import {
-  type ReactNode,
-  type ComponentProps,
   useState,
   useCallback,
   useEffect,
@@ -435,9 +434,9 @@ const useSearchDialogStateContext = () => {
   );
 
   useEffect(() => {
-    window.addEventListener("keydown", handleKeyDown);
+    globalThis.addEventListener("keydown", handleKeyDown);
     return () => {
-      window.removeEventListener("keydown", handleKeyDown);
+      globalThis.removeEventListener("keydown", handleKeyDown);
     };
   }, [handleKeyDown]);
 

+ 2 - 4
apps/insights/src/components/Root/support-drawer.tsx

@@ -5,10 +5,8 @@ import { Coins } from "@phosphor-icons/react/dist/ssr/Coins";
 import { Gavel } from "@phosphor-icons/react/dist/ssr/Gavel";
 import { Plug } from "@phosphor-icons/react/dist/ssr/Plug";
 import { ShieldChevron } from "@phosphor-icons/react/dist/ssr/ShieldChevron";
-import {
-  type Props as CardProps,
-  Card,
-} from "@pythnetwork/component-library/Card";
+import type { Props as CardProps } from "@pythnetwork/component-library/Card";
+import { Card } from "@pythnetwork/component-library/Card";
 import { Drawer } from "@pythnetwork/component-library/Drawer";
 import type { Link as UnstyledLink } from "@pythnetwork/component-library/unstyled/Link";
 import type { ComponentProps, ReactNode } from "react";

+ 3 - 2
apps/insights/src/components/Root/tabs.tsx

@@ -6,9 +6,10 @@ import {
   Tabs,
 } from "@pythnetwork/component-library/unstyled/Tabs";
 import { useSelectedLayoutSegment, usePathname } from "next/navigation";
-import { type ComponentProps } from "react";
+import type { ComponentProps } from "react";
 
-import { type VariantArg, LayoutTransition } from "../LayoutTransition";
+import type { VariantArg } from "../LayoutTransition";
+import { LayoutTransition } from "../LayoutTransition";
 
 export const TabRoot = (
   props: Omit<ComponentProps<typeof Tabs>, "selectedKey">,

+ 4 - 11
apps/insights/src/components/Root/theme-switch.tsx

@@ -4,20 +4,13 @@ import type { IconProps } from "@phosphor-icons/react";
 import { Desktop } from "@phosphor-icons/react/dist/ssr/Desktop";
 import { Moon } from "@phosphor-icons/react/dist/ssr/Moon";
 import { Sun } from "@phosphor-icons/react/dist/ssr/Sun";
-import {
-  type Props as ButtonProps,
-  Button,
-} from "@pythnetwork/component-library/Button";
+import type { Props as ButtonProps } from "@pythnetwork/component-library/Button";
+import { Button } from "@pythnetwork/component-library/Button";
 import clsx from "clsx";
 import { motion } from "motion/react";
 import { useTheme } from "next-themes";
-import {
-  type ReactNode,
-  type ElementType,
-  useCallback,
-  useRef,
-  useMemo,
-} from "react";
+import type { ReactNode, ElementType } from "react";
+import { useCallback, useRef, useMemo } from "react";
 import { useIsSSR } from "react-aria";
 
 import styles from "./theme-switch.module.scss";

+ 2 - 1
apps/insights/src/components/SemicircleMeter/index.tsx

@@ -3,7 +3,8 @@
 import { Meter } from "@pythnetwork/component-library/unstyled/Meter";
 import clsx from "clsx";
 import dynamic from "next/dynamic";
-import { type ComponentProps, type CSSProperties, Suspense } from "react";
+import type { ComponentProps, CSSProperties } from "react";
+import { Suspense } from "react";
 import { PolarAngleAxis, RadialBar } from "recharts";
 
 import styles from "./index.module.scss";

+ 2 - 1
apps/insights/src/components/Tabs/index.tsx

@@ -6,7 +6,8 @@ import {
   Tabs as UnstyledTabs,
 } from "@pythnetwork/component-library/unstyled/Tabs";
 import { useSelectedLayoutSegment, usePathname } from "next/navigation";
-import { useMemo, type ComponentProps } from "react";
+import type { ComponentProps } from "react";
+import { useMemo } from "react";
 
 import { LayoutTransition } from "../LayoutTransition";
 

+ 2 - 1
apps/insights/src/components/ZoomLayoutTransition/index.tsx

@@ -2,7 +2,8 @@
 
 import type { ReactNode } from "react";
 
-import { type VariantArg, LayoutTransition } from "../LayoutTransition";
+import type { VariantArg } from "../LayoutTransition";
+import { LayoutTransition } from "../LayoutTransition";
 
 type Props = {
   children: ReactNode;

+ 2 - 1
apps/insights/src/hooks/use-data.ts

@@ -1,6 +1,7 @@
 import { useLogger } from "@pythnetwork/app-logger";
 import { useCallback } from "react";
-import useSWR, { type KeyedMutator } from "swr";
+import type { KeyedMutator } from "swr";
+import useSWR from "swr";
 
 export const useData = <T>(
   key: Parameters<typeof useSWR<T>>[0],

+ 1 - 1
apps/insights/src/hooks/use-live-price-data.tsx

@@ -4,8 +4,8 @@ import { useLogger } from "@pythnetwork/app-logger";
 import type { PriceData } from "@pythnetwork/client";
 import { useMap } from "@react-hookz/web";
 import { PublicKey } from "@solana/web3.js";
+import type { ComponentProps } from "react";
 import {
-  type ComponentProps,
   use,
   createContext,
   useEffect,

+ 2 - 1
apps/insights/src/hooks/use-price-feeds.tsx

@@ -1,6 +1,7 @@
 "use client";
 
-import { type ReactNode, type ComponentProps, createContext, use } from "react";
+import type { ReactNode, ComponentProps } from "react";
+import { createContext, use } from "react";
 
 import type { Cluster } from "../services/pyth";
 

+ 5 - 7
apps/insights/src/hooks/use-query-param-filter-pagination.ts

@@ -16,13 +16,11 @@ export const useQueryParamFilterPagination = <T>(
   items: T[],
   predicate: (item: T, term: string) => boolean,
   doSort: (a: T, b: T, descriptor: SortDescriptor) => number,
-  options?:
-    | {
-        defaultPageSize?: number | undefined;
-        defaultSort?: string | undefined;
-        defaultDescending?: boolean;
-      }
-    | undefined,
+  options?: {
+    defaultPageSize?: number | undefined;
+    defaultSort?: string | undefined;
+    defaultDescending?: boolean;
+  },
 ) => {
   const logger = useLogger();
 

+ 1 - 4
apps/insights/src/omit-keys.ts

@@ -1,7 +1,4 @@
-export const omitKeys = <T extends Record<string, unknown>>(
-  obj: T,
-  keys: string[],
-) => {
+export const omitKeys = (obj: Record<string, unknown>, keys: string[]) => {
   const omitSet = new Set(keys);
   return Object.fromEntries(
     Object.entries(obj).filter(([key]) => !omitSet.has(key)),

+ 2 - 1
apps/insights/src/services/clickhouse.ts

@@ -1,7 +1,8 @@
 import "server-only";
 
 import { createClient } from "@clickhouse/client";
-import { z, type ZodSchema, type ZodTypeDef } from "zod";
+import type { ZodSchema, ZodTypeDef } from "zod";
+import { z } from "zod";
 
 import { Cluster, ClusterToName } from "./pyth";
 import { CLICKHOUSE } from "../config/server";

+ 1 - 1
apps/staking/jest.config.js

@@ -1 +1 @@
-export { nextjs as default } from "@cprussin/jest-config";
+export { nextjs as default } from "@cprussin/jest-config/next";

+ 35 - 37
apps/staking/package.json

@@ -19,60 +19,58 @@
     "test:unit": "jest --selectProjects unit"
   },
   "dependencies": {
-    "@amplitude/analytics-browser": "^2.9.3",
-    "@amplitude/plugin-autocapture-browser": "^0.9.0",
-    "@bonfida/spl-name-service": "^3.0.0",
-    "@heroicons/react": "^2.1.4",
-    "@next/third-parties": "^14.2.5",
+    "@amplitude/analytics-browser": "catalog:",
+    "@amplitude/plugin-autocapture-browser": "catalog:",
+    "@bonfida/spl-name-service": "catalog:",
+    "@heroicons/react": "catalog:",
+    "@next/third-parties": "catalog:",
     "@pythnetwork/hermes-client": "workspace:*",
     "@pythnetwork/known-publishers": "workspace:*",
     "@pythnetwork/staking-sdk": "workspace:*",
-    "@react-aria/toast": "3.0.0-beta.16",
-    "@react-hookz/web": "^24.0.4",
-    "@react-stately/toast": "3.0.0-beta.6",
-    "@solana/wallet-adapter-base": "^0.9.23",
-    "@solana/wallet-adapter-react": "^0.15.35",
-    "@solana/wallet-adapter-react-ui": "^0.9.35",
-    "@solana/wallet-adapter-wallets": "0.19.10",
-    "@solana/web3.js": "1.92.3",
-    "@vercel/functions": "^1.5.0",
-    "bcp-47": "^2.1.0",
-    "clsx": "^2.1.1",
-    "dnum": "^2.13.1",
+    "@react-hookz/web": "catalog:",
+    "@solana/wallet-adapter-base": "catalog:",
+    "@solana/wallet-adapter-react": "catalog:",
+    "@solana/wallet-adapter-react-ui": "catalog:",
+    "@solana/wallet-adapter-wallets": "catalog:",
+    "@solana/web3.js": "catalog:",
+    "@vercel/functions": "catalog:",
+    "bcp-47": "catalog:",
+    "clsx": "catalog:",
+    "dnum": "catalog:",
     "framer-motion": "catalog:",
-    "ip-range-check": "^0.2.0",
+    "ip-range-check": "catalog:",
     "next": "catalog:",
-    "pino": "^9.3.2",
-    "proxycheck-ts": "^0.0.11",
+    "pino": "catalog:",
+    "proxycheck-ts": "catalog:",
     "react": "catalog:",
     "react-aria": "catalog:",
     "react-aria-components": "catalog:",
     "react-dom": "catalog:",
-    "recharts": "^2.13.3",
-    "swr": "^2.2.5",
-    "zod": "^3.23.8"
+    "recharts": "catalog:",
+    "swr": "catalog:",
+    "zod": "catalog:"
   },
   "devDependencies": {
-    "@axe-core/react": "^4.9.1",
+    "@axe-core/react": "catalog:",
     "@cprussin/eslint-config": "catalog:",
     "@cprussin/jest-config": "catalog:",
     "@cprussin/prettier-config": "catalog:",
     "@cprussin/tsconfig": "catalog:",
-    "@svgr/webpack": "^8.1.0",
-    "@tailwindcss/forms": "^0.5.7",
-    "@types/jest": "^29.5.12",
-    "@types/node": "^22.0.0",
+    "@svgr/webpack": "catalog:",
+    "@tailwindcss/forms": "catalog:",
+    "@types/jest": "catalog:",
+    "@types/node": "catalog:",
     "@types/react": "catalog:",
     "@types/react-dom": "catalog:",
-    "autoprefixer": "^10.4.19",
-    "eslint": "^9.8.0",
-    "jest": "^29.7.0",
-    "postcss": "^8.4.40",
+    "autoprefixer": "catalog:",
+    "eslint": "catalog:",
+    "jest": "catalog:",
+    "postcss": "catalog:",
     "prettier": "catalog:",
-    "tailwindcss": "^3.4.7",
-    "tailwindcss-animate": "^1.0.7",
-    "tailwindcss-react-aria-components": "^1.1.5",
-    "typescript": "^5.5.4",
-    "vercel": "^35.2.2"
+    "tailwindcss": "catalog:",
+    "tailwindcss-animate": "catalog:",
+    "tailwindcss-react-aria-components": "catalog:",
+    "typescript": "catalog:",
+    "vercel": "catalog:"
   }
 }

+ 2 - 2
apps/staking/src/api.ts

@@ -1,5 +1,6 @@
 import type { HermesClient, PublisherCaps } from "@pythnetwork/hermes-client";
 import { lookup } from "@pythnetwork/known-publishers";
+import type { StakeAccountPositions } from "@pythnetwork/staking-sdk";
 import {
   epochToDate,
   extractPublisherData,
@@ -8,7 +9,6 @@ import {
   PositionState,
   PythnetClient,
   PythStakingClient,
-  type StakeAccountPositions,
 } from "@pythnetwork/staking-sdk";
 import { PublicKey } from "@solana/web3.js";
 import { z } from "zod";
@@ -102,7 +102,7 @@ export const loadData = async (
   client: PythStakingClient,
   pythnetClient: PythnetClient,
   hermesClient: HermesClient,
-  stakeAccount?: PublicKey | undefined,
+  stakeAccount?: PublicKey,
   simulationPayer?: PublicKey,
 ): Promise<Data> =>
   stakeAccount === undefined

+ 4 - 8
apps/staking/src/components/AccountSummary/index.tsx

@@ -2,20 +2,16 @@ import { InformationCircleIcon } from "@heroicons/react/24/outline";
 import { epochToDate } from "@pythnetwork/staking-sdk";
 import clsx from "clsx";
 import Image from "next/image";
-import {
-  type ComponentProps,
-  type ReactNode,
-  useCallback,
-  useState,
-  useMemo,
-} from "react";
+import type { ComponentProps, ReactNode } from "react";
+import { useCallback, useState, useMemo } from "react";
 import {
   DialogTrigger,
   Button as ReactAriaButton,
 } from "react-aria-components";
 
 import background from "./background.png";
-import { type States, StateType as ApiStateType } from "../../hooks/use-api";
+import type { States } from "../../hooks/use-api";
+import { StateType as ApiStateType } from "../../hooks/use-api";
 import { StateType, useAsync } from "../../hooks/use-async";
 import { useToast } from "../../hooks/use-toast";
 import { Button } from "../Button";

+ 2 - 1
apps/staking/src/components/CopyButton/index.tsx

@@ -1,6 +1,7 @@
 import { ClipboardDocumentIcon, CheckIcon } from "@heroicons/react/24/outline";
 import clsx from "clsx";
-import { type ComponentProps, useCallback, useEffect, useState } from "react";
+import type { ComponentProps } from "react";
+import { useCallback, useEffect, useState } from "react";
 import { Button } from "react-aria-components";
 
 import { useLogger } from "../../hooks/use-logger";

+ 7 - 13
apps/staking/src/components/Dashboard/index.tsx

@@ -1,15 +1,9 @@
 import { useLocalStorageValue } from "@react-hookz/web";
 import clsx from "clsx";
-import Image, { type StaticImageData } from "next/image";
-import {
-  type ComponentProps,
-  type ReactNode,
-  type FormEvent,
-  useState,
-  useMemo,
-  useEffect,
-  useCallback,
-} from "react";
+import type { StaticImageData } from "next/image";
+import Image from "next/image";
+import type { ComponentProps, ReactNode, FormEvent } from "react";
+import { useState, useMemo, useEffect, useCallback } from "react";
 import { Tabs, TabList, TabPanel, Tab, Form } from "react-aria-components";
 
 import type { States, StateType as ApiStateType } from "../../hooks/use-api";
@@ -252,7 +246,7 @@ const useIntegrityStakingSum = (
     [publishers, field],
   );
 
-// eslint-disable-next-line unicorn/no-array-reduce
+// eslint-disable-next-line unicorn/no-array-reduce, unicorn/prefer-math-min-max
 const bigIntMin = (...args: bigint[]) => args.reduce((m, e) => (e < m ? e : m));
 
 type TabId = Exclude<ComponentProps<typeof Tabs>["selectedKey"], undefined>;
@@ -274,12 +268,12 @@ const Journey = ({
 }: JourneyProps) => (
   <Tab
     className={clsx(
-      "group/tab flex flex-1 cursor-pointer flex-col items-center bg-pythpurple-800 focus:outline-none focus-visible:ring-1 focus-visible:ring-pythpurple-400 selected:cursor-default group-data-[empty]:sm:bg-transparent",
+      "group/tab flex flex-1 cursor-pointer flex-col items-center bg-pythpurple-800 data-[selected]:cursor-default focus:outline-none focus-visible:ring-1 focus-visible:ring-pythpurple-400 group-data-[empty]:sm:bg-transparent",
       className,
     )}
     {...props}
   >
-    <div className="grid size-full flex-none basis-0 place-content-center border border-neutral-600/50 bg-pythpurple-800 p-2 text-center font-semibold transition group-data-[empty]:py-8 group-hover/tab:bg-pythpurple-600/30 group-selected/tab:border-pythpurple-400/60 group-selected/tab:bg-pythpurple-600/60 group-hover/tab:group-selected/tab:bg-pythpurple-600/60 sm:py-4 sm:text-lg group-data-[empty]:sm:py-2">
+    <div className="grid size-full flex-none basis-0 place-content-center border border-neutral-600/50 bg-pythpurple-800 p-2 text-center font-semibold transition group-hover/tab:bg-pythpurple-600/30 group-data-[selected]/tab:border-pythpurple-400/60 group-data-[selected]/tab:bg-pythpurple-600/60 group-data-[empty]:py-8 group-hover/tab:group-data-[selected]/tab:bg-pythpurple-600/60 sm:py-4 sm:text-lg group-data-[empty]:sm:py-2">
       <span className="hidden group-data-[empty]:inline sm:inline">
         {longText}
       </span>

+ 4 - 2
apps/staking/src/components/Date/index.tsx

@@ -1,5 +1,7 @@
-import { useMemo, type HTMLProps } from "react";
-import { useDateFormatter, type DateFormatterOptions } from "react-aria";
+import type { HTMLProps } from "react";
+import { useMemo } from "react";
+import type { DateFormatterOptions } from "react-aria";
+import { useDateFormatter } from "react-aria";
 
 type Props = Omit<HTMLProps<HTMLSpanElement>, "children"> & {
   children: Date;

+ 0 - 3
apps/staking/src/components/ErrorMessage/index.tsx

@@ -49,9 +49,6 @@ const UnknownError = ({ error }: { error: unknown }) => {
         </div>
       </Button>
       <m.div
-        // @ts-expect-error the framer-motion types don't currently expose props
-        // like `className` correctly for some reason, even though this works
-        // correctly...
         className="overflow-hidden pt-1 opacity-60"
         initial={{ height: 0 }}
         animate={{ height: detailsOpen ? "auto" : 0 }}

+ 2 - 9
apps/staking/src/components/Faq/index.tsx

@@ -1,11 +1,7 @@
 import clsx from "clsx";
 import { LazyMotion, m, domAnimation } from "framer-motion";
-import {
-  type HTMLProps,
-  type ReactNode,
-  type ComponentProps,
-  useState,
-} from "react";
+import type { HTMLProps, ReactNode, ComponentProps } from "react";
+import { useState } from "react";
 import { Button } from "react-aria-components";
 
 type Props = Omit<HTMLProps<HTMLDivElement>, "title"> & {
@@ -60,9 +56,6 @@ export const Faq = ({ title, questions, className, ...props }: Props) => {
                 </Button>
               </dt>
               <m.dt
-                // @ts-expect-error the framer-motion types don't currently
-                // expose props like `className` correctly for some reason, even
-                // though this works correctly...
                 className="-mt-1 flex max-w-prose flex-col gap-4 overflow-hidden font-light"
                 initial={{ height: openItem === i ? "auto" : 0 }}
                 animate={{ height: openItem === i ? "auto" : 0 }}

+ 2 - 1
apps/staking/src/components/Governance/index.tsx

@@ -1,6 +1,7 @@
 import clsx from "clsx";
 
-import { type States, StateType as ApiStateType } from "../../hooks/use-api";
+import type { States } from "../../hooks/use-api";
+import { StateType as ApiStateType } from "../../hooks/use-api";
 import { GovernanceGuide } from "../GovernanceGuide";
 import { ProgramSection } from "../ProgramSection";
 

+ 12 - 12
apps/staking/src/components/Guide/index.tsx

@@ -1,12 +1,12 @@
-import Image, { type StaticImageData } from "next/image";
-import {
-  type ComponentProps,
-  type ComponentType,
-  type ReactNode,
-  type SVGAttributes,
-  useMemo,
-  useRef,
+import type { StaticImageData } from "next/image";
+import Image from "next/image";
+import type {
+  ComponentProps,
+  ComponentType,
+  ReactNode,
+  SVGAttributes,
 } from "react";
+import { useMemo, useRef } from "react";
 import {
   Tabs,
   TabList,
@@ -61,14 +61,14 @@ export const Guide = ({ title, description, steps, ...props }: Props) => {
           {({ title, icon: Icon, index }) => (
             <Tab
               id={index.toString()}
-              className="group flex cursor-pointer flex-row items-center gap-4 border border-neutral-600/50 px-6 py-4 transition focus:outline-none focus-visible:ring-1 focus-visible:ring-pythpurple-400 selected:cursor-default selected:border-pythpurple-600 selected:bg-pythpurple-600/20 md:flex-1 md:px-4 md:py-2 lg:border-b lg:border-x-transparent lg:border-t-transparent lg:bg-black/40 lg:px-4 lg:py-6 lg:selected:border-neutral-600/50 lg:selected:border-b-transparent lg:selected:bg-black/40 xl:px-10 2xl:px-20"
+              className="group flex cursor-pointer flex-row items-center gap-4 border border-neutral-600/50 px-6 py-4 transition data-[selected]:cursor-default data-[selected]:border-pythpurple-600 data-[selected]:bg-pythpurple-600/20 focus:outline-none focus-visible:ring-1 focus-visible:ring-pythpurple-400 md:flex-1 md:px-4 md:py-2 lg:border-b lg:border-x-transparent lg:border-t-transparent lg:bg-black/40 lg:px-4 lg:py-6 lg:data-[selected]:border-neutral-600/50 lg:data-[selected]:border-b-transparent lg:data-[selected]:bg-black/40 xl:px-10 2xl:px-20"
             >
-              <Icon className="size-10 flex-none opacity-50 transition group-selected:opacity-100" />
+              <Icon className="size-10 flex-none opacity-50 transition group-data-[selected]:opacity-100" />
               <div className="flex flex-col justify-between">
                 <div className="text-sm tracking-[0.5rem] opacity-50 md:tracking-wide">
                   STEP {index + 1}
                 </div>
-                <div className="opacity-50 transition group-selected:opacity-100 xl:text-xl">
+                <div className="opacity-50 transition group-data-[selected]:opacity-100 xl:text-xl">
                   {title}
                 </div>
               </div>
@@ -95,7 +95,7 @@ export const Guide = ({ title, description, steps, ...props }: Props) => {
                   {({ title, index: subtabIndex }) => (
                     <Tab
                       id={subtabIndex.toString()}
-                      className="grid cursor-pointer place-content-center border border-neutral-600/50 p-2 text-center opacity-60 transition focus:outline-none focus-visible:ring-1 focus-visible:ring-pythpurple-400 selected:cursor-default selected:border-pythpurple-600/50 selected:bg-pythpurple-600/10 selected:opacity-100 sm:h-20 sm:flex-1 sm:px-2 sm:py-4 md:px-4"
+                      className="grid cursor-pointer place-content-center border border-neutral-600/50 p-2 text-center opacity-60 transition data-[selected]:cursor-default data-[selected]:border-pythpurple-600/50 data-[selected]:bg-pythpurple-600/10 data-[selected]:opacity-100 focus:outline-none focus-visible:ring-1 focus-visible:ring-pythpurple-400 sm:h-20 sm:flex-1 sm:px-2 sm:py-4 md:px-4"
                     >
                       {title}
                     </Tab>

+ 1 - 1
apps/staking/src/components/Header/current-stake-account.tsx

@@ -2,7 +2,7 @@
 
 import clsx from "clsx";
 import { useSelectedLayoutSegment } from "next/navigation";
-import { type HTMLProps } from "react";
+import type { HTMLProps } from "react";
 
 import { VPN_BLOCKED_SEGMENT } from "../../config/isomorphic";
 import { StateType as ApiStateType, useApi } from "../../hooks/use-api";

+ 2 - 5
apps/staking/src/components/Home/index.tsx

@@ -2,11 +2,8 @@
 
 import { useIsSSR } from "react-aria";
 
-import {
-  type States,
-  StateType as ApiStateType,
-  useApi,
-} from "../../hooks/use-api";
+import type { States } from "../../hooks/use-api";
+import { StateType as ApiStateType, useApi } from "../../hooks/use-api";
 import {
   StateType as DashboardDataStateType,
   useData,

+ 1 - 1
apps/staking/src/components/Menu/index.tsx

@@ -9,7 +9,7 @@ import {
   Popover,
   Menu as BaseMenu,
   MenuItem as BaseMenuItem,
-  Section as BaseSection,
+  MenuSection as BaseSection,
   Separator as BaseSeparator,
 } from "react-aria-components";
 

+ 7 - 14
apps/staking/src/components/NoWalletHome/index.tsx

@@ -1,17 +1,10 @@
 import { WalletIcon } from "@heroicons/react/24/outline";
 import { useWalletModal } from "@solana/wallet-adapter-react-ui";
 import clsx from "clsx";
-import Image, { type StaticImageData } from "next/image";
-import {
-  type ReactNode,
-  type ComponentType,
-  type SVGProps,
-  type ComponentProps,
-  useCallback,
-  useState,
-  useRef,
-  useEffect,
-} from "react";
+import type { StaticImageData } from "next/image";
+import Image from "next/image";
+import type { ReactNode, ComponentType, SVGProps, ComponentProps } from "react";
+import { useCallback, useState, useRef, useEffect } from "react";
 import { Tabs, TabList, Tab, TabPanel } from "react-aria-components";
 
 import governance from "./governance.png";
@@ -211,19 +204,19 @@ const ProgramTab = ({
 }: ProgramTabProps) => (
   <Tab
     className={clsx(
-      "group flex flex-1 cursor-pointer flex-col items-center focus:outline-none focus-visible:ring-1 focus-visible:ring-pythpurple-400 selected:cursor-default",
+      "group flex flex-1 cursor-pointer flex-col items-center data-[selected]:cursor-default focus:outline-none focus-visible:ring-1 focus-visible:ring-pythpurple-400",
       className,
     )}
     {...props}
   >
-    <div className="relative hidden w-4/5 opacity-30 transition group-hover:opacity-60 group-selected:opacity-100 md:block">
+    <div className="relative hidden w-4/5 opacity-30 transition group-hover:opacity-60 group-data-[selected]:opacity-100 md:block">
       <div className="absolute inset-0 bg-[#E6DAFE] mix-blend-color" />
       <Image src={image} alt="" className="size-full" />
       <div className="absolute inset-0 top-16 text-center text-2xl text-pythpurple-800 lg:text-3xl">
         {description}
       </div>
     </div>
-    <div className="size-full border border-transparent text-center font-semibold leading-none transition group-selected:border-pythpurple-400 group-selected:bg-pythpurple-600 md:border-neutral-600/50 md:bg-pythpurple-800 md:text-lg md:group-selected:border-pythpurple-400">
+    <div className="size-full border border-transparent text-center font-semibold leading-none transition group-data-[selected]:border-pythpurple-400 group-data-[selected]:bg-pythpurple-600 md:border-neutral-600/50 md:bg-pythpurple-800 md:text-lg md:group-data-[selected]:border-pythpurple-400">
       <div className="grid size-full place-content-center p-2 group-hover:bg-pythpurple-600/60 md:p-4">
         {children}
       </div>

+ 9 - 12
apps/staking/src/components/OracleIntegrityStaking/index.tsx

@@ -11,18 +11,14 @@ import type { lookup } from "@pythnetwork/known-publishers";
 import { calculateApy } from "@pythnetwork/staking-sdk";
 import { PublicKey } from "@solana/web3.js";
 import clsx from "clsx";
-import {
-  useMemo,
-  useCallback,
-  useState,
-  useRef,
-  createElement,
-  type ComponentProps,
-  type Dispatch,
-  type SetStateAction,
-  type HTMLAttributes,
-  type FormEvent,
+import type {
+  ComponentProps,
+  Dispatch,
+  SetStateAction,
+  HTMLAttributes,
+  FormEvent,
 } from "react";
+import { useMemo, useCallback, useState, useRef, createElement } from "react";
 import { useFilter, useCollator } from "react-aria";
 import {
   SearchField,
@@ -35,7 +31,8 @@ import {
   MenuTrigger,
 } from "react-aria-components";
 
-import { type States, StateType as ApiStateType } from "../../hooks/use-api";
+import type { States } from "../../hooks/use-api";
+import { StateType as ApiStateType } from "../../hooks/use-api";
 import {
   StateType as UseAsyncStateType,
   useAsync,

+ 3 - 2
apps/staking/src/components/Root/i18n-provider.tsx

@@ -1,7 +1,8 @@
 "use client";
 
 import { parse } from "bcp-47";
-import { useMemo, type ComponentProps } from "react";
+import type { ComponentProps } from "react";
+import { useMemo } from "react";
 import { I18nProvider as I18nProviderBase, useIsSSR } from "react-aria";
 
 const SUPPORTED_LANGUAGES = new Set(["en"]);
@@ -15,7 +16,7 @@ export const I18nProvider = (
     () =>
       isSSR
         ? DEFAULT_LOCALE
-        : (window.navigator.languages.find((locale) => {
+        : (globalThis.navigator.languages.find((locale) => {
             const language = parse(locale).language;
             return (
               language !== undefined &&

+ 80 - 74
apps/staking/src/components/Root/toast-region.tsx

@@ -1,94 +1,100 @@
 "use client";
 
 import { XMarkIcon } from "@heroicons/react/24/solid";
-import {
-  type AriaToastRegionProps,
-  type AriaToastProps,
-  useToastRegion,
-  useToast as reactAriaUseToast,
-} from "@react-aria/toast";
 import clsx from "clsx";
-import { useRef, useState } from "react";
-import { Button } from "react-aria-components";
-
+import { AnimatePresence, motion } from "framer-motion";
+import type { ComponentProps } from "react";
+import { useState, useCallback } from "react";
 import {
-  type Toast as ToastContentType,
-  ToastType,
-  useToast,
-} from "../../hooks/use-toast";
+  Button,
+  Text,
+  UNSTABLE_Toast as BaseToast,
+  UNSTABLE_ToastContent as BaseToastContent,
+  UNSTABLE_ToastRegion as BaseToastRegion,
+} from "react-aria-components";
+
+import type { Toast as ToastContentType } from "../../hooks/use-toast";
+import { ToastType, useToast } from "../../hooks/use-toast";
 import { ErrorMessage } from "../ErrorMessage";
 
-export const ToastRegion = (props: AriaToastRegionProps) => {
-  const state = useToast();
-  const ref = useRef(null);
-  const { regionProps } = useToastRegion(props, state, ref);
+const MotionBaseToast = motion(BaseToast);
+
+export const ToastRegion = (
+  props: Omit<
+    ComponentProps<typeof BaseToastRegion<ToastContentType>>,
+    "queue" | "children"
+  >,
+) => {
+  const toast = useToast();
 
   return (
-    <div
-      {...regionProps}
-      ref={ref}
-      className="pointer-events-none fixed top-0 z-50 flex w-full flex-col items-center"
+    <BaseToastRegion
+      className="pointer-events-none fixed top-0 z-50 flex w-full flex-col-reverse items-center"
+      queue={toast.queue}
+      {...props}
     >
-      {state.visibleToasts.map((toast) => (
-        <Toast key={toast.key} toast={toast} />
-      ))}
-    </div>
+      {({ toast }) => <Toast key={toast.key} toast={toast} />}
+    </BaseToastRegion>
   );
 };
 
-const Toast = (props: AriaToastProps<ToastContentType>) => {
+const Toast = (props: ComponentProps<typeof BaseToast<ToastContentType>>) => {
+  const toast = useToast();
+  const [isVisible, setIsVisible] = useState(true);
   const [isTimerStarted, setIsTimerStarted] = useState(false);
-  const state = useToast();
-  const ref = useRef(null);
-  const { toastProps, contentProps, titleProps, closeButtonProps } =
-    reactAriaUseToast(props, state, ref);
+  const hide = useCallback(() => {
+    setIsVisible(false);
+  }, [setIsVisible]);
+  const handlePresenceAnimationComplete = useCallback(
+    (name: string) => {
+      if (name === "exit") {
+        toast.queue.close(props.toast.key);
+      } else {
+        setIsTimerStarted(true);
+      }
+    },
+    [toast, props.toast, setIsTimerStarted],
+  );
 
   return (
-    <div
-      {...toastProps}
-      ref={ref}
-      className="pt-4 data-[entering]:animate-in data-[exiting]:animate-out data-[entering]:slide-in-from-top data-[exiting]:slide-out-to-top"
-      {...((props.toast.animation === "entering" ||
-        props.toast.animation === "queued") && { "data-entering": "" })}
-      {...(props.toast.animation === "exiting" && { "data-exiting": "" })}
-      onAnimationEnd={() => {
-        if (
-          props.toast.animation === "entering" ||
-          props.toast.animation === "queued"
-        ) {
-          setIsTimerStarted(true);
-        }
-        if (props.toast.animation === "exiting") {
-          state.remove(props.toast.key);
-        }
-      }}
-    >
-      <div className="pointer-events-auto w-96 bg-pythpurple-100 text-pythpurple-950">
-        <div
-          className={clsx(
-            "h-1 w-full origin-left bg-green-500 transition-transform [transition-duration:5000ms] [transition-timing-function:linear]",
-            {
-              "scale-x-0": isTimerStarted,
-              "bg-green-500": props.toast.content.type === ToastType.Success,
-              "bg-red-500": props.toast.content.type === ToastType.Error,
-            },
-          )}
-          onTransitionEnd={() => {
-            state.close(props.toast.key);
-          }}
-        />
-        <div className="flex flex-row items-start justify-between gap-8 px-4 py-2">
-          <div {...contentProps}>
-            <div {...titleProps}>
-              <ToastContent>{props.toast.content}</ToastContent>
-            </div>
+    <AnimatePresence>
+      {isVisible && (
+        <MotionBaseToast
+          // @ts-expect-error the framer-motion types don't currently expose
+          // props like `className` correctly for some reason, even though this
+          // works correctly...
+          className="pt-4"
+          initial={{ y: "-100%" }}
+          animate={{ y: 0 }}
+          exit={{ y: "-100%", transition: { ease: "linear", duration: 0.1 } }}
+          onAnimationComplete={handlePresenceAnimationComplete}
+          {...props}
+        >
+          <div className="pointer-events-auto w-96 bg-pythpurple-100 text-pythpurple-950">
+            <div
+              className={clsx(
+                "h-1 w-full origin-left bg-green-500 transition-transform [transition-duration:5000ms] [transition-timing-function:linear]",
+                {
+                  "scale-x-0": isTimerStarted,
+                  "bg-green-500":
+                    props.toast.content.type === ToastType.Success,
+                  "bg-red-500": props.toast.content.type === ToastType.Error,
+                },
+              )}
+              onTransitionEnd={hide}
+            />
+            <BaseToastContent className="flex flex-row items-start justify-between gap-8 px-4 py-2">
+              <Text slot="description">
+                <ToastContent>{props.toast.content}</ToastContent>
+              </Text>
+              <Button onPress={hide}>
+                <XMarkIcon className="mt-1 size-4" />
+              </Button>
+            </BaseToastContent>
           </div>
-          <Button {...closeButtonProps}>
-            <XMarkIcon className="mt-1 size-4" />
-          </Button>
-        </div>
-      </div>
-    </div>
+        </MotionBaseToast>
+      )}
+    </AnimatePresence>
   );
 };
 

+ 2 - 1
apps/staking/src/components/RouterProvider/index.tsx

@@ -1,7 +1,8 @@
 "use client";
 
 import { useRouter } from "next/navigation";
-import { type ComponentProps, useCallback } from "react";
+import type { ComponentProps } from "react";
+import { useCallback } from "react";
 import { RouterProvider as ReactAriaRouterProvider } from "react-aria-components";
 
 export const RouterProvider = (

+ 2 - 1
apps/staking/src/components/Tokens/index.tsx

@@ -2,7 +2,8 @@
 
 import clsx from "clsx";
 import * as dnum from "dnum";
-import { type ComponentProps, useMemo } from "react";
+import type { ComponentProps } from "react";
+import { useMemo } from "react";
 import { Button, TooltipTrigger, useLocale } from "react-aria-components";
 
 import Pyth from "./pyth.svg";

+ 2 - 8
apps/staking/src/components/TransferButton/index.tsx

@@ -1,11 +1,5 @@
-import {
-  type ComponentProps,
-  type ReactNode,
-  type FormEvent,
-  useCallback,
-  useMemo,
-  useState,
-} from "react";
+import type { ComponentProps, ReactNode, FormEvent } from "react";
+import { useCallback, useMemo, useState } from "react";
 import {
   DialogTrigger,
   TextField,

+ 2 - 1
apps/staking/src/components/TruncatedKey/index.tsx

@@ -1,5 +1,6 @@
 import type { PublicKey } from "@solana/web3.js";
-import { useMemo, type HTMLAttributes } from "react";
+import type { HTMLAttributes } from "react";
+import { useMemo } from "react";
 
 type Props = Omit<HTMLAttributes<HTMLElement>, "children"> & {
   children: PublicKey | `0x${string}`;

+ 4 - 12
apps/staking/src/components/WalletButton/index.tsx

@@ -14,13 +14,8 @@ import { useWalletModal } from "@solana/wallet-adapter-react-ui";
 import type { PublicKey } from "@solana/web3.js";
 import clsx from "clsx";
 import { useSelectedLayoutSegment } from "next/navigation";
-import {
-  type ComponentProps,
-  type ReactNode,
-  useCallback,
-  useMemo,
-  type ReactElement,
-} from "react";
+import type { ComponentProps, ReactNode, ReactElement } from "react";
+import { useCallback, useMemo } from "react";
 import {
   MenuTrigger,
   SubmenuTrigger,
@@ -30,11 +25,8 @@ import {
 } from "react-aria-components";
 
 import { VPN_BLOCKED_SEGMENT } from "../../config/isomorphic";
-import {
-  StateType as ApiStateType,
-  type States,
-  useApi,
-} from "../../hooks/use-api";
+import type { States } from "../../hooks/use-api";
+import { StateType as ApiStateType, useApi } from "../../hooks/use-api";
 import { StateType as DataStateType, useData } from "../../hooks/use-data";
 import { useLogger } from "../../hooks/use-logger";
 import { useNetwork } from "../../hooks/use-network";

+ 2 - 7
apps/staking/src/components/WalletProvider/index.tsx

@@ -7,18 +7,16 @@ import {
 } from "@solana/wallet-adapter-react";
 import { WalletModalProvider } from "@solana/wallet-adapter-react-ui";
 import {
-  BraveWalletAdapter,
-  BackpackWalletAdapter,
   CoinbaseWalletAdapter,
   PhantomWalletAdapter,
-  GlowWalletAdapter,
   LedgerWalletAdapter,
   SolflareWalletAdapter,
   TorusWalletAdapter,
   WalletConnectWalletAdapter,
 } from "@solana/wallet-adapter-wallets";
 import { clusterApiUrl } from "@solana/web3.js";
-import { type ReactNode, useMemo } from "react";
+import type { ReactNode } from "react";
+import { useMemo } from "react";
 
 import { useNetwork } from "../../hooks/use-network";
 import { metadata } from "../../metadata";
@@ -52,11 +50,8 @@ export const WalletProvider = ({
 
   const wallets = useMemo(
     () => [
-      new BraveWalletAdapter(),
-      new BackpackWalletAdapter(),
       new CoinbaseWalletAdapter(),
       new PhantomWalletAdapter(),
-      new GlowWalletAdapter(),
       new LedgerWalletAdapter(),
       new SolflareWalletAdapter(),
       new TorusWalletAdapter(),

+ 2 - 1
apps/staking/src/hooks/use-api.tsx

@@ -5,7 +5,8 @@ import { PythnetClient, PythStakingClient } from "@pythnetwork/staking-sdk";
 import { useLocalStorageValue } from "@react-hookz/web";
 import { useConnection, useWallet } from "@solana/wallet-adapter-react";
 import { Connection, PublicKey } from "@solana/web3.js";
-import { type ComponentProps, createContext, useContext, useMemo } from "react";
+import type { ComponentProps } from "react";
+import { createContext, useContext, useMemo } from "react";
 import { useSWRConfig } from "swr";
 
 import { StateType as DataStateType, useData } from "./use-data";

+ 2 - 1
apps/staking/src/hooks/use-data.ts

@@ -1,5 +1,6 @@
 import { useCallback } from "react";
-import useSWR, { type KeyedMutator } from "swr";
+import type { KeyedMutator } from "swr";
+import useSWR from "swr";
 
 import { useLogger } from "./use-logger";
 

+ 4 - 2
apps/staking/src/hooks/use-logger.tsx

@@ -1,7 +1,9 @@
 "use client";
 
-import pino, { type Logger } from "pino";
-import { type ComponentProps, createContext, useContext, useMemo } from "react";
+import type { Logger } from "pino";
+import pino from "pino";
+import type { ComponentProps } from "react";
+import { createContext, useContext, useMemo } from "react";
 
 const LoggerContext = createContext<undefined | Logger<string>>(undefined);
 

+ 2 - 7
apps/staking/src/hooks/use-network.tsx

@@ -1,12 +1,7 @@
 "use client";
 
-import {
-  type ComponentProps,
-  createContext,
-  useContext,
-  useState,
-  useCallback,
-} from "react";
+import type { ComponentProps } from "react";
+import { createContext, useContext, useState, useCallback } from "react";
 
 const NetworkContext = createContext<undefined | NetworkContext>(undefined);
 

+ 17 - 23
apps/staking/src/hooks/use-toast.tsx

@@ -1,16 +1,8 @@
 "use client";
 
-import {
-  type ToastState as BaseToastState,
-  useToastState,
-} from "@react-stately/toast";
-import {
-  type ComponentProps,
-  type ReactNode,
-  createContext,
-  useContext,
-  useCallback,
-} from "react";
+import type { ComponentProps, ReactNode } from "react";
+import { createContext, useContext, useCallback, useMemo } from "react";
+import { UNSTABLE_ToastQueue as ToastQueue } from "react-aria-components";
 
 export enum ToastType {
   Success,
@@ -25,7 +17,8 @@ const Toast = {
 };
 export type Toast = ReturnType<(typeof Toast)[keyof typeof Toast]>;
 
-type ToastState = BaseToastState<Toast> & {
+type ToastState = {
+  queue: ToastQueue<Toast>;
   success: (message: ReactNode) => void;
   error: (error: unknown) => void;
 };
@@ -38,23 +31,24 @@ type ToastContextProps = Omit<
 >;
 
 export const ToastProvider = (props: ToastContextProps) => {
-  const toast = useToastState<Toast>({
-    maxVisibleToasts: 3,
-    hasExitAnimation: true,
-  });
+  const queue = useMemo(
+    () =>
+      new ToastQueue<Toast>({
+        maxVisibleToasts: 3,
+      }),
+    [],
+  );
 
   const success = useCallback(
-    (message: ReactNode) => toast.add(Toast.Success(message)),
-    [toast],
+    (message: ReactNode) => queue.add(Toast.Success(message)),
+    [queue],
   );
   const error = useCallback(
-    (error: unknown) => toast.add(Toast.ErrorToast(error)),
-    [toast],
+    (error: unknown) => queue.add(Toast.ErrorToast(error)),
+    [queue],
   );
 
-  return (
-    <ToastContext.Provider value={{ ...toast, success, error }} {...props} />
-  );
+  return <ToastContext.Provider value={{ queue, success, error }} {...props} />;
 };
 
 export const useToast = () => {

+ 4 - 2
apps/staking/src/middleware.ts

@@ -1,6 +1,8 @@
-import { type Geo, geolocation, ipAddress } from "@vercel/functions";
+import type { Geo } from "@vercel/functions";
+import { geolocation, ipAddress } from "@vercel/functions";
 import ipRangeCheck from "ip-range-check";
-import { type NextRequest, NextResponse } from "next/server";
+import type { NextRequest } from "next/server";
+import { NextResponse } from "next/server";
 import ProxyCheck from "proxycheck-ts";
 
 import {

Някои файлове не бяха показани, защото твърде много файлове са промени