@ensnode/ensdb-sdk 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ensindexer-abstract/index.d.ts +2 -2
- package/dist/ensindexer-abstract/index.js +53 -29
- package/dist/ensindexer-abstract/index.js.map +1 -1
- package/dist/{index-CUYtpVSw.d.ts → index-DN0SGSyd.d.ts} +137 -20
- package/dist/index.d.ts +63 -3
- package/dist/index.js +190 -42
- package/dist/index.js.map +1 -1
- package/migrations/0001_enable_ext_pg_trgm.sql +3 -0
- package/migrations/meta/0001_snapshot.json +55 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +11 -7
package/dist/index.js
CHANGED
|
@@ -4,18 +4,6 @@ var __export = (target, all) => {
|
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// src/client/ensdb-reader.ts
|
|
8
|
-
import { and, eq } from "drizzle-orm/sql";
|
|
9
|
-
import {
|
|
10
|
-
deserializeCrossChainIndexingStatusSnapshot,
|
|
11
|
-
deserializeEnsIndexerPublicConfig
|
|
12
|
-
} from "@ensnode/ensnode-sdk";
|
|
13
|
-
|
|
14
|
-
// src/lib/drizzle.ts
|
|
15
|
-
import { drizzle } from "drizzle-orm/node-postgres";
|
|
16
|
-
import { isPgEnum } from "drizzle-orm/pg-core";
|
|
17
|
-
import { isTable, Table } from "drizzle-orm/table";
|
|
18
|
-
|
|
19
7
|
// src/ensindexer-abstract/index.ts
|
|
20
8
|
var ensindexer_abstract_exports = {};
|
|
21
9
|
__export(ensindexer_abstract_exports, {
|
|
@@ -316,15 +304,16 @@ var registrationType = onchainEnum("RegistrationType", [
|
|
|
316
304
|
"NameWrapper",
|
|
317
305
|
"BaseRegistrar",
|
|
318
306
|
"ThreeDNS",
|
|
319
|
-
"
|
|
307
|
+
"ENSv2RegistryRegistration",
|
|
308
|
+
"ENSv2RegistryReservation"
|
|
320
309
|
]);
|
|
321
310
|
var registration = onchainTable(
|
|
322
311
|
"registrations",
|
|
323
312
|
(t) => ({
|
|
324
|
-
// keyed by (domainId,
|
|
313
|
+
// keyed by (domainId, registrationIndex)
|
|
325
314
|
id: t.text().primaryKey().$type(),
|
|
326
315
|
domainId: t.text().notNull().$type(),
|
|
327
|
-
|
|
316
|
+
registrationIndex: t.integer().notNull(),
|
|
328
317
|
// has a type
|
|
329
318
|
type: registrationType().notNull(),
|
|
330
319
|
// has a start
|
|
@@ -336,9 +325,11 @@ var registration = onchainTable(
|
|
|
336
325
|
// registrar AccountId
|
|
337
326
|
registrarChainId: t.integer().notNull().$type(),
|
|
338
327
|
registrarAddress: t.hex().notNull().$type(),
|
|
339
|
-
//
|
|
328
|
+
// may reference a registrant
|
|
340
329
|
registrantId: t.hex().$type(),
|
|
341
|
-
// may
|
|
330
|
+
// may reference an unregistrant
|
|
331
|
+
unregistrantId: t.hex().$type(),
|
|
332
|
+
// may have referrer data
|
|
342
333
|
referrer: t.hex().$type(),
|
|
343
334
|
// may have fuses (NameWrapper, Wrapped BaseRegistrar)
|
|
344
335
|
fuses: t.integer(),
|
|
@@ -353,12 +344,12 @@ var registration = onchainTable(
|
|
|
353
344
|
eventId: t.text().notNull()
|
|
354
345
|
}),
|
|
355
346
|
(t) => ({
|
|
356
|
-
byId: uniqueIndex().on(t.domainId, t.
|
|
347
|
+
byId: uniqueIndex().on(t.domainId, t.registrationIndex)
|
|
357
348
|
})
|
|
358
349
|
);
|
|
359
350
|
var latestRegistrationIndex = onchainTable("latest_registration_indexes", (t) => ({
|
|
360
351
|
domainId: t.text().primaryKey().$type(),
|
|
361
|
-
|
|
352
|
+
registrationIndex: t.integer().notNull()
|
|
362
353
|
}));
|
|
363
354
|
var registration_relations = relations(registration, ({ one, many }) => ({
|
|
364
355
|
// belongs to either v1Domain or v2Domain
|
|
@@ -376,6 +367,12 @@ var registration_relations = relations(registration, ({ one, many }) => ({
|
|
|
376
367
|
references: [account.id],
|
|
377
368
|
relationName: "registrant"
|
|
378
369
|
}),
|
|
370
|
+
// has one unregistrant
|
|
371
|
+
unregistrant: one(account, {
|
|
372
|
+
fields: [registration.unregistrantId],
|
|
373
|
+
references: [account.id],
|
|
374
|
+
relationName: "unregistrant"
|
|
375
|
+
}),
|
|
379
376
|
// has many renewals
|
|
380
377
|
renewals: many(renewal),
|
|
381
378
|
// has an event
|
|
@@ -391,7 +388,7 @@ var renewal = onchainTable(
|
|
|
391
388
|
id: t.text().primaryKey().$type(),
|
|
392
389
|
domainId: t.text().notNull().$type(),
|
|
393
390
|
registrationIndex: t.integer().notNull(),
|
|
394
|
-
|
|
391
|
+
renewalIndex: t.integer().notNull(),
|
|
395
392
|
// all renewals have a duration
|
|
396
393
|
duration: t.bigint().notNull(),
|
|
397
394
|
// may have a referrer
|
|
@@ -405,14 +402,14 @@ var renewal = onchainTable(
|
|
|
405
402
|
eventId: t.text().notNull()
|
|
406
403
|
}),
|
|
407
404
|
(t) => ({
|
|
408
|
-
byId: uniqueIndex().on(t.domainId, t.registrationIndex, t.
|
|
405
|
+
byId: uniqueIndex().on(t.domainId, t.registrationIndex, t.renewalIndex)
|
|
409
406
|
})
|
|
410
407
|
);
|
|
411
408
|
var renewal_relations = relations(renewal, ({ one }) => ({
|
|
412
409
|
// belongs to registration
|
|
413
410
|
registration: one(registration, {
|
|
414
411
|
fields: [renewal.domainId, renewal.registrationIndex],
|
|
415
|
-
references: [registration.domainId, registration.
|
|
412
|
+
references: [registration.domainId, registration.registrationIndex]
|
|
416
413
|
}),
|
|
417
414
|
// has an event
|
|
418
415
|
event: one(event, {
|
|
@@ -425,7 +422,7 @@ var latestRenewalIndex = onchainTable(
|
|
|
425
422
|
(t) => ({
|
|
426
423
|
domainId: t.text().notNull().$type(),
|
|
427
424
|
registrationIndex: t.integer().notNull(),
|
|
428
|
-
|
|
425
|
+
renewalIndex: t.integer().notNull()
|
|
429
426
|
}),
|
|
430
427
|
(t) => ({ pk: primaryKey({ columns: [t.domainId, t.registrationIndex] }) })
|
|
431
428
|
);
|
|
@@ -524,13 +521,9 @@ var reverseNameRecord = onchainTable2(
|
|
|
524
521
|
/**
|
|
525
522
|
* Represents the ENSIP-19 Reverse Name Record for a given (address, coinType).
|
|
526
523
|
*
|
|
527
|
-
* The value of this field is guaranteed to be a non-empty
|
|
528
|
-
* `interpretNameRecordValue` for additional context and specific guarantees). Unnormalized
|
|
529
|
-
* names and empty string values are interpreted as a deletion of the associated Reverse Name
|
|
530
|
-
* Record entity (represented in the schema as the _absence_ of a relevant Reverse Name Record
|
|
531
|
-
* entity).
|
|
524
|
+
* The value of this field is guaranteed to be a non-empty {@link InterpretedName}.
|
|
532
525
|
*/
|
|
533
|
-
value: t.text().notNull()
|
|
526
|
+
value: t.text().notNull().$type()
|
|
534
527
|
}),
|
|
535
528
|
(t) => ({
|
|
536
529
|
pk: primaryKey2({ columns: [t.address, t.coinType] })
|
|
@@ -583,14 +576,30 @@ var resolverRecords = onchainTable2(
|
|
|
583
576
|
/**
|
|
584
577
|
* Represents the value of the reverse-resolution (ENSIP-3) name() record, used for Reverse Resolution.
|
|
585
578
|
*
|
|
586
|
-
*
|
|
587
|
-
|
|
588
|
-
|
|
579
|
+
* If present, the value of this field is guaranteed to be a non-empty {@link InterpretedName}.
|
|
580
|
+
*/
|
|
581
|
+
name: t.text().$type(),
|
|
582
|
+
/**
|
|
583
|
+
* ENSIP-7 contenthash raw bytes or null if not set.
|
|
584
|
+
*/
|
|
585
|
+
contenthash: t.hex(),
|
|
586
|
+
/**
|
|
587
|
+
* PubkeyResolver (x, y) pair, or null if not set.
|
|
589
588
|
*
|
|
590
|
-
*
|
|
591
|
-
* (see `interpretNameRecordValue` for additional context and specific guarantees).
|
|
589
|
+
* Invariant: both null together, or both set together.
|
|
592
590
|
*/
|
|
593
|
-
|
|
591
|
+
pubkeyX: t.hex(),
|
|
592
|
+
pubkeyY: t.hex(),
|
|
593
|
+
/**
|
|
594
|
+
* IDNSZoneResolver zonehash or null if not set.
|
|
595
|
+
*/
|
|
596
|
+
dnszonehash: t.hex(),
|
|
597
|
+
/**
|
|
598
|
+
* IVersionableResolver version. Null when no `VersionChanged` event has been seen for this
|
|
599
|
+
* (chainId, address, node) — the resolver may not implement `IVersionableResolver`, or simply
|
|
600
|
+
* may never have been version-bumped. Consumers should treat null as "unknown" rather than 0.
|
|
601
|
+
*/
|
|
602
|
+
version: t.bigint().$type()
|
|
594
603
|
}),
|
|
595
604
|
(t) => ({
|
|
596
605
|
byId: uniqueIndex2().on(t.chainId, t.address, t.node)
|
|
@@ -668,7 +677,7 @@ var resolverTextRecordRelations = relations2(resolverTextRecord, ({ one }) => ({
|
|
|
668
677
|
})
|
|
669
678
|
}));
|
|
670
679
|
var migratedNode = onchainTable2("migrated_nodes", (t) => ({
|
|
671
|
-
node: t.hex().primaryKey()
|
|
680
|
+
node: t.hex().primaryKey().$type()
|
|
672
681
|
}));
|
|
673
682
|
|
|
674
683
|
// src/ensindexer-abstract/registrars.schema.ts
|
|
@@ -935,7 +944,7 @@ var registrarActions = onchainTable3(
|
|
|
935
944
|
* 3) May be the "zero address" to represent that an `encodedReferrer` is
|
|
936
945
|
* defined but that it is interpreted as no referrer.
|
|
937
946
|
*/
|
|
938
|
-
decodedReferrer: t.hex(),
|
|
947
|
+
decodedReferrer: t.hex().$type(),
|
|
939
948
|
/**
|
|
940
949
|
* Number of the block that includes the "logical registrar action".
|
|
941
950
|
*
|
|
@@ -1049,7 +1058,7 @@ var registrarActionRelations = relations3(registrarActions, ({ one }) => ({
|
|
|
1049
1058
|
}));
|
|
1050
1059
|
|
|
1051
1060
|
// src/ensindexer-abstract/subgraph.schema.ts
|
|
1052
|
-
import { index as index3, onchainTable as onchainTable4, relations as relations4 } from "ponder";
|
|
1061
|
+
import { index as index3, onchainTable as onchainTable4, relations as relations4, sql as sql2 } from "ponder";
|
|
1053
1062
|
|
|
1054
1063
|
// src/lib/collate.ts
|
|
1055
1064
|
function monkeypatchCollate(col, collation) {
|
|
@@ -1129,9 +1138,12 @@ var subgraph_domain = onchainTable4(
|
|
|
1129
1138
|
expiryDate: t.bigint()
|
|
1130
1139
|
}),
|
|
1131
1140
|
(t) => ({
|
|
1132
|
-
//
|
|
1133
|
-
|
|
1134
|
-
//
|
|
1141
|
+
// uses a hash index because some name values exceed the btree max row size (8191 bytes)
|
|
1142
|
+
byExactName: index3().using("hash", t.name),
|
|
1143
|
+
// GIN trigram index for partial-match filters (_contains, _starts_with, _ends_with).
|
|
1144
|
+
// (inline `gin_trgm_ops` via `sql` because passing it through `.op()` gets dropped by Ponder,
|
|
1145
|
+
// producing `USING gin (name)` with no opclass)
|
|
1146
|
+
byFuzzyName: index3().using("gin", sql2`${t.name} gin_trgm_ops`),
|
|
1135
1147
|
byLabelhash: index3().on(t.labelhash),
|
|
1136
1148
|
byParentId: index3().on(t.parentId),
|
|
1137
1149
|
byOwnerId: index3().on(t.ownerId),
|
|
@@ -1983,6 +1995,17 @@ var metadata = ENSNODE_SCHEMA.table(
|
|
|
1983
1995
|
]
|
|
1984
1996
|
);
|
|
1985
1997
|
|
|
1998
|
+
// src/lib/drizzle.ts
|
|
1999
|
+
import { drizzle } from "drizzle-orm/node-postgres";
|
|
2000
|
+
import { isPgEnum } from "drizzle-orm/pg-core";
|
|
2001
|
+
import { isTable, Table } from "drizzle-orm/table";
|
|
2002
|
+
|
|
2003
|
+
// src/lib/checksum.ts
|
|
2004
|
+
import { createHash } from "crypto";
|
|
2005
|
+
function createChecksum(data) {
|
|
2006
|
+
return createHash("sha256").update(data).digest("hex").slice(0, 10);
|
|
2007
|
+
}
|
|
2008
|
+
|
|
1986
2009
|
// src/lib/drizzle.ts
|
|
1987
2010
|
var appliedNameForConcreteEnsIndexerSchema;
|
|
1988
2011
|
function buildConcreteEnsIndexerSchema(ensIndexerSchemaName) {
|
|
@@ -2023,6 +2046,50 @@ function buildEnsDbDrizzleClient(connectionString, concreteEnsIndexerSchema, log
|
|
|
2023
2046
|
logger
|
|
2024
2047
|
});
|
|
2025
2048
|
}
|
|
2049
|
+
function safeStringifyDrizzleSchema(schema) {
|
|
2050
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
2051
|
+
return JSON.stringify(schema, (_key, value) => {
|
|
2052
|
+
if (typeof value === "bigint") return `${value}n`;
|
|
2053
|
+
if (typeof value === "object" && value !== null) {
|
|
2054
|
+
if (seen.has(value)) return "[circular]";
|
|
2055
|
+
seen.add(value);
|
|
2056
|
+
}
|
|
2057
|
+
return value;
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
function getDrizzleSchemaChecksum(schema) {
|
|
2061
|
+
const stringifiedSchema = safeStringifyDrizzleSchema(schema);
|
|
2062
|
+
return createChecksum(stringifiedSchema);
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
// src/client/ensdb-config.ts
|
|
2066
|
+
var ENSDB_SCHEMA_CHECKSUM = getDrizzleSchemaChecksum({
|
|
2067
|
+
...ensindexer_abstract_exports,
|
|
2068
|
+
...ensnode_exports
|
|
2069
|
+
});
|
|
2070
|
+
|
|
2071
|
+
// src/client/ensdb-reader.ts
|
|
2072
|
+
import { and, eq } from "drizzle-orm/sql";
|
|
2073
|
+
import {
|
|
2074
|
+
deserializeCrossChainIndexingStatusSnapshot,
|
|
2075
|
+
deserializeEnsIndexerPublicConfig
|
|
2076
|
+
} from "@ensnode/ensnode-sdk";
|
|
2077
|
+
|
|
2078
|
+
// src/lib/parse-pg-version-info.ts
|
|
2079
|
+
function parsePgVersionInfo(versionString) {
|
|
2080
|
+
if (typeof versionString !== "string") {
|
|
2081
|
+
throw new Error("PostgreSQL version string must be a string");
|
|
2082
|
+
}
|
|
2083
|
+
const match = versionString.match(/PostgreSQL (\d+\.\d+)/);
|
|
2084
|
+
if (!match) {
|
|
2085
|
+
throw new Error(`Failed to parse PostgreSQL version from version string: '${versionString}'`);
|
|
2086
|
+
}
|
|
2087
|
+
const parsedVersion = match[1];
|
|
2088
|
+
if (typeof parsedVersion !== "string") {
|
|
2089
|
+
throw new Error(`Parsed PostgreSQL version is not a string: '${parsedVersion}'`);
|
|
2090
|
+
}
|
|
2091
|
+
return parsedVersion;
|
|
2092
|
+
}
|
|
2026
2093
|
|
|
2027
2094
|
// src/client/ensnode-metadata.ts
|
|
2028
2095
|
var EnsNodeMetadataKeys = {
|
|
@@ -2131,6 +2198,15 @@ var EnsDbReader = class {
|
|
|
2131
2198
|
}
|
|
2132
2199
|
return deserializeEnsIndexerPublicConfig(record);
|
|
2133
2200
|
}
|
|
2201
|
+
/**
|
|
2202
|
+
* Build ENSDb Public Config
|
|
2203
|
+
*/
|
|
2204
|
+
async buildEnsDbPublicConfig() {
|
|
2205
|
+
const versionInfo = await this.buildEnsDbVersionInfo();
|
|
2206
|
+
return {
|
|
2207
|
+
versionInfo
|
|
2208
|
+
};
|
|
2209
|
+
}
|
|
2134
2210
|
/**
|
|
2135
2211
|
* Get Indexing Status Snapshot
|
|
2136
2212
|
*
|
|
@@ -2172,6 +2248,33 @@ var EnsDbReader = class {
|
|
|
2172
2248
|
`There must be exactly one ENSNodeMetadata record for ('${this.ensIndexerSchemaName}', '${metadata2.key}') composite key`
|
|
2173
2249
|
);
|
|
2174
2250
|
}
|
|
2251
|
+
/**
|
|
2252
|
+
* Get PostgreSQL version for the server hosting the ENSDb instance.
|
|
2253
|
+
*
|
|
2254
|
+
* @throws when the version cannot be retrieved or parsed from the query result.
|
|
2255
|
+
*/
|
|
2256
|
+
async getPostgresVersion() {
|
|
2257
|
+
const result = await this.ensDb.execute("SELECT version();");
|
|
2258
|
+
const versionString = result.rows[0]?.version;
|
|
2259
|
+
try {
|
|
2260
|
+
return parsePgVersionInfo(versionString);
|
|
2261
|
+
} catch (error) {
|
|
2262
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2263
|
+
throw new Error(`Failed to get PostgreSQL version for the ENSDb instance: ${errorMessage}`);
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Build ENSDb version info.
|
|
2268
|
+
*
|
|
2269
|
+
* @throws when version info cannot be retrieved or parsed from
|
|
2270
|
+
* the ENSDb instance.
|
|
2271
|
+
*/
|
|
2272
|
+
async buildEnsDbVersionInfo() {
|
|
2273
|
+
const postgresVersion = await this.getPostgresVersion();
|
|
2274
|
+
return {
|
|
2275
|
+
postgresql: postgresVersion
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2175
2278
|
};
|
|
2176
2279
|
|
|
2177
2280
|
// src/client/ensdb-writer.ts
|
|
@@ -2243,9 +2346,54 @@ var EnsDbWriter = class extends EnsDbReader {
|
|
|
2243
2346
|
});
|
|
2244
2347
|
}
|
|
2245
2348
|
};
|
|
2349
|
+
|
|
2350
|
+
// src/client/validate/ensdb-config.ts
|
|
2351
|
+
import { prettifyError } from "zod/v4";
|
|
2352
|
+
|
|
2353
|
+
// src/client/zod-schemas/ensdb-config.ts
|
|
2354
|
+
import { parse as parseConnectionString } from "pg-connection-string";
|
|
2355
|
+
import { z } from "zod/v4";
|
|
2356
|
+
var EnsDbUrlSchema = z.string().refine(
|
|
2357
|
+
(url) => {
|
|
2358
|
+
try {
|
|
2359
|
+
if (!url.startsWith("postgresql://") && !url.startsWith("postgres://")) {
|
|
2360
|
+
return false;
|
|
2361
|
+
}
|
|
2362
|
+
const config = parseConnectionString(url);
|
|
2363
|
+
return !!(config.host && config.port && config.database);
|
|
2364
|
+
} catch {
|
|
2365
|
+
return false;
|
|
2366
|
+
}
|
|
2367
|
+
},
|
|
2368
|
+
{
|
|
2369
|
+
error: "Invalid PostgreSQL connection string for ENSDb. Expected format: postgresql://username:password@host:port/database"
|
|
2370
|
+
}
|
|
2371
|
+
);
|
|
2372
|
+
var EnsIndexerSchemaNameSchema = z.string({
|
|
2373
|
+
error: "ENSIndexer Schema Name is required."
|
|
2374
|
+
}).trim().nonempty({
|
|
2375
|
+
error: "ENSIndexer Schema Name cannot be an empty string."
|
|
2376
|
+
});
|
|
2377
|
+
var EnsDbConfigSchema = z.object({
|
|
2378
|
+
ensDbUrl: EnsDbUrlSchema,
|
|
2379
|
+
ensIndexerSchemaName: EnsIndexerSchemaNameSchema
|
|
2380
|
+
});
|
|
2381
|
+
|
|
2382
|
+
// src/client/validate/ensdb-config.ts
|
|
2383
|
+
function validateEnsDbConfig(unvalidatedConfig) {
|
|
2384
|
+
const ensDbConfig = EnsDbConfigSchema.safeParse(unvalidatedConfig);
|
|
2385
|
+
if (!ensDbConfig.success) {
|
|
2386
|
+
throw new Error(`Failed to parse ENSDb configuration:
|
|
2387
|
+
${prettifyError(ensDbConfig.error)}
|
|
2388
|
+
`);
|
|
2389
|
+
}
|
|
2390
|
+
return ensDbConfig.data;
|
|
2391
|
+
}
|
|
2246
2392
|
export {
|
|
2393
|
+
ENSDB_SCHEMA_CHECKSUM,
|
|
2247
2394
|
EnsDbReader,
|
|
2248
2395
|
EnsDbWriter,
|
|
2249
|
-
EnsNodeMetadataKeys
|
|
2396
|
+
EnsNodeMetadataKeys,
|
|
2397
|
+
validateEnsDbConfig
|
|
2250
2398
|
};
|
|
2251
2399
|
//# sourceMappingURL=index.js.map
|