-
Notifications
You must be signed in to change notification settings - Fork 5
chore: Add new apps -- Tranche 2, May 2026 #214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b514519
d7278fd
8e692b6
f35b9b5
2fce38b
d7e3f4c
5ef4e6f
cb4969c
9ae8c2d
eaec4c3
1b96f1a
9e9aa00
bb1b2c6
0c060b6
8dd6549
5542d92
e6773bf
e79ae89
7efbbef
2d93d38
161dd35
9faf4b4
8d3a637
afd0fbd
d4a4482
25d43d7
35c7e4a
c935f7f
1870bc0
61ad7f6
e678c27
5a9f69a
d384e95
91a880d
b92a0b3
8dbab09
6cf9f90
a1daa0f
681dc06
a9fcc60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { ACCEPTANCE_TESTS } from "data/acceptance-tests"; | ||
| import { isValidSlug } from "data/shared/slugs"; | ||
| import { describe, expect, it } from "vitest"; | ||
|
|
||
| import { areStringsUnique } from "@/utils"; | ||
|
|
||
| describe("Acceptance test data", () => { | ||
| it("Should have valid and unique slugs", () => { | ||
| const slugArray: string[] = []; | ||
|
|
||
| ACCEPTANCE_TESTS.forEach((acceptanceTest) => { | ||
| expect( | ||
| isValidSlug(acceptanceTest.acceptanceTestSlug), | ||
| `Slug={${acceptanceTest.acceptanceTestSlug}} is not valid`, | ||
| ).toEqual(true); | ||
|
|
||
| slugArray.push(acceptanceTest.acceptanceTestSlug); | ||
| }); | ||
|
|
||
| expect(areStringsUnique(slugArray), `Slugs for Acceptance Tests are not unique`).toEqual(true); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| import { ENS_BEST_PRACTICES } from "data/ens-best-practices"; | ||
|
|
||
| export const ACCEPTANCE_TESTS = [ | ||
| ...ENS_BEST_PRACTICES.flatMap((bestPractice) => bestPractice.technicalDetails.acceptanceTests), | ||
| ]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| import { type BenchmarkResult, BenchmarkResults } from "data/benchmarks/types"; | ||
| import type { Contribution } from "data/contributors/types"; | ||
| import type { JSX } from "react"; | ||
|
|
||
| /** A unique identifier for an acceptance test. | ||
| * | ||
| * @invariant Must be unique across all acceptance tests. | ||
| * @invariant Must match {@link ENSAWARDS_SLUG_PATTERN}. | ||
| */ | ||
| export type AcceptanceTestSlug = string; | ||
|
|
||
| /** | ||
| * Represents an acceptance test that an app can be evaluated against. | ||
| */ | ||
| export interface AcceptanceTest { | ||
| /** | ||
| * Unique identifier for the acceptance test. | ||
| */ | ||
| acceptanceTestSlug: AcceptanceTestSlug; | ||
|
|
||
| /** | ||
| * Description of the acceptance test, | ||
| * which should provide clear and detailed information | ||
| * about the criteria and requirements that | ||
| * an {@link App} must meet to pass the test. | ||
| * This may include specific functionalities to be tested, | ||
| * user interactions to be evaluated, | ||
| * and any relevant technical details or considerations. | ||
| * | ||
| * @note The description should not include examples of passed or failed benchmarks, | ||
| * there are dedicated fields for that | ||
| * (see {@link AcceptanceTest.examplePass}, | ||
| * {@link AcceptanceTest.examplePartialPass}, | ||
| * or {@link AcceptanceTest.exampleFail}). | ||
| */ | ||
| description: JSX.Element; | ||
|
|
||
| /** | ||
| * Examples of benchmark results that illustrate | ||
| * what a passing, partially passing, or failing result | ||
| * looks like for this acceptance test. | ||
| */ | ||
| examplePass: AcceptanceTestBenchmarkPass; | ||
| examplePartialPass?: AcceptanceTestBenchmarkPartialPass; | ||
| exampleFail?: AcceptanceTestBenchmarkFail; | ||
| } | ||
|
|
||
| /** | ||
| * Represents the benchmark of an {@link AcceptanceTest} on an {@link App} against a {@link BestPractice}. | ||
| */ | ||
| export interface AcceptanceTestBenchmarkAbstract<BenchmarkResultT extends BenchmarkResult> { | ||
| /** The result of the benchmark */ | ||
| result: BenchmarkResultT; | ||
|
|
||
| /** A record of all contributors involved | ||
| * in the addition or maintenance of the benchmark's data. | ||
| * | ||
| * @invariant Multiple {@link Contribution} from the same contributor | ||
| * on the same app benchmark are not allowed. | ||
| * When a contributor makes updates to their existing contribution, | ||
| * they should update the `lastUpdated` timestamp of their existing `Contribution`. | ||
| */ | ||
| contributions: [Contribution, ...Contribution[]]; | ||
|
|
||
| /** | ||
| * Notes about how the benchmark result was determined, | ||
| * which may include details about the testing process, | ||
| * any challenges encountered, and explanations, | ||
| * as well as a visual proof, for the final result. | ||
| */ | ||
| notes: JSX.Element; | ||
| } | ||
|
|
||
| /** | ||
| * Represents a benchmark of an {@link AcceptanceTest} on an {@link App} against a {@link BestPractice}, | ||
| * that has fully passed the acceptance test. | ||
| */ | ||
| export interface AcceptanceTestBenchmarkPass | ||
| extends AcceptanceTestBenchmarkAbstract<typeof BenchmarkResults.Pass> {} | ||
|
|
||
| /** | ||
| * Represents a benchmark of an {@link AcceptanceTest} on an {@link App} against a {@link BestPractice}, | ||
| * that has partially passed the acceptance test. | ||
| */ | ||
| export interface AcceptanceTestBenchmarkPartialPass | ||
| extends AcceptanceTestBenchmarkAbstract<typeof BenchmarkResults.PartialPass> {} | ||
|
|
||
| /** | ||
| * Represents a benchmark of an {@link AcceptanceTest} on an {@link App} against a {@link BestPractice}, | ||
| * that hasn't passed the acceptance test. | ||
| */ | ||
| export interface AcceptanceTestBenchmarkFail | ||
| extends AcceptanceTestBenchmarkAbstract<typeof BenchmarkResults.Fail> {} | ||
|
|
||
| export type AcceptanceTestBenchmark = | ||
| | AcceptanceTestBenchmarkPass | ||
| | AcceptanceTestBenchmarkPartialPass | ||
| | AcceptanceTestBenchmarkFail; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| import { generalizeAcceptanceTestBenchmarks } from "data/acceptance-tests/utils"; | ||
| import { type AcceptanceTestBenchmarks, BenchmarkResults } from "data/benchmarks/types"; | ||
| import { createMockAcceptanceTestBenchmark } from "data/shared/test-utils"; | ||
| import { describe, expect, it } from "vitest"; | ||
|
|
||
| describe("Acceptance test utils", () => { | ||
| describe("generalizeAcceptanceTestBenchmarks", () => { | ||
| it( | ||
| "Returns `BenchmarkResults.Pass` if in all defined benchmarks there is at least one `BenchmarkResults.Pass`" + | ||
| " and all others are `BenchmarkResults.Pass` or `BenchmarkResults.PartialPass`", | ||
| () => { | ||
| const expectedResult = BenchmarkResults.Pass; | ||
|
|
||
| const inputBenchmarks = { | ||
| "mock-acceptance-test-1": createMockAcceptanceTestBenchmark(BenchmarkResults.Pass), | ||
| "mock-acceptance-test-2": createMockAcceptanceTestBenchmark(BenchmarkResults.PartialPass), | ||
| "mock-acceptance-test-3": undefined, | ||
| // pending benchmarks should be ignored in this case of the generalization | ||
| } as const satisfies AcceptanceTestBenchmarks; | ||
|
|
||
| expect( | ||
| generalizeAcceptanceTestBenchmarks(inputBenchmarks), | ||
| "generalizeAcceptanceTestBenchmarks should return `BenchmarkResults.Pass`", | ||
| ).toEqual(expectedResult); | ||
| }, | ||
| ); | ||
|
|
||
| it("Returns `BenchmarkResults.Fail` if all defined benchmarks are `BenchmarkResults.Fail`", () => { | ||
| const expectedResult = BenchmarkResults.Fail; | ||
|
|
||
| const inputBenchmarks = { | ||
| "mock-acceptance-test-1": createMockAcceptanceTestBenchmark(BenchmarkResults.Fail), | ||
| "mock-acceptance-test-2": createMockAcceptanceTestBenchmark(BenchmarkResults.Fail), | ||
| "mock-acceptance-test-3": undefined, | ||
| // pending benchmarks should be ignored in this case of the generalization | ||
| } as const satisfies AcceptanceTestBenchmarks; | ||
|
|
||
| expect( | ||
| generalizeAcceptanceTestBenchmarks(inputBenchmarks), | ||
| "generalizeAcceptanceTestBenchmarks should return `BenchmarkResults.Fail`", | ||
| ).toEqual(expectedResult); | ||
| }); | ||
|
|
||
| it( | ||
| "Returns `BenchmarkResults.PartialPass` if at least one defined benchmark is `BenchmarkResults.Fail`" + | ||
| " and at least one defined benchmark is `BenchmarkResults.Pass`", | ||
| () => { | ||
| const expectedResult = BenchmarkResults.PartialPass; | ||
|
|
||
| const inputBenchmarks = { | ||
| "mock-acceptance-test-1": createMockAcceptanceTestBenchmark(BenchmarkResults.Fail), | ||
| "mock-acceptance-test-2": createMockAcceptanceTestBenchmark(BenchmarkResults.Pass), | ||
| "mock-acceptance-test-3": createMockAcceptanceTestBenchmark(BenchmarkResults.PartialPass), | ||
| "mock-acceptance-test-4": undefined, | ||
| // pending benchmarks should be ignored in this case of the generalization | ||
| } as const satisfies AcceptanceTestBenchmarks; | ||
|
|
||
| expect( | ||
| generalizeAcceptanceTestBenchmarks(inputBenchmarks), | ||
| "generalizeAcceptanceTestBenchmarks should return `BenchmarkResults.PartialPass`", | ||
| ).toEqual(expectedResult); | ||
| }, | ||
| ); | ||
|
|
||
| it("Returns `BenchmarkResults.PartialPass` if all defined benchmarks are `BenchmarkResults.PartialPass`", () => { | ||
| const expectedResult = BenchmarkResults.PartialPass; | ||
|
|
||
| const inputBenchmarks = { | ||
| "mock-acceptance-test-1": createMockAcceptanceTestBenchmark(BenchmarkResults.PartialPass), | ||
| "mock-acceptance-test-2": createMockAcceptanceTestBenchmark(BenchmarkResults.PartialPass), | ||
| "mock-acceptance-test-3": undefined, | ||
| // pending benchmarks should be ignored in this case of the generalization | ||
| } as const satisfies AcceptanceTestBenchmarks; | ||
|
|
||
| expect( | ||
| generalizeAcceptanceTestBenchmarks(inputBenchmarks), | ||
| "generalizeAcceptanceTestBenchmarks should return `BenchmarkResults.PartialPass`", | ||
| ).toEqual(expectedResult); | ||
| }); | ||
|
|
||
| it("Returns `undefined` if all benchmarks are `undefined` (pending)", () => { | ||
| const expectedResult = undefined; | ||
|
|
||
| const inputBenchmarks = { | ||
| "mock-acceptance-test-1": undefined, | ||
| "mock-acceptance-test-2": undefined, | ||
| } as const satisfies AcceptanceTestBenchmarks; | ||
|
|
||
| expect( | ||
| generalizeAcceptanceTestBenchmarks(inputBenchmarks), | ||
| "generalizeAcceptanceTestBenchmarks should return `undefined` for all pending benchmarks", | ||
| ).toEqual(expectedResult); | ||
| }); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| import { ACCEPTANCE_TESTS } from "data/acceptance-tests"; | ||
| import type { | ||
| AcceptanceTest, | ||
| AcceptanceTestBenchmark, | ||
| AcceptanceTestSlug, | ||
| } from "data/acceptance-tests/types"; | ||
| import type { AppSlug } from "data/apps/types"; | ||
| import { | ||
| type AcceptanceTestBenchmarks, | ||
| type BenchmarkResult, | ||
| BenchmarkResults, | ||
| } from "data/benchmarks/types"; | ||
| import { getAppBenchmarks } from "data/benchmarks/utils.ts"; | ||
|
|
||
| /** Returns an {@link AcceptanceTest} by {@link AcceptanceTestSlug}. */ | ||
| export const getAcceptanceTestBySlug = (slug: AcceptanceTestSlug): AcceptanceTest | undefined => { | ||
| return ACCEPTANCE_TESTS.find((acceptanceTest) => acceptanceTest.acceptanceTestSlug === slug); | ||
| }; | ||
|
|
||
| /** Returns all {@link AcceptanceTestBenchmark}s of an `App` by {@link AppSlug}. */ | ||
| export const getAcceptanceTestBenchmarksByApp = ( | ||
| appSlug: AppSlug, | ||
| ): (AcceptanceTestBenchmark | undefined)[] => { | ||
| const appBenchmarks = getAppBenchmarks(appSlug); | ||
|
|
||
| return Object.values(appBenchmarks).flatMap((acceptanceTestBenchmarks) => | ||
| Object.values(acceptanceTestBenchmarks), | ||
| ); | ||
| }; | ||
|
|
||
| /** | ||
| * Generalizes multiple `AcceptanceTestBenchmark`s into a single `BenchmarkResult` | ||
| * based on the following rules: | ||
| * - Returns {@link BenchmarkResults.Pass} if: | ||
| * - in all defined benchmarks there is at least one | ||
| * {@link BenchmarkResults.Pass} | ||
| * - and all others are {@link BenchmarkResults.Pass} or {@link BenchmarkResults.PartialPass} | ||
| * | ||
| * - Returns {@link BenchmarkResults.Fail} if all defined benchmarks | ||
| * are {@link BenchmarkResults.Fail}, | ||
| * | ||
| * - Returns {@link BenchmarkResults.PartialPass} if: | ||
| * - at least one defined benchmark is {@link BenchmarkResults.Fail} | ||
| * and at least one defined benchmark is | ||
| * {@link BenchmarkResults.Pass} or {@link BenchmarkResults.PartialPass}, | ||
| * - or all defined benchmarks are {@link BenchmarkResults.PartialPass}, | ||
| * | ||
| * - Returns `undefined` if all benchmarks are `undefined` (pending). | ||
| */ | ||
| export const generalizeAcceptanceTestBenchmarks = ( | ||
| acceptanceTestBenchmarks: AcceptanceTestBenchmarks, | ||
| ): BenchmarkResult | undefined => { | ||
| const benchmarkResults = Object.values(acceptanceTestBenchmarks).map( | ||
| (benchmark) => benchmark?.result, | ||
| ); | ||
|
|
||
| const definedBenchmarkResults = benchmarkResults.filter((result) => result !== undefined); | ||
|
|
||
| if (definedBenchmarkResults.length === 0) { | ||
| return undefined; | ||
| } | ||
|
|
||
| const allDefinedBenchmarksPassPartially = definedBenchmarkResults.every( | ||
| (result) => result === BenchmarkResults.PartialPass, | ||
| ); | ||
|
|
||
| if (allDefinedBenchmarksPassPartially) { | ||
| return BenchmarkResults.PartialPass; | ||
| } | ||
|
|
||
| // For now, we'll explicitly treat pass and partial pass equally | ||
| // (For cases where not all benchmarks are partial pass) | ||
| const allDefinedBenchmarksPass = definedBenchmarkResults.every( | ||
| (result) => result === BenchmarkResults.Pass || result === BenchmarkResults.PartialPass, | ||
| ); | ||
|
|
||
| if (allDefinedBenchmarksPass) { | ||
| return BenchmarkResults.Pass; | ||
| } | ||
|
|
||
| const allDefinedBenchmarksFail = definedBenchmarkResults.every( | ||
| (result) => result === BenchmarkResults.Fail, | ||
| ); | ||
|
|
||
| if (allDefinedBenchmarksFail) { | ||
| return BenchmarkResults.Fail; | ||
| } | ||
|
|
||
| return BenchmarkResults.PartialPass; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // Read https://github.com/namehash/ensawards/blob/main/CONTRIBUTING.md | ||
| // for additional advice on adding and modifying app benchmarks | ||
|
|
||
| import OneInchDeFiApp from "data/apps/1inch-defi-app"; | ||
| import { defineAppBenchmarks } from "data/benchmarks/registry"; | ||
| import type { BestPracticeBenchmarks } from "data/ens-best-practices/types"; | ||
|
|
||
| // TODO; Add proper benchmarks | ||
| const benchmarks: BestPracticeBenchmarks = { | ||
| "display-named-smart-contracts-mainnet": { | ||
| "mainnet-interactions-display-named-smart-contracts": undefined, | ||
| }, | ||
| "display-named-smart-contracts-l2-chains": { | ||
| "l2-chain-interactions-display-named-smart-contracts": undefined, | ||
| }, | ||
| }; | ||
|
|
||
| defineAppBenchmarks(OneInchDeFiApp, benchmarks); | ||
|
|
||
| export default benchmarks; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import React from "react"; | ||
|
|
||
| const Icon = ({ className, ...props }: React.SVGProps<SVGSVGElement>) => ( | ||
| <svg | ||
| id="1" | ||
| data-name="1" | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| width="181mm" | ||
| height="181mm" | ||
| version="1.1" | ||
| viewBox="0 0 513 513" | ||
| className={className} | ||
| {...props} | ||
| > | ||
| <path d="M512.8,0H0v512.8h512.8V0Z" /> | ||
| <path | ||
| d="M169.7,383.7h172.9v-36.7h-63.8s0-218.7,0-218.7h-37.8c-1.5,30.6-10.3,38.3-52.1,38.3h-19.2v34.6h63.8v145.8h-63.8v36.7ZM360.7,201.2v-72.9h-36.7v72.9h36.7ZM425.1,201.2v-72.9h-36.7v72.9h36.7Z" | ||
| fill="#fff" | ||
| /> | ||
| </svg> | ||
| ); | ||
|
|
||
| export default Icon; | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||||
| // Read https://github.com/namehash/ensawards/blob/main/CONTRIBUTING.md | ||||||
| // for additional advice on adding and modifying apps | ||||||
|
|
||||||
| import OneInchProject from "data/projects/1inch/index.ts"; | ||||||
| import { asInterpretedName } from "enssdk"; | ||||||
|
|
||||||
| import { defineApp } from "../registry.ts"; | ||||||
| import { type App, AppTypes } from "../types.ts"; | ||||||
| import OneInchIcon from "./icon.tsx"; | ||||||
|
|
||||||
| const OneInchDeFiApp: App = { | ||||||
| id: "1inch-defi-app", | ||||||
| appSlug: "1inch-defi-app", | ||||||
| type: AppTypes.DeFi, | ||||||
| project: OneInchProject, | ||||||
| name: '1inch"', | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix malformed app name string. Line 16 includes an extra trailing quote in the displayed name ( Proposed fix- name: '1inch"',
+ name: "1inch",📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
vercel[bot] marked this conversation as resolved.
|
||||||
| description: | ||||||
| "A DeFi aggregator app for swapping tokens across 13+ chains with the only native connection between Solana and EVM networks, with true self-custody and built-in security.", | ||||||
| socials: { | ||||||
| website: new URL("https://1inch.com/swap"), | ||||||
| twitter: new URL("https://x.com/1inch"), | ||||||
| ens: asInterpretedName("1inch.eth"), | ||||||
| }, | ||||||
| icon: OneInchIcon, // TODO: The icon is not perfect for dark bgs. Same case as with Ledger. Brainstorm fix ideas (but no hacky ifs in the code) | ||||||
| // TODO: Add OG images | ||||||
| }; | ||||||
|
|
||||||
| defineApp(OneInchDeFiApp); | ||||||
|
|
||||||
| export default OneInchDeFiApp; | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove static SVG IDs to avoid duplicate DOM IDs across multiple renders.
Hardcoded
id="1"/data-name="1"can duplicate on pages rendering this icon more than once.Suggested fix
📝 Committable suggestion
🤖 Prompt for AI Agents