Skip to content
Merged
Changes from all 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
108 changes: 96 additions & 12 deletions src/components/CCIP/Landing/ccip-landing.astro
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { getTokenIconUrl } from "~/features/utils"
import LazyNetworkGrid from "./LazyNetworkGrid"
import LazyTokenGrid from "../TokenGrid/LazyTokenGrid"
import LazyVerifierGrid from "../VerifierGrid/LazyVerifierGrid"
import StructuredData from "~/components/StructuredData.astro"
import { generateDirectoryStructuredData } from "~/utils/ccipStructuredData"
import { DOCS_BASE_URL } from "~/utils/structuredData"
import AddButton from "~/components/CCIP/AddButton/AddButton.astro"
Expand All @@ -25,37 +24,119 @@ export type Props = {
}
const { environment } = Astro.props as Props

const entry = await getEntry("ccip", "index")
if (!entry) {
throw new Error('No "ccip/index" doc found! Please make sure it exists in src/content/ccip/index.mdx or .md.')
// ----------------------
// Featured ranking (exact canonical names)
// ----------------------

const FEATURED_NETWORK_RANK: Record<string, number> = {
Ethereum: 1,
Plasma: 2,
Solana: 3,
"BNB Chain": 4,
Base: 5,
"Arbitrum One": 6,
Avalanche: 7,
Monad: 8,
}

const FEATURED_TOKEN_RANK: Record<string, number> = {
LINK: 1,
USDC: 2,
USDT: 3,
WETH: 4,
syrupUSDC: 5,
syrupUSDT: 6,
GHO: 7,
cbBTC: 8,
}

// ----------------------

const entry = await getEntry("ccip", "index")
if (!entry) throw new Error('No "ccip/index" doc found!')

const { headings } = await render(entry)

const networks = getAllNetworks({ filter: environment })
// ----------------------
// Networks (exact match)
// ----------------------

const networksRaw = getAllNetworks({ filter: environment })

const networks = networksRaw.map((n) => ({
...n,
featuredRank: FEATURED_NETWORK_RANK[n.name],
}))

const featuredNetworkCount = networks.filter((n) => n.featuredRank !== undefined).length
if (featuredNetworkCount !== 8) {
console.warn(`Expected 8 featured networks, got ${featuredNetworkCount}`)
}

// ----------------------
// Tokens (exact match)
// ----------------------

const supportedTokens = getAllSupportedTokens({
environment,
version: Version.V1_2_0,
})

const tokens = Object.keys(supportedTokens).sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base" }))

const allTokens = tokens.map((token) => {
const logo = getTokenIconUrl(token) || ""
return {
id: token,
logo,
totalNetworks: getChainsOfToken({ token, filter: environment }).length,
featuredRank: FEATURED_TOKEN_RANK[token],
}
})

const featuredTokenCount = allTokens.filter((t) => t.featuredRank !== undefined).length
if (featuredTokenCount !== 8) {
console.warn(`Expected 8 featured tokens, got ${featuredTokenCount}`)
}

// ----------------------
// Split + order
// ----------------------

function splitFeatured(items) {
const featured = items.filter((i) => i.featuredRank !== undefined).sort((a, b) => a.featuredRank - b.featuredRank)

const rest = items
.filter((i) => i.featuredRank === undefined)
.sort((a, b) => {
const aKey = a.name || a.id
const bKey = b.name || b.id
return aKey.localeCompare(bKey, undefined, { sensitivity: "base" })
})

return { featured, rest }
}

const { featured: featuredNetworks, rest: restNetworks } = splitFeatured(networks)
const { featured: featuredTokens, rest: restTokens } = splitFeatured(allTokens)

const orderedNetworks = [...featuredNetworks, ...restNetworks]
const orderedTokens = [...featuredTokens, ...restTokens]

// ----------------------
// Other data
// ----------------------

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

const searchLanes = getSearchLanes({ environment })

// Generate directory-level structured data (DataCatalog/Dataset)
// Use production base for canonical JSON-LD URLs (avoid local IPv6/port)
const currentPath = new URL(Astro.request.url).pathname
const canonicalForJsonLd = `${DOCS_BASE_URL}${currentPath}`

const directoryStructuredData = generateDirectoryStructuredData(environment, networks, tokens, canonicalForJsonLd)
---

Expand All @@ -67,33 +148,36 @@ const directoryStructuredData = generateDirectoryStructuredData(environment, net
pageTitleOverride={`CCIP Directory - ${environment === Environment.Mainnet ? "Mainnet" : "Testnet"}`}
metadataOverride={{
...(entry.data.metadata || {}),
description: `Explore CCIP Directory for ${environment === Environment.Mainnet ? "Mainnet" : "Testnet"}: configuration data for supported blockchains and tokens, cross-chain lanes, contract addresses, rate limits, and operational status on ${environment === Environment.Mainnet ? "Mainnet" : "Testnet"}.`,
description: `Explore CCIP Directory for ${environment === Environment.Mainnet ? "Mainnet" : "Testnet"}.`,
image: "/files/ccip-directory.jpg",
}}
suppressDefaultStructuredData={true}
>
<Hero
chains={networks}
tokens={allTokens}
chains={featuredNetworks}
tokens={featuredTokens}
environment={environment}
client:visible
lanes={searchLanes}
verifiers={allVerifiers}
/>

<section class="layout">
<div>
<div class="ccip-heading">
<h2>Networks {environment} <span>({networks.length})</span></h2>
</div>
<LazyNetworkGrid networks={networks} environment={environment} client:visible />
<LazyNetworkGrid networks={orderedNetworks} environment={environment} client:visible />
</div>

<div>
<div class="ccip-heading">
<h2>Tokens <span>({allTokens.length})</span></h2>
<AddButton href="/ccip/tutorials/evm/token-manager#verifying-your-token" text="Add my token" />
</div>
<LazyTokenGrid tokens={allTokens} environment={environment} client:visible />
<LazyTokenGrid tokens={orderedTokens} environment={environment} client:visible />
</div>

<div>
<div class="ccip-heading">
<h2>Verifiers <span>({allVerifiers.length})</span></h2>
Expand Down
Loading