Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/green-webs-see.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ensnode/ponder-sdk": minor
---

Extended `PonderAppContext` data model with `localPonderAppUrl` field.
5 changes: 5 additions & 0 deletions .changeset/late-jobs-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ensnode/ponder-sdk": minor
---

Replaced `localPonderAppUrl` reference with `ponderAppContext.localPonderAppUrl` in the constructor for `LocalPonderClient`.
5 changes: 5 additions & 0 deletions .changeset/loose-waves-slide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ensnode/ensnode-sdk": minor
---

Removed the `EnsIndexerUrlEnvironment` interface as it was unused.
5 changes: 5 additions & 0 deletions .changeset/social-bottles-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ensindexer": minor
---

Cleaned up all references to `config.ensIndexerUrl`. The local Ponder app URL is now automatically derived from the Ponder app runtime context, eliminating the need for manual configuration.
14 changes: 3 additions & 11 deletions .github/scripts/run_ensindexer_healthcheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,10 @@ PID=$!

echo "ENSIndexer started with PID: $PID"

# Require ENSINDEXER_URL to be set
if [ -z "$ENSINDEXER_URL" ]; then
echo "Error: ENSINDEXER_URL environment variable must be set"
kill -9 $PID 2>/dev/null || true
wait $PID 2>/dev/null || true
rm -f "$LOG_FILE"
[ -f "$ENV_FILE" ] && rm -f "$ENV_FILE"
exit 1
fi
ENSINDEXER_HEALTHCHECK="http://localhost:42069/health"

# Wait for health check to pass
echo "Waiting for health check to pass at ${ENSINDEXER_URL}/health (up to $HEALTH_CHECK_TIMEOUT seconds)..."
echo "Waiting for health check to pass at ${ENSINDEXER_HEALTHCHECK} (up to $HEALTH_CHECK_TIMEOUT seconds)..."
health_check_start=$(date +%s)
last_log_check=0

Expand All @@ -76,7 +68,7 @@ while true; do
fi

# Check health endpoint
if curl -sf "${ENSINDEXER_URL}/health" >/dev/null 2>&1; then
if curl -sf "${ENSINDEXER_HEALTHCHECK}" >/dev/null 2>&1; then
echo "Health check passed! ENSIndexer is up and running."
echo "Test successful - terminating ENSIndexer"
# Force kill the ENSIndexer process
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/test_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ jobs:
DATABASE_SCHEMA: public
PLUGINS: subgraph,basenames,lineanames,threedns,protocol-acceleration,registrars,tokenscope
ENSRAINBOW_URL: https://api.ensrainbow.io
ENSINDEXER_URL: http://localhost:42069
ALCHEMY_API_KEY: ${{ secrets.ALCHEMY_API_KEY }}
QUICKNODE_API_KEY: ${{ secrets.QUICKNODE_API_KEY }}
QUICKNODE_ENDPOINT_NAME: ${{ secrets.QUICKNODE_ENDPOINT_NAME}}
Expand Down
7 changes: 0 additions & 7 deletions apps/ensindexer/.env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,6 @@ LABEL_SET_ID=subgraph
# LABEL_SET_VERSION: see https://ensnode.io/ensrainbow/concepts/glossary#label-set-version.
LABEL_SET_VERSION=0

# The "primary" ENSIndexer service URL
# Required. This must be an instance of ENSIndexer using either `ponder start` or `ponder dev`,
# (not `ponder serve`). This URL is used to read Ponder's internal indexing state to power the Config
# and Indexing Status APIs. This should be configured so that ENSIndexer refers back to itself.
# ex: http://localhost:{port}.
ENSINDEXER_URL=http://localhost:42069

# A feature flag to enable/disable ENSIndexer's Subgraph Compatible Indexing Behavior
# Optional. If this is not set, the default value is set to `DEFAULT_SUBGRAPH_COMPAT` (false).
#
Expand Down
3 changes: 0 additions & 3 deletions apps/ensindexer/src/config/config.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
buildRpcConfigsFromEnv,
DatabaseSchemaNameSchema,
ENSNamespaceSchema,
EnsIndexerUrlSchema,
invariant_isSubgraphCompatibleRequirements,
invariant_rpcConfigsSpecifiedForRootChain,
makeFullyPinnedLabelSetSchema,
Expand Down Expand Up @@ -110,7 +109,6 @@ const ENSIndexerConfigSchema = z
databaseUrl: DatabaseUrlSchema,
databaseSchemaName: DatabaseSchemaNameSchema,
rpcConfigs: RpcConfigsSchema,
ensIndexerUrl: EnsIndexerUrlSchema,

