Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d3acb62
feat: started OpenAPI implementation
stevedylandev Dec 2, 2025
fac5510
chore: lint
stevedylandev Dec 2, 2025
593cceb
chore: Merge branch 'main' into feat/open-api
stevedylandev Dec 16, 2025
dc38b3b
chore: fix merge conflict aftermath
stevedylandev Dec 16, 2025
132f36b
chore: updated name and description for openapi spec
stevedylandev Dec 16, 2025
7f1ed55
chore: Updates to name-tokens-api types
stevedylandev Dec 18, 2025
6993d26
chore: relocated resolution response schemas
stevedylandev Dec 18, 2025
aed5cd4
chore: updated resolution schemas
stevedylandev Dec 18, 2025
4cad8db
chore: revert registrar api
stevedylandev Dec 18, 2025
35668e4
chore: moved zod schema exports to internal.ts
stevedylandev Dec 19, 2025
ddfad21
chore: applied suggested changes from PR #1414
stevedylandev Dec 19, 2025
d51eaad
chore: rename resolver and remove unnecessary comments
stevedylandev Dec 19, 2025
37382ab
chore: applied suggestions from review
stevedylandev Dec 19, 2025
025691a
chore: merge main
stevedylandev Dec 19, 2025
c8daee5
chore: small updates per review feedback
stevedylandev Dec 19, 2025
3547a15
chore: updated logic for indexing error
stevedylandev Dec 19, 2025
bb6766c
chore: updated response codes for name tokens api
stevedylandev Dec 19, 2025
818bbc2
chore: updated query object for docs
stevedylandev Dec 19, 2025
1ce8577
chore: lint
stevedylandev Dec 19, 2025
11181af
chore: updated lndexing-status description
stevedylandev Dec 22, 2025
bf2cf56
chore: Merge branch 'main' into feat/open-api
stevedylandev Dec 22, 2025
a637380
chore: applied suggestions from review
stevedylandev Dec 22, 2025
25596f4
chore: applied suggestions from review
stevedylandev Dec 23, 2025
c6ad743
chore: update validation errror response
stevedylandev Dec 23, 2025
d8925ad
chore: updated validate and error-response
stevedylandev Dec 23, 2025
c00f656
chore: refactored 404 responses from name tokens api
stevedylandev Dec 23, 2025
58b9e73
chore: added 400 reponse to name tokens api schema
stevedylandev Dec 23, 2025
c436fd0
chore: updated error message for 503
stevedylandev Dec 23, 2025
f91a9f8
chore: updated comment
stevedylandev Dec 23, 2025
7603c97
chore: updated description for name tokens api 503 response
stevedylandev Dec 29, 2025
6a8ac0b
chore: refactored response schema and added 500 case
stevedylandev Dec 29, 2025
508260a
chore: update comment
stevedylandev Dec 29, 2025
42d4577
Merge branch 'main' into feat/open-api
stevedylandev Dec 29, 2025
487a39a
chore: lint
stevedylandev Dec 29, 2025
ce12087
chore: updated comments
stevedylandev Dec 29, 2025
335fe6e
Merge branch 'main' into feat/open-api
stevedylandev Dec 29, 2025
aaeb6b2
chore: updated indexing status checks
stevedylandev Dec 30, 2025
91e7942
Merge branch 'main' into feat/open-api
stevedylandev Dec 30, 2025
95b79ec
docs(changeset): Adds OpenAPI schema endpoint and route descriptions …
stevedylandev Dec 30, 2025
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
6 changes: 6 additions & 0 deletions .changeset/vast-parents-roll.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@ensnode/ensnode-sdk": patch
"ensapi": patch
---

