diff --git a/ensawards.org/data/apps/index.ts b/ensawards.org/data/apps/index.ts index bd1b37c6..61a87cb3 100644 --- a/ensawards.org/data/apps/index.ts +++ b/ensawards.org/data/apps/index.ts @@ -1,6 +1,16 @@ import { getDefinedApps } from "./registry.ts"; -import type { App } from "./types.ts"; +import { type App, type AppType, AppTypes } from "./types.ts"; import.meta.glob("./*/index.ts", { eager: true }); export const APPS: App[] = [...getDefinedApps()]; + +/** + * Display groups of the app leaderboard snippets on the main page. + * * Divides the app types into two groups based on their position on the landing page (top and bottom). + * * Decides the order of the app types inside each group. + */ + +export const TOP_DISPLAY_APP_TYPES: AppType[] = [AppTypes.Wallet, AppTypes.DeFi]; + +export const BOTTOM_DISPLAY_APP_TYPES: AppType[] = [AppTypes.Exchange, AppTypes.Explorer]; diff --git a/ensawards.org/data/apps/walletchan-wallet/benchmarks/correctly-resolve-ensv2-test-name-address-proof.png b/ensawards.org/data/apps/walletchan-wallet/benchmarks/correctly-resolve-ensv2-test-name-address-proof.png index 27ae1224..f5d3f61b 100644 Binary files a/ensawards.org/data/apps/walletchan-wallet/benchmarks/correctly-resolve-ensv2-test-name-address-proof.png and b/ensawards.org/data/apps/walletchan-wallet/benchmarks/correctly-resolve-ensv2-test-name-address-proof.png differ diff --git a/ensawards.org/data/apps/walletchan-wallet/benchmarks/index.tsx b/ensawards.org/data/apps/walletchan-wallet/benchmarks/index.tsx index ecf4f51a..f7d1aca2 100644 --- a/ensawards.org/data/apps/walletchan-wallet/benchmarks/index.tsx +++ b/ensawards.org/data/apps/walletchan-wallet/benchmarks/index.tsx @@ -64,18 +64,18 @@ const benchmarks: BestPracticeBenchmarks = { }, "ensv2-ready-resolution": { "correctly-resolve-ensv2-test-name-address": { - result: BenchmarkResults.Fail, + result: BenchmarkResults.Pass, contributions: [ - { from: contributors.y3drk, lastUpdated: parseTimestamp("2026-06-05T16:07:00Z") }, + { from: contributors.y3drk, lastUpdated: parseTimestamp("2026-06-18T08:26:11Z") }, ], notes: (

- ENSv2 ready resolution was tested using the "send" flow. The app fails to - resolve the address for the test name, which we interpret as a failure. + ENSv2 ready resolution was tested using the "send" flow. The resolved address + is correct.

WalletChan fails to resolve the name for ENSv2 diff --git a/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-fail-example.png b/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-fail-example.png index c5ad4fe2..a48bf46f 100644 Binary files a/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-fail-example.png and b/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-fail-example.png differ diff --git a/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-not-applicable-example.gif b/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-not-applicable-example.gif new file mode 100644 index 00000000..f7c9dfd5 Binary files /dev/null and b/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-not-applicable-example.gif differ diff --git a/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-pass-example.gif b/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-pass-example.gif new file mode 100644 index 00000000..7f81f28c Binary files /dev/null and b/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-pass-example.gif differ diff --git a/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-pass-example.png b/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-pass-example.png deleted file mode 100644 index da93b13b..00000000 Binary files a/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/images/correctly-resolve-ensv2-test-name-address-pass-example.png and /dev/null differ diff --git a/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/technicalDetails.tsx b/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/technicalDetails.tsx index 2141c9c4..1033ff22 100644 --- a/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/technicalDetails.tsx +++ b/ensawards.org/data/ens-best-practices/ensv2-readiness/ensv2-ready-resolution/technicalDetails.tsx @@ -1,6 +1,7 @@ import type { AcceptanceTest, AcceptanceTestBenchmarkFail, + AcceptanceTestBenchmarkNotApplicable, AcceptanceTestBenchmarkPass, } from "data/acceptance-tests/types"; import { BenchmarkResults } from "data/benchmarks/types"; @@ -16,7 +17,8 @@ import { parseTimestamp } from "@ensnode/ensnode-sdk"; import { cn } from "@/utils/tailwindClassConcatenation"; import correctlyResolveEnsv2TestNameAddressExampleFailImage from "./images/correctly-resolve-ensv2-test-name-address-fail-example.png"; -import correctlyResolveEnsv2TestNameAddressExamplePassImage from "./images/correctly-resolve-ensv2-test-name-address-pass-example.png"; +import correctlyResolveEnsv2TestNameAddressExampleNotApplicableImage from "./images/correctly-resolve-ensv2-test-name-address-not-applicable-example.gif"; +import correctlyResolveEnsv2TestNameAddressExamplePassImage from "./images/correctly-resolve-ensv2-test-name-address-pass-example.gif"; const useCaseSummary = (
@@ -201,14 +203,14 @@ const acceptanceTest1 = { examplePass: { result: BenchmarkResults.Pass, contributions: [ - { from: contributors.y3drk, lastUpdated: parseTimestamp("2026-06-05T15:34:00Z") }, + { from: contributors.y3drk, lastUpdated: parseTimestamp("2026-06-18T10:00:00Z") }, ], notes: (

An ENSv2-ready app such as{" "} - - MetaMask + + Rabby Wallet {" "} resolves the name{" "} @@ -221,7 +223,7 @@ const acceptanceTest1 = { .

MetaMask correctly resolves the name for ENSv2 @@ -231,7 +233,7 @@ const acceptanceTest1 = { exampleFail: { result: BenchmarkResults.Fail, contributions: [ - { from: contributors.y3drk, lastUpdated: parseTimestamp("2026-06-05T15:34:00Z") }, + { from: contributors.y3drk, lastUpdated: parseTimestamp("2026-06-18T10:00:00Z") }, ], notes: (
@@ -244,18 +246,45 @@ const acceptanceTest1 = { 0x1111111111111111111111111111111111111111 - , or fails to resolve the name at all.
+ . +

Apps failing this test require an urgent update! 🚨

Rainbow Wallet fails to resolve the name for ENSv2
), } as const satisfies AcceptanceTestBenchmarkFail, + exampleNotApplicable: { + result: BenchmarkResults.NotApplicable, + contributions: [ + { from: contributors.y3drk, lastUpdated: parseTimestamp("2026-06-18T10:48:00Z") }, + ], + notes: ( +
+

+ This best practice is targeted towards apps that already support ENS resolution being + ENSv2 ready. +
+
+ Therefore, any app that currently doesn’t support ENS resolution at all is classified as + + Not Applicable + {" "} + for this best practice. +

+ Binance Wallet doesn't currently support ENS resolution at all +
+ ), + } as const satisfies AcceptanceTestBenchmarkNotApplicable, } as const satisfies AcceptanceTest; const technicalDetails = { diff --git a/ensawards.org/src/components/molecules/technicalDetails/bestPractice/index.tsx b/ensawards.org/src/components/molecules/technicalDetails/bestPractice/index.tsx index 8254bc42..833ea6fb 100644 --- a/ensawards.org/src/components/molecules/technicalDetails/bestPractice/index.tsx +++ b/ensawards.org/src/components/molecules/technicalDetails/bestPractice/index.tsx @@ -91,6 +91,25 @@ export const BestPracticeTechnicalDetails = ({ {acceptanceTest.exampleFail.notes}
)} + {acceptanceTest.exampleNotApplicable !== undefined && ( +
+

+ Example test result + +

+ {acceptanceTest.exampleNotApplicable.notes} +
+ )} ))} diff --git a/ensawards.org/src/components/organisms/AppLeaderboardSnippet.astro b/ensawards.org/src/components/organisms/AppLeaderboardSnippet.astro new file mode 100644 index 00000000..f9e972ec --- /dev/null +++ b/ensawards.org/src/components/organisms/AppLeaderboardSnippet.astro @@ -0,0 +1,70 @@ +--- +import { Image } from "astro:assets"; +import type { ImageMetadata } from "astro"; +import LeaderboardCard from "@/components/atoms/cards/LeaderboardCard.astro"; +import ItemsList from "@/components/molecules/ItemsList.astro"; +import { shadcnButtonVariants } from "@/components/ui/shadcnButtonStyles"; +import { APPS } from "data/apps"; +import { type AppType } from "data/apps/types.ts"; +import { cn } from "@/utils/tailwindClassConcatenation"; +import { formatBestPracticeTarget } from "data/ens-best-practices/utils.ts"; +import { calcAppScore, sortApps, formatAppType } from "data/apps/utils.ts"; + +interface Props { + appType: AppType; +} + +const { appType } = Astro.props; + +const images = import.meta.glob<{ default: ImageMetadata }>("/src/assets/*.{jpeg,jpg,png,gif,svg}"); +const placeIcons = [ + "/src/assets/firstPlaceAward.svg", + "/src/assets/secondPlaceAward.svg", + "/src/assets/thirdPlaceAward.svg", +]; + +const relevantApps = APPS.filter((app) => app.type === appType); +const rankedApps = relevantApps + .map((app) => ({ app, score: calcAppScore(app) })) + .sort((a, b) => sortApps(a.app, b.app)) + .slice(0, 3); +--- + +{ + rankedApps.length > 0 && ( + + {rankedApps.map(({ app, score }, idx) => { + const AppIcon = app.icon; + return ( + + + {`${idx + + ); + })} + + View full {formatAppType(appType, { plural: false, lowercase: true })}{" "} + leaderboard + + + ) +} diff --git a/ensawards.org/src/components/organisms/ProtocolLeaderboardSnippet.astro b/ensawards.org/src/components/organisms/ProtocolLeaderboardSnippet.astro new file mode 100644 index 00000000..9745b7b0 --- /dev/null +++ b/ensawards.org/src/components/organisms/ProtocolLeaderboardSnippet.astro @@ -0,0 +1,82 @@ +--- +import { Image } from "astro:assets"; +import type { ImageMetadata } from "astro"; +import LeaderboardCard from "@/components/atoms/cards/LeaderboardCard.astro"; +import ItemsList from "@/components/molecules/ItemsList.astro"; +import type { ProtocolType } from "data/protocols/types"; +import { getContractNamingScoresByProtocolType } from "@/contract-pipelines/utils.ts"; +import { getProtocolById, formatProtocolType } from "data/protocols/utils.ts"; +import { type ProtocolId } from "data/protocols/types.ts"; +import { shadcnButtonVariants } from "@/components/ui/shadcnButtonStyles"; +import { formatBestPracticeTarget } from "data/ens-best-practices/utils.ts"; +import { cn } from "@/utils/tailwindClassConcatenation"; +import { EnsAwardsScoreResultTypes } from "data/shared/ens-awards-score"; + +interface Props { + protocolType: ProtocolType; +} + +const { protocolType } = Astro.props; + +const images = import.meta.glob<{ default: ImageMetadata }>("/src/assets/*.{jpeg,jpg,png,gif,svg}"); +const placeIcons = [ + "/src/assets/firstPlaceAward.svg", + "/src/assets/secondPlaceAward.svg", + "/src/assets/thirdPlaceAward.svg", +]; + +const protocolScores = getContractNamingScoresByProtocolType(protocolType); + +const protocolScoresEntries = [...Object.entries(protocolScores)]; +--- + +{ + protocolScoresEntries.length > 0 && ( + + {protocolScoresEntries + .slice(0, 3) + .map(([scoredProtocolId, ensAwardsScore], idx) => { + // Type casting is necessary due to `Record`'s type nature. + // We are completely sure of its correctness + const protocolId = scoredProtocolId as ProtocolId; + const protocol = getProtocolById(protocolId); + const ProtocolIcon = protocol.icon; + return ( + + {`${idx + + + ); + })} + + View full {formatProtocolType(protocolType)} leaderboard + + + ) +} diff --git a/ensawards.org/src/pages/index.astro b/ensawards.org/src/pages/index.astro index 3a737ac2..939934aa 100644 --- a/ensawards.org/src/pages/index.astro +++ b/ensawards.org/src/pages/index.astro @@ -1,30 +1,12 @@ --- -import { Image } from "astro:assets"; -import type { ImageMetadata } from "astro"; -import LeaderboardCard from "@/components/atoms/cards/LeaderboardCard.astro"; import ReferralProgramsCTA from "@/components/atoms/banners/ReferralProgramsCTA.astro"; import Hero from "@/components/molecules/Hero.astro"; -import ItemsList from "@/components/molecules/ItemsList.astro"; import { ReferrerLeaderboardSnippet } from "@/components/referral-awards-program/referrers/ReferrerLeaderboardSnippet"; -import { shadcnButtonVariants } from "@/components/ui/shadcnButtonStyles"; -import { APPS } from "data/apps"; +import { TOP_DISPLAY_APP_TYPES, BOTTOM_DISPLAY_APP_TYPES } from "data/apps"; import Layout from "@/layouts/Layout.astro"; -import { AppTypes } from "data/apps/types.ts"; -import { type ProtocolId } from "data/protocols/types.ts"; -import { cn } from "@/utils/tailwindClassConcatenation"; import { ProtocolTypes } from "data/protocols/types.ts"; -import { formatBestPracticeTarget } from "data/ens-best-practices/utils.ts"; -import { getContractNamingScoresByProtocolType } from "@/contract-pipelines/utils.ts"; -import { getProtocolById, formatProtocolType } from "data/protocols/utils.ts"; -import { calcAppScore, sortApps, formatAppType } from "data/apps/utils.ts"; -import { EnsAwardsScoreResultTypes } from "data/shared/ens-awards-score.ts"; - -const images = import.meta.glob<{ default: ImageMetadata }>("/src/assets/*.{jpeg,jpg,png,gif,svg}"); -const placeIcons = [ - "/src/assets/firstPlaceAward.svg", - "/src/assets/secondPlaceAward.svg", - "/src/assets/thirdPlaceAward.svg", -]; +import AppLeaderboardSnippet from "@/components/organisms/AppLeaderboardSnippet.astro"; +import ProtocolLeaderboardSnippet from "@/components/organisms/ProtocolLeaderboardSnippet.astro"; --- @@ -34,115 +16,19 @@ const placeIcons = [ class="w-full box-border h-fit flex flex-col flex-nowrap justify-center items-center max-sm:gap-6 gap-10 py-5 sm:py-[60px] px-5 sm:px-8"> { - [...Object.values(AppTypes)].map((appType) => { - const relevantApps = APPS.filter((app) => app.type === appType); - const rankedApps = relevantApps - .map((app) => ({ app, score: calcAppScore(app) })) - .sort((a, b) => sortApps(a.app, b.app)) - .slice(0, 3); - - if (rankedApps.length === 0) { - return null; - } - - return ( - - {rankedApps.map(({ app, score }, idx) => { - const AppIcon = app.icon; - return ( - - - {`${idx - - ); - })} - - View full{" "} - {formatAppType(appType, { plural: false, lowercase: true })}{" "} - leaderboard - - - ); - }) + TOP_DISPLAY_APP_TYPES.map((appType) => ( + + )) } { - [...Object.values(ProtocolTypes)].map((protocolType) => { - const protocolScores = - getContractNamingScoresByProtocolType(protocolType); - - return ( - - {[...Object.entries(protocolScores)] - .slice(0, 3) - .map(([scoredProtocolId, ensAwardsScore], idx) => { - // Type casting is necessary due to `Record`'s type nature. - // We are completely sure of its correctness - const protocolId = scoredProtocolId as ProtocolId; - const protocol = getProtocolById(protocolId); - const ProtocolIcon = protocol.icon; - return ( - - {`${idx - - - ); - })} - - View full {formatProtocolType(protocolType)} leaderboard - - - ); - }) + [...Object.values(ProtocolTypes)].map((protocolType) => ( + + )) + } + { + BOTTOM_DISPLAY_APP_TYPES.map((appType) => ( + + )) }