namespace: ENSNamespaceSchema,
plugins: PluginsSchema,
Expand Down Expand Up @@ -188,7 +186,6 @@ export function buildConfigFromEnvironment(_env: ENSIndexerEnvironment): EnsInde
return ENSIndexerConfigSchema.parse({
databaseUrl: env.DATABASE_URL,
databaseSchemaName: env.DATABASE_SCHEMA,
ensIndexerUrl: env.ENSINDEXER_URL,
namespace: env.NAMESPACE,
rpcConfigs,

Expand Down
33 changes: 1 addition & 32 deletions apps/ensindexer/src/config/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const BASE_ENV: ENSIndexerEnvironment = {
PLUGINS: "subgraph",
DATABASE_SCHEMA: "ensnode",
DATABASE_URL: "postgresql://user:password@localhost:5432/mydb",
ENSINDEXER_URL: "http://localhost:42069",
ENSRAINBOW_URL: "http://localhost:3223",
LABEL_SET_ID: "ens-test-env",
LABEL_SET_VERSION: "0",
Expand Down Expand Up @@ -144,34 +143,6 @@ describe("config (with base env)", () => {
});
});

describe(".ensIndexerUrl", () => {
it("throws an error if ENSINDEXER_URL is not a valid URL", async () => {
vi.stubEnv("ENSINDEXER_URL", "invalid url");
await expect(getConfig()).rejects.toThrow(/ENSINDEXER_URL must be a valid URL string/i);
});

it("throws an error if ENSINDEXER_URL is empty", async () => {
vi.stubEnv("ENSINDEXER_URL", "");
await expect(getConfig()).rejects.toThrow(/ENSINDEXER_URL must be a valid URL string/i);
});

it("throws an error if ENSINDEXER_URL is undefined", async () => {
vi.stubEnv("ENSINDEXER_URL", undefined);
await expect(getConfig()).rejects.toThrow(/ENSINDEXER_URL must be a valid URL string/i);
});

it("returns the ENSINDEXER_URL if it is a valid URL", async () => {
const config = await getConfig();
expect(config.ensIndexerUrl).toStrictEqual(new URL("http://localhost:42069"));
});

it("returns a different valid ENSINDEXER_URL if set", async () => {
vi.stubEnv("ENSINDEXER_URL", "https://someotherurl.com");
const config = await getConfig();
expect(config.ensIndexerUrl).toStrictEqual(new URL("https://someotherurl.com"));
});
});

describe(".ensRainbowUrl", () => {
it("throws an error if ENSRAINBOW_URL is not a valid URL", async () => {
vi.stubEnv("ENSRAINBOW_URL", "invalid url");
Expand Down Expand Up @@ -676,11 +647,9 @@ 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, ENSRAINBOW_URL, DATABASE_URL, DATABASE_SCHEMA, RPC_URL_1 } = BASE_ENV;
stubEnv({
NAMESPACE,
ENSINDEXER_URL,
ENSRAINBOW_URL,
DATABASE_URL,
DATABASE_SCHEMA,
Expand Down
7 changes: 1 addition & 6 deletions apps/ensindexer/src/config/environment.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import type {
EnsIndexerDatabaseEnvironment,
EnsIndexerUrlEnvironment,
RpcEnvironment,
} from "@ensnode/ensnode-sdk/internal";
import type { EnsIndexerDatabaseEnvironment, RpcEnvironment } from "@ensnode/ensnode-sdk/internal";

/**
* Represents the raw, unvalidated environment variables for the ENSIndexer application.
Expand All @@ -12,7 +8,6 @@ import type {
* mapped/parsed into a structured configuration object like `ENSIndexerConfig`.
*/
export type ENSIndexerEnvironment = EnsIndexerDatabaseEnvironment &
EnsIndexerUrlEnvironment &
RpcEnvironment & {
NAMESPACE?: string;
PLUGINS?: string;
Expand Down
1 change: 0 additions & 1 deletion apps/ensindexer/src/config/serialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export function serializeRedactedENSIndexerConfig(
return {
databaseSchemaName: redactedConfig.databaseSchemaName,
databaseUrl: redactedConfig.databaseUrl,
ensIndexerUrl: serializeUrl(redactedConfig.ensIndexerUrl),
ensRainbowUrl: serializeUrl(redactedConfig.ensRainbowUrl),
labelSet: redactedConfig.labelSet,
globalBlockrange: redactedConfig.globalBlockrange,
Expand Down
10 changes: 1 addition & 9 deletions apps/ensindexer/src/config/serialized-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,7 @@ export interface SerializedRpcConfig extends Omit<RpcConfig, "httpRPCs" | "webso
* Serialized representation of {@link ENSIndexerConfig}
*/
export interface SerializedENSIndexerConfig
extends Omit<
ENSIndexerConfig,
"ensIndexerUrl" | "ensRainbowUrl" | "indexedChainIds" | "rpcConfigs" | "plugins"
> {
/**
* Serialized representation of {@link ENSIndexerConfig.ensIndexerUrl}.
*/
ensIndexerUrl: UrlString;

extends Omit<ENSIndexerConfig, "ensRainbowUrl" | "indexedChainIds" | "rpcConfigs" | "plugins"> {
/**
* Serialized representation of {@link ENSIndexerConfig.ensRainbowUrl}.
*/
Expand Down
16 changes: 0 additions & 16 deletions apps/ensindexer/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,6 @@ export interface EnsIndexerConfig {
*/
databaseUrl: DatabaseUrl;

/**
* The "primary" ENSIndexer service URL
* This must be an instance of ENSIndexer using either `ponder start`
* or `ponder dev`, and not `ponder serve`.
* This URL is used to read Ponder's internal indexing state using
* the `/status` and `/metrics` endpoints that are served directly by Ponder
* within the specified ENSIndexer.
* For ENSIndexer instances started using `ponder start` or `ponder dev`,
* this should be configured so that ENSIndexer refers back to itself, ex:
* http://localhost:{port}. For ENSIndexer instances started using
* `ponder serve`, this should be set to the hostname of
* the related ENSIndexer instance started using `ponder start` or
* `ponder dev` that is writing to the same ENSDb.
*/
ensIndexerUrl: URL;

/**
* Constrains the global blockrange for indexing, useful for testing purposes.
*
Expand Down
1 change: 0 additions & 1 deletion apps/ensindexer/src/lib/__test__/mockConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const _defaultMockConfig = buildConfigFromEnvironment({
DATABASE_SCHEMA: "test_schema",
NAMESPACE: "mainnet",
PLUGINS: "subgraph",
ENSINDEXER_URL: "http://localhost:42069",
ENSRAINBOW_URL: "http://localhost:3223",
LABEL_SET_ID: "ens-test-env",
LABEL_SET_VERSION: "0",
Expand Down
1 change: 0 additions & 1 deletion apps/ensindexer/src/lib/local-ponder-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const pluginsAllDatasourceNames = getPluginsAllDatasourceNames(config.plugins);
const indexedBlockranges = buildIndexedBlockranges(config.namespace, pluginsAllDatasourceNames);

export const localPonderClient = new LocalPonderClient(
config.ensIndexerUrl,
config.indexedChainIds,
indexedBlockranges,
publicClients,
Expand Down
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ services:
DATABASE_URL: postgresql://postgres:password@postgres:5432/postgres
DATABASE_SCHEMA: ensindexer_0
ENSRAINBOW_URL: http://ensrainbow:3223
ENSINDEXER_URL: http://ensindexer:42069
env_file:
# NOTE: must define apps/ensindexer/.env.local (see apps/ensindexer/.env.local.example)
# Copy .env.local.example to .env.local and configure all required values
Expand Down
7 changes: 0 additions & 7 deletions packages/ensnode-sdk/src/shared/config/environments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ export interface RpcEnvironment {
RPC_AUTO_GEN_MODE?: string;
}

/**
* Environment variables for ENSIndexer URL configuration.
*/
export interface EnsIndexerUrlEnvironment {
ENSINDEXER_URL?: string;
}

/**
* Environment variables for port configuration.
*/
Expand Down
2 changes: 0 additions & 2 deletions packages/ensnode-sdk/src/shared/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { UrlString } from "../serialized-types";
import type { ChainId } from "../types";
import type {
DatabaseSchemaNameSchema,
EnsIndexerUrlSchema,
PortNumberSchema,
TheGraphApiKeySchema,
} from "./zod-schemas";
Expand Down Expand Up @@ -47,7 +46,6 @@ export type RpcConfigs = Map<ChainId, RpcConfig>;

export type DatabaseUrl = UrlString;
export type DatabaseSchemaName = z.infer<typeof DatabaseSchemaNameSchema>;
export type EnsIndexerUrl = z.infer<typeof EnsIndexerUrlSchema>;
export type TheGraphApiKey = z.infer<typeof TheGraphApiKeySchema>;

export type PortNumber = z.infer<typeof PortNumberSchema>;
2 changes: 0 additions & 2 deletions packages/ensnode-sdk/src/shared/config/zod-schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ export const RpcConfigsSchema = z
return rpcConfigs;
});

export const EnsIndexerUrlSchema = makeUrlSchema("ENSINDEXER_URL");

export const ENSNamespaceSchema = z.enum(ENSNamespaceIds, {
error: ({ input }) =>
`Invalid NAMESPACE. Got '${input}', but supported ENS namespaces are: ${Object.keys(ENSNamespaceIds).join(", ")}`,
Expand Down
2 changes: 0 additions & 2 deletions packages/integration-test-env/src/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,6 @@ async function main() {
await waitForHealth(`http://localhost:${ENSRAINBOW_PORT}/health`, 30_000, "ENSRainbow");

// Phase 3: Start ENSIndexer
const ENSINDEXER_URL = `http://localhost:${ENSINDEXER_PORT}`;
const ENSINDEXER_SCHEMA_NAME = "ensindexer_0";

log("Starting ENSIndexer...");
Expand All @@ -331,7 +330,6 @@ async function main() {
DATABASE_SCHEMA: ENSINDEXER_SCHEMA_NAME,
PLUGINS: "ensv2,protocol-acceleration",
ENSRAINBOW_URL,
ENSINDEXER_URL,
LABEL_SET_ID,
LABEL_SET_VERSION,
},
Expand Down
14 changes: 13 additions & 1 deletion packages/ponder-sdk/src/deserialize/ponder-app-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,22 @@ import {
} from "../ponder-app-context";
import type { Unvalidated } from "./utils";

/**
* Schema representing a valid port number for the Ponder app to listen on.
*/
export const schemaPortNumber = z
.number({ error: "Port must be a number." })
.int({ error: "Port must be an integer." })
.min(1, { error: "Port must be greater than or equal to 1." })
.max(65535, { error: "Port must be less than or equal to 65535." });

/**
* Type representing the "raw" context of a local Ponder app.
*/
const schemaRawPonderAppContext = z.object({
options: z.object({
command: z.string(),
command: z.enum(PonderAppCommands),
port: schemaPortNumber,
}),
});

Expand All @@ -36,6 +46,7 @@ export type RawPonderAppContext = z.infer<typeof schemaRawPonderAppContext>;
*/
const schemaPonderAppContext = z.object({
command: z.enum(PonderAppCommands),
localPonderAppUrl: z.instanceof(URL, { error: "localPonderAppUrl must be a valid URL." }),
});

/**
Expand All @@ -50,6 +61,7 @@ function buildUnvalidatedPonderAppContext(
): Unvalidated<PonderAppContext> {
return {
command: rawPonderAppContext.options.command as Unvalidated<PonderAppCommand>,
localPonderAppUrl: new URL(`http://localhost:${rawPonderAppContext.options.port}`),
};
}

Expand Down
12 changes: 5 additions & 7 deletions packages/ponder-sdk/src/local-ponder-client.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function createLocalPonderClientMock(overrides?: {
indexedChainIds?: Set<ChainId>;
indexedBlockranges?: Map<ChainId, BlockNumberRangeWithStartBlock>;
cachedPublicClients?: Record<ChainIdString, CachedPublicClient>;
ponderAppContext?: PonderAppContext;
ponderAppContext?: Pick<PonderAppContext, "command">;
}): LocalPonderClient {
const indexedChainIds =
overrides?.indexedChainIds ?? new Set<ChainId>([chainIds.Mainnet, chainIds.Optimism]);
Expand All @@ -35,14 +35,12 @@ export function createLocalPonderClientMock(overrides?: {
[`${chainIds.Base}`]: {} as CachedPublicClient,
} satisfies Record<ChainIdString, CachedPublicClient>);

const ponderAppContext =
overrides?.ponderAppContext ??
({
command: PonderAppCommands.Start,
} satisfies PonderAppContext);
const ponderAppContext = {
command: overrides?.ponderAppContext?.command ?? PonderAppCommands.Start,
localPonderAppUrl: new URL("http://localhost:3000"),
} satisfies PonderAppContext;

return new LocalPonderClient(
new URL("http://localhost:3000"),
indexedChainIds,
indexedBlockranges,
cachedPublicClients,
Expand Down
4 changes: 1 addition & 3 deletions packages/ponder-sdk/src/local-ponder-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,19 @@ export class LocalPonderClient extends PonderClient {
private ponderAppContext: PonderAppContext;

/**
* @param localPonderAppUrl URL of the local Ponder app to connect to.
* @param indexedChainIds Configured indexed chain IDs which are used to validate and filter the Ponder app metadata to only include entries for indexed chains.
* @param indexedBlockranges Configured indexing blockrange for each indexed chain.
* @param ponderPublicClients All cached public clients provided by the local Ponder app
* (may include non-indexed chains).
* @param ponderAppContext The internal context of the local Ponder app.
*/
constructor(
localPonderAppUrl: URL,
indexedChainIds: Set<ChainId>,
indexedBlockranges: Map<ChainId, BlockNumberRangeWithStartBlock>,
ponderPublicClients: Record<ChainIdString, CachedPublicClient>,
ponderAppContext: PonderAppContext,
) {
super(localPonderAppUrl);
super(ponderAppContext.localPonderAppUrl);

this.indexedChainIds = indexedChainIds;

Expand Down
Loading
Loading