Adds OpenAPI schema endpoint and route descriptions to ENSApi
3 changes: 3 additions & 0 deletions apps/ensapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@ensnode/ponder-subgraph": "workspace:*",
"@hono/node-server": "^1.19.5",
"@hono/otel": "^0.2.2",
"@hono/standard-validator": "^0.2.0",
"@hono/zod-validator": "^0.7.2",
"@namehash/ens-referrals": "workspace:*",
"@opentelemetry/api": "^1.9.0",
Expand All @@ -40,9 +41,11 @@
"@opentelemetry/sdk-trace-node": "^2.0.1",
"@opentelemetry/semantic-conventions": "^1.34.0",
"@ponder/utils": "catalog:",
"@standard-schema/utils": "^0.3.0",
"date-fns": "catalog:",
"drizzle-orm": "catalog:",
"hono": "catalog:",
"hono-openapi": "^1.1.1",
"p-memoize": "^8.0.0",
"p-retry": "^7.1.0",
"pg-connection-string": "catalog:",
Expand Down
96 changes: 71 additions & 25 deletions apps/ensapi/src/handlers/ensnode-api.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import config from "@/config";

import { describeRoute, resolver as validationResolver } from "hono-openapi";

import {
IndexingStatusResponseCodes,
type IndexingStatusResponseError,
type IndexingStatusResponseOk,
serializeENSApiPublicConfig,
serializeIndexingStatusResponse,
} from "@ensnode/ensnode-sdk";
import {
makeENSApiPublicConfigSchema,
makeIndexingStatusResponseSchema,
} from "@ensnode/ensnode-sdk/internal";

import { buildEnsApiPublicConfig } from "@/config/config.schema";
import { factory } from "@/lib/hono-factory";
Expand All @@ -17,36 +23,76 @@ import resolutionApi from "./resolution-api";

const app = factory.createApp();

// include ENSApi Public Config endpoint
app.get("/config", async (c) => {
const ensApiPublicConfig = buildEnsApiPublicConfig(config);
return c.json(serializeENSApiPublicConfig(ensApiPublicConfig));
});
app.get(
"/config",
describeRoute({
summary: "Get ENSApi Public Config",
description: "Gets the public config of the ENSApi instance",
responses: {
200: {
description: "Successfully retrieved ENSApi public config",
content: {
"application/json": {
schema: validationResolver(makeENSApiPublicConfigSchema()),
},
},
},
},
}),
async (c) => {
const ensApiPublicConfig = buildEnsApiPublicConfig(config);
return c.json(serializeENSApiPublicConfig(ensApiPublicConfig));
},
);

app.get(
"/indexing-status",
describeRoute({
summary: "Get ENSIndexer Indexing Status",
description: "Returns the indexing status snapshot most recently captured from ENSIndexer",
responses: {
200: {
description: "Successfully retrieved indexing status",
content: {
"application/json": {
schema: validationResolver(makeIndexingStatusResponseSchema()),
},
},
},
503: {
description: "Indexing status snapshot unavailable",
content: {
"application/json": {
schema: validationResolver(makeIndexingStatusResponseSchema()),
},
},
},
},
}),
async (c) => {
// context must be set by the required middleware
if (c.var.indexingStatus === undefined) {
throw new Error(`Invariant(indexing-status): indexingStatusMiddleware required`);
}

// include ENSIndexer Indexing Status endpoint
app.get("/indexing-status", async (c) => {
// context must be set by the required middleware
if (c.var.indexingStatus === undefined) {
throw new Error(`Invariant(ensnode-api): indexingStatusMiddleware required`);
}
if (c.var.indexingStatus instanceof Error) {
return c.json(
serializeIndexingStatusResponse({
responseCode: IndexingStatusResponseCodes.Error,
} satisfies IndexingStatusResponseError),
503,
);
}

if (c.var.indexingStatus instanceof Error) {
// return successful response using the indexing status projection from the middleware context
return c.json(
serializeIndexingStatusResponse({
responseCode: IndexingStatusResponseCodes.Error,
} satisfies IndexingStatusResponseError),
503,
responseCode: IndexingStatusResponseCodes.Ok,
realtimeProjection: c.var.indexingStatus,
} satisfies IndexingStatusResponseOk),
);
}

// return successful response using the indexing status projection from the context
return c.json(
serializeIndexingStatusResponse({
responseCode: IndexingStatusResponseCodes.Ok,
realtimeProjection: c.var.indexingStatus,
} satisfies IndexingStatusResponseOk),
);
});
},
);

// Name Tokens API
app.route("/name-tokens", nameTokensApi);
Expand Down
Loading