diff --git a/src/components/CCIP/Chain/Chain.astro b/src/components/CCIP/Chain/Chain.astro index 6a424001c00..1c9d760b1e3 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,7 @@ const chainStructuredData = generateChainStructuredData( network={network} environment={environment} lanes={searchLanes} + verifiers={allVerifiers} 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..f65de34c258 100644 --- a/src/components/CCIP/Landing/ccip-landing.astro +++ b/src/components/CCIP/Landing/ccip-landing.astro @@ -72,7 +72,14 @@ const directoryStructuredData = generateDirectoryStructuredData(environment, net }} suppressDefaultStructuredData={true} > - +
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..874fbdc18f2 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,7 @@ const tokenStructuredData = generateTokenStructuredData(token, environment, chai tokens={allTokens} client:load lanes={searchLanes} + verifiers={allVerifiers} 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..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,12 +76,9 @@ const canonicalForJsonLd = `${DOCS_BASE_URL}${currentPath}` > ({ - id: verifier.id, - totalNetworks: verifier.totalNetworks, - logo: verifier.logo, - }))} + tokens={allTokens} lanes={searchLanes} + verifiers={uniqueVerifiers} 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