From ce86bced142621e4406d0dd3fcb89bed3afccb1d Mon Sep 17 00:00:00 2001 From: Connor Prussin Date: Wed, 7 May 2025 22:17:50 -0700 Subject: [PATCH] feat(entropy-explorer): add initial build of entropy explorer This is an initial build of the new Entropy Explorer app, to replace the old Entropy Debugger app. It's mostly ready, with the following exceptions: 1. The data is currently mock data, and will need to be replaced with live APIs. 2. We should add some error payload parsing to the details drawer. 3. Not all chains are currently added (Viem doesn't have chain metadata for all the chains we support and I want to get this merged and the UI figured out before I worry about ensuring the chain metadata is correct) --- apps/entropy-explorer/.gitignore | 1 + apps/entropy-explorer/.prettierignore | 7 + apps/entropy-explorer/eslint.config.js | 1 + apps/entropy-explorer/jest.config.js | 1 + apps/entropy-explorer/next-env.d.ts | 5 + apps/entropy-explorer/next.config.js | 54 ++ apps/entropy-explorer/package.json | 57 +++ apps/entropy-explorer/prettier.config.js | 1 + .../public/android-chrome-192x192.png | Bin 0 -> 3420 bytes .../public/android-chrome-512x512.png | Bin 0 -> 8471 bytes .../public/apple-touch-icon.png | Bin 0 -> 3293 bytes .../entropy-explorer/public/favicon-16x16.png | Bin 0 -> 965 bytes .../entropy-explorer/public/favicon-32x32.png | Bin 0 -> 1453 bytes .../entropy-explorer/public/favicon-light.ico | Bin 0 -> 15086 bytes apps/entropy-explorer/public/favicon.ico | Bin 0 -> 15086 bytes apps/entropy-explorer/src/app/error.ts | 3 + .../entropy-explorer/src/app/global-error.tsx | 16 + apps/entropy-explorer/src/app/layout.ts | 2 + apps/entropy-explorer/src/app/manifest.ts | 25 + apps/entropy-explorer/src/app/not-found.ts | 1 + apps/entropy-explorer/src/app/page.ts | 1 + apps/entropy-explorer/src/app/robots.ts | 11 + .../components/Home/chain-select.module.scss | 15 + .../src/components/Home/chain-select.tsx | 107 ++++ .../src/components/Home/index.module.scss | 30 ++ .../src/components/Home/index.tsx | 27 + .../src/components/Home/results.module.scss | 75 +++ .../src/components/Home/results.tsx | 420 ++++++++++++++++ .../src/components/Home/search-bar.tsx | 37 ++ .../src/components/Home/use-query.ts | 48 ++ .../src/components/Root/evm-provider.tsx | 21 + .../src/components/Root/index.tsx | 30 ++ .../entropy-explorer/src/config/isomorphic.ts | 13 + apps/entropy-explorer/src/config/server.ts | 30 ++ .../src/entropy-deployments.ts | 471 ++++++++++++++++++ .../src/get-requests-for-chain.ts | 71 +++ apps/entropy-explorer/src/metadata.ts | 52 ++ apps/entropy-explorer/src/type-utils.ts | 4 + apps/entropy-explorer/stylelint.config.js | 21 + apps/entropy-explorer/svg.d.ts | 6 + apps/entropy-explorer/tsconfig.json | 5 + apps/entropy-explorer/turbo.json | 41 ++ apps/entropy-explorer/vercel.json | 5 + apps/insights/src/app/error.ts | 2 +- apps/insights/src/app/global-error.tsx | 7 +- apps/insights/src/app/not-found.ts | 2 +- .../src/app/price-feeds/[slug]/error.ts | 2 +- .../app/publishers/[cluster]/[key]/error.ts | 2 +- .../insights/src/components/FeedKey/index.tsx | 2 +- .../PriceComponentDrawer/index.module.scss | 2 +- .../components/PriceComponentDrawer/index.tsx | 4 +- .../components/PriceComponentsCard/index.tsx | 16 +- .../PriceFeedChangePercent/index.tsx | 2 +- .../PriceFeeds/coming-soon-list.tsx | 11 +- .../PriceFeeds/price-feeds-card.tsx | 15 +- .../src/components/Publisher/layout.tsx | 2 +- .../src/components/Publisher/performance.tsx | 6 +- .../components/Publisher/top-feeds-table.tsx | 2 +- .../src/components/PublisherKey/index.tsx | 3 +- .../components/Publishers/publishers-card.tsx | 6 +- .../components/Root/search-button.module.scss | 4 +- .../src/components/Root/search-button.tsx | 2 +- packages/component-library/package.json | 4 +- .../src/AppShell/index.module.scss | 4 + .../component-library/src/AppShell/index.tsx | 2 +- .../src/Badge/index.module.scss | 9 +- .../src/Button/index.module.scss | 14 +- .../component-library/src/Button/index.tsx | 12 +- .../src}/CopyButton/index.module.scss | 10 +- .../src}/CopyButton/index.tsx | 4 +- .../src}/EntityList/index.module.scss | 2 + .../src}/EntityList/index.tsx | 4 +- .../src/ErrorPage}/index.module.scss | 2 +- .../src/ErrorPage}/index.tsx | 4 +- .../component-library/src/Footer/index.tsx | 5 +- .../src/Header/index.module.scss | 2 +- .../src/Header/theme-switch.tsx | 4 +- .../src}/Meter/index.module.scss | 11 + .../component-library/src}/Meter/index.tsx | 17 +- .../src/MobileNavTabs/index.tsx | 2 +- .../src}/NoResults/index.module.scss | 0 .../src}/NoResults/index.tsx | 12 +- .../src/NotFoundPage}/index.module.scss | 2 +- .../src/NotFoundPage}/index.tsx | 4 +- .../component-library/src/Paginator/index.tsx | 4 +- .../src/Select/index.module.scss | 32 +- .../src/Select/index.stories.tsx | 17 +- .../component-library/src/Select/index.tsx | 138 +++-- .../src/Status/index.module.scss | 27 +- .../component-library/src/useData/index.ts | 10 +- .../src/useDrawer/index.module.scss | 2 +- .../component-library/src/useDrawer/index.tsx | 124 ++--- pnpm-lock.yaml | 100 ++++ 93 files changed, 2158 insertions(+), 233 deletions(-) create mode 100644 apps/entropy-explorer/.gitignore create mode 100644 apps/entropy-explorer/.prettierignore create mode 100644 apps/entropy-explorer/eslint.config.js create mode 100644 apps/entropy-explorer/jest.config.js create mode 100644 apps/entropy-explorer/next-env.d.ts create mode 100644 apps/entropy-explorer/next.config.js create mode 100644 apps/entropy-explorer/package.json create mode 100644 apps/entropy-explorer/prettier.config.js create mode 100644 apps/entropy-explorer/public/android-chrome-192x192.png create mode 100644 apps/entropy-explorer/public/android-chrome-512x512.png create mode 100644 apps/entropy-explorer/public/apple-touch-icon.png create mode 100644 apps/entropy-explorer/public/favicon-16x16.png create mode 100644 apps/entropy-explorer/public/favicon-32x32.png create mode 100644 apps/entropy-explorer/public/favicon-light.ico create mode 100644 apps/entropy-explorer/public/favicon.ico create mode 100644 apps/entropy-explorer/src/app/error.ts create mode 100644 apps/entropy-explorer/src/app/global-error.tsx create mode 100644 apps/entropy-explorer/src/app/layout.ts create mode 100644 apps/entropy-explorer/src/app/manifest.ts create mode 100644 apps/entropy-explorer/src/app/not-found.ts create mode 100644 apps/entropy-explorer/src/app/page.ts create mode 100644 apps/entropy-explorer/src/app/robots.ts create mode 100644 apps/entropy-explorer/src/components/Home/chain-select.module.scss create mode 100644 apps/entropy-explorer/src/components/Home/chain-select.tsx create mode 100644 apps/entropy-explorer/src/components/Home/index.module.scss create mode 100644 apps/entropy-explorer/src/components/Home/index.tsx create mode 100644 apps/entropy-explorer/src/components/Home/results.module.scss create mode 100644 apps/entropy-explorer/src/components/Home/results.tsx create mode 100644 apps/entropy-explorer/src/components/Home/search-bar.tsx create mode 100644 apps/entropy-explorer/src/components/Home/use-query.ts create mode 100644 apps/entropy-explorer/src/components/Root/evm-provider.tsx create mode 100644 apps/entropy-explorer/src/components/Root/index.tsx create mode 100644 apps/entropy-explorer/src/config/isomorphic.ts create mode 100644 apps/entropy-explorer/src/config/server.ts create mode 100644 apps/entropy-explorer/src/entropy-deployments.ts create mode 100644 apps/entropy-explorer/src/get-requests-for-chain.ts create mode 100644 apps/entropy-explorer/src/metadata.ts create mode 100644 apps/entropy-explorer/src/type-utils.ts create mode 100644 apps/entropy-explorer/stylelint.config.js create mode 100644 apps/entropy-explorer/svg.d.ts create mode 100644 apps/entropy-explorer/tsconfig.json create mode 100644 apps/entropy-explorer/turbo.json create mode 100644 apps/entropy-explorer/vercel.json rename {apps/insights/src/components => packages/component-library/src}/CopyButton/index.module.scss (91%) rename {apps/insights/src/components => packages/component-library/src}/CopyButton/index.tsx (92%) rename {apps/insights/src/components => packages/component-library/src}/EntityList/index.module.scss (96%) rename {apps/insights/src/components => packages/component-library/src}/EntityList/index.tsx (95%) rename {apps/insights/src/components/Error => packages/component-library/src/ErrorPage}/index.module.scss (99%) rename {apps/insights/src/components/Error => packages/component-library/src/ErrorPage}/index.tsx (90%) rename {apps/insights/src/components => packages/component-library/src}/Meter/index.module.scss (80%) rename {apps/insights/src/components => packages/component-library/src}/Meter/index.tsx (68%) rename {apps/insights/src/components => packages/component-library/src}/NoResults/index.module.scss (100%) rename {apps/insights/src/components => packages/component-library/src}/NoResults/index.tsx (79%) rename {apps/insights/src/components/NotFound => packages/component-library/src/NotFoundPage}/index.module.scss (98%) rename {apps/insights/src/components/NotFound => packages/component-library/src/NotFoundPage}/index.tsx (87%) rename apps/insights/src/hooks/use-data.ts => packages/component-library/src/useData/index.ts (83%) diff --git a/apps/entropy-explorer/.gitignore b/apps/entropy-explorer/.gitignore new file mode 100644 index 0000000000..9d2ee2a739 --- /dev/null +++ b/apps/entropy-explorer/.gitignore @@ -0,0 +1 @@ +.env*.local diff --git a/apps/entropy-explorer/.prettierignore b/apps/entropy-explorer/.prettierignore new file mode 100644 index 0000000000..5f66a649b5 --- /dev/null +++ b/apps/entropy-explorer/.prettierignore @@ -0,0 +1,7 @@ +.next/ +coverage/ +node_modules/ +*.tsbuildinfo +.env*.local +.env +.DS_Store diff --git a/apps/entropy-explorer/eslint.config.js b/apps/entropy-explorer/eslint.config.js new file mode 100644 index 0000000000..7035c57cb4 --- /dev/null +++ b/apps/entropy-explorer/eslint.config.js @@ -0,0 +1 @@ +export { nextjs as default } from "@cprussin/eslint-config"; diff --git a/apps/entropy-explorer/jest.config.js b/apps/entropy-explorer/jest.config.js new file mode 100644 index 0000000000..0bac66ed0e --- /dev/null +++ b/apps/entropy-explorer/jest.config.js @@ -0,0 +1 @@ +export { nextjs as default } from "@cprussin/jest-config/next"; diff --git a/apps/entropy-explorer/next-env.d.ts b/apps/entropy-explorer/next-env.d.ts new file mode 100644 index 0000000000..1b3be0840f --- /dev/null +++ b/apps/entropy-explorer/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/entropy-explorer/next.config.js b/apps/entropy-explorer/next.config.js new file mode 100644 index 0000000000..58ecfdcf9e --- /dev/null +++ b/apps/entropy-explorer/next.config.js @@ -0,0 +1,54 @@ +const config = { + reactStrictMode: true, + + pageExtensions: ["ts", "tsx", "mdx"], + + logging: { + fetches: { + fullUrl: true, + }, + }, + + webpack(config) { + config.module.rules.push({ + test: /\.svg$/i, + use: ["@svgr/webpack"], + }); + + config.resolve.extensionAlias = { + ".js": [".js", ".ts", ".tsx"], + }; + + return config; + }, + + headers: async () => [ + { + source: "/:path*", + headers: [ + { + key: "X-XSS-Protection", + value: "1; mode=block", + }, + { + key: "Referrer-Policy", + value: "strict-origin-when-cross-origin", + }, + { + key: "Strict-Transport-Security", + value: "max-age=2592000", + }, + { + key: "X-Content-Type-Options", + value: "nosniff", + }, + { + key: "Permissions-Policy", + value: + "vibrate=(), geolocation=(), midi=(), notifications=(), push=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), speaker=(), vibrate=(), fullscreen=self", + }, + ], + }, + ], +}; +export default config; diff --git a/apps/entropy-explorer/package.json b/apps/entropy-explorer/package.json new file mode 100644 index 0000000000..f96d2064eb --- /dev/null +++ b/apps/entropy-explorer/package.json @@ -0,0 +1,57 @@ +{ + "name": "@pythnetwork/entropy-explorer", + "version": "0.0.0", + "private": true, + "type": "module", + "engines": { + "node": "22" + }, + "scripts": { + "build:vercel": "next build", + "fix:format": "prettier --write .", + "fix:lint:eslint": "eslint --fix .", + "fix:lint:stylelint": "stylelint --fix 'src/**/*.scss'", + "pull:env": "[ $CI ] || VERCEL_ORG_ID=team_BKQrg3JJFLxZyTqpuYtIY0rj VERCEL_PROJECT_ID=prj_TBkf9EyQjQF37gs4Vk0sQKJj97kE vercel env pull", + "start:dev": "next dev --port 3006", + "start:prod": "next start --port 3006", + "test:format": "prettier --check .", + "test:lint:eslint": "eslint . --max-warnings 0", + "test:lint:stylelint": "stylelint 'src/**/*.scss' --max-warnings 0", + "test:types": "tsc" + }, + "dependencies": { + "@phosphor-icons/react": "catalog:", + "@pythnetwork/component-library": "workspace:*", + "clsx": "catalog:", + "connectkit": "catalog:", + "next": "catalog:", + "nuqs": "catalog:", + "react": "catalog:", + "react-aria": "catalog:", + "react-dom": "catalog:", + "viem": "catalog:", + "wagmi": "catalog:", + "zod": "catalog:" + }, + "devDependencies": { + "@cprussin/eslint-config": "catalog:", + "@cprussin/jest-config": "catalog:", + "@cprussin/prettier-config": "catalog:", + "@cprussin/tsconfig": "catalog:", + "@svgr/webpack": "catalog:", + "@types/jest": "catalog:", + "@types/node": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "autoprefixer": "catalog:", + "eslint": "catalog:", + "jest": "catalog:", + "postcss": "catalog:", + "prettier": "catalog:", + "sass": "catalog:", + "stylelint": "catalog:", + "stylelint-config-standard-scss": "catalog:", + "typescript": "catalog:", + "vercel": "catalog:" + } +} diff --git a/apps/entropy-explorer/prettier.config.js b/apps/entropy-explorer/prettier.config.js new file mode 100644 index 0000000000..1e43aeeddb --- /dev/null +++ b/apps/entropy-explorer/prettier.config.js @@ -0,0 +1 @@ +export { base as default } from "@cprussin/prettier-config"; diff --git a/apps/entropy-explorer/public/android-chrome-192x192.png b/apps/entropy-explorer/public/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..596667cefb00ef348c8ddf7ae5a67dc907e0a0f9 GIT binary patch literal 3420 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 QdL031sOTuyC|Za72NpGk#{d8T literal 0 HcmV?d00001 diff --git a/apps/entropy-explorer/public/android-chrome-512x512.png b/apps/entropy-explorer/public/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..cf0ba050d8fb45921a76df0748c7d36873e00505 GIT binary patch literal 8471 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 KuM{=@`hNhask34L literal 0 HcmV?d00001 diff --git a/apps/entropy-explorer/public/apple-touch-icon.png b/apps/entropy-explorer/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1f9a443c8aeca50a234f03e4a6c31353fb856300 GIT binary patch literal 3293 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 GBmNI`raiO( literal 0 HcmV?d00001 diff --git a/apps/entropy-explorer/public/favicon-16x16.png b/apps/entropy-explorer/public/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..85b3a417a78950f44132b3e1fa05626cdffecca8 GIT binary patch literal 965 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>`T@Ck7RDtLD5-zdTw z0{{R2w+Os72^dE4B|(0`@K))$|JU)tk5lvK8Qy*n!^^hpohNtJ4!t)sS=)YI5C0Xc z^lXE~dgU}b%Wrw*U(Hg|zuQ`yo{)+Q$PmBwF_m-O<4nF1`#vTvjm}R8Wev^>Z+p8& zRdMljKOV-**{=S%d#iTW;4YHDIyQc6k!!^fL9EG>5Ku(Z5!(?O}H$7WB>AEu@zrav`%Y#apL z92FA<0}Trc4Fd%e6&)8ev@DsjrDx5YIcs{hOj*Jb;1K5+=o#r68tNMv8|WyfvEbms zl}pziKCxo;^7F?M8AJ?BjLZy$l1)q>n{J=5wS_Yx^7f5eH?1v<4zkRd6C1;NwCBzp z$25m66%|#Lzkf8zJbV70D@0I0;)tLOQ{l?Y6@~!{IyOo|&&1ur7l^&oFyQBrxVku5 zz-Gg&8x}xcS09r4J+b9!H_(5oC9V-ADTyViR>?)FK#IZ0z{p6~&_LJFB*ehP%EZXZ z)I!_9z{nC}Q!>*kacju>t&|4T5MC7$Q4*9`u24{vpO%@Es!&o{kgAYb zP?F5RP%-E6CmxQ%Fb$1U{-@7)J`G}ER_4}A<`z~K_MR-lEUe(tU~)KxS$T7a!s#1V nP8>ONMCJ(l=?0GlUV03##05(}IhjrcTEXDy>gTe~DWM4fL9_D> literal 0 HcmV?d00001 diff --git a/apps/entropy-explorer/public/favicon-32x32.png b/apps/entropy-explorer/public/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..034afe45c1e6c2e71ea30e9a88b26249e260f3d9 GIT binary patch literal 1453 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+081LNiZpAc7|f@in>J-hV_ zOad9BXi$g1|NsAc4efh@(biuQp1!W^&$#$lw5&KzG`t2% z|MYZm46!)fdO6eimV*FW!o4a1-OwoulstOe7BMMlv99XqTCw!owOiiRx1y@=m#^LX z{=0rTb0gbAtNUh^W}7z~Z@hViAuH?ktGAO<)~{c^mNCbgiMRK+tjXcR1sfN}F!-MR zdHvipvGjQ+=8^VHTXv}gm2KZzUb1ET&eWiytx+sCbCafDzn*Ht{Ksy6MA z)mK1vp_Nup|H@XatA_RltBO>*oZ4m_X)aVyr7}bK4$x*ZvyuL8_Vfu zn~yGjV)($K^3f7TrR6JrHC%pjsYsMz&cw`k#&eUNPw`sdem-77f1T2Hw>T%&9dAUZ z7e3W0ID7E*>(*)wX7jvB(sryjqnA`~=GsyFJg>-=@!j3!Ul>9izCBdFsGTA=*?-=w zwKoEn8O}X#=5qd8Ag@EDpKZOO+o^w>O!(HvdH+A~Z1(o|+g#l5A8$I^c#Hk~wqFOM zSa)vy61ef)8uc$HndU_O`aJ!UJagVEHw_<5frWYr`4jpjc-7V|&2`RrDn zLr47na#k~ze`~^;_J?zUO_QmvAUQh^kMk%5tsuAzahp-G5= ziIs_wm8pfcfq|8Qf%LLjw@@_X=BH$)RpQo=^;;Rr~FT!@q8M@z^u%zm&`4!EbKj5gjra@rNQKI3bXR& s5QWn>uADe>=7`J@_R|d>3%v9gUWp5qd~!0K3bca3)78&qol`;+008wU@Bjb+ literal 0 HcmV?d00001 diff --git a/apps/entropy-explorer/public/favicon-light.ico b/apps/entropy-explorer/public/favicon-light.ico new file mode 100644 index 0000000000000000000000000000000000000000..9c0d28fbda20eac2cd2e025db68d151dfb954673 GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/apps/entropy-explorer/public/favicon.ico b/apps/entropy-explorer/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..56072a486055f0cb90acbd9b72358be0677d0245 GIT binary patch literal 15086 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 qpgYS}@pfZXAFKmTqpPlmRay2J) => ( + + + + + + + +); +export default GlobalError; diff --git a/apps/entropy-explorer/src/app/layout.ts b/apps/entropy-explorer/src/app/layout.ts new file mode 100644 index 0000000000..47f8c23fd1 --- /dev/null +++ b/apps/entropy-explorer/src/app/layout.ts @@ -0,0 +1,2 @@ +export { Root as default } from "../components/Root"; +export { metadata, viewport } from "../metadata"; diff --git a/apps/entropy-explorer/src/app/manifest.ts b/apps/entropy-explorer/src/app/manifest.ts new file mode 100644 index 0000000000..fa9e6f5ab9 --- /dev/null +++ b/apps/entropy-explorer/src/app/manifest.ts @@ -0,0 +1,25 @@ +import type { MetadataRoute } from "next"; + +import { metadata, viewport } from "../metadata"; + +const manifest = (): MetadataRoute.Manifest => ({ + name: metadata.applicationName, + short_name: metadata.applicationName, + description: metadata.description, + theme_color: viewport.themeColor, + background_color: viewport.themeColor, + icons: [ + { + src: "/android-chrome-192x192.png", + sizes: "192x192", + type: "image/png", + }, + { + src: "/android-chrome-512x512.png", + sizes: "512x512", + type: "image/png", + }, + ], + display: "standalone", +}); +export default manifest; diff --git a/apps/entropy-explorer/src/app/not-found.ts b/apps/entropy-explorer/src/app/not-found.ts new file mode 100644 index 0000000000..3053e90df1 --- /dev/null +++ b/apps/entropy-explorer/src/app/not-found.ts @@ -0,0 +1 @@ +export { NotFoundPage as default } from "@pythnetwork/component-library/NotFoundPage"; diff --git a/apps/entropy-explorer/src/app/page.ts b/apps/entropy-explorer/src/app/page.ts new file mode 100644 index 0000000000..b84f5687c5 --- /dev/null +++ b/apps/entropy-explorer/src/app/page.ts @@ -0,0 +1 @@ +export { Home as default } from "../components/Home"; diff --git a/apps/entropy-explorer/src/app/robots.ts b/apps/entropy-explorer/src/app/robots.ts new file mode 100644 index 0000000000..28eaa31c59 --- /dev/null +++ b/apps/entropy-explorer/src/app/robots.ts @@ -0,0 +1,11 @@ +import type { MetadataRoute } from "next"; + +import { IS_PRODUCTION_SERVER } from "../config/server"; + +const robots = (): MetadataRoute.Robots => ({ + rules: { + userAgent: "*", + ...(IS_PRODUCTION_SERVER ? { allow: "/" } : { disallow: "/" }), + }, +}); +export default robots; diff --git a/apps/entropy-explorer/src/components/Home/chain-select.module.scss b/apps/entropy-explorer/src/components/Home/chain-select.module.scss new file mode 100644 index 0000000000..a51fda260c --- /dev/null +++ b/apps/entropy-explorer/src/components/Home/chain-select.module.scss @@ -0,0 +1,15 @@ +@use "@pythnetwork/component-library/theme"; + +.searchBar { + display: grid; + grid-template-columns: max-content 1fr; + gap: theme.spacing(2); + width: 100%; +} + +.chainSelectItem { + display: grid; + grid-template-columns: max-content 1fr; + gap: theme.spacing(2); + align-items: center; +} diff --git a/apps/entropy-explorer/src/components/Home/chain-select.tsx b/apps/entropy-explorer/src/components/Home/chain-select.tsx new file mode 100644 index 0000000000..4ac63d4f98 --- /dev/null +++ b/apps/entropy-explorer/src/components/Home/chain-select.tsx @@ -0,0 +1,107 @@ +"use client"; + +import type { Props as SelectProps } from "@pythnetwork/component-library/Select"; +import { Select } from "@pythnetwork/component-library/Select"; +import { ChainIcon } from "connectkit"; +import type { ComponentProps } from "react"; +import { Suspense, useCallback, useMemo } from "react"; +import { useCollator } from "react-aria"; +import * as viemChains from "viem/chains"; + +import styles from "./chain-select.module.scss"; +import { useQuery } from "./use-query"; +import { EntropyDeployments } from "../../entropy-deployments"; +import type { ConstrainedOmit } from "../../type-utils"; + +export const ChainSelect = ( + props: ComponentProps, +) => ( + + } + > + + +); + +type Deployment = ReturnType[number]; + +const ResolvedChainSelect = ( + props: ConstrainedOmit< + SelectProps, + keyof typeof defaultProps | keyof ReturnType + >, +) => { + const resolvedProps = useResolvedProps(); + + return ({ id })), + }, ]} hideGroupLabel - show={(value) => (value === "" ? "All" : value)} + show={({ id }) => (id === "" ? "All" : id)} placement="bottom end" selectedKey={assetClass} onSelectionChange={setAssetClass} diff --git a/apps/insights/src/components/PriceFeeds/price-feeds-card.tsx b/apps/insights/src/components/PriceFeeds/price-feeds-card.tsx index 53aa45bd20..755450e197 100644 --- a/apps/insights/src/components/PriceFeeds/price-feeds-card.tsx +++ b/apps/insights/src/components/PriceFeeds/price-feeds-card.tsx @@ -3,6 +3,8 @@ import { ChartLine } from "@phosphor-icons/react/dist/ssr/ChartLine"; import { Badge } from "@pythnetwork/component-library/Badge"; import { Card } from "@pythnetwork/component-library/Card"; +import { EntityList } from "@pythnetwork/component-library/EntityList"; +import { NoResults } from "@pythnetwork/component-library/NoResults"; import { Paginator } from "@pythnetwork/component-library/Paginator"; import { SearchInput } from "@pythnetwork/component-library/SearchInput"; import { Select } from "@pythnetwork/component-library/Select"; @@ -21,7 +23,6 @@ import styles from "./price-feeds-card.module.scss"; import { useQueryParamFilterPagination } from "../../hooks/use-query-param-filter-pagination"; import { Cluster } from "../../services/pyth"; import { AssetClassBadge } from "../AssetClassBadge"; -import { EntityList } from "../EntityList"; import { FeedKey } from "../FeedKey"; import { SKELETON_WIDTH, @@ -29,7 +30,6 @@ import { LiveConfidence, LiveValue, } from "../LivePrices"; -import { NoResults } from "../NoResults"; import { PriceFeedTag } from "../PriceFeedTag"; import { PriceName } from "../PriceName"; @@ -249,7 +249,7 @@ const PriceFeedsCardContents = ({ id, ...props }: PriceFeedsCardContents) => ( onChange: props.onSearchChange, })} /> - +