Skip to content
This repository was archived by the owner on Aug 5, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
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
12 changes: 11 additions & 1 deletion ensawards.org/data/apps/index.ts
Original file line number Diff line number Diff line change
@@ -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];
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 5 additions & 5 deletions ensawards.org/data/apps/walletchan-wallet/benchmarks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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: (
<div className={cn(acceptanceTestDetailsContainerStyles, "w-full")}>
<p className="w-full">
ENSv2 ready resolution was tested using the &quot;send&quot; 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 &quot;send&quot; flow. The resolved address
is correct.
</p>
<img
alt="WalletChan fails to resolve the name for ENSv2"
alt="WalletChan correctly resolves the name for ENSv2"
src={correctlyResolveEnsv2TestNameAddressProofImage.src}
className="w-auto h-full max-h-[325px] rounded-xl"
/>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
AcceptanceTest,
AcceptanceTestBenchmarkFail,
AcceptanceTestBenchmarkNotApplicable,
AcceptanceTestBenchmarkPass,
} from "data/acceptance-tests/types";
import { BenchmarkResults } from "data/benchmarks/types";
Expand All @@ -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 = (
<div className="flex flex-col gap-2">
Expand Down Expand Up @@ -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: (
<div className={cn(acceptanceTestDetailsContainerStyles, "w-full")}>
<p className="w-full">
An ENSv2-ready app such as{" "}
<a className={bestPracticeTechnicalDetailsLinkStyles} href="/app/metamask-wallet">
MetaMask
<a className={bestPracticeTechnicalDetailsLinkStyles} href="/app/rabby-wallet">
Rabby Wallet
</a>{" "}
resolves the name{" "}
<span className="px-1.5 py-0.5 rounded bg-gray-100 text-gray-800 font-mono text-sm min-[400px]:whitespace-nowrap max-[400px]:break-all">
Expand All @@ -221,7 +223,7 @@ const acceptanceTest1 = {
.
</p>
<img
alt="MetaMask correctly resolves the name for ENSv2"
alt="Rabby Wallet correctly resolves the name for ENSv2"
src={correctlyResolveEnsv2TestNameAddressExamplePassImage.src}
className="w-auto h-full max-h-[325px] rounded-xl"
/>
Expand All @@ -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: (
<div className={cn(acceptanceTestDetailsContainerStyles, "w-full")}>
Expand All @@ -244,18 +246,45 @@ const acceptanceTest1 = {
<span className="px-1.5 py-0.5 rounded bg-gray-100 text-gray-800 font-mono text-sm min-[400px]:whitespace-nowrap max-[400px]:break-all">
0x1111111111111111111111111111111111111111
</span>
, or fails to resolve the name at all. <br />
.
<br />
<br />
<b>Apps failing this test require an urgent update! 🚨</b>
</p>
<img
alt="Rainbow Wallet fails to resolve the name for ENSv2"
alt="Zerion fails to resolve the name for ENSv2"
src={correctlyResolveEnsv2TestNameAddressExampleFailImage.src}
className="w-auto h-full max-h-[325px] rounded-xl"
/>
</div>
),
} as const satisfies AcceptanceTestBenchmarkFail,
exampleNotApplicable: {
result: BenchmarkResults.NotApplicable,
contributions: [
{ from: contributors.y3drk, lastUpdated: parseTimestamp("2026-06-18T10:48:00Z") },
],
notes: (
<div className={cn(acceptanceTestDetailsContainerStyles, "w-full")}>
<p className="w-full">
This best practice is targeted towards apps that already support ENS resolution being
ENSv2 ready.
Comment thread
Y3drk marked this conversation as resolved.
<br />
<br />
Therefore, any app that currently doesn’t support ENS resolution at all is classified as
<span className="px-1.5 py-0.5 rounded bg-gray-100 text-gray-800 font-mono text-sm min-[400px]:whitespace-nowrap max-[400px]:break-all">
Not Applicable
</span>{" "}
for this best practice.
</p>
<img
alt="Binance Wallet doesn't currently support ENS resolution at all"
src={correctlyResolveEnsv2TestNameAddressExampleNotApplicableImage.src}
className="w-auto h-full max-h-[325px] rounded-xl"
/>
</div>
),
} as const satisfies AcceptanceTestBenchmarkNotApplicable,
} as const satisfies AcceptanceTest;

const technicalDetails = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,25 @@ export const BestPracticeTechnicalDetails = ({
{acceptanceTest.exampleFail.notes}
</div>
)}
{acceptanceTest.exampleNotApplicable !== undefined && (
<div
className={cn(
technicalSectionContainerStyles,
"w-full p-4 bg-neutral-50 rounded-lg",
)}
>
<h4
className={cn(
technicalSectionHeaderStyles,
"text-xl w-full flex flex-row items-start justify-between gap-3",
)}
>
Example test result
<BenchmarkResultBadge benchmarkResult={BenchmarkResults.NotApplicable} />
</h4>
{acceptanceTest.exampleNotApplicable.notes}
</div>
)}
</>
</AcceptanceTestDetailsContainer>
))}
Expand Down
Original file line number Diff line number Diff line change
@@ -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 && (
<ItemsList
header={`Top ${formatBestPracticeTarget(appType, { lowercase: false, plural: true })}`}
containerStyles="gap-3 sm:gap-2 sm:justify-start max-sm:justify-center">
{rankedApps.map(({ app, score }, idx) => {
const AppIcon = app.icon;
return (
<LeaderboardCard
key={`${appType}-review-card-${app.id}`}
name={app.name}
ensAwardsScore={score}
viewDetailsHref={`/app/${app.appSlug}`}
viewDetailsText={`${formatAppType(appType, { plural: false, lowercase: false })} report`}>
<AppIcon slot="rankedEntityIcon" className="w-10 h-10 rounded-md" />
<Image
alt={`${idx + 1}-place`}
src={images[placeIcons[idx]]()}
slot="placeIcon"
/>
</LeaderboardCard>
);
})}
<a
href={`/leaderboards/${appType}`}
class={cn(
shadcnButtonVariants({
variant: "ghost",
size: "default",
className: "cursor-pointer rounded-full text-sm max-sm:w-full",
}),
)}>
View full {formatAppType(appType, { plural: false, lowercase: true })}{" "}
leaderboard
</a>
</ItemsList>
)
}
Original file line number Diff line number Diff line change
@@ -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 && (
<ItemsList
header={`Top ${formatBestPracticeTarget(protocolType, { lowercase: false, plural: true })}`}
containerStyles="gap-3 sm:gap-2 sm:justify-start max-sm:justify-center">
{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 (
<LeaderboardCard
key={`leaderboard-card-${protocol.protocolSlug}`}
name={protocol.name}
ensAwardsScore={{
type: EnsAwardsScoreResultTypes.Defined,
score: ensAwardsScore,
label: undefined,
}}
viewDetailsHref={`/protocol/${protocol.protocolSlug}`}
viewDetailsText={`${formatProtocolType(protocolType)} report`}>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
<Image
alt={`${idx + 1}-place`}
src={images[placeIcons[idx]]()}
slot="placeIcon"
/>
<ProtocolIcon
slot="rankedEntityIcon"
className="w-10 h-10 rounded-md"
/>
</LeaderboardCard>
);
})}
<a
href={`/leaderboards/${protocolType}`}
class={cn(
shadcnButtonVariants({
variant: "ghost",
size: "default",
className: "cursor-pointer rounded-full text-sm max-sm:w-full",
}),
)}>
View full {formatProtocolType(protocolType)} leaderboard
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</a>
</ItemsList>
)
}
Loading
Loading