From acebde717c49593b728c175ef90e7abcad0c5ce8 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:03:49 +0100 Subject: [PATCH 01/28] Mechanical updates only Replacements applied: - `databaseSchemaName` to `ensIndexerSchemaName` - `databaseUrl` to `ensDbUrl` - `DATABASE_SCHEMA` to `ENSINDEXER_SCHEMA_NAME` - `DATABASE_URL` to `ENSDB_URL` - `DatabaseUrlSchema` to `EnsDbUrlSchema` - `DatabaseSchemaNameSchema` to `EnsIndexerSchemaNameSchema` --- apps/ensadmin/src/app/mock/config-api.mock.ts | 2 +- .../src/app/mock/config-info/data.json | 10 +-- apps/ensapi/src/config/config.schema.test.ts | 26 +++--- apps/ensapi/src/config/config.schema.ts | 4 +- .../src/config/config.singleton.test.ts | 14 ++-- apps/ensapi/src/config/ensdb-config.schema.ts | 8 +- apps/ensapi/src/config/environment.ts | 4 +- apps/ensapi/src/config/redact.ts | 2 +- .../src/handlers/subgraph/subgraph-api.ts | 2 +- apps/ensapi/src/lib/ensdb/singleton.ts | 4 +- apps/ensindexer/src/config/config.schema.ts | 14 ++-- apps/ensindexer/src/config/config.test.ts | 84 ++++++++++--------- apps/ensindexer/src/config/environment.ts | 4 +- apps/ensindexer/src/config/redact.ts | 2 +- apps/ensindexer/src/config/serialize.ts | 4 +- .../ensindexer/src/lib/__test__/mockConfig.ts | 4 +- .../ensdb-writer-worker.mock.ts | 2 +- apps/ensindexer/src/lib/ensdb/singleton.ts | 2 +- .../public-config-builder.test.ts | 14 ++-- .../public-config-builder.ts | 2 +- docker-compose.yml | 6 +- .../src/content/docs/docs/usage/api.mdx | 2 +- .../ensdb-sdk/src/client/ensdb-client.mock.ts | 2 +- .../ensnode-sdk/src/ensapi/client.test.ts | 2 +- .../src/ensapi/config/conversions.test.ts | 4 +- .../ensnode-sdk/src/ensindexer/client.mock.ts | 2 +- .../src/ensindexer/config/compatibility.ts | 2 +- .../src/ensindexer/config/conversions.test.ts | 4 +- .../src/ensindexer/config/serialize.ts | 4 +- .../src/ensindexer/config/zod-schemas.test.ts | 26 +++--- .../src/ensindexer/config/zod-schemas.ts | 6 +- .../ensnode-sdk/src/shared/config/types.ts | 4 +- .../src/shared/config/zod-schemas.ts | 6 +- 33 files changed, 143 insertions(+), 135 deletions(-) diff --git a/apps/ensadmin/src/app/mock/config-api.mock.ts b/apps/ensadmin/src/app/mock/config-api.mock.ts index 54d0244f91..0181cc2046 100644 --- a/apps/ensadmin/src/app/mock/config-api.mock.ts +++ b/apps/ensadmin/src/app/mock/config-api.mock.ts @@ -6,7 +6,7 @@ export const ensIndexerPublicConfig = deserializeENSIndexerPublicConfig({ labelSetVersion: 0, }, indexedChainIds: [1, 8453, 59144, 10, 42161, 534352, 567], - databaseSchemaName: "alphaSchema0.34.0", + ensIndexerSchemaName: "alphaSchema0.34.0", ensRainbowPublicConfig: { version: "0.34.0", labelSet: { diff --git a/apps/ensadmin/src/app/mock/config-info/data.json b/apps/ensadmin/src/app/mock/config-info/data.json index fd9319ecba..43de682f44 100644 --- a/apps/ensadmin/src/app/mock/config-info/data.json +++ b/apps/ensadmin/src/app/mock/config-info/data.json @@ -11,7 +11,7 @@ "labelSetVersion": 0 }, "indexedChainIds": [1, 8453, 59144, 10, 42161, 534352, 567], - "databaseSchemaName": "alphaSchema0.34.0", + "ensIndexerSchemaName": "alphaSchema0.34.0", "ensRainbowPublicConfig": { "version": "0.34.0", "labelSet": { @@ -68,7 +68,7 @@ "protocol-acceleration", "registrars" ], - "databaseSchemaName": "alphaSepoliaSchema0.34.0", + "ensIndexerSchemaName": "alphaSepoliaSchema0.34.0", "ensRainbowPublicConfig": { "version": "0.34.0", "labelSet": { @@ -101,7 +101,7 @@ "indexedChainIds": [1], "namespace": "mainnet", "plugins": ["subgraph"], - "databaseSchemaName": "mainnetSchema0.34.0", + "ensIndexerSchemaName": "mainnetSchema0.34.0", "ensRainbowPublicConfig": { "version": "0.34.0", "labelSet": { @@ -134,7 +134,7 @@ "indexedChainIds": [11155111], "namespace": "sepolia", "plugins": ["subgraph"], - "databaseSchemaName": "sepoliaSchema0.34.0", + "ensIndexerSchemaName": "sepoliaSchema0.34.0", "ensRainbowPublicConfig": { "version": "0.34.0", "labelSet": { @@ -167,7 +167,7 @@ "indexedChainIds": [11155111], "namespace": "sepolia", "plugins": ["subgraph"], - "databaseSchemaName": "DeserializationSchema0.34.0", + "ensIndexerSchemaName": "DeserializationSchema0.34.0", "ensRainbowPublicConfig": { "version": "", "labelSet": { diff --git a/apps/ensapi/src/config/config.schema.test.ts b/apps/ensapi/src/config/config.schema.test.ts index 7c4ef0ccec..fb8c4bbd82 100644 --- a/apps/ensapi/src/config/config.schema.test.ts +++ b/apps/ensapi/src/config/config.schema.test.ts @@ -26,13 +26,13 @@ vi.mock("@/lib/logger", () => ({ const VALID_RPC_URL = "https://eth-sepolia.g.alchemy.com/v2/1234"; const BASE_ENV = { - DATABASE_URL: "postgresql://user:password@localhost:5432/mydb", + ENSDB_URL: "postgresql://user:password@localhost:5432/mydb", RPC_URL_1: VALID_RPC_URL, } satisfies EnsApiEnvironment; const ENSINDEXER_PUBLIC_CONFIG = { namespace: "mainnet", - databaseSchemaName: "ensapi", + ensIndexerSchemaName: "ensindexer_0", ensRainbowPublicConfig: { version: packageJson.version, labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 }, @@ -55,12 +55,12 @@ describe("buildConfigFromEnvironment", () => { it("returns a valid config object using environment variables", async () => { await expect(buildConfigFromEnvironment(BASE_ENV)).resolves.toStrictEqual({ port: ENSApi_DEFAULT_PORT, - databaseUrl: BASE_ENV.DATABASE_URL, + ensDbUrl: BASE_ENV.ENSDB_URL, theGraphApiKey: undefined, ensIndexerPublicConfig: ENSINDEXER_PUBLIC_CONFIG, namespace: ENSINDEXER_PUBLIC_CONFIG.namespace, - ensIndexerSchemaName: ENSINDEXER_PUBLIC_CONFIG.databaseSchemaName, + ensIndexerSchemaName: ENSINDEXER_PUBLIC_CONFIG.ensIndexerSchemaName, rpcConfigs: new Map([ [ 1, @@ -98,7 +98,7 @@ describe("buildConfigFromEnvironment", () => { }); const TEST_ENV: EnsApiEnvironment = { - DATABASE_URL: BASE_ENV.DATABASE_URL, + ENSDB_URL: BASE_ENV.ENSDB_URL, }; it("logs error and exits when CUSTOM_REFERRAL_PROGRAM_EDITIONS is not a valid URL", async () => { @@ -149,10 +149,10 @@ describe("buildEnsApiPublicConfig", () => { it("returns a valid ENSApi public config with correct structure", () => { const mockConfig = { port: ENSApi_DEFAULT_PORT, - databaseUrl: BASE_ENV.DATABASE_URL, + ensDbUrl: BASE_ENV.ENSDB_URL, ensIndexerPublicConfig: ENSINDEXER_PUBLIC_CONFIG, namespace: ENSINDEXER_PUBLIC_CONFIG.namespace, - ensIndexerSchemaName: ENSINDEXER_PUBLIC_CONFIG.databaseSchemaName, + ensIndexerSchemaName: ENSINDEXER_PUBLIC_CONFIG.ensIndexerSchemaName, rpcConfigs: new Map([ [ 1, @@ -180,10 +180,10 @@ describe("buildEnsApiPublicConfig", () => { it("preserves the complete ENSIndexer public config structure", () => { const mockConfig = { port: ENSApi_DEFAULT_PORT, - databaseUrl: BASE_ENV.DATABASE_URL, + ensDbUrl: BASE_ENV.ENSDB_URL, ensIndexerPublicConfig: ENSINDEXER_PUBLIC_CONFIG, namespace: ENSINDEXER_PUBLIC_CONFIG.namespace, - ensIndexerSchemaName: ENSINDEXER_PUBLIC_CONFIG.databaseSchemaName, + ensIndexerSchemaName: ENSINDEXER_PUBLIC_CONFIG.ensIndexerSchemaName, rpcConfigs: new Map(), customReferralProgramEditionConfigSetUrl: undefined, }; @@ -201,22 +201,22 @@ describe("buildEnsApiPublicConfig", () => { ENSINDEXER_PUBLIC_CONFIG.isSubgraphCompatible, ); expect(result.ensIndexerPublicConfig.labelSet).toEqual(ENSINDEXER_PUBLIC_CONFIG.labelSet); - expect(result.ensIndexerPublicConfig.databaseSchemaName).toBe( - ENSINDEXER_PUBLIC_CONFIG.databaseSchemaName, + expect(result.ensIndexerPublicConfig.ensIndexerSchemaName).toBe( + ENSINDEXER_PUBLIC_CONFIG.ensIndexerSchemaName, ); }); it("includes the theGraphFallback and redacts api key", () => { const mockConfig = { port: ENSApi_DEFAULT_PORT, - databaseUrl: BASE_ENV.DATABASE_URL, + ensDbUrl: BASE_ENV.ENSDB_URL, ensIndexerPublicConfig: { ...ENSINDEXER_PUBLIC_CONFIG, plugins: ["subgraph"], isSubgraphCompatible: true, }, namespace: ENSINDEXER_PUBLIC_CONFIG.namespace, - ensIndexerSchemaName: ENSINDEXER_PUBLIC_CONFIG.databaseSchemaName, + ensIndexerSchemaName: ENSINDEXER_PUBLIC_CONFIG.ensIndexerSchemaName, rpcConfigs: new Map(), customReferralProgramEditionConfigSetUrl: undefined, theGraphApiKey: "secret-api-key", diff --git a/apps/ensapi/src/config/config.schema.ts b/apps/ensapi/src/config/config.schema.ts index e608b74c0c..e64c17da34 100644 --- a/apps/ensapi/src/config/config.schema.ts +++ b/apps/ensapi/src/config/config.schema.ts @@ -90,11 +90,11 @@ export async function buildConfigFromEnvironment(env: EnsApiEnvironment): Promis return EnsApiConfigSchema.parse({ port: env.PORT, - databaseUrl: env.DATABASE_URL, + ensDbUrl: env.ENSDB_URL, theGraphApiKey: env.THEGRAPH_API_KEY, ensIndexerPublicConfig, namespace: ensIndexerPublicConfig.namespace, - ensIndexerSchemaName: ensIndexerPublicConfig.databaseSchemaName, + ensIndexerSchemaName: ensIndexerPublicConfig.ensIndexerSchemaName, rpcConfigs, customReferralProgramEditionConfigSetUrl: env.CUSTOM_REFERRAL_PROGRAM_EDITIONS, }); diff --git a/apps/ensapi/src/config/config.singleton.test.ts b/apps/ensapi/src/config/config.singleton.test.ts index 29f52cd493..191ddc4cfa 100644 --- a/apps/ensapi/src/config/config.singleton.test.ts +++ b/apps/ensapi/src/config/config.singleton.test.ts @@ -7,14 +7,14 @@ vi.mock("@/lib/logger", () => ({ }, })); -const VALID_DB_URL = "postgresql://user:password@localhost:5432/mydb"; -const VALID_SCHEMA_NAME = "ensapi"; +const VALID_ENSDB_URL = "postgresql://user:password@localhost:5432/mydb"; +const VALID_ENSINDEXER_SCHEMA_NAME = "ensapi"; describe("ensdb singleton bootstrap", () => { beforeEach(() => { vi.resetModules(); - vi.stubEnv("DATABASE_URL", VALID_DB_URL); - vi.stubEnv("ENSINDEXER_SCHEMA_NAME", VALID_SCHEMA_NAME); + vi.stubEnv("ENSDB_URL", VALID_ENSDB_URL); + vi.stubEnv("ENSINDEXER_SCHEMA_NAME", VALID_ENSINDEXER_SCHEMA_NAME); }); afterEach(() => { @@ -26,18 +26,18 @@ describe("ensdb singleton bootstrap", () => { // ensDbClient is a lazyProxy — construction is deferred until first property access. // Accessing a property triggers EnsDbReader construction; verify it succeeds. - expect(ensDbClient.ensIndexerSchemaName).toBe(VALID_SCHEMA_NAME); + expect(ensDbClient.ensIndexerSchemaName).toBe(VALID_ENSINDEXER_SCHEMA_NAME); expect(ensDb).toBeDefined(); expect(ensIndexerSchema).toBeDefined(); }); - it("exits when DATABASE_URL is missing", async () => { + it("exits when ENSDB_URL is missing", async () => { const mockExit = vi.spyOn(process, "exit").mockImplementation((() => { throw new Error("process.exit"); }) as never); const { default: logger } = await import("@/lib/logger"); - vi.stubEnv("DATABASE_URL", ""); + vi.stubEnv("ENSDB_URL", ""); // ensDbClient is a lazyProxy — import succeeds but first property access triggers construction, // which calls buildEnsDbConfigFromEnvironment and exits on invalid config. const { ensDbClient } = await import("@/lib/ensdb/singleton"); diff --git a/apps/ensapi/src/config/ensdb-config.schema.ts b/apps/ensapi/src/config/ensdb-config.schema.ts index eabf2b0fc0..8dbfdcc854 100644 --- a/apps/ensapi/src/config/ensdb-config.schema.ts +++ b/apps/ensapi/src/config/ensdb-config.schema.ts @@ -4,7 +4,7 @@ import { prettifyError, z } from "zod/v4"; import type { EnsApiEnvironment } from "@/config/environment"; import logger from "@/lib/logger"; -export const DatabaseUrlSchema = z.string().refine( +export const EnsDbUrlSchema = z.string().refine( (url) => { try { if (!url.startsWith("postgresql://") && !url.startsWith("postgres://")) { @@ -18,7 +18,7 @@ export const DatabaseUrlSchema = z.string().refine( }, { error: - "Invalid PostgreSQL connection string. Expected format: postgresql://username:password@host:port/database", + "Invalid PostgreSQL connection string for ENSDb. Expected format: postgresql://username:password@host:port/database", }, ); @@ -32,7 +32,7 @@ const EnsIndexerSchemaNameSchema = z }); export const EnsDbConfigSchema = z.object({ - databaseUrl: DatabaseUrlSchema, + ensDbUrl: EnsDbUrlSchema, ensIndexerSchemaName: EnsIndexerSchemaNameSchema, }); @@ -45,7 +45,7 @@ export type EnsDbConfig = z.infer; */ export function buildEnsDbConfigFromEnvironment(env: EnsApiEnvironment): EnsDbConfig { const ensDbConfig = EnsDbConfigSchema.safeParse({ - databaseUrl: env.DATABASE_URL, + ensDbUrl: env.ENSDB_URL, ensIndexerSchemaName: env.ENSINDEXER_SCHEMA_NAME, }); diff --git a/apps/ensapi/src/config/environment.ts b/apps/ensapi/src/config/environment.ts index 305f671b4d..adb00fe7e1 100644 --- a/apps/ensapi/src/config/environment.ts +++ b/apps/ensapi/src/config/environment.ts @@ -1,5 +1,5 @@ import type { - EnsApiDatabaseEnvironment, + DatabaseEnvironment, LogLevelEnvironment, PortEnvironment, ReferralProgramEditionsEnvironment, @@ -14,7 +14,7 @@ import type { * their state in `process.env`. This interface is intended to be the source type which then gets * mapped/parsed into a structured configuration object like `EnsApiConfig`. */ -export type EnsApiEnvironment = EnsApiDatabaseEnvironment & +export type EnsApiEnvironment = DatabaseEnvironment & RpcEnvironment & PortEnvironment & LogLevelEnvironment & diff --git a/apps/ensapi/src/config/redact.ts b/apps/ensapi/src/config/redact.ts index c26730cacc..3399ee1ae5 100644 --- a/apps/ensapi/src/config/redact.ts +++ b/apps/ensapi/src/config/redact.ts @@ -8,7 +8,7 @@ import type { EnsApiConfig } from "@/config/config.schema"; export function redactEnsApiConfig(config: EnsApiConfig) { return { ...config, - databaseUrl: redactString(config.databaseUrl), + ensDbUrl: redactString(config.ensDbUrl), rpcConfigs: redactRpcConfigs(config.rpcConfigs), }; } diff --git a/apps/ensapi/src/handlers/subgraph/subgraph-api.ts b/apps/ensapi/src/handlers/subgraph/subgraph-api.ts index a3e8a71dc9..74c000e8ac 100644 --- a/apps/ensapi/src/handlers/subgraph/subgraph-api.ts +++ b/apps/ensapi/src/handlers/subgraph/subgraph-api.ts @@ -55,7 +55,7 @@ app.use(subgraphMetaMiddleware); // imported without env vars being present (e.g. during OpenAPI generation). const getSubgraphMiddleware = lazy(() => subgraphGraphQLMiddleware({ - databaseUrl: config.databaseUrl, + databaseUrl: config.ensDbUrl, databaseSchema: config.ensIndexerSchemaName, schema: subgraphSchema, // describes the polymorphic (interface) relationships in the schema diff --git a/apps/ensapi/src/lib/ensdb/singleton.ts b/apps/ensapi/src/lib/ensdb/singleton.ts index b2d4ee481b..0e392fd53a 100644 --- a/apps/ensapi/src/lib/ensdb/singleton.ts +++ b/apps/ensapi/src/lib/ensdb/singleton.ts @@ -10,8 +10,8 @@ import { lazyProxy } from "@/lib/lazy"; * Singleton instance of ENSDbReader for the ENSApi application. */ export const ensDbClient = lazyProxy(() => { - const { databaseUrl, ensIndexerSchemaName } = buildEnsDbConfigFromEnvironment(process.env); - return new EnsDbReader(databaseUrl, ensIndexerSchemaName); + const { ensDbUrl, ensIndexerSchemaName } = buildEnsDbConfigFromEnvironment(process.env); + return new EnsDbReader(ensDbUrl, ensIndexerSchemaName); }); /** diff --git a/apps/ensindexer/src/config/config.schema.ts b/apps/ensindexer/src/config/config.schema.ts index ef14defcd8..3eb404204c 100644 --- a/apps/ensindexer/src/config/config.schema.ts +++ b/apps/ensindexer/src/config/config.schema.ts @@ -4,8 +4,8 @@ import { prettifyError, ZodError, z } from "zod/v4"; import { buildBlockNumberRange, PluginName, uniq } from "@ensnode/ensnode-sdk"; import { buildRpcConfigsFromEnv, - DatabaseSchemaNameSchema, ENSNamespaceSchema, + EnsIndexerSchemaNameSchema, EnsIndexerUrlSchema, invariant_isSubgraphCompatibleRequirements, invariant_rpcConfigsSpecifiedForRootChain, @@ -28,7 +28,7 @@ import { invariant_validContractConfigs, } from "./validations"; -export const DatabaseUrlSchema = z.string().refine( +export const EnsDbUrlSchema = z.string().refine( (url) => { try { if (!url.startsWith("postgresql://") && !url.startsWith("postgres://")) { @@ -42,7 +42,7 @@ export const DatabaseUrlSchema = z.string().refine( }, { error: - "Invalid PostgreSQL connection string. Expected format: postgresql://username:password@host:port/database", + "Invalid PostgreSQL connection string for ENSDb. Expected format: postgresql://username:password@host:port/database", }, ); @@ -107,8 +107,8 @@ const IsSubgraphCompatibleSchema = const ENSIndexerConfigSchema = z .object({ - databaseUrl: DatabaseUrlSchema, - databaseSchemaName: DatabaseSchemaNameSchema, + ensDbUrl: EnsDbUrlSchema, + ensIndexerSchemaName: EnsIndexerSchemaNameSchema, rpcConfigs: RpcConfigsSchema, ensIndexerUrl: EnsIndexerUrlSchema, @@ -186,8 +186,8 @@ export function buildConfigFromEnvironment(_env: ENSIndexerEnvironment): EnsInde // parse/validate with ENSIndexerConfigSchema return ENSIndexerConfigSchema.parse({ - databaseUrl: env.DATABASE_URL, - databaseSchemaName: env.DATABASE_SCHEMA, + ensDbUrl: env.ENSDB_URL, + ensIndexerSchemaName: env.ENSINDEXER_SCHEMA_NAME, ensIndexerUrl: env.ENSINDEXER_URL, namespace: env.NAMESPACE, rpcConfigs, diff --git a/apps/ensindexer/src/config/config.test.ts b/apps/ensindexer/src/config/config.test.ts index 7deb8a22f2..f6ae74e1aa 100644 --- a/apps/ensindexer/src/config/config.test.ts +++ b/apps/ensindexer/src/config/config.test.ts @@ -23,8 +23,8 @@ const VALID_RPC_WS_URL_ALT = "wss://lb.drpc.org/ethereum/987"; const BASE_ENV: ENSIndexerEnvironment = { NAMESPACE: "mainnet", PLUGINS: "subgraph", - DATABASE_SCHEMA: "ensnode", - DATABASE_URL: "postgresql://user:password@localhost:5432/mydb", + ENSINDEXER_SCHEMA_NAME: "ensnode", + ENSDB_URL: "postgresql://user:password@localhost:5432/mydb", ENSINDEXER_URL: "http://localhost:42069", ENSRAINBOW_URL: "http://localhost:3223", LABEL_SET_ID: "ens-test-env", @@ -67,7 +67,7 @@ describe("config (with base env)", () => { const config = await getConfig(); expect(config.namespace).toBe("mainnet"); expect(config.globalBlockrange).toEqual(buildBlockNumberRange(undefined, undefined)); - expect(config.databaseSchemaName).toBe("ensnode"); + expect(config.ensIndexerSchemaName).toBe("ensnode"); expect(config.plugins).toEqual(["subgraph"]); expect(config.ensRainbowUrl).toStrictEqual(new URL("http://localhost:3223")); }); @@ -190,29 +190,29 @@ describe("config (with base env)", () => { }); }); - describe(".databaseSchemaName", () => { - it("returns the DATABASE_SCHEMA if set", async () => { - vi.stubEnv("DATABASE_SCHEMA", "someschema"); + describe(".ensIndexerSchemaName", () => { + it("returns the ENSINDEXER_SCHEMA_NAME if set", async () => { + vi.stubEnv("ENSINDEXER_SCHEMA_NAME", "someschema"); const config = await getConfig(); - expect(config.databaseSchemaName).toBe("someschema"); + expect(config.ensIndexerSchemaName).toBe("someschema"); }); - it("throws an error when DATABASE_SCHEMA is not set", async () => { - vi.stubEnv("DATABASE_SCHEMA", undefined); - await expect(getConfig()).rejects.toThrow(/DATABASE_SCHEMA is required/); + it("throws an error when ENSINDEXER_SCHEMA_NAME is not set", async () => { + vi.stubEnv("ENSINDEXER_SCHEMA_NAME", undefined); + await expect(getConfig()).rejects.toThrow(/ENSINDEXER_SCHEMA_NAME is required/); }); - it("throws an error when DATABASE_SCHEMA is empty", async () => { - vi.stubEnv("DATABASE_SCHEMA", ""); + it("throws an error when ENSINDEXER_SCHEMA_NAME is empty", async () => { + vi.stubEnv("ENSINDEXER_SCHEMA_NAME", ""); await expect(getConfig()).rejects.toThrow( - /DATABASE_SCHEMA is required and cannot be an empty string/, + /ENSINDEXER_SCHEMA_NAME is required and cannot be an empty string/, ); }); - it("throws an error when DATABASE_SCHEMA is only whitespace", async () => { - vi.stubEnv("DATABASE_SCHEMA", " "); + it("throws an error when ENSINDEXER_SCHEMA_NAME is only whitespace", async () => { + vi.stubEnv("ENSINDEXER_SCHEMA_NAME", " "); await expect(getConfig()).rejects.toThrow( - /DATABASE_SCHEMA is required and cannot be an empty string/, + /ENSINDEXER_SCHEMA_NAME is required and cannot be an empty string/, ); }); }); @@ -416,56 +416,56 @@ describe("config (with base env)", () => { }); }); - describe(".databaseUrl", () => { + describe(".ensDbUrl", () => { it("accepts a valid PostgreSQL connection string", async () => { - vi.stubEnv("DATABASE_URL", "postgresql://user:password@localhost:5432/mydb"); + vi.stubEnv("ENSDB_URL", "postgresql://user:password@localhost:5432/mydb"); const config = await getConfig(); - expect(config.databaseUrl).toBe("postgresql://user:password@localhost:5432/mydb"); + expect(config.ensDbUrl).toBe("postgresql://user:password@localhost:5432/mydb"); }); it("accepts a connection string with additional parameters", async () => { - vi.stubEnv("DATABASE_URL", "postgresql://user:password@localhost:5432/mydb?sslmode=require"); + vi.stubEnv("ENSDB_URL", "postgresql://user:password@localhost:5432/mydb?sslmode=require"); const config = await getConfig(); - expect(config.databaseUrl).toBe( + expect(config.ensDbUrl).toBe( "postgresql://user:password@localhost:5432/mydb?sslmode=require", ); }); - it("throws an error if DATABASE_URL is not set", async () => { - vi.stubEnv("DATABASE_URL", undefined); + it("throws an error if ENSDB_URL is not set", async () => { + vi.stubEnv("ENSDB_URL", undefined); await expect(getConfig()).rejects.toThrow(/Invalid input/); }); - it("throws an error if DATABASE_URL is empty", async () => { - vi.stubEnv("DATABASE_URL", ""); + it("throws an error if ENSDB_URL is empty", async () => { + vi.stubEnv("ENSDB_URL", ""); await expect(getConfig()).rejects.toThrow(/Invalid PostgreSQL connection string/); }); - it("throws an error if DATABASE_URL is not a valid postgres connection string", async () => { - vi.stubEnv("DATABASE_URL", "not-a-postgres-connection-string"); + it("throws an error if ENSDB_URL is not a valid postgres connection string", async () => { + vi.stubEnv("ENSDB_URL", "not-a-postgres-connection-string"); await expect(getConfig()).rejects.toThrow(/Invalid PostgreSQL connection string/); }); - it("throws an error if DATABASE_URL uses the wrong protocol", async () => { - vi.stubEnv("DATABASE_URL", "mysql://user:password@localhost:3306/mydb"); + it("throws an error if ENSDB_URL uses the wrong protocol", async () => { + vi.stubEnv("ENSDB_URL", "mysql://user:password@localhost:3306/mydb"); await expect(getConfig()).rejects.toThrow(/Invalid PostgreSQL connection string/); }); - it("throws an error if DATABASE_URL is missing required components", async () => { - vi.stubEnv("DATABASE_URL", "postgresql://localhost:5432"); + it("throws an error if ENSDB_URL is missing required components", async () => { + vi.stubEnv("ENSDB_URL", "postgresql://localhost:5432"); await expect(getConfig()).rejects.toThrow(/Invalid PostgreSQL connection string/); }); it("accepts postgres:// protocol", async () => { - vi.stubEnv("DATABASE_URL", "postgres://user:password@localhost:5432/mydb"); + vi.stubEnv("ENSDB_URL", "postgres://user:password@localhost:5432/mydb"); const config = await getConfig(); - expect(config.databaseUrl).toBe("postgres://user:password@localhost:5432/mydb"); + expect(config.ensDbUrl).toBe("postgres://user:password@localhost:5432/mydb"); }); it("accepts postgresql:// protocol", async () => { - vi.stubEnv("DATABASE_URL", "postgresql://user:password@localhost:5432/mydb"); + vi.stubEnv("ENSDB_URL", "postgresql://user:password@localhost:5432/mydb"); const config = await getConfig(); - expect(config.databaseUrl).toBe("postgresql://user:password@localhost:5432/mydb"); + expect(config.ensDbUrl).toBe("postgresql://user:password@localhost:5432/mydb"); }); }); @@ -676,14 +676,20 @@ describe("config (with base env)", () => { */ describe("config (minimal base env)", () => { beforeEach(() => { - const { NAMESPACE, ENSINDEXER_URL, ENSRAINBOW_URL, DATABASE_URL, DATABASE_SCHEMA, RPC_URL_1 } = - BASE_ENV; + const { + NAMESPACE, + ENSINDEXER_URL, + ENSRAINBOW_URL, + ENSDB_URL, + ENSINDEXER_SCHEMA_NAME, + RPC_URL_1, + } = BASE_ENV; stubEnv({ NAMESPACE, ENSINDEXER_URL, ENSRAINBOW_URL, - DATABASE_URL, - DATABASE_SCHEMA, + ENSDB_URL, + ENSINDEXER_SCHEMA_NAME, RPC_URL_1, }); }); diff --git a/apps/ensindexer/src/config/environment.ts b/apps/ensindexer/src/config/environment.ts index 33092d21fb..ca2a46ffa2 100644 --- a/apps/ensindexer/src/config/environment.ts +++ b/apps/ensindexer/src/config/environment.ts @@ -1,5 +1,5 @@ import type { - EnsIndexerDatabaseEnvironment, + DatabaseEnvironment, EnsIndexerUrlEnvironment, RpcEnvironment, } from "@ensnode/ensnode-sdk/internal"; @@ -11,7 +11,7 @@ import type { * their state in `process.env`. This interface is intended to be the source type which then gets * mapped/parsed into a structured configuration object like `ENSIndexerConfig`. */ -export type ENSIndexerEnvironment = EnsIndexerDatabaseEnvironment & +export type ENSIndexerEnvironment = DatabaseEnvironment & EnsIndexerUrlEnvironment & RpcEnvironment & { NAMESPACE?: string; diff --git a/apps/ensindexer/src/config/redact.ts b/apps/ensindexer/src/config/redact.ts index 91d7376703..04a166314a 100644 --- a/apps/ensindexer/src/config/redact.ts +++ b/apps/ensindexer/src/config/redact.ts @@ -8,7 +8,7 @@ import type { ENSIndexerConfig } from "@/config/types"; export function redactENSIndexerConfig(config: ENSIndexerConfig) { return { ...config, - databaseUrl: redactString(config.databaseUrl), + ensDbUrl: redactString(config.ensDbUrl), rpcConfigs: redactRpcConfigs(config.rpcConfigs), }; } diff --git a/apps/ensindexer/src/config/serialize.ts b/apps/ensindexer/src/config/serialize.ts index 3324d9d2dd..1d30d97e87 100644 --- a/apps/ensindexer/src/config/serialize.ts +++ b/apps/ensindexer/src/config/serialize.ts @@ -44,8 +44,8 @@ export function serializeRedactedENSIndexerConfig( const redactedConfig = redactENSIndexerConfig(config); return { - databaseSchemaName: redactedConfig.databaseSchemaName, - databaseUrl: redactedConfig.databaseUrl, + ensIndexerSchemaName: redactedConfig.ensIndexerSchemaName, + ensDbUrl: redactedConfig.ensDbUrl, ensIndexerUrl: serializeUrl(redactedConfig.ensIndexerUrl), ensRainbowUrl: serializeUrl(redactedConfig.ensRainbowUrl), labelSet: redactedConfig.labelSet, diff --git a/apps/ensindexer/src/lib/__test__/mockConfig.ts b/apps/ensindexer/src/lib/__test__/mockConfig.ts index 8bd2acb4c4..086fbbc04a 100644 --- a/apps/ensindexer/src/lib/__test__/mockConfig.ts +++ b/apps/ensindexer/src/lib/__test__/mockConfig.ts @@ -8,8 +8,8 @@ import { deepClone } from "@/lib/lib-helpers"; // default, non-exported mock configuration template const _defaultMockConfig = buildConfigFromEnvironment({ - DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/postgres", - DATABASE_SCHEMA: "test_schema", + ENSDB_URL: "postgresql://postgres:postgres@localhost:5432/postgres", + ENSINDEXER_SCHEMA_NAME: "ensindexer_0", NAMESPACE: "mainnet", PLUGINS: "subgraph", ENSINDEXER_URL: "http://localhost:42069", diff --git a/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.mock.ts b/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.mock.ts index daaa6968b6..40cc671e98 100644 --- a/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.mock.ts +++ b/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.mock.ts @@ -36,7 +36,7 @@ export const mockVersionInfo: EnsIndexerVersionInfo = { // Test fixture for EnsIndexerPublicConfig export const mockPublicConfig: EnsIndexerPublicConfig = { - databaseSchemaName: "public", + ensIndexerSchemaName: "ensindexer_0", labelSet: { labelSetId: "subgraph", labelSetVersion: 0 }, ensRainbowPublicConfig: mockEnsRainbowPublicConfig, indexedChainIds: new Set([1, 8453]), diff --git a/apps/ensindexer/src/lib/ensdb/singleton.ts b/apps/ensindexer/src/lib/ensdb/singleton.ts index 1250e4f410..08cd7707fe 100644 --- a/apps/ensindexer/src/lib/ensdb/singleton.ts +++ b/apps/ensindexer/src/lib/ensdb/singleton.ts @@ -2,7 +2,7 @@ import config from "@/config"; import { EnsDbWriter } from "@ensnode/ensdb-sdk"; -const { databaseUrl: ensDbUrl, databaseSchemaName: ensIndexerSchemaName } = config; +const { ensDbUrl, ensIndexerSchemaName } = config; /** * Singleton instance of ENSDbWriter for the ENSIndexer application. diff --git a/apps/ensindexer/src/lib/public-config-builder/public-config-builder.test.ts b/apps/ensindexer/src/lib/public-config-builder/public-config-builder.test.ts index 7810d9159d..220161eb2f 100644 --- a/apps/ensindexer/src/lib/public-config-builder/public-config-builder.test.ts +++ b/apps/ensindexer/src/lib/public-config-builder/public-config-builder.test.ts @@ -14,7 +14,7 @@ import { PublicConfigBuilder } from "./public-config-builder"; // Mock the config module vi.mock("@/config", () => ({ default: { - databaseSchemaName: "public", + ensIndexerSchemaName: "ensindexer_0", labelSet: { labelSetId: "subgraph", labelSetVersion: 0 }, indexedChainIds: new Set([1, 8453]), isSubgraphCompatible: true, @@ -68,7 +68,7 @@ const mockVersionInfo: EnsIndexerVersionInfo = { // Helper to create unique mock config objects for each call function createMockPublicConfig(overrides: Partial = {}) { return { - databaseSchemaName: "public", + ensIndexerSchemaName: "ensindexer_0", labelSet: { labelSetId: "subgraph", labelSetVersion: 0 }, ensRainbowPublicConfig: mockEnsRainbowConfig, indexedChainIds: new Set([1, 8453]), @@ -125,7 +125,7 @@ describe("PublicConfigBuilder", () => { }); expect(validateEnsIndexerPublicConfig).toHaveBeenCalledWith({ - databaseSchemaName: config.databaseSchemaName, + ensIndexerSchemaName: config.ensIndexerSchemaName, ensRainbowPublicConfig: mockEnsRainbowConfig, labelSet: config.labelSet, indexedChainIds: config.indexedChainIds, @@ -301,8 +301,8 @@ describe("PublicConfigBuilder", () => { describe("Caching behavior", () => { it("each builder instance has its own independent cache", async () => { // Arrange - create unique config objects for each builder - const config1 = createMockPublicConfig({ databaseSchemaName: "schema1" }); - const config2 = createMockPublicConfig({ databaseSchemaName: "schema2" }); + const config1 = createMockPublicConfig({ ensIndexerSchemaName: "schema1" }); + const config2 = createMockPublicConfig({ ensIndexerSchemaName: "schema2" }); let callCount = 0; const ensRainbowClientMock = { @@ -331,8 +331,8 @@ describe("PublicConfigBuilder", () => { expect(result1).toBe(config1); expect(result2).toBe(config2); expect(result1).not.toBe(result2); - expect(result1.databaseSchemaName).toBe("schema1"); - expect(result2.databaseSchemaName).toBe("schema2"); + expect(result1.ensIndexerSchemaName).toBe("schema1"); + expect(result2.ensIndexerSchemaName).toBe("schema2"); }); it("retries building config on subsequent calls after failure", async () => { diff --git a/apps/ensindexer/src/lib/public-config-builder/public-config-builder.ts b/apps/ensindexer/src/lib/public-config-builder/public-config-builder.ts index 33d5911518..206c3aa6af 100644 --- a/apps/ensindexer/src/lib/public-config-builder/public-config-builder.ts +++ b/apps/ensindexer/src/lib/public-config-builder/public-config-builder.ts @@ -51,7 +51,7 @@ export class PublicConfigBuilder { ]); this.immutablePublicConfig = validateEnsIndexerPublicConfig({ - databaseSchemaName: config.databaseSchemaName, + ensIndexerSchemaName: config.ensIndexerSchemaName, ensRainbowPublicConfig, labelSet: config.labelSet, indexedChainIds: config.indexedChainIds, diff --git a/docker-compose.yml b/docker-compose.yml index 7239f80665..39bf06ace6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,8 +6,8 @@ services: - "42069:42069" environment: # Override environment variables to point to docker instances - DATABASE_URL: postgresql://postgres:password@postgres:5432/postgres - DATABASE_SCHEMA: ensindexer_0 + ENSDB_URL: postgresql://postgres:password@postgres:5432/postgres + ENSINDEXER_SCHEMA_NAME: ensindexer_0 ENSRAINBOW_URL: http://ensrainbow:3223 ENSINDEXER_URL: http://ensindexer:42069 env_file: @@ -35,7 +35,7 @@ services: - "4334:4334" environment: # Override environment variables to point to docker instances - DATABASE_URL: postgresql://postgres:password@postgres:5432/postgres + ENSDB_URL: postgresql://postgres:password@postgres:5432/postgres ENSINDEXER_SCHEMA_NAME: ensindexer_0 env_file: # NOTE: must define apps/ensapi/.env.local (see apps/ensapi/.env.local.example) diff --git a/docs/ensnode.io/src/content/docs/docs/usage/api.mdx b/docs/ensnode.io/src/content/docs/docs/usage/api.mdx index db67ae306b..9a1b42c5cf 100644 --- a/docs/ensnode.io/src/content/docs/docs/usage/api.mdx +++ b/docs/ensnode.io/src/content/docs/docs/usage/api.mdx @@ -100,7 +100,7 @@ The response includes several important configuration categories: 42161, 534352 ], - "databaseSchemaName": "alphaSchema0.35.0", + "ensIndexerSchemaName": "alphaSchema0.35.0", "isSubgraphCompatible": false, "labelSet": { "labelSetId": "subgraph", diff --git a/packages/ensdb-sdk/src/client/ensdb-client.mock.ts b/packages/ensdb-sdk/src/client/ensdb-client.mock.ts index 7cb2c59d0b..21cbdcd596 100644 --- a/packages/ensdb-sdk/src/client/ensdb-client.mock.ts +++ b/packages/ensdb-sdk/src/client/ensdb-client.mock.ts @@ -24,7 +24,7 @@ export const ensDbUrl = "postgres://user:pass@localhost:5432/ensdb"; export const ensIndexerSchemaName = "ensindexer_0"; export const publicConfig = { - databaseSchemaName: ensIndexerSchemaName, + ensIndexerSchemaName, ensRainbowPublicConfig: { version: "0.32.0", labelSet: { diff --git a/packages/ensnode-sdk/src/ensapi/client.test.ts b/packages/ensnode-sdk/src/ensapi/client.test.ts index f53ea9ce0b..acb3db6222 100644 --- a/packages/ensnode-sdk/src/ensapi/client.test.ts +++ b/packages/ensnode-sdk/src/ensapi/client.test.ts @@ -74,7 +74,7 @@ const EXAMPLE_CONFIG_RESPONSE = { labelSetVersion: 0, }, indexedChainIds: [1, 8453, 59144, 10, 42161, 534352], - databaseSchemaName: "alphaSchema0.31.0", + ensIndexerSchemaName: "alphaSchema0.31.0", isSubgraphCompatible: false, namespace: "mainnet", plugins: [ diff --git a/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts b/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts index ae15afb0cc..c9ebd0bf30 100644 --- a/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts +++ b/packages/ensnode-sdk/src/ensapi/config/conversions.test.ts @@ -16,7 +16,7 @@ const MOCK_ENSAPI_PUBLIC_CONFIG = { }, ensIndexerPublicConfig: { namespace: ENSNamespaceIds.Mainnet, - databaseSchemaName: "ensapi", + ensIndexerSchemaName: "ensindexer_0", ensRainbowPublicConfig: { version: "0.36.0", labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 }, @@ -51,7 +51,7 @@ describe("ENSApi Config Serialization/Deserialization", () => { }, ensIndexerPublicConfig: { namespace: ENSNamespaceIds.Mainnet, - databaseSchemaName: "ensapi", + ensIndexerSchemaName: "ensindexer_0", ensRainbowPublicConfig: { version: "0.36.0", labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 }, diff --git a/packages/ensnode-sdk/src/ensindexer/client.mock.ts b/packages/ensnode-sdk/src/ensindexer/client.mock.ts index 84d0ceaa2e..c504f5e059 100644 --- a/packages/ensnode-sdk/src/ensindexer/client.mock.ts +++ b/packages/ensnode-sdk/src/ensindexer/client.mock.ts @@ -13,7 +13,7 @@ export const configResponseMock = { labelSetVersion: 0, }, indexedChainIds: [1, 8453, 59144, 10, 42161, 534352], - databaseSchemaName: "alphaSchema0.31.0", + ensIndexerSchemaName: "alphaSchema0.31.0", ensRainbowPublicConfig: { version: "0.31.0", labelSet: { diff --git a/packages/ensnode-sdk/src/ensindexer/config/compatibility.ts b/packages/ensnode-sdk/src/ensindexer/config/compatibility.ts index 2258e2b8de..b38f3769c1 100644 --- a/packages/ensnode-sdk/src/ensindexer/config/compatibility.ts +++ b/packages/ensnode-sdk/src/ensindexer/config/compatibility.ts @@ -2,7 +2,7 @@ import type { EnsIndexerPublicConfig } from "./types"; export type EnsIndexerPublicConfigCompatibilityCheck = Omit< EnsIndexerPublicConfig, - "databaseSchemaName" | "ensRainbowPublicConfig" | "versionInfo" + "ensIndexerSchemaName" | "ensRainbowPublicConfig" | "versionInfo" >; /** diff --git a/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts b/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts index 79b1c82c0c..7f1051adf6 100644 --- a/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts +++ b/packages/ensnode-sdk/src/ensindexer/config/conversions.test.ts @@ -10,7 +10,7 @@ describe("ENSIndexer: Config", () => { it("can serialize EnsIndexerPublicConfig", () => { // arrange const config = { - databaseSchemaName: "public", + ensIndexerSchemaName: "ensindexer_0", ensRainbowPublicConfig: { version: "0.32.0", labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 }, @@ -53,7 +53,7 @@ describe("ENSIndexer: Config", () => { describe("deserialization", () => { const correctSerializedConfig = { - databaseSchemaName: "public", + ensIndexerSchemaName: "ensindexer_0", ensRainbowPublicConfig: { version: "0.32.0", labelSet: { labelSetId: "subgraph", highestLabelSetVersion: 0 }, diff --git a/packages/ensnode-sdk/src/ensindexer/config/serialize.ts b/packages/ensnode-sdk/src/ensindexer/config/serialize.ts index a24838803e..5e42b736df 100644 --- a/packages/ensnode-sdk/src/ensindexer/config/serialize.ts +++ b/packages/ensnode-sdk/src/ensindexer/config/serialize.ts @@ -19,7 +19,7 @@ export function serializeEnsIndexerPublicConfig( config: EnsIndexerPublicConfig, ): SerializedEnsIndexerPublicConfig { const { - databaseSchemaName, + ensIndexerSchemaName, ensRainbowPublicConfig, indexedChainIds, isSubgraphCompatible, @@ -30,7 +30,7 @@ export function serializeEnsIndexerPublicConfig( } = config; return { - databaseSchemaName, + ensIndexerSchemaName, ensRainbowPublicConfig, indexedChainIds: serializeIndexedChainIds(indexedChainIds), isSubgraphCompatible, diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts index 1822516131..5174c53143 100644 --- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts +++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.test.ts @@ -5,8 +5,8 @@ import { buildUnvalidatedEnsIndexerPublicConfig } from "./deserialize"; import type { SerializedEnsIndexerPublicConfig } from "./serialized-types"; import { type EnsIndexerVersionInfo, PluginName } from "./types"; import { - makeDatabaseSchemaNameSchema, makeEnsIndexerPublicConfigSchema, + makeEnsIndexerSchemaNameSchema, makeEnsIndexerVersionInfoSchema, makeFullyPinnedLabelSetSchema, makeIndexedChainIdsSchema, @@ -21,12 +21,12 @@ describe("ENSIndexer: Config", () => { describe("Parsing", () => { it("can parse database schema name values", () => { - expect(makeDatabaseSchemaNameSchema().parse("public")).toBe("public"); - expect(makeDatabaseSchemaNameSchema().parse("the_schema")).toBe("the_schema"); - expect(makeDatabaseSchemaNameSchema().parse("theSchema")).toBe("theSchema"); + expect(makeEnsIndexerSchemaNameSchema().parse("public")).toBe("public"); + expect(makeEnsIndexerSchemaNameSchema().parse("the_schema")).toBe("the_schema"); + expect(makeEnsIndexerSchemaNameSchema().parse("theSchema")).toBe("theSchema"); - expect(formatParseError(makeDatabaseSchemaNameSchema().safeParse(1))).toContain( - "Database schema name must be a string", + expect(formatParseError(makeEnsIndexerSchemaNameSchema().safeParse(1))).toContain( + "ENS Indexer Schema Name must be a string", ); }); @@ -169,7 +169,7 @@ describe("ENSIndexer: Config", () => { isSubgraphCompatible: false, // Set to false to bypass isSubgraphCompatible invariant namespace: "mainnet" as const, plugins: [PluginName.Subgraph, PluginName.Registrars], // Multiple plugins allowed when not subgraph compatible - databaseSchemaName: "test_schema", + ensIndexerSchemaName: "ensindexer_0", versionInfo: { nodejs: "v22.22.22", ponder: "0.11.25", @@ -224,7 +224,7 @@ describe("ENSIndexer: Config", () => { isSubgraphCompatible: true, namespace: "mainnet" as const, plugins: [PluginName.Subgraph], - databaseSchemaName: "test_schema", + ensIndexerSchemaName: "ensindexer_0", versionInfo: { nodejs: "v22.22.22", ponder: "0.11.25", @@ -271,11 +271,13 @@ describe("ENSIndexer: Config", () => { describe("Useful error messages", () => { it("can apply custom value labels", () => { expect( - formatParseError(makeDatabaseSchemaNameSchema("databaseSchema").safeParse("")), - ).toContain("databaseSchema is required and must be a non-empty string."); + formatParseError(makeEnsIndexerSchemaNameSchema("ensIndexerSchemaName").safeParse("")), + ).toContain("ensIndexerSchemaName is required and must be a non-empty string."); expect( - formatParseError(makeDatabaseSchemaNameSchema("DATABASE_SCHEMA env var").safeParse("")), - ).toContain("DATABASE_SCHEMA env var is required and must be a non-empty string."); + formatParseError( + makeEnsIndexerSchemaNameSchema("ENSINDEXER_SCHEMA_NAME env var").safeParse(""), + ), + ).toContain("ENSINDEXER_SCHEMA_NAME env var is required and must be a non-empty string."); expect( formatParseError( diff --git a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts index c491b88445..ecaf713e09 100644 --- a/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts +++ b/packages/ensnode-sdk/src/ensindexer/config/zod-schemas.ts @@ -63,7 +63,7 @@ export const makePluginsListSchema = (valueLabel: string = "Plugins") => * * The name is guaranteed to be a non-empty string. */ -export const makeDatabaseSchemaNameSchema = (valueLabel: string = "Database schema name") => +export const makeEnsIndexerSchemaNameSchema = (valueLabel: string = "ENS Indexer Schema Name") => z .string({ error: `${valueLabel} must be a string` }) .trim() @@ -162,7 +162,7 @@ export function invariant_ensRainbowSupportedLabelSetAndVersion( export const makeEnsIndexerPublicConfigSchema = (valueLabel: string = "ENSIndexerPublicConfig") => z .object({ - databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`), + ensIndexerSchemaName: makeEnsIndexerSchemaNameSchema(`${valueLabel}.ensIndexerSchemaName`), ensRainbowPublicConfig: makeEnsRainbowPublicConfigSchema( `${valueLabel}.ensRainbowPublicConfig`, ), @@ -194,7 +194,7 @@ export const makeSerializedEnsIndexerPublicConfigSchema = ( valueLabel: string = "Serialized ENSIndexerPublicConfig", ) => z.object({ - databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`), + ensIndexerSchemaName: makeEnsIndexerSchemaNameSchema(`${valueLabel}.ensIndexerSchemaName`), ensRainbowPublicConfig: makeEnsRainbowPublicConfigSchema( `${valueLabel}.ensRainbowPublicConfig`, ), diff --git a/packages/ensnode-sdk/src/shared/config/types.ts b/packages/ensnode-sdk/src/shared/config/types.ts index 1248870a79..d717501dbe 100644 --- a/packages/ensnode-sdk/src/shared/config/types.ts +++ b/packages/ensnode-sdk/src/shared/config/types.ts @@ -3,7 +3,7 @@ import type { z } from "zod/v4"; import type { UrlString } from "../serialized-types"; import type { ChainId } from "../types"; import type { - DatabaseSchemaNameSchema, + EnsIndexerSchemaNameSchema, EnsIndexerUrlSchema, PortNumberSchema, TheGraphApiKeySchema, @@ -46,7 +46,7 @@ export interface RpcConfig { export type RpcConfigs = Map; export type DatabaseUrl = UrlString; -export type DatabaseSchemaName = z.infer; +export type EnsIndexerSchemaName = z.infer; export type EnsIndexerUrl = z.infer; export type TheGraphApiKey = z.infer; diff --git a/packages/ensnode-sdk/src/shared/config/zod-schemas.ts b/packages/ensnode-sdk/src/shared/config/zod-schemas.ts index 91c9b9b83c..09c5b3ef6b 100644 --- a/packages/ensnode-sdk/src/shared/config/zod-schemas.ts +++ b/packages/ensnode-sdk/src/shared/config/zod-schemas.ts @@ -12,13 +12,13 @@ import { invariant_rpcEndpointConfigIncludesAtMostOneWebSocketsProtocolURL, } from "./validatons"; -export const DatabaseSchemaNameSchema = z +export const EnsIndexerSchemaNameSchema = z .string({ - error: "DATABASE_SCHEMA is required.", + error: "ENSINDEXER_SCHEMA_NAME is required.", }) .trim() .min(1, { - error: "DATABASE_SCHEMA is required and cannot be an empty string.", + error: "ENSINDEXER_SCHEMA_NAME is required and cannot be an empty string.", }); const RpcConfigSchema = z From dfbf9df070bf4cd12d2955afb96e8d6404e906d4 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:09:55 +0100 Subject: [PATCH 02/28] Update ENSAdmin: connection view tooltips --- .../connection/cards/ensnode-info.tsx | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx index d922aa9462..b17540689f 100644 --- a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx +++ b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx @@ -299,12 +299,12 @@ function ENSNodeConfigCardContent({ Postgres

} /> {ensIndexerPublicConfig.databaseSchemaName}

+

{ensIndexerPublicConfig.ensIndexerSchemaName}

} additionalInfo={ -

ENSApi reads indexed data from tables within this Postgres database schema.

+

ENSApi reads indexed data from tables within this ENSIndexer Schema in ENSDb.

} /> Postgres

} /> {ensIndexerPublicConfig.databaseSchemaName}

+

{ensIndexerPublicConfig.ensIndexerSchemaName}

} additionalInfo={ -

ENSIndexer writes indexed data to tables within this Postgres database schema.

+

+ ENSIndexer writes indexed data to tables within this ENSIndexer Schema in ENSDb. +

} />
@@ -412,12 +414,14 @@ function ENSNodeConfigCardContent({ Postgres

} /> {ensIndexerPublicConfig.databaseSchemaName}

+

{ensIndexerPublicConfig.ensIndexerSchemaName}

} additionalInfo={ -

ENSIndexer writes indexed data to tables within this Postgres database schema.

+

+ ENSIndexer writes indexed data to tables within this ENSIndexer Schema in ENSDb. +

} /> Date: Wed, 25 Mar 2026 18:10:28 +0100 Subject: [PATCH 03/28] Update `.env.local.example` files for ENSApi and ENSIndexer --- apps/ensapi/.env.local.example | 8 ++++---- apps/ensindexer/.env.local.example | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/ensapi/.env.local.example b/apps/ensapi/.env.local.example index 8d4832ea0c..393a19fd12 100644 --- a/apps/ensapi/.env.local.example +++ b/apps/ensapi/.env.local.example @@ -4,15 +4,15 @@ # ENSDb: Database URL # Required. This is the connection string for the ENSDb database in which ENSIndexer is storing data. -# It should match the DATABASE_URL used by your ENSIndexer. +# It should match the ENSDB_URL used by your ENSIndexer. # It should be in the format of `postgresql://:@:/` # # See https://ensnode.io/ensindexer/usage/configuration for additional information. -DATABASE_URL=postgresql://dbuser:abcd1234@localhost:5432/my_database +ENSDB_URL=postgresql://dbuser:abcd1234@localhost:5432/my_database # ENSDb: ENSIndexer Schema Name -# Required. This is a name of the database schema in DATABASE_URL where ENSApi should read indexed data stored by your ENSIndexer. -# It should match the DATABASE_SCHEMA used by your ENSIndexer. +# Required. This is a name of the ENSIndexer Schema in ENSDb where ENSApi should read indexed data stored by your ENSIndexer. +# It should match the ENSINDEXER_SCHEMA_NAME used by your ENSIndexer. ENSINDEXER_SCHEMA_NAME=ensindexer_0 # ENSApi: RPC Configuration diff --git a/apps/ensindexer/.env.local.example b/apps/ensindexer/.env.local.example index 0d2c9ec33a..e4701ebbd8 100644 --- a/apps/ensindexer/.env.local.example +++ b/apps/ensindexer/.env.local.example @@ -166,27 +166,27 @@ # - required if the configured namespace is ens-test-env # RPC_URL_1337= -# Database configuration -# Required. This is a namespace for the tables that the indexer will create to store indexed data. +# ENSDb config: ENSIndexer Schema Name +# Required. This is a name of the ENSIndexer Schema in ENSDb where the indexer will create tables to store indexed data. # It should be a string that is unique to the running indexer instance. # -# Keeping the database schema unique to the indexer instance is important to +# Keeping the ENSINDEXER_SCHEMA_NAME value unique to the ENSIndexer instance is important to # 1) speed up indexing after a restart -# 2) prevent data corruption from multiple indexer app instances writing state +# 2) prevent data corruption from multiple ENSIndexer instances writing state # concurrently to the same db schema # -# No two indexer instances can use the same database schema at the same time. +# No two ENSIndexer instances can use the same database schema at the same time. # # Read more about database schema rules here: -# https://ponder.sh/docs/api-reference/database#database-schema-rules +# https://ponder.sh/docs/api-reference/ponder/database#database-schema-rules # # Avoid using the `public` schema as we force that in the `dev` command. Using `public` # cause conflicts as you interchange between dev and start commands so use literally # anything else. -DATABASE_SCHEMA=production +ENSINDEXER_SCHEMA_NAME=ensindexer_0 # Required. This is the connection string for the database that the indexer will use to store data. # It should be in the format of `postgresql://:@:/` -DATABASE_URL=postgresql://dbuser:abcd1234@localhost:5432/my_database +ENSDB_URL=postgresql://dbuser:abcd1234@localhost:5432/my_database # ENS Namespace Configuration # Required. Must be an ENS namespace's Identifier such as mainnet, sepolia, or ens-test-env. From 70d5f309aa28bc6b63f3627be1ccb12f4dd33736 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:11:59 +0100 Subject: [PATCH 04/28] Update code docs for `EnsIndexerConfig` and `EnsIndexerPublicConfig` types --- apps/ensindexer/src/config/types.ts | 19 ++++++++++--------- .../src/ensindexer/config/types.ts | 6 +++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/ensindexer/src/config/types.ts b/apps/ensindexer/src/config/types.ts index 279ec90184..f8fdf59134 100644 --- a/apps/ensindexer/src/config/types.ts +++ b/apps/ensindexer/src/config/types.ts @@ -1,8 +1,8 @@ import type { ENSNamespaceId } from "@ensnode/datasources"; import type { BlockNumberRange, ChainId, PluginName } from "@ensnode/ensnode-sdk"; import { - type DatabaseSchemaName, type DatabaseUrl, + type EnsIndexerSchemaName, RpcConfig, type RpcConfigs, } from "@ensnode/ensnode-sdk/internal"; @@ -38,15 +38,15 @@ export interface EnsIndexerConfig { labelSet: Required; /** - * A Postgres database schema name. This instance of ENSIndexer will write indexed data to the - * tables in this schema. + * The name of the ENSIndexer Schema in the ENSDb instance, + * which the ENSIndexer instance will use while indexing and querying. * - * The {@link databaseSchemaName} must be unique per running instance of ENSIndexer (ponder will + * The {@link ensIndexerSchemaName} must be unique per running instance of ENSIndexer (ponder will * enforce this with database locks). If multiple instances of ENSIndexer with the same - * {@link databaseSchemaName} are running, only the first will successfully acquire the lock and begin + * {@link ensIndexerSchemaName} are running, only the first will successfully acquire the lock and begin * indexing: the rest will crash. * - * If an ENSIndexer instance with the same configuration (including `databaseSchemaName`) is + * If an ENSIndexer instance with the same configuration (including `ensIndexerSchemaName`) is * started, and it successfully acquires the lock on this schema, it will continue indexing from * the current state. * @@ -58,7 +58,7 @@ export interface EnsIndexerConfig { * Invariants: * - Must be a non-empty string that is a valid Postgres database schema identifier. */ - databaseSchemaName: DatabaseSchemaName; + ensIndexerSchemaName: EnsIndexerSchemaName; /** * A set of {@link PluginName}s indicating which plugins to activate. @@ -91,12 +91,13 @@ export interface EnsIndexerConfig { indexedChainIds: Set; /** - * The database connection string for the indexer. + * The connection string for ENSIndexer instance to connect to + * the ENSDb instance. * * Invariants: * - The URL must be a valid PostgreSQL connection string */ - databaseUrl: DatabaseUrl; + ensDbUrl: DatabaseUrl; /** * The "primary" ENSIndexer service URL diff --git a/packages/ensnode-sdk/src/ensindexer/config/types.ts b/packages/ensnode-sdk/src/ensindexer/config/types.ts index afc70c50dd..7d69475284 100644 --- a/packages/ensnode-sdk/src/ensindexer/config/types.ts +++ b/packages/ensnode-sdk/src/ensindexer/config/types.ts @@ -87,14 +87,14 @@ export interface EnsIndexerPublicConfig { labelSet: Required; /** - * A Postgres database schema name. This instance of ENSIndexer will write - * indexed data to the tables in this schema. + * The name of the ENSIndexer Schema in the ENSDb instance, + * which the ENSIndexer instance will write indexed data to. * * Invariants: * - Must be a non-empty string that is a valid Postgres database schema * identifier. */ - databaseSchemaName: string; + ensIndexerSchemaName: string; /** * ENSRainbow public config From 4daa3880f01cffa5c5fb93fff6b94bcd0cd9f5ff Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:13:33 +0100 Subject: [PATCH 05/28] Update docs: releases page --- docs/ensnode.io/src/content/docs/docs/contributing/releases.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ensnode.io/src/content/docs/docs/contributing/releases.mdx b/docs/ensnode.io/src/content/docs/docs/contributing/releases.mdx index 00d26d9817..3b9e11f418 100644 --- a/docs/ensnode.io/src/content/docs/docs/contributing/releases.mdx +++ b/docs/ensnode.io/src/content/docs/docs/contributing/releases.mdx @@ -110,7 +110,7 @@ In particular, when deploying ENSNode to production environments, using the `lat ::: :::caution -Each ENSIndexer version update is likely to produce an updated [Ponder Build Id](https://ponder.sh/docs/api-reference/ponder/database). When updating your ENSIndexer version, you should expect to update the `DATABASE_SCHEMA` environment variable to point to a new Postgres Database Schema for a complete reindexing with the new Ponder Build Id. A complete reindexing may take over 24 hours depending on your configuration. ENSNode version updates require special coordination and should not be assumed to be a simple version bump. +Each ENSIndexer version update is likely to produce an updated [Ponder Build Id](https://ponder.sh/docs/api-reference/ponder/database). When updating your ENSIndexer version, you should expect to update the `ENSINDEXER_SCHEMA_NAME` environment variable to point to a new ENSIndexer Schema in ENSDb for a complete reindexing with the new Ponder Build Id. A complete reindexing may take over 24 hours depending on your configuration. ENSNode version updates require special coordination and should not be assumed to be a simple version bump. ::: From e9064485af2550b7ca128a44bf47acbef90352f2 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:14:13 +0100 Subject: [PATCH 06/28] Make a single `DatabaseEnvironments` type for ENSApi and ENSIndexer to use --- .../ensnode-sdk/src/shared/config/environments.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/ensnode-sdk/src/shared/config/environments.ts b/packages/ensnode-sdk/src/shared/config/environments.ts index 02f24b10ec..2f58862d7c 100644 --- a/packages/ensnode-sdk/src/shared/config/environments.ts +++ b/packages/ensnode-sdk/src/shared/config/environments.ts @@ -1,19 +1,11 @@ /** - * Environment variables for ENSApi database configuration. + * Environment variables for database configuration. */ -export interface EnsApiDatabaseEnvironment { - DATABASE_URL?: string; +export interface DatabaseEnvironment { + ENSDB_URL?: string; ENSINDEXER_SCHEMA_NAME?: string; } -/** - * Environment variables for ENSIndexer database configuration. - */ -export interface EnsIndexerDatabaseEnvironment { - DATABASE_URL?: string; - DATABASE_SCHEMA?: string; -} - /** * Environment variables for RPC configuration. */ From dda93259a7242f746ec1a5126196b7b8320303bc Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:16:24 +0100 Subject: [PATCH 07/28] Update `dev` and `start` commands for `ensindexer` app Ponder requires setting the database schema value with either `DATABASE_SCHEMA` evn var, or `--schema` CLI arg. We just stopped using the `DATABASE_SCHEMA` env var, so we need to use the `--schema` CLI arg and pass the selected ENSIndexer Schema Name value there. --- apps/ensindexer/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ensindexer/package.json b/apps/ensindexer/package.json index 3859f3dc32..357555f76e 100644 --- a/apps/ensindexer/package.json +++ b/apps/ensindexer/package.json @@ -12,8 +12,8 @@ }, "homepage": "https://github.com/namehash/ensnode/tree/main/apps/ensindexer", "scripts": { - "dev": "DATABASE_SCHEMA=public ponder --root ./ponder dev --disable-ui", - "start": "ponder --root ./ponder start", + "dev": "ENSINDEXER_SCHEMA_NAME=public ponder --root ./ponder dev --disable-ui --schema public", + "start": "ponder --root ./ponder start --schema $ENSINDEXER_SCHEMA_NAME", "serve": "ponder --root ./ponder serve", "db": "ponder --root ./ponder db", "codegen": "ponder --root ./ponder codegen", From 76fb7643cee2f0aa59134fe6dc704dcba628fc17 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:16:35 +0100 Subject: [PATCH 08/28] Code cleanup --- apps/ensapi/src/lib/handlers/drizzle.ts | 32 ------------------------- 1 file changed, 32 deletions(-) delete mode 100644 apps/ensapi/src/lib/handlers/drizzle.ts diff --git a/apps/ensapi/src/lib/handlers/drizzle.ts b/apps/ensapi/src/lib/handlers/drizzle.ts deleted file mode 100644 index a5d8f36daf..0000000000 --- a/apps/ensapi/src/lib/handlers/drizzle.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { setDatabaseSchema } from "@ponder/client"; -import { drizzle } from "drizzle-orm/node-postgres"; - -import { makeLogger } from "@/lib/logger"; - -type Schema = { [name: string]: unknown }; - -const logger = makeLogger("drizzle"); - -/** - * Makes a Drizzle DB object. - */ -export const makeDrizzle = ({ - schema, - databaseUrl, - databaseSchema, -}: { - schema: SCHEMA; - databaseUrl: string; - databaseSchema: string; -}) => { - // monkeypatch schema onto tables - setDatabaseSchema(schema, databaseSchema); - - return drizzle(databaseUrl, { - schema, - casing: "snake_case", - logger: { - logQuery: (query, params) => logger.trace({ params }, query), - }, - }); -}; From 84f395874d5b885b78bf19499c7b0a6ed9ebfaf4 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:28:22 +0100 Subject: [PATCH 09/28] Fix redacted `EnsApiConfig` object Using lazy proxy for constructing `config` object does not allow for using `...config` spread operator. Instead, we have to list the `config` fields manually. --- apps/ensapi/src/config/redact.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/ensapi/src/config/redact.ts b/apps/ensapi/src/config/redact.ts index 3399ee1ae5..e8cc47a339 100644 --- a/apps/ensapi/src/config/redact.ts +++ b/apps/ensapi/src/config/redact.ts @@ -7,7 +7,10 @@ import type { EnsApiConfig } from "@/config/config.schema"; */ export function redactEnsApiConfig(config: EnsApiConfig) { return { - ...config, + port: config.port, + namespace: config.namespace, + customReferralProgramEditionConfigSetUrl: config.customReferralProgramEditionConfigSetUrl, + ensIndexerPublicConfig: config.ensIndexerPublicConfig, ensDbUrl: redactString(config.ensDbUrl), rpcConfigs: redactRpcConfigs(config.rpcConfigs), }; From ee9facdd6abd7a4db55b3ef317c7b319e952acc5 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:39:29 +0100 Subject: [PATCH 10/28] docs(changeset): Renamed the `databaseSchemaName` field on `EnsIndexerPublicConfig` type to `ensIndexerSchemaName`. --- .changeset/metal-views-start.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/metal-views-start.md diff --git a/.changeset/metal-views-start.md b/.changeset/metal-views-start.md new file mode 100644 index 0000000000..be23169a02 --- /dev/null +++ b/.changeset/metal-views-start.md @@ -0,0 +1,5 @@ +--- +"@ensnode/ensnode-sdk": minor +--- + +Renamed the `databaseSchemaName` field on `EnsIndexerPublicConfig` type to `ensIndexerSchemaName`. From 2463451f0653be8487650eb5b65fe9fe31c85cd8 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:42:58 +0100 Subject: [PATCH 11/28] docs(changeset): Renamed environment variables: `DATABASE_URL` to `ENSDB_URL`, and `DATABASE_SCHEMA` to `ENSINDEXER_SCHEMA_NAME`. --- .changeset/wide-trams-rule.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/wide-trams-rule.md diff --git a/.changeset/wide-trams-rule.md b/.changeset/wide-trams-rule.md new file mode 100644 index 0000000000..f3a90b17a8 --- /dev/null +++ b/.changeset/wide-trams-rule.md @@ -0,0 +1,5 @@ +--- +"ensindexer": minor +--- + +Renamed environment variables: `DATABASE_URL` to `ENSDB_URL`, and `DATABASE_SCHEMA` to `ENSINDEXER_SCHEMA_NAME`. From 39fb4130e8d9bfa52f8331be9433d09da0f10b29 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:44:31 +0100 Subject: [PATCH 12/28] docs(changeset): Renamed environment variable: `DATABASE_URL` to `ENSDB_URL`. --- .changeset/slick-kings-travel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/slick-kings-travel.md diff --git a/.changeset/slick-kings-travel.md b/.changeset/slick-kings-travel.md new file mode 100644 index 0000000000..19dc8699b3 --- /dev/null +++ b/.changeset/slick-kings-travel.md @@ -0,0 +1,5 @@ +--- +"ensapi": minor +--- + +Renamed environment variable: `DATABASE_URL` to `ENSDB_URL`. From 83b8e1aa75985fcae3d3cc60379f20bca7c17b0b Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 18:45:59 +0100 Subject: [PATCH 13/28] docs(changeset): Updated the Connection view to reference "ENSIndexer Schema Name". --- .changeset/slow-readers-pay.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/slow-readers-pay.md diff --git a/.changeset/slow-readers-pay.md b/.changeset/slow-readers-pay.md new file mode 100644 index 0000000000..16f769ad49 --- /dev/null +++ b/.changeset/slow-readers-pay.md @@ -0,0 +1,5 @@ +--- +"ensadmin": minor +--- + +Updated the Connection view to reference "ENSIndexer Schema Name". From 408c182862bd6be27cb58976357532022c02a213 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 19:10:31 +0100 Subject: [PATCH 14/28] Update terraform scripts to reference updated env vars --- terraform/main.tf | 12 ++++++------ terraform/modules/ensindexer/main.tf | 8 +++----- terraform/modules/ensindexer/variables.tf | 5 +++-- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/terraform/main.tf b/terraform/main.tf index 0c2f538fb6..f2d110fb98 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -46,7 +46,7 @@ locals { sepolia = { ensnode_indexer_type = "sepolia" ensnode_environment_name = var.render_environment - database_schema = "sepoliaSchema-${var.ensnode_version}" + ensindexer_schema_name = "sepoliaSchema-${var.ensnode_version}" plugins = "subgraph" namespace = "sepolia" render_instance_plan = "starter" @@ -57,7 +57,7 @@ locals { v2-sepolia = { ensnode_indexer_type = "v2-sepolia" ensnode_environment_name = var.render_environment - database_schema = "v2SepoliaSchema-${var.ensnode_version}" + ensindexer_schema_name = "v2SepoliaSchema-${var.ensnode_version}" plugins = "ensv2,protocol-acceleration" namespace = "sepolia" render_instance_plan = "starter" @@ -68,7 +68,7 @@ locals { mainnet = { ensnode_indexer_type = "mainnet" ensnode_environment_name = var.render_environment - database_schema = "mainnetSchema-${var.ensnode_version}" + ensindexer_schema_name = "mainnetSchema-${var.ensnode_version}" plugins = "subgraph" namespace = "mainnet" render_instance_plan = "standard" @@ -79,7 +79,7 @@ locals { alpha = { ensnode_indexer_type = "alpha" ensnode_environment_name = var.render_environment - database_schema = "alphaSchema-${var.ensnode_version}" + ensindexer_schema_name = "alphaSchema-${var.ensnode_version}" plugins = "subgraph,basenames,lineanames,threedns,protocol-acceleration,registrars,tokenscope" namespace = "mainnet" render_instance_plan = "standard" @@ -91,7 +91,7 @@ locals { alpha-sepolia = { ensnode_indexer_type = "alpha-sepolia" ensnode_environment_name = var.render_environment - database_schema = "alphaSepoliaSchema-${var.ensnode_version}" + ensindexer_schema_name = "alphaSepoliaSchema-${var.ensnode_version}" plugins = "subgraph,basenames,lineanames,registrars" namespace = "sepolia" render_instance_plan = "starter" @@ -161,7 +161,7 @@ module "ensindexer" { ensnode_indexer_type = each.value.ensnode_indexer_type render_instance_plan = each.value.render_instance_plan ensnode_environment_name = each.value.ensnode_environment_name - database_schema = each.value.database_schema + ensindexer_schema_name = each.value.ensindexer_schema_name plugins = each.value.plugins namespace = each.value.namespace subgraph_compat = each.value.subgraph_compat diff --git a/terraform/modules/ensindexer/main.tf b/terraform/modules/ensindexer/main.tf index 847645f96f..5cebe471aa 100644 --- a/terraform/modules/ensindexer/main.tf +++ b/terraform/modules/ensindexer/main.tf @@ -1,7 +1,8 @@ locals { common_variables = { # Common configuration - "DATABASE_URL" = { value = var.ensdb_url }, + "ENSDB_URL" = { value = var.ensdb_url }, + "ENSINDEXER_SCHEMA_NAME" = { value = var.ensindexer_schema_name }, "ALCHEMY_API_KEY" = { value = var.alchemy_api_key } "QUICKNODE_API_KEY" = { value = var.quicknode_api_key } "QUICKNODE_ENDPOINT_NAME" = { value = var.quicknode_endpoint_name } @@ -28,7 +29,6 @@ resource "render_web_service" "ensindexer" { } env_vars = merge(local.common_variables, { - "DATABASE_SCHEMA" = { value = var.database_schema }, "ENSRAINBOW_URL" = { value = var.ensrainbow_url }, "LABEL_SET_ID" = { value = var.ensindexer_label_set_id }, "LABEL_SET_VERSION" = { value = var.ensindexer_label_set_version }, @@ -60,9 +60,7 @@ resource "render_web_service" "ensapi" { } } - env_vars = merge(local.common_variables, { - "ENSINDEXER_SCHEMA_NAME" = { value = var.database_schema }, - }) + env_vars = local.common_variables # See https://render.com/docs/custom-domains custom_domains = [ diff --git a/terraform/modules/ensindexer/variables.tf b/terraform/modules/ensindexer/variables.tf index 392d9c133b..00b0d44d3c 100644 --- a/terraform/modules/ensindexer/variables.tf +++ b/terraform/modules/ensindexer/variables.tf @@ -45,8 +45,9 @@ variable "ensdb_url" { type = string } -variable "database_schema" { - type = string +variable "ensindexer_schema_name" { + type = string + description = "The name of a specific ENSIndexer Schema in ENSDb." } variable "ensrainbow_url" { From fca6b506d08c68d69401aca173f8274fc45d59b9 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 19:10:43 +0100 Subject: [PATCH 15/28] Update integration tests to reference updated env vars --- packages/integration-test-env/src/orchestrator.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/integration-test-env/src/orchestrator.ts b/packages/integration-test-env/src/orchestrator.ts index e46ac7f3b4..4b76832cff 100644 --- a/packages/integration-test-env/src/orchestrator.ts +++ b/packages/integration-test-env/src/orchestrator.ts @@ -259,7 +259,7 @@ async function main() { return c; }); const [postgres] = await Promise.all([postgresPromise, devnetPromise]); - const DATABASE_URL = postgres.getConnectionUri(); + const ENSDB_URL = postgres.getConnectionUri(); log(`Postgres is ready (port ${postgres.getPort()})`); log("Devnet is ready"); @@ -321,8 +321,8 @@ async function main() { ENSINDEXER_DIR, { NAMESPACE: ENSNamespaceIds.EnsTestEnv, - DATABASE_URL, - DATABASE_SCHEMA: ENSINDEXER_SCHEMA_NAME, + ENSDB_URL, + ENSINDEXER_SCHEMA_NAME, PLUGINS: "ensv2,protocol-acceleration", ENSRAINBOW_URL, ENSINDEXER_URL, @@ -334,7 +334,7 @@ async function main() { await waitForHealth(`http://localhost:${ENSINDEXER_PORT}/health`, 60_000, "ENSIndexer"); // Phase 4: Wait for indexing to complete - await pollIndexingStatus(DATABASE_URL, ENSINDEXER_SCHEMA_NAME, 30_000); + await pollIndexingStatus(ENSDB_URL, ENSINDEXER_SCHEMA_NAME, 30_000); // Phase 5: Start ENSApi log("Starting ENSApi..."); @@ -343,7 +343,7 @@ async function main() { ["start"], ENSAPI_DIR, { - DATABASE_URL, + ENSDB_URL, ENSINDEXER_SCHEMA_NAME, }, "ensapi", From b04c90c404742bba59c46eb13643171cbd718b4e Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 19:11:04 +0100 Subject: [PATCH 16/28] Update CI tests to reference updated env vars --- .github/workflows/test_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_ci.yml b/.github/workflows/test_ci.yml index 8564258c22..8a82d89128 100644 --- a/.github/workflows/test_ci.yml +++ b/.github/workflows/test_ci.yml @@ -129,8 +129,8 @@ jobs: # Public RPC URLs are used as fallbacks for repository forks # that don't have the relevant secrets configured. NAMESPACE: mainnet - DATABASE_URL: postgresql://postgres:password@localhost:5432/postgres - DATABASE_SCHEMA: public + ENSDB_URL: postgresql://postgres:password@localhost:5432/postgres + ENSINDEXER_SCHEMA_NAME: public PLUGINS: subgraph,basenames,lineanames,threedns,protocol-acceleration,registrars,tokenscope ENSRAINBOW_URL: https://api.ensrainbow.io ENSINDEXER_URL: http://localhost:42069 From 82ac70bb0c36c580eeb5cc71b49ecff031ca67d2 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 19:12:41 +0100 Subject: [PATCH 17/28] Update the Railway deployment script Requires updating shared variables in Railway --- .github/workflows/deploy_ensnode_blue_green.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy_ensnode_blue_green.yml b/.github/workflows/deploy_ensnode_blue_green.yml index a437c467dd..36b8d3e9da 100644 --- a/.github/workflows/deploy_ensnode_blue_green.yml +++ b/.github/workflows/deploy_ensnode_blue_green.yml @@ -158,7 +158,7 @@ jobs: #ENSADMIN update_service_image ${RAILWAY_ENVIRONMENT_ID} ${ENSADMIN_SVC_ID} ${{ env.ENSADMIN_DOCKER_IMAGE }} - # Update DATABASE_SCHEMA for each indexer based on input tag + # Update ENSINDEXER_SCHEMA_NAME for each indexer based on input tag - name: Update shared environment variable run: | set_shared_variable() { @@ -176,11 +176,11 @@ jobs: echo "Finished setting $variable_name" } - set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA_DATABASE_SCHEMA" "alphaSchema${TAG}" - set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "MAINNET_DATABASE_SCHEMA" "mainnetSchema${TAG}" - set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA-SEPOLIA_DATABASE_SCHEMA" "alphaSepoliaSchema${TAG}" - set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "V2-SEPOLIA_DATABASE_SCHEMA" "v2SepoliaSchema${TAG}" - set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "SEPOLIA_DATABASE_SCHEMA" "sepoliaSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA_ENSINDEXER_SCHEMA_NAME" "alphaSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "MAINNET_ENSINDEXER_SCHEMA_NAME" "mainnetSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA-SEPOLIA_ENSINDEXER_SCHEMA_NAME" "alphaSepoliaSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "V2-SEPOLIA_ENSINDEXER_SCHEMA_NAME" "v2SepoliaSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "SEPOLIA_ENSINDEXER_SCHEMA_NAME" "sepoliaSchema${TAG}" - name: Redeploy ENSNode instances run: | From e60e4c108a89b613085291e047a3ede6b5c91a5d Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 19:12:54 +0100 Subject: [PATCH 18/28] Apply AI PR feedback --- apps/ensindexer/src/config/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ensindexer/src/config/types.ts b/apps/ensindexer/src/config/types.ts index f8fdf59134..7a48519002 100644 --- a/apps/ensindexer/src/config/types.ts +++ b/apps/ensindexer/src/config/types.ts @@ -53,7 +53,7 @@ export interface EnsIndexerConfig { * Many clients can read from this Postgres schema during or after indexing. * * Read more about database schema rules here: - * @see https://ponder.sh/docs/api-reference/database#database-schema-rules + * @see https://ponder.sh/docs/api-reference/ponder/database#database-schema-rules * * Invariants: * - Must be a non-empty string that is a valid Postgres database schema identifier. From e8e4bf5ae8bba5947f0fc463b7b73f66d5d7aa3f Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 19:27:38 +0100 Subject: [PATCH 19/28] Update OpenAPI spec file --- docs/docs.ensnode.io/ensapi-openapi.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs.ensnode.io/ensapi-openapi.json b/docs/docs.ensnode.io/ensapi-openapi.json index 75f86ad1a8..0507fdc296 100644 --- a/docs/docs.ensnode.io/ensapi-openapi.json +++ b/docs/docs.ensnode.io/ensapi-openapi.json @@ -72,7 +72,7 @@ "ensIndexerPublicConfig": { "type": "object", "properties": { - "databaseSchemaName": { "type": "string", "minLength": 1 }, + "ensIndexerSchemaName": { "type": "string", "minLength": 1 }, "ensRainbowPublicConfig": { "type": "object", "properties": { @@ -135,7 +135,7 @@ } }, "required": [ - "databaseSchemaName", + "ensIndexerSchemaName", "ensRainbowPublicConfig", "indexedChainIds", "isSubgraphCompatible", From 41e6f235b11b5a9bd77771af77d41a80eda6d5cc Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 25 Mar 2026 22:17:45 +0100 Subject: [PATCH 20/28] Update Ponder config to include ENSDb config --- apps/ensindexer/src/ponder/config.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/ensindexer/src/ponder/config.ts b/apps/ensindexer/src/ponder/config.ts index 18a46f445f..c1996c2ee3 100644 --- a/apps/ensindexer/src/ponder/config.ts +++ b/apps/ensindexer/src/ponder/config.ts @@ -54,4 +54,14 @@ const ponderConfig = activePlugins.reduce( // For additional info see: https://ponder.sh/docs/api-reference/ponder/config#guarantees ponderConfig.ordering = "omnichain"; +// If `DATABASE_URL` environment variable is set, +// Ponder will use it for the connection string to the Postgres database. +// However, we want to be explicit and use `ENSDB_URL` for clarity. +// Therefore, we set the connection string to ENSDb for Ponder app to use +// during indexing. +ponderConfig.database = { + connectionString: config.ensDbUrl, + kind: "postgres", +}; + export default ponderConfig; From 8013642846e2dee3070c535989f7c233905cf019 Mon Sep 17 00:00:00 2001 From: Tomek Kopacki Date: Wed, 1 Apr 2026 05:59:10 +0200 Subject: [PATCH 21/28] Apply suggestions from code review Co-authored-by: lightwalker.eth <126201998+lightwalker-eth@users.noreply.github.com> --- .../components/connection/cards/ensnode-info.tsx | 2 +- apps/ensapi/.env.local.example | 2 +- apps/ensindexer/.env.local.example | 15 +++++++-------- apps/ensindexer/src/config/types.ts | 5 ++--- apps/ensindexer/src/ponder/config.ts | 9 ++++----- .../ensnode-sdk/src/ensindexer/config/types.ts | 2 +- .../ensnode-sdk/src/shared/config/environments.ts | 2 +- terraform/modules/ensindexer/variables.tf | 1 - 8 files changed, 17 insertions(+), 21 deletions(-) diff --git a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx index b17540689f..7e4fd05998 100644 --- a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx +++ b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx @@ -420,7 +420,7 @@ function ENSNodeConfigCardContent({ } additionalInfo={

- ENSIndexer writes indexed data to tables within this ENSIndexer Schema in ENSDb. + ENSIndexer is the exclusive writer of indexed data to tables within this ENSIndexer Schema in ENSDb.

} /> diff --git a/apps/ensapi/.env.local.example b/apps/ensapi/.env.local.example index 393a19fd12..ae524f3117 100644 --- a/apps/ensapi/.env.local.example +++ b/apps/ensapi/.env.local.example @@ -3,7 +3,7 @@ # PORT=4334 # ENSDb: Database URL -# Required. This is the connection string for the ENSDb database in which ENSIndexer is storing data. +# Required. This is the connection string for the ENSDb database where your ENSIndexer is writing data. # It should match the ENSDB_URL used by your ENSIndexer. # It should be in the format of `postgresql://:@:/` # diff --git a/apps/ensindexer/.env.local.example b/apps/ensindexer/.env.local.example index e4701ebbd8..bb79a48e0f 100644 --- a/apps/ensindexer/.env.local.example +++ b/apps/ensindexer/.env.local.example @@ -167,24 +167,23 @@ # RPC_URL_1337= # ENSDb config: ENSIndexer Schema Name -# Required. This is a name of the ENSIndexer Schema in ENSDb where the indexer will create tables to store indexed data. -# It should be a string that is unique to the running indexer instance. +# Required. This is the name of the ENSIndexer Schema in ENSDb where ENSIndexer will create tables to store indexed data. +# Each ENSIndexer instance is the exclusive writer to its ENSIndexer Schema within an ENSDb. Therefore, this must be a unique ENSIndexer Schema Name for all ENSIndexer instances writing to the same ENSDb. Multiple ENSIndexer instances can write to the same ENSDb, but each requires a distinct ENSIndexer Schema Name. # -# Keeping the ENSINDEXER_SCHEMA_NAME value unique to the ENSIndexer instance is important to -# 1) speed up indexing after a restart +# Keeping the ENSINDEXER_SCHEMA_NAME value unique to each ENSIndexer instance is important to +# 1) continue where indexing left off if ENSIndexer is restarted # 2) prevent data corruption from multiple ENSIndexer instances writing state -# concurrently to the same db schema +# concurrently to the same ENSIndexer schema # -# No two ENSIndexer instances can use the same database schema at the same time. # -# Read more about database schema rules here: +# ENSIndexer Schemas follow the rules of Ponder-managed database schemas. Read more about these rules here: # https://ponder.sh/docs/api-reference/ponder/database#database-schema-rules # # Avoid using the `public` schema as we force that in the `dev` command. Using `public` # cause conflicts as you interchange between dev and start commands so use literally # anything else. ENSINDEXER_SCHEMA_NAME=ensindexer_0 -# Required. This is the connection string for the database that the indexer will use to store data. +# Required. This is the connection string for the Postgres database where ENSIndexer will store data. # It should be in the format of `postgresql://:@:/` ENSDB_URL=postgresql://dbuser:abcd1234@localhost:5432/my_database diff --git a/apps/ensindexer/src/config/types.ts b/apps/ensindexer/src/config/types.ts index 7a48519002..66da54263b 100644 --- a/apps/ensindexer/src/config/types.ts +++ b/apps/ensindexer/src/config/types.ts @@ -39,7 +39,7 @@ export interface EnsIndexerConfig { /** * The name of the ENSIndexer Schema in the ENSDb instance, - * which the ENSIndexer instance will use while indexing and querying. + * where the ENSIndexer instance will store indexed data. * * The {@link ensIndexerSchemaName} must be unique per running instance of ENSIndexer (ponder will * enforce this with database locks). If multiple instances of ENSIndexer with the same @@ -91,8 +91,7 @@ export interface EnsIndexerConfig { indexedChainIds: Set; /** - * The connection string for ENSIndexer instance to connect to - * the ENSDb instance. + * The Postgres connection string for the ENSDb instance the ENSIndexer instance will use. * * Invariants: * - The URL must be a valid PostgreSQL connection string diff --git a/apps/ensindexer/src/ponder/config.ts b/apps/ensindexer/src/ponder/config.ts index c1996c2ee3..a00fb68964 100644 --- a/apps/ensindexer/src/ponder/config.ts +++ b/apps/ensindexer/src/ponder/config.ts @@ -54,11 +54,10 @@ const ponderConfig = activePlugins.reduce( // For additional info see: https://ponder.sh/docs/api-reference/ponder/config#guarantees ponderConfig.ordering = "omnichain"; -// If `DATABASE_URL` environment variable is set, -// Ponder will use it for the connection string to the Postgres database. -// However, we want to be explicit and use `ENSDB_URL` for clarity. -// Therefore, we set the connection string to ENSDb for Ponder app to use -// during indexing. +// By default, if the `DATABASE_URL` environment variable is set, +// Ponder will use it for the connection string to the Postgres database. +// However, we want Ponder to always use the `ENSDB_URL` environment variable instead and so +// we make explicit use of it here. ponderConfig.database = { connectionString: config.ensDbUrl, kind: "postgres", diff --git a/packages/ensnode-sdk/src/ensindexer/config/types.ts b/packages/ensnode-sdk/src/ensindexer/config/types.ts index 7d69475284..fc14eb11fe 100644 --- a/packages/ensnode-sdk/src/ensindexer/config/types.ts +++ b/packages/ensnode-sdk/src/ensindexer/config/types.ts @@ -88,7 +88,7 @@ export interface EnsIndexerPublicConfig { /** * The name of the ENSIndexer Schema in the ENSDb instance, - * which the ENSIndexer instance will write indexed data to. + * where the ENSIndexer instance writes indexed data. * * Invariants: * - Must be a non-empty string that is a valid Postgres database schema diff --git a/packages/ensnode-sdk/src/shared/config/environments.ts b/packages/ensnode-sdk/src/shared/config/environments.ts index 2f58862d7c..f59c27d18d 100644 --- a/packages/ensnode-sdk/src/shared/config/environments.ts +++ b/packages/ensnode-sdk/src/shared/config/environments.ts @@ -1,5 +1,5 @@ /** - * Environment variables for database configuration. + * Environment variables for ENSDb configuration. */ export interface DatabaseEnvironment { ENSDB_URL?: string; diff --git a/terraform/modules/ensindexer/variables.tf b/terraform/modules/ensindexer/variables.tf index 00b0d44d3c..44c340e6e6 100644 --- a/terraform/modules/ensindexer/variables.tf +++ b/terraform/modules/ensindexer/variables.tf @@ -47,7 +47,6 @@ variable "ensdb_url" { variable "ensindexer_schema_name" { type = string - description = "The name of a specific ENSIndexer Schema in ENSDb." } variable "ensrainbow_url" { From d64217e703fd77cd01d50e137c1deaa354836fa8 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 1 Apr 2026 06:34:31 +0200 Subject: [PATCH 22/28] Apply renames as per PR feedback --- .github/workflows/test_ci.yml | 2 +- apps/ensapi/src/config/config.singleton.test.ts | 2 +- apps/ensapi/src/config/environment.ts | 4 ++-- apps/ensindexer/package.json | 3 +-- apps/ensindexer/src/config/environment.ts | 4 ++-- packages/ensnode-sdk/src/shared/config/environments.ts | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test_ci.yml b/.github/workflows/test_ci.yml index 4eabc88ca4..d2b3104de0 100644 --- a/.github/workflows/test_ci.yml +++ b/.github/workflows/test_ci.yml @@ -155,7 +155,7 @@ jobs: # that don't have the relevant secrets configured. NAMESPACE: mainnet ENSDB_URL: postgresql://postgres:password@localhost:5432/postgres - ENSINDEXER_SCHEMA_NAME: public + ENSINDEXER_SCHEMA_NAME: ensindexer_test_ci PLUGINS: subgraph,basenames,lineanames,threedns,protocol-acceleration,registrars,tokenscope ENSRAINBOW_URL: https://api.ensrainbow.io ALCHEMY_API_KEY: ${{ secrets.ALCHEMY_API_KEY }} diff --git a/apps/ensapi/src/config/config.singleton.test.ts b/apps/ensapi/src/config/config.singleton.test.ts index 191ddc4cfa..834dcc3495 100644 --- a/apps/ensapi/src/config/config.singleton.test.ts +++ b/apps/ensapi/src/config/config.singleton.test.ts @@ -8,7 +8,7 @@ vi.mock("@/lib/logger", () => ({ })); const VALID_ENSDB_URL = "postgresql://user:password@localhost:5432/mydb"; -const VALID_ENSINDEXER_SCHEMA_NAME = "ensapi"; +const VALID_ENSINDEXER_SCHEMA_NAME = "ensindexer_test"; describe("ensdb singleton bootstrap", () => { beforeEach(() => { diff --git a/apps/ensapi/src/config/environment.ts b/apps/ensapi/src/config/environment.ts index adb00fe7e1..1b191a73c6 100644 --- a/apps/ensapi/src/config/environment.ts +++ b/apps/ensapi/src/config/environment.ts @@ -1,5 +1,5 @@ import type { - DatabaseEnvironment, + EnsDbEnvironment, LogLevelEnvironment, PortEnvironment, ReferralProgramEditionsEnvironment, @@ -14,7 +14,7 @@ import type { * their state in `process.env`. This interface is intended to be the source type which then gets * mapped/parsed into a structured configuration object like `EnsApiConfig`. */ -export type EnsApiEnvironment = DatabaseEnvironment & +export type EnsApiEnvironment = EnsDbEnvironment & RpcEnvironment & PortEnvironment & LogLevelEnvironment & diff --git a/apps/ensindexer/package.json b/apps/ensindexer/package.json index 5d656a5700..75d0330fb0 100644 --- a/apps/ensindexer/package.json +++ b/apps/ensindexer/package.json @@ -12,9 +12,8 @@ }, "homepage": "https://github.com/namehash/ensnode/tree/main/apps/ensindexer", "scripts": { - "dev": "ENSINDEXER_SCHEMA_NAME=public ponder --root ./ponder dev --disable-ui --schema public", + "dev": "ENSINDEXER_SCHEMA_NAME=ensindexer_temp_dev ponder --root ./ponder dev --disable-ui --schema ensindexer_temp_dev", "start": "ponder --root ./ponder start --schema $ENSINDEXER_SCHEMA_NAME", - "serve": "ponder --root ./ponder serve", "db": "ponder --root ./ponder db", "codegen": "ponder --root ./ponder codegen", "test": "vitest", diff --git a/apps/ensindexer/src/config/environment.ts b/apps/ensindexer/src/config/environment.ts index 104a14a1bb..a764c271c5 100644 --- a/apps/ensindexer/src/config/environment.ts +++ b/apps/ensindexer/src/config/environment.ts @@ -1,4 +1,4 @@ -import type { DatabaseEnvironment, RpcEnvironment } from "@ensnode/ensnode-sdk/internal"; +import type { EnsDbEnvironment, RpcEnvironment } from "@ensnode/ensnode-sdk/internal"; /** * Represents the raw, unvalidated environment variables for the ENSIndexer application. @@ -7,7 +7,7 @@ import type { DatabaseEnvironment, RpcEnvironment } from "@ensnode/ensnode-sdk/i * their state in `process.env`. This interface is intended to be the source type which then gets * mapped/parsed into a structured configuration object like `ENSIndexerConfig`. */ -export type ENSIndexerEnvironment = DatabaseEnvironment & +export type ENSIndexerEnvironment = EnsDbEnvironment & RpcEnvironment & { NAMESPACE?: string; PLUGINS?: string; diff --git a/packages/ensnode-sdk/src/shared/config/environments.ts b/packages/ensnode-sdk/src/shared/config/environments.ts index f9e6992d9a..7069400f1f 100644 --- a/packages/ensnode-sdk/src/shared/config/environments.ts +++ b/packages/ensnode-sdk/src/shared/config/environments.ts @@ -1,7 +1,7 @@ /** * Environment variables for ENSDb configuration. */ -export interface DatabaseEnvironment { +export interface EnsDbEnvironment { ENSDB_URL?: string; ENSINDEXER_SCHEMA_NAME?: string; } From 0873874be0195b62dbe3ef661c25a2df588b5255 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 1 Apr 2026 06:38:10 +0200 Subject: [PATCH 23/28] Replace remaining symbols in docs --- .../src/content/docs/docs/contributing/index.mdx | 4 ++-- .../src/content/docs/ensindexer/usage/management.mdx | 2 +- packages/integration-test-env/README.md | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx b/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx index f83ba6e9dd..b9beadb5d7 100644 --- a/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx +++ b/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx @@ -50,9 +50,9 @@ ENSNode is a suite of services, and some depend on others. Refer to the `docker- /> ::: -### 1. Running Postgres +### 1. Running ENSDb -Ensure Postgres in the background, providing its connection details to ENSIndexer via `DATABASE_URL`. +Ensure ENSDb is running in the background, providing its connection details to ENSIndexer via `ENSDB_URL`. ### 2. Running ENSRainbow diff --git a/docs/ensnode.io/src/content/docs/ensindexer/usage/management.mdx b/docs/ensnode.io/src/content/docs/ensindexer/usage/management.mdx index 51a706457b..3a2bad06f6 100644 --- a/docs/ensnode.io/src/content/docs/ensindexer/usage/management.mdx +++ b/docs/ensnode.io/src/content/docs/ensindexer/usage/management.mdx @@ -17,7 +17,7 @@ TODO ### Dropping Orphaned Indexing Schemas -When re-deploying any Ponder indexer, including ENSNode a new schema is created (via the `DATABASE_SCHEMA` env variable) and the previous schemas are abandoned. They remain available for rollbacks, but take up database space—dropping these schemas once no longer available is useful for reclaiming space in your Postgres instance. +When re-deploying any Ponder indexer, including ENSNode a new schema is created (via the `ENSINDEXER_SCHEMA_NAME` env variable) and the previous schemas are abandoned. They remain available for rollbacks, but take up database space—dropping these schemas once no longer available is useful for reclaiming space in your Postgres instance. ```sql DROP SCHEMA CASCADE; diff --git a/packages/integration-test-env/README.md b/packages/integration-test-env/README.md index 5eb0320fbf..d75e8899b3 100644 --- a/packages/integration-test-env/README.md +++ b/packages/integration-test-env/README.md @@ -91,12 +91,12 @@ cd apps/ensindexer && pnpm dev with environment variables: ```env -DATABASE_SCHEMA=ensindexer_0 +ENSINDEXER_SCHEMA_NAME=ensindexer_0 NAMESPACE=ens-test-env PLUGINS=ensv2,protocol-acceleration ``` -`DATABASE_SCHEMA` can be any valid Postgres schema name — just make sure ENSApi uses the same value. +`ENSINDEXER_SCHEMA_NAME` can be any valid Postgres schema name — just make sure ENSApi uses the same value. #### 5. Start ENSApi @@ -107,11 +107,11 @@ cd apps/ensapi && pnpm dev with environment variables: ```env -DATABASE_URL=postgresql://ensnode:ensnode@localhost:5432/ensnode +ENSDB_URL=postgresql://ensnode:ensnode@localhost:5432/ensnode ENSINDEXER_SCHEMA_NAME=ensindexer_0 ``` -`ENSINDEXER_SCHEMA_NAME` must match the `DATABASE_SCHEMA` used by ENSIndexer above. +`ENSINDEXER_SCHEMA_NAME` must match the `ENSINDEXER_SCHEMA_NAME` used by ENSIndexer above. #### 6. Run Integration Tests From c282b46495e21c96cfe6ca6889501de45ed7ef32 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 1 Apr 2026 06:42:09 +0200 Subject: [PATCH 24/28] Set shared railway variables Maintain backward compatibility to allow smooth deployment pipeline operations. --- .github/workflows/deploy_ensnode_blue_green.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/deploy_ensnode_blue_green.yml b/.github/workflows/deploy_ensnode_blue_green.yml index 36b8d3e9da..1a76900671 100644 --- a/.github/workflows/deploy_ensnode_blue_green.yml +++ b/.github/workflows/deploy_ensnode_blue_green.yml @@ -176,6 +176,12 @@ jobs: echo "Finished setting $variable_name" } + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA_DATABASE_SCHEMA" "alphaSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "MAINNET_DATABASE_SCHEMA" "mainnetSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA-SEPOLIA_DATABASE_SCHEMA" "alphaSepoliaSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "V2-SEPOLIA_DATABASE_SCHEMA" "v2SepoliaSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "SEPOLIA_DATABASE_SCHEMA" "sepoliaSchema${TAG}" + set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA_ENSINDEXER_SCHEMA_NAME" "alphaSchema${TAG}" set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "MAINNET_ENSINDEXER_SCHEMA_NAME" "mainnetSchema${TAG}" set_shared_variable ${RAILWAY_ENVIRONMENT_ID} "ALPHA-SEPOLIA_ENSINDEXER_SCHEMA_NAME" "alphaSepoliaSchema${TAG}" From 8978d7f23091896132ba7b06be3c3a2d6ca09f2d Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Wed, 1 Apr 2026 07:19:50 +0200 Subject: [PATCH 25/28] Update the Connection view in ENSAmin Apply feedback from Slack thread https://namehash.slack.com/archives/C086Z6FNBHN/p1774501067795749\?thread_ts\=1774453698.764489\&cid\=C086Z6FNBHN --- .../connection/cards/ensnode-info.tsx | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx index 238140d2a7..aa04aa36aa 100644 --- a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx +++ b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx @@ -297,9 +297,8 @@ function ENSNodeConfigCardContent({ docsLink={new URL("https://ensnode.io/ensapi")} > - Postgres

} /> {ensIndexerPublicConfig.ensIndexerSchemaName}

} @@ -385,13 +384,36 @@ function ENSNodeConfigCardContent({ Postgres

} /> {ensIndexerPublicConfig.ensIndexerSchemaName}

} additionalInfo={

- ENSIndexer writes indexed data to tables within this ENSIndexer Schema in ENSDb. + ENSDb enables devs to build custom services and APIs on top of indexed ENS data in + this schema using{" "} + + ensdb-sdk + + . +

+ } + /> + ensnode

} + additionalInfo={ +

This database schema stores Metadata about each ENSIndexer schema in ENSDb.

+ } + /> + + ponder_sync

} + additionalInfo={ +

+ Ponder manages this database schema to stores cached RPC results and is shared + across all ENSIndexer instances using this ENSDb.

} /> @@ -412,9 +434,8 @@ function ENSNodeConfigCardContent({ docsLink={new URL("https://ensnode.io/ensindexer")} > - Postgres

} /> {ensIndexerPublicConfig.ensIndexerSchemaName}

} @@ -452,23 +473,6 @@ function ENSNodeConfigCardContent({ } /> - {ensIndexerPublicConfig.versionInfo.nodejs}

- } - additionalInfo={ -

- Version of the{" "} - - Node.js - {" "} - runtime. -

- } - /> Date: Wed, 1 Apr 2026 15:59:31 +0200 Subject: [PATCH 26/28] Apply PR feedback to code docs --- .../connection/cards/ensnode-info.tsx | 4 +- apps/ensapi/.env.local.example | 4 +- apps/ensapi/src/config/redact.ts | 2 + apps/ensindexer/.env.local.example | 47 +++++++++++----- apps/ensindexer/src/config/types.ts | 53 +++++++++++++------ 5 files changed, 79 insertions(+), 31 deletions(-) diff --git a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx index 6d53e42a2e..22f6e23c39 100644 --- a/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx +++ b/apps/ensadmin/src/components/connection/cards/ensnode-info.tsx @@ -429,8 +429,8 @@ function ENSNodeConfigCardContent({ value={

ponder_sync

} additionalInfo={

- Ponder manages this database schema to stores cached RPC results and is shared - across all ENSIndexer instances using this ENSDb. + Ponder manages this database schema to store cached RPC results and is shared across + all ENSIndexer instances using this ENSDb.

} /> diff --git a/apps/ensapi/.env.local.example b/apps/ensapi/.env.local.example index ae524f3117..ebef750e7e 100644 --- a/apps/ensapi/.env.local.example +++ b/apps/ensapi/.env.local.example @@ -3,7 +3,7 @@ # PORT=4334 # ENSDb: Database URL -# Required. This is the connection string for the ENSDb database where your ENSIndexer is writing data. +# Required. This is the connection string for the ENSDb database where your ENSIndexer is writing data. # It should match the ENSDB_URL used by your ENSIndexer. # It should be in the format of `postgresql://:@:/` # @@ -11,7 +11,7 @@ ENSDB_URL=postgresql://dbuser:abcd1234@localhost:5432/my_database # ENSDb: ENSIndexer Schema Name -# Required. This is a name of the ENSIndexer Schema in ENSDb where ENSApi should read indexed data stored by your ENSIndexer. +# Required. This is the name of the ENSIndexer Schema in ENSDb where ENSApi should read indexed data stored by your ENSIndexer. # It should match the ENSINDEXER_SCHEMA_NAME used by your ENSIndexer. ENSINDEXER_SCHEMA_NAME=ensindexer_0 diff --git a/apps/ensapi/src/config/redact.ts b/apps/ensapi/src/config/redact.ts index e8cc47a339..8676218072 100644 --- a/apps/ensapi/src/config/redact.ts +++ b/apps/ensapi/src/config/redact.ts @@ -13,5 +13,7 @@ export function redactEnsApiConfig(config: EnsApiConfig) { ensIndexerPublicConfig: config.ensIndexerPublicConfig, ensDbUrl: redactString(config.ensDbUrl), rpcConfigs: redactRpcConfigs(config.rpcConfigs), + ensIndexerSchemaName: config.ensIndexerSchemaName, + theGraphApiKey: config.theGraphApiKey ? redactString(config.theGraphApiKey) : undefined, }; } diff --git a/apps/ensindexer/.env.local.example b/apps/ensindexer/.env.local.example index 90314fb6bf..cd5b3d948d 100644 --- a/apps/ensindexer/.env.local.example +++ b/apps/ensindexer/.env.local.example @@ -167,23 +167,46 @@ # RPC_URL_1337= # ENSDb config: ENSIndexer Schema Name -# Required. This is the name of the ENSIndexer Schema in ENSDb where ENSIndexer will create tables to store indexed data. -# Each ENSIndexer instance is the exclusive writer to its ENSIndexer Schema within an ENSDb. Therefore, this must be a unique ENSIndexer Schema Name for all ENSIndexer instances writing to the same ENSDb. Multiple ENSIndexer instances can write to the same ENSDb, but each requires a distinct ENSIndexer Schema Name. +# Required. This is the name of the ENSIndexer Schema in ENSDb where ENSIndexer will create tables to store indexed data. +# Each ENSIndexer instance is the exclusive writer to its ENSIndexer Schema within an ENSDb. +# Therefore, this must be a unique ENSIndexer Schema Name for all ENSIndexer instances writing to the same ENSDb. +# Multiple ENSIndexer instances can write to the same ENSDb, but each requires a distinct ENSIndexer Schema Name. # -# Keeping the ENSINDEXER_SCHEMA_NAME value unique to each ENSIndexer instance is important to -# 1) continue where indexing left off if ENSIndexer is restarted -# 2) prevent data corruption from multiple ENSIndexer instances writing state -# concurrently to the same ENSIndexer schema +# ENSIndexer can run in production mode (i.e. with `pnpm -F ensindexer start` command). +# In production mode, the following rules apply: +# - For safety, any changes to the indexing behavior in ENSIndexer (including +# any changes to indexing code or any changes to environment variables that +# influence indexing behavior) will cause ENSIndexer to refuse to use +# an ENSIndexer Schema that was already built with different indexing behavior. +# This is to prevent data corruption from multiple ENSIndexer instances writing +# state to the same ENSIndexer Schema at the same time. +# - If you wish to change the indexing behavior of your ENSIndexer (such as +# upgrading to a new ENSIndexer version or changing environment variables +# that influence indexing behavior) you must either: +# - Configure a new ENSIndexer Schema Name +# - Remove or rename the existing ENSIndexer Schema you previously built +# - Each time you configure a new ENSIndexer Schema Name there is +# no automatic "garbage collection" of any ENSIndexer Schemas you may have +# previously built. Over time, this can result in the consumption of more and +# more storage space consumption. To solve for this, manually garbage collect +# any ENSIndexer Schemas you have previously built when they are +# no longer needed. +# - If ENSIndexer restarts without changes in the indexing behavior, +# the indexing will continue from where it left off. # +# ENSIndexer can also run in dev mode (i.e. with `pnpm -F ensindexer dev` command). +# In dev mode, the following rules apply: +# - ENSIndexer uses the ENSIndexer Schema Name that is configured inline in the `dev` script in package.json. +# - Any change to indexing behavior in ENSIndexer results in the ENSIndexer instance being restarted. +# - Each time ENSIndexer starts in dev mode, the ENSIndexer Schema for +# the configured ENSIndexer Schema Name is recreated. This means that any existing ENSIndexer Schema with +# the ENSIndexer Schema Name will be dropped and a new ENSIndexer Schema with the same name will be created. # -# ENSIndexer Schemas follow the rules of Ponder-managed database schemas. Read more about these rules here: +# ENSIndexer manages the ENSIndexer Schemas according to the rules of Ponder-managed database schemas. +# Read more about these rules here: # https://ponder.sh/docs/api-reference/ponder/database#database-schema-rules -# -# Avoid using the `public` schema as we force that in the `dev` command. Using `public` -# cause conflicts as you interchange between dev and start commands so use literally -# anything else. ENSINDEXER_SCHEMA_NAME=ensindexer_0 -# Required. This is the connection string for the Postgres database where ENSIndexer will store data. +# Required. This is the connection string for the Postgres database where ENSIndexer will store data. # It should be in the format of `postgresql://:@:/` ENSDB_URL=postgresql://dbuser:abcd1234@localhost:5432/my_database diff --git a/apps/ensindexer/src/config/types.ts b/apps/ensindexer/src/config/types.ts index be4bc2065c..fc70c9b182 100644 --- a/apps/ensindexer/src/config/types.ts +++ b/apps/ensindexer/src/config/types.ts @@ -38,21 +38,44 @@ export interface EnsIndexerConfig { labelSet: Required; /** - * The name of the ENSIndexer Schema in the ENSDb instance, - * where the ENSIndexer instance will store indexed data. - * - * The {@link ensIndexerSchemaName} must be unique per running instance of ENSIndexer (ponder will - * enforce this with database locks). If multiple instances of ENSIndexer with the same - * {@link ensIndexerSchemaName} are running, only the first will successfully acquire the lock and begin - * indexing: the rest will crash. - * - * If an ENSIndexer instance with the same configuration (including `ensIndexerSchemaName`) is - * started, and it successfully acquires the lock on this schema, it will continue indexing from - * the current state. - * - * Many clients can read from this Postgres schema during or after indexing. - * - * Read more about database schema rules here: + * The name of the ENSIndexer Schema in ENSDb where ENSIndexer will create + * tables to store indexed data. + * + * Each ENSIndexer instance is the exclusive writer to its ENSIndexer Schema + * within an ENSDb. Therefore, {@link ensIndexerSchemaName} must be + * a unique ENSIndexer Schema Name for all ENSIndexer instances writing to + * the same ENSDb. Multiple ENSIndexer instances can write to the same ENSDb, + * but each requires a distinct ENSIndexer Schema Name. + * + * When ENSIndexer runs in production mode, the following rules apply: + * - For safety, any changes to the indexing behavior in ENSIndexer (including + * any changes to indexing code or any changes to environment variables that + * influence indexing behavior) will cause ENSIndexer to refuse to use + * an ENSIndexer Schema that was already built with different indexing behavior. + * This is to prevent data corruption from multiple ENSIndexer instances writing + * state to the same ENSIndexer Schema at the same time. + * - If you wish to change the indexing behavior of your ENSIndexer (such as + * upgrading to a new ENSIndexer version or changing environment variables + * that influence indexing behavior) you must either: + * - Configure a new ENSIndexer Schema Name + * - Remove or rename the existing ENSIndexer Schema you previously built + * - Each time you configure a new ENSIndexer Schema Name there is + * no automatic "garbage collection" of any ENSIndexer Schemas you may have + * previously built. Over time, this can result in the consumption of more and + * more storage space consumption. To solve for this, manually garbage collect + * any ENSIndexer Schemas you have previously built when they are + * no longer needed. + * - If ENSIndexer restarts without changes in the indexing behavior, + * the indexing will continue from where it left off. + * + * When ENSIndexer runs in dev mode, the following rules apply: + * - Any change to indexing behavior in ENSIndexer results in the ENSIndexer instance being restarted. + * - Each time ENSIndexer starts in dev mode, the ENSIndexer Schema for + * the {@link ensIndexerSchemaName} is recreated. This means that any existing ENSIndexer Schema with + * the {@link ensIndexerSchemaName} will be dropped and a new ENSIndexer Schema with the same name will be created. + * + * ENSIndexer manages the ENSIndexer Schemas according to the rules of Ponder-managed database schemas. + * Read more about these rules here: * @see https://ponder.sh/docs/api-reference/ponder/database#database-schema-rules * * Invariants: From b3f0d1ac98a2c67dd9480c1691a632f1f32b4c6c Mon Sep 17 00:00:00 2001 From: shrugs Date: Wed, 1 Apr 2026 19:20:04 -0500 Subject: [PATCH 27/28] docs: clean up integration test readme with schema name changing --- packages/integration-test-env/README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/integration-test-env/README.md b/packages/integration-test-env/README.md index d75e8899b3..92de243d9b 100644 --- a/packages/integration-test-env/README.md +++ b/packages/integration-test-env/README.md @@ -91,13 +91,10 @@ cd apps/ensindexer && pnpm dev with environment variables: ```env -ENSINDEXER_SCHEMA_NAME=ensindexer_0 NAMESPACE=ens-test-env PLUGINS=ensv2,protocol-acceleration ``` -`ENSINDEXER_SCHEMA_NAME` can be any valid Postgres schema name — just make sure ENSApi uses the same value. - #### 5. Start ENSApi ```sh @@ -108,14 +105,14 @@ with environment variables: ```env ENSDB_URL=postgresql://ensnode:ensnode@localhost:5432/ensnode -ENSINDEXER_SCHEMA_NAME=ensindexer_0 +ENSINDEXER_SCHEMA_NAME=ensindexer_temp_dev ``` -`ENSINDEXER_SCHEMA_NAME` must match the `ENSINDEXER_SCHEMA_NAME` used by ENSIndexer above. +`ENSINDEXER_SCHEMA_NAME` must match the `ENSINDEXER_SCHEMA_NAME` used by ENSIndexer above, and `ensindexer_temp_dev` is the schema name used when running ENSIndexer with `pnpm dev`. #### 6. Run Integration Tests -Finally, you can run vitest on the integration tests using: +Finally, you can run vitest with the integration test suite using: ```sh pnpm test:integration From 42a86a11a9f68a4c19829f7f634064fe02e909d5 Mon Sep 17 00:00:00 2001 From: shrugs Date: Wed, 1 Apr 2026 19:40:53 -0500 Subject: [PATCH 28/28] fix: allow keytar build --- .github/workflows/test_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_ci.yml b/.github/workflows/test_ci.yml index d2b3104de0..cfb1dd66fd 100644 --- a/.github/workflows/test_ci.yml +++ b/.github/workflows/test_ci.yml @@ -87,7 +87,7 @@ jobs: fi echo "OpenAPI spec is in sync with codebase" - name: Validate OpenAPI spec with Mintlify - run: pnpm dlx mint@^4.1.0 openapi-check docs/docs.ensnode.io/ensapi-openapi.json + run: pnpm dlx --allow-build=keytar mint@^4.1.0 openapi-check docs/docs.ensnode.io/ensapi-openapi.json graphql-schema-check: name: "GraphQL Schema Check"