From 20dc73cb846cd8b35841e1f9aa3cb34c057919e3 Mon Sep 17 00:00:00 2001 From: Mark Shenouda Date: Tue, 16 Dec 2025 17:15:13 +0200 Subject: [PATCH 1/4] feat: add verifiers to the search --- src/components/CCIP/Chain/Chain.astro | 13 ++++ src/components/CCIP/ChainHero/ChainHero.tsx | 27 ++++++++- src/components/CCIP/Hero/Hero.tsx | 11 +++- .../CCIP/Landing/ccip-landing.astro | 15 ++++- src/components/CCIP/Search/Search.tsx | 60 ++++++++++++++++--- src/components/CCIP/Token/Token.astro | 13 ++++ src/components/CCIP/Verifiers/Verifiers.astro | 7 +++ src/workers/data-worker.ts | 20 ++++++- 8 files changed, 151 insertions(+), 15 deletions(-) diff --git a/src/components/CCIP/Chain/Chain.astro b/src/components/CCIP/Chain/Chain.astro index 6a424001c00..8e9a8736755 100644 --- a/src/components/CCIP/Chain/Chain.astro +++ b/src/components/CCIP/Chain/Chain.astro @@ -6,6 +6,7 @@ import { Network, getAllNetworkLanes, getAllNetworks, + getAllUniqueVerifiers, getSearchLanes, getTokensOfChain, Version, @@ -49,6 +50,11 @@ const lanes = await getAllNetworkLanes({ const searchLanes = getSearchLanes({ environment }) +const allVerifiers = getAllUniqueVerifiers({ + environment, + version: Version.V1_2_0, +}) + // Generate dynamic metadata for this specific chain const environmentText = environment === Environment.Mainnet ? "Mainnet" : "Testnet" const logoPath = network.logo || "" @@ -107,6 +113,13 @@ const chainStructuredData = generateChainStructuredData( network={network} environment={environment} lanes={searchLanes} + verifiers={allVerifiers.map((verifier) => ({ + id: verifier.id, + name: verifier.name, + type: verifier.type, + logo: verifier.logo, + totalNetworks: verifier.totalNetworks, + }))} client:load />
diff --git a/src/components/CCIP/ChainHero/ChainHero.tsx b/src/components/CCIP/ChainHero/ChainHero.tsx index 1b0550380ee..bc4b18ab7c6 100644 --- a/src/components/CCIP/ChainHero/ChainHero.tsx +++ b/src/components/CCIP/ChainHero/ChainHero.tsx @@ -46,6 +46,13 @@ interface ChainHeroProps { } lane: LaneConfig }[] + verifiers?: { + id: string + name: string + type: string + logo: string + totalNetworks: number + }[] network?: Network token?: { id: string @@ -60,7 +67,16 @@ interface ChainHeroProps { }> } -function ChainHero({ chains, tokens, network, token, environment, lanes, breadcrumbItems }: ChainHeroProps) { +function ChainHero({ + chains, + tokens, + network, + token, + environment, + lanes, + verifiers = [], + breadcrumbItems, +}: ChainHeroProps) { // Get chain-specific tooltip configuration const chainTooltipConfig = network?.chain ? getChainTooltip(network.chain) : null @@ -119,7 +135,14 @@ function ChainHero({ chains, tokens, network, token, environment, lanes, breadcr } />
- +
diff --git a/src/components/CCIP/Hero/Hero.tsx b/src/components/CCIP/Hero/Hero.tsx index 5f479f22828..2886a4c2a95 100644 --- a/src/components/CCIP/Hero/Hero.tsx +++ b/src/components/CCIP/Hero/Hero.tsx @@ -33,17 +33,24 @@ interface HeroProps { } lane: LaneConfig }[] + verifiers?: { + id: string + name: string + type: string + logo: string + totalNetworks: number + }[] environment: Environment } -function Hero({ chains, tokens, environment, lanes }: HeroProps) { +function Hero({ chains, tokens, environment, lanes, verifiers = [] }: HeroProps) { return (
CCIP Directory - +
) diff --git a/src/components/CCIP/Landing/ccip-landing.astro b/src/components/CCIP/Landing/ccip-landing.astro index 4e101df4cbe..ef30803ca09 100644 --- a/src/components/CCIP/Landing/ccip-landing.astro +++ b/src/components/CCIP/Landing/ccip-landing.astro @@ -72,7 +72,20 @@ const directoryStructuredData = generateDirectoryStructuredData(environment, net }} suppressDefaultStructuredData={true} > - + ({ + id: verifier.id, + name: verifier.name, + type: verifier.type, + logo: verifier.logo, + totalNetworks: verifier.totalNetworks, + }))} + />
diff --git a/src/components/CCIP/Search/Search.tsx b/src/components/CCIP/Search/Search.tsx index b53ab4cdbfc..7d908596af7 100644 --- a/src/components/CCIP/Search/Search.tsx +++ b/src/components/CCIP/Search/Search.tsx @@ -38,11 +38,18 @@ interface SearchProps { } lane: LaneConfig }[] + verifiers?: { + id: string + name: string + type: string + logo: string + totalNetworks: number + }[] small?: boolean environment: Environment } -function Search({ chains, tokens, small, environment, lanes }: SearchProps) { +function Search({ chains, tokens, small, environment, lanes, verifiers = [] }: SearchProps) { const [search, setSearch] = useState("") const [debouncedSearch, setDebouncedSearch] = useState("") const [openSearchMenu, setOpenSearchMenu] = useState(false) @@ -50,6 +57,7 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) { const [networksResults, setNetworksResults] = useState([]) const [tokensResults, setTokensResults] = useState([]) const [lanesResults, setLanesResults] = useState([]) + const [verifiersResults, setVerifiersResults] = useState([]) const searchRef = useRef(null) const workerRef = useRef(null) const workerReadyRef = useRef(false) @@ -59,10 +67,11 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) { if (workerReadyRef.current || typeof window === "undefined") return workerRef.current = new Worker(new URL("~/workers/data-worker.ts", import.meta.url), { type: "module" }) workerRef.current.onmessage = (event: MessageEvent) => { - const { networks, tokens: workerTokens, lanes: workerLanes } = event.data + const { networks, tokens: workerTokens, lanes: workerLanes, verifiers: workerVerifiers } = event.data setNetworksResults(networks || []) setTokensResults(workerTokens || []) setLanesResults(workerLanes || []) + setVerifiersResults(workerVerifiers || []) } workerReadyRef.current = true } @@ -90,6 +99,7 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) { setNetworksResults([]) setTokensResults([]) setLanesResults([]) + setVerifiersResults([]) return } @@ -102,11 +112,12 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) { chains, tokens, lanes, + verifiers, }, } workerRef.current.postMessage(message) } - }, [debouncedSearch, chains, tokens, lanes]) + }, [debouncedSearch, chains, tokens, lanes, verifiers]) // Handle menu visibility useEffect(() => { @@ -146,7 +157,7 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) { Search icon setSearch(e.target.value)} onFocus={() => { @@ -154,7 +165,7 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) { ensureWorker() }} onBlur={() => setIsActive(false)} - aria-label="Search networks, tokens, and lanes" + aria-label="Search networks, tokens, lanes, and verifiers" aria-describedby={openSearchMenu ? "search-results" : undefined} /> {openSearchMenu && ( @@ -167,9 +178,12 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) { aria-live="polite" aria-label="Search results" > - {networksResults.length === 0 && tokensResults.length === 0 && ( - No results found - )} + {networksResults.length === 0 && + tokensResults.length === 0 && + lanesResults.length === 0 && + verifiersResults.length === 0 && ( + No results found + )} {networksResults.length > 0 && ( <> Networks @@ -284,6 +298,36 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) { )} + + {verifiersResults.length > 0 && ( + <> + Verifiers + + + )}
)}
diff --git a/src/components/CCIP/Token/Token.astro b/src/components/CCIP/Token/Token.astro index 7d82846121e..090ddf1e6ba 100644 --- a/src/components/CCIP/Token/Token.astro +++ b/src/components/CCIP/Token/Token.astro @@ -5,6 +5,7 @@ import { getAllNetworks, getAllSupportedTokens, getAllTokenLanes, + getAllUniqueVerifiers, getChainsOfToken, getSearchLanes, getTokenData, @@ -76,6 +77,11 @@ const tokenLanes = getAllTokenLanes({ const searchLanes = getSearchLanes({ environment }) +const allVerifiers = getAllUniqueVerifiers({ + environment, + version: Version.V1_2_0, +}) + // Generate dynamic metadata for this specific token const environmentText = environment === Environment.Mainnet ? "Mainnet" : "Testnet" const tokenMetadata = { @@ -117,6 +123,13 @@ const tokenStructuredData = generateTokenStructuredData(token, environment, chai tokens={allTokens} client:load lanes={searchLanes} + verifiers={allVerifiers.map((verifier) => ({ + id: verifier.id, + name: verifier.name, + type: verifier.type, + logo: verifier.logo, + totalNetworks: verifier.totalNetworks, + }))} token={{ id: token, name: data[firstSupportedChain]?.name || "", diff --git a/src/components/CCIP/Verifiers/Verifiers.astro b/src/components/CCIP/Verifiers/Verifiers.astro index 2672f983332..124737700e2 100644 --- a/src/components/CCIP/Verifiers/Verifiers.astro +++ b/src/components/CCIP/Verifiers/Verifiers.astro @@ -76,6 +76,13 @@ const canonicalForJsonLd = `${DOCS_BASE_URL}${currentPath}` logo: verifier.logo, }))} lanes={searchLanes} + verifiers={uniqueVerifiers.map((verifier) => ({ + id: verifier.id, + name: verifier.name, + type: verifier.type, + logo: verifier.logo, + totalNetworks: verifier.totalNetworks, + }))} environment={environment} breadcrumbItems={[ { diff --git a/src/workers/data-worker.ts b/src/workers/data-worker.ts index ac75689d4ba..db3cf94b45f 100644 --- a/src/workers/data-worker.ts +++ b/src/workers/data-worker.ts @@ -33,6 +33,13 @@ interface SearchData { } lane: LaneConfig }> + verifiers: Array<{ + id: string + name: string + type: string + logo: string + totalNetworks: number + }> } interface WorkerMessage { @@ -44,6 +51,7 @@ interface WorkerResponse { networks: SearchData["chains"] tokens: SearchData["tokens"] lanes: SearchData["lanes"] + verifiers: SearchData["verifiers"] } self.onmessage = (event: MessageEvent) => { @@ -51,7 +59,7 @@ self.onmessage = (event: MessageEvent) => { const { search, data } = event.data if (!search || !data) { - self.postMessage({ networks: [], tokens: [], lanes: [] } as WorkerResponse) + self.postMessage({ networks: [], tokens: [], lanes: [], verifiers: [] } as WorkerResponse) return } @@ -74,7 +82,15 @@ self.onmessage = (event: MessageEvent) => { return matchesNetwork && hasTokens }) - self.postMessage({ networks, tokens, lanes } as WorkerResponse) + // Filter verifiers + const verifiers = data.verifiers.filter( + (verifier) => + verifier.name.toLowerCase().includes(searchLower) || + verifier.id.toLowerCase().includes(searchLower) || + verifier.type.toLowerCase().includes(searchLower) + ) + + self.postMessage({ networks, tokens, lanes, verifiers } as WorkerResponse) } // Export types for use in main thread From 6235ce74d721cdd688e5bf699d660c8f78795d11 Mon Sep 17 00:00:00 2001 From: Mark Shenouda Date: Wed, 17 Dec 2025 16:19:20 +0200 Subject: [PATCH 2/4] refactor: simplify verifiers mapping in Chain component --- src/components/CCIP/Chain/Chain.astro | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/components/CCIP/Chain/Chain.astro b/src/components/CCIP/Chain/Chain.astro index 8e9a8736755..1c9d760b1e3 100644 --- a/src/components/CCIP/Chain/Chain.astro +++ b/src/components/CCIP/Chain/Chain.astro @@ -113,13 +113,7 @@ const chainStructuredData = generateChainStructuredData( network={network} environment={environment} lanes={searchLanes} - verifiers={allVerifiers.map((verifier) => ({ - id: verifier.id, - name: verifier.name, - type: verifier.type, - logo: verifier.logo, - totalNetworks: verifier.totalNetworks, - }))} + verifiers={allVerifiers} client:load />
From 6f302f0fe22cf1724e57c921dc82f7e6252abb3d Mon Sep 17 00:00:00 2001 From: Mark Shenouda Date: Fri, 19 Dec 2025 10:08:38 +0200 Subject: [PATCH 3/4] refactor: simplify verifiers mapping in CCIP components --- src/components/CCIP/Landing/ccip-landing.astro | 8 +------- src/components/CCIP/Token/Token.astro | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/components/CCIP/Landing/ccip-landing.astro b/src/components/CCIP/Landing/ccip-landing.astro index ef30803ca09..f65de34c258 100644 --- a/src/components/CCIP/Landing/ccip-landing.astro +++ b/src/components/CCIP/Landing/ccip-landing.astro @@ -78,13 +78,7 @@ const directoryStructuredData = generateDirectoryStructuredData(environment, net environment={environment} client:visible lanes={searchLanes} - verifiers={allVerifiers.map((verifier) => ({ - id: verifier.id, - name: verifier.name, - type: verifier.type, - logo: verifier.logo, - totalNetworks: verifier.totalNetworks, - }))} + verifiers={allVerifiers} />
diff --git a/src/components/CCIP/Token/Token.astro b/src/components/CCIP/Token/Token.astro index 090ddf1e6ba..874fbdc18f2 100644 --- a/src/components/CCIP/Token/Token.astro +++ b/src/components/CCIP/Token/Token.astro @@ -123,13 +123,7 @@ const tokenStructuredData = generateTokenStructuredData(token, environment, chai tokens={allTokens} client:load lanes={searchLanes} - verifiers={allVerifiers.map((verifier) => ({ - id: verifier.id, - name: verifier.name, - type: verifier.type, - logo: verifier.logo, - totalNetworks: verifier.totalNetworks, - }))} + verifiers={allVerifiers} token={{ id: token, name: data[firstSupportedChain]?.name || "", From 25285bef8f8eb692c3f1bd2896667eceb4e79bba Mon Sep 17 00:00:00 2001 From: Mark Shenouda Date: Fri, 19 Dec 2025 10:13:47 +0200 Subject: [PATCH 4/4] refactor: optimize token mapping for verifiers in CCIP components --- src/components/CCIP/Verifiers/Verifiers.astro | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/components/CCIP/Verifiers/Verifiers.astro b/src/components/CCIP/Verifiers/Verifiers.astro index 124737700e2..79cdc2dc916 100644 --- a/src/components/CCIP/Verifiers/Verifiers.astro +++ b/src/components/CCIP/Verifiers/Verifiers.astro @@ -35,6 +35,12 @@ const uniqueVerifiers = getAllUniqueVerifiers({ const searchLanes = getSearchLanes({ environment }) +const allTokens = uniqueVerifiers.map((verifier) => ({ + id: verifier.id, + totalNetworks: verifier.totalNetworks, + logo: verifier.logo, +})) + // Generate dynamic metadata for verifiers page const environmentText = environment === Environment.Mainnet ? "Mainnet" : "Testnet" const verifiersMetadata = { @@ -70,19 +76,9 @@ const canonicalForJsonLd = `${DOCS_BASE_URL}${currentPath}` > ({ - id: verifier.id, - totalNetworks: verifier.totalNetworks, - logo: verifier.logo, - }))} + tokens={allTokens} lanes={searchLanes} - verifiers={uniqueVerifiers.map((verifier) => ({ - id: verifier.id, - name: verifier.name, - type: verifier.type, - logo: verifier.logo, - totalNetworks: verifier.totalNetworks, - }))} + verifiers={uniqueVerifiers} environment={environment} breadcrumbItems={[ {