Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions src/components/CCIP/Tables/VerifiersTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import Address from "~/components/AddressReact.tsx"
import "./Table.css"
import { Environment, Verifier, getVerifierTypeDisplay } from "~/config/data/ccip/index.ts"

Check warning on line 3 in src/components/CCIP/Tables/VerifiersTable.tsx

View workflow job for this annotation

GitHub Actions / eslint

'Environment' is defined but never used

Check warning on line 3 in src/components/CCIP/Tables/VerifiersTable.tsx

View workflow job for this annotation

GitHub Actions / eslint

'Environment' is defined but never used
import TableSearchInput from "./TableSearchInput.tsx"
import { useState } from "react"
import {
getExplorerAddressUrl,
fallbackVerifierIconUrl,
getChainIcon,
getTitle,
directoryToSupportedChain,
getExplorer,
getChainTypeAndFamily,
} from "~/features/utils/index.ts"

interface VerifiersTableProps {
verifiers: Verifier[]
}

function VerifiersTable({ verifiers }: VerifiersTableProps) {
const [search, setSearch] = useState("")

// Transform verifiers data to include network information
const verifiersWithNetworkInfo = verifiers.map((verifier) => {
const supportedChain = directoryToSupportedChain(verifier.network)
const networkName = getTitle(supportedChain) || verifier.network
const networkLogo = getChainIcon(supportedChain) || ""
const explorer = getExplorer(supportedChain)
const { chainType } = getChainTypeAndFamily(supportedChain)

return {
...verifier,
networkName,
networkLogo,
supportedChain,
explorer,
chainType,
}
})

const filteredVerifiers = verifiersWithNetworkInfo.filter(
(verifier) =>
verifier.name.toLowerCase().includes(search.toLowerCase()) ||
verifier.networkName.toLowerCase().includes(search.toLowerCase()) ||
verifier.address.toLowerCase().includes(search.toLowerCase()) ||
getVerifierTypeDisplay(verifier.type).toLowerCase().includes(search.toLowerCase())
)

return (
<>
<div className="ccip-table__filters">
<div className="ccip-table__filters-title">
Verifiers <span>({verifiers.length})</span>
</div>
<TableSearchInput search={search} setSearch={setSearch} />
</div>
<div className="ccip-table__wrapper">
<table className="ccip-table">
<thead>
<tr>
<th>Verifier</th>
<th>Network</th>
<th>Verifier address</th>
<th>Verifier type</th>
</tr>
</thead>
<tbody>
{filteredVerifiers.map((verifier, index) => (

Check warning on line 68 in src/components/CCIP/Tables/VerifiersTable.tsx

View workflow job for this annotation

GitHub Actions / eslint

'index' is defined but never used

Check warning on line 68 in src/components/CCIP/Tables/VerifiersTable.tsx

View workflow job for this annotation

GitHub Actions / eslint

'index' is defined but never used
<tr key={`${verifier.network}-${verifier.address}`}>
<td>
<div className="ccip-table__network-name">
<span className="ccip-table__logoContainer">
<img
src={verifier.logo}
alt={`${verifier.name} verifier logo`}
className="ccip-table__logo"
onError={({ currentTarget }) => {
currentTarget.onerror = null // prevents looping
currentTarget.src = fallbackVerifierIconUrl
}}
/>
</span>
{verifier.name}
</div>
</td>
<td>
<div className="ccip-table__network-name">
<span className="ccip-table__logoContainer">
<img
src={verifier.networkLogo}
alt={`${verifier.networkName} blockchain logo`}
className="ccip-table__logo"
onError={({ currentTarget }) => {
currentTarget.onerror = null // prevents looping
currentTarget.src = fallbackVerifierIconUrl
}}
/>
</span>
{verifier.networkName}
</div>
</td>
<td data-clipboard-type="verifier-address">
<Address
contractUrl={
verifier.explorer
? getExplorerAddressUrl(verifier.explorer, verifier.chainType)(verifier.address)
: ""
}
address={verifier.address}
endLength={4}
/>
</td>
<td>{getVerifierTypeDisplay(verifier.type)}</td>
</tr>
))}
</tbody>
</table>
<div className="ccip-table__notFound">{filteredVerifiers.length === 0 && <>No verifiers found</>}</div>
</div>
</>
)
}

export default VerifiersTable
6 changes: 3 additions & 3 deletions src/components/CCIP/VerifierGrid/VerifierGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function VerifierGrid({ verifiers, environment }: VerifierGridProps) {
items={verifiers}
initialDisplayCount={BEFORE_SEE_MORE}
seeMoreLabel="View all verifiers"
seeMoreLink="/verifiers"
seeMoreLink={`/ccip/directory/${environment}/verifiers`}
renderItem={(verifier) => {
const subtitle = `${verifier.totalNetworks} ${verifier.totalNetworks === 1 ? "network" : "networks"}`
const logoElement = (
Expand All @@ -34,8 +34,8 @@ function VerifierGrid({ verifiers, environment }: VerifierGridProps) {
logo={logoElement}
title={verifier.name}
subtitle={subtitle}
link={`/ccip/directory/${environment}/verifier/${verifier.id}`}
ariaLabel={`View ${verifier.name} verifier details`}
link={`/ccip/directory/${environment}/verifiers`}
ariaLabel={`View verifiers page for ${verifier.name}`}
/>
)
}}
Expand Down
191 changes: 191 additions & 0 deletions src/components/CCIP/Verifiers/Verifiers.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
---
import CcipDirectoryLayout from "~/layouts/CcipDirectoryLayout.astro"
import { getEntry, render } from "astro:content"
import { getAllNetworks, getAllVerifiers, getSearchLanes, Version, Environment } from "~/config/data/ccip"
import Table from "~/components/CCIP/Tables/VerifiersTable"
import { getAllUniqueVerifiers } from "~/config/data/ccip/data.ts"
import { DOCS_BASE_URL } from "~/utils/structuredData"
import Breadcrumb from "~/components/CCIP/Breadcrumb/Breadcrumb"
import Search from "~/components/CCIP/Search/Search"

interface Props {
environment: Environment
}

const { environment } = Astro.props as Props

const entry = await getEntry("ccip", "index")
if (!entry) {
throw new Error('Could not find "ccip/index" doc. Check src/content/ccip/index.mdx!')
}

const { headings } = await render(entry)

const networks = getAllNetworks({ filter: environment })

const allVerifiers = getAllVerifiers({
environment,
version: Version.V1_2_0,
})

const uniqueVerifiers = getAllUniqueVerifiers({
environment,
version: Version.V1_2_0,
})

const searchLanes = getSearchLanes({ environment })

// Generate dynamic metadata for verifiers page
const environmentText = environment === Environment.Mainnet ? "Mainnet" : "Testnet"
const verifiersMetadata = {
title: `CCIP Verifiers - ${environmentText} Networks`,
description: `View all CCIP verifiers across ${environmentText} networks. Explore ${allVerifiers.length} verifiers, their addresses, types, and supported networks for cross-chain verification.`,
image: "/assets/product-logos/ccip-logo.svg",
excerpt: `CCIP verifiers ${environmentText.toLowerCase()} networks addresses types committee api cross-chain verification blockchain interoperability`,
}

// Generate structured data for verifiers page
const currentPath = new URL(Astro.request.url).pathname
const canonicalForJsonLd = `${DOCS_BASE_URL}${currentPath}`
---

<CcipDirectoryLayout
frontmatter={{
title: verifiersMetadata.title,
section: "ccip",
metadata: {
description: verifiersMetadata.description,
image: verifiersMetadata.image,
excerpt: verifiersMetadata.excerpt,
},
}}
{headings}
environment={environment}
pageTitleOverride={verifiersMetadata.title}
metadataOverride={{
description: verifiersMetadata.description,
image: verifiersMetadata.image,
excerpt: verifiersMetadata.excerpt,
}}
>
<section class="ccip-chain-hero">
<div class="ccip-chain-hero__content">
<div class="ccip-chain-hero__top">
<Breadcrumb
items={[
{
name: "CCIP Directory",
url: `/ccip/directory/${environment}`,
},
{
name: "Verifiers",
url: `/ccip/directory/${environment}/verifiers`,
},
]}
/>
<div class="ccip-chain-hero__chainSearch">
<Search
chains={networks}
tokens={uniqueVerifiers.map((verifier) => ({
id: verifier.id,
totalNetworks: verifier.totalNetworks,
logo: verifier.logo,
}))}
small
environment={environment}
lanes={searchLanes}
client:load
/>
</div>
</div>
</div>
</section>

<section class="layout">
<div>
<Table client:load verifiers={allVerifiers} />
</div>
</section>
</CcipDirectoryLayout>

<style scoped="false">
.ccip-chain-hero {
background: var(--gray-50);
border-bottom: 1px solid var(--gray-200);
}

.ccip-chain-hero__content {
max-width: 1500px;
margin: 0 auto;
padding: var(--space-6x);
}

.ccip-chain-hero__top {
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--space-4x);
}

.ccip-chain-hero__chainSearch {
flex-shrink: 0;
}

@media (max-width: 768px) {
.ccip-chain-hero__top {
flex-direction: column;
align-items: stretch;
gap: var(--space-3x);
}
}

@media (min-width: 992px) {
.ccip-chain-hero__content {
padding: var(--space-10x) var(--space-8x);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that the Docs has mixed usecase, but if possible change this to use the module architecture and move it out of this file.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I used the ChainHero instead by making some lite changes to the component


.layout {
margin: 0 auto;
padding: var(--space-6x);
}

.layout h2 {
color: var(--gray-900);
font-size: 22px;
line-height: var(--space-10x);
padding-bottom: var(--space-4x);
border-bottom: 1px solid var(--gray-200);
margin-bottom: var(--space-6x);
}

.layout h2 span {
color: var(--gray-400);
font-weight: 600;
letter-spacing: 0.5px;
}

.networks__grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-8x);
}

.tokens__grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-8x);
}

@media (min-width: 50em) {
.layout {
max-width: 1500px;
}
}

@media (min-width: 992px) {
.layout {
padding: var(--space-10x) var(--space-8x);
}
}
</style>
8 changes: 8 additions & 0 deletions src/pages/ccip/directory/mainnet/verifiers/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
import Verifiers from "~/components/CCIP/Verifiers/Verifiers.astro"
import { Environment } from "~/config/data/ccip"

export const prerender = true
---

<Verifiers environment={Environment.Mainnet} />
8 changes: 8 additions & 0 deletions src/pages/ccip/directory/testnet/verifiers/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
import Verifiers from "~/components/CCIP/Verifiers/Verifiers.astro"
import { Environment } from "~/config/data/ccip"

export const prerender = true
---

<Verifiers environment={Environment.Testnet} />
Loading