@artblocks/abx-indexer 0.1.0-alpha.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Art Blocks, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @artblocks/abx-indexer — Layer 3 reference indexer.
3
+ *
4
+ * Replays the event spine from chain into a disposable, rebuildable projection.
5
+ * The canonical re-index: how every service onboards or exits a project.
6
+ */
7
+ export { SelfHostIndexer, type IndexResult } from './indexer.js';
8
+ export { SqliteStore, type Store, type ProjectRegistration, type EffectStatusRow, type EffectArtifactRow, } from './store.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAC,eAAe,EAAE,KAAK,WAAW,EAAC,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,WAAW,EACX,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @artblocks/abx-indexer — Layer 3 reference indexer.
3
+ *
4
+ * Replays the event spine from chain into a disposable, rebuildable projection.
5
+ * The canonical re-index: how every service onboards or exits a project.
6
+ */
7
+ export { SelfHostIndexer } from './indexer.js';
8
+ export { SqliteStore, } from './store.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAC,eAAe,EAAmB,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,WAAW,GAKZ,MAAM,YAAY,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { type Address, type ProjectState, type PublicClient } from '@artblocks/abx-sdk';
2
+ import { type Store, type ProjectRegistration } from './store.js';
3
+ export interface IndexResult {
4
+ state: ProjectState;
5
+ elapsedMs: number;
6
+ mode: 'full' | 'incremental';
7
+ }
8
+ /**
9
+ * The reference indexer (Layer 3). It does one thing well: replay the event
10
+ * spine from chain into the store. Because every state change rides a standard,
11
+ * versioned event, re-indexing is a *compute* cost, not an engineering one — and
12
+ * it needs no cooperation from whatever provider held the data before. This is
13
+ * the implementation everyone re-indexes with when they onboard or leave a
14
+ * service; running a different one changes nothing the protocol guarantees.
15
+ */
16
+ export declare class SelfHostIndexer {
17
+ readonly store: Store;
18
+ private clients;
19
+ constructor(store?: Store);
20
+ private client;
21
+ /** The RPC client for a chain — exposed for reads that aren't a reindex (e.g. deploy-block
22
+ * discovery in the admin control plane). Reuses the same pooled client as `reindex`. */
23
+ publicClient(chainKey: string): PublicClient;
24
+ /** Register a project to index (the minimum needed to replay it). */
25
+ register(reg: Omit<ProjectRegistration, 'registeredAt'>): ProjectRegistration;
26
+ /**
27
+ * Re-index a single project. By default this is **incremental**: it resumes from
28
+ * the stored checkpoint and only fetches blocks added since — so re-indexing is
29
+ * fast no matter how far head has moved — yet yields state identical to a full
30
+ * replay. `{full: true}` forces a replay from the deploy block (the durability
31
+ * proof, and what runs automatically when there's no prior state). Idempotent.
32
+ */
33
+ reindex(address: Address, opts?: {
34
+ full?: boolean;
35
+ }): Promise<IndexResult>;
36
+ /** Re-index every registered project. */
37
+ reindexAll(opts?: {
38
+ full?: boolean;
39
+ }): Promise<IndexResult[]>;
40
+ getProject(address: Address): ProjectState | null;
41
+ listProjects(): ProjectState[];
42
+ }
43
+ //# sourceMappingURL=indexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAc,KAAK,KAAK,EAAE,KAAK,mBAAmB,EAAC,MAAM,YAAY,CAAC;AAE7E,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,OAAO,CAAC,OAAO,CAAmC;gBAEtC,KAAK,CAAC,EAAE,KAAK;IAIzB,OAAO,CAAC,MAAM;IAMd;6FACyF;IACzF,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY;IAI5C,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,mBAAmB,EAAE,cAAc,CAAC,GAAG,mBAAmB;IAM7E;;;;;;OAMG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAE;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA2BlF,yCAAyC;IACnC,UAAU,CAAC,IAAI,GAAE;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAQrE,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI;IAIjD,YAAY,IAAI,YAAY,EAAE;CAG/B"}
@@ -0,0 +1,82 @@
1
+ import { makePublicClient, reconstructIncremental, reconstructProject, } from '@artblocks/abx-sdk';
2
+ import { SqliteStore } from './store.js';
3
+ /**
4
+ * The reference indexer (Layer 3). It does one thing well: replay the event
5
+ * spine from chain into the store. Because every state change rides a standard,
6
+ * versioned event, re-indexing is a *compute* cost, not an engineering one — and
7
+ * it needs no cooperation from whatever provider held the data before. This is
8
+ * the implementation everyone re-indexes with when they onboard or leave a
9
+ * service; running a different one changes nothing the protocol guarantees.
10
+ */
11
+ export class SelfHostIndexer {
12
+ store;
13
+ clients = new Map();
14
+ constructor(store) {
15
+ this.store = store ?? new SqliteStore();
16
+ }
17
+ client(chainKey) {
18
+ let c = this.clients.get(chainKey);
19
+ if (!c)
20
+ this.clients.set(chainKey, (c = makePublicClient({ chainKey })));
21
+ return c;
22
+ }
23
+ /** The RPC client for a chain — exposed for reads that aren't a reindex (e.g. deploy-block
24
+ * discovery in the admin control plane). Reuses the same pooled client as `reindex`. */
25
+ publicClient(chainKey) {
26
+ return this.client(chainKey);
27
+ }
28
+ /** Register a project to index (the minimum needed to replay it). */
29
+ register(reg) {
30
+ const full = { ...reg, registeredAt: new Date().toISOString() };
31
+ this.store.register(full);
32
+ return full;
33
+ }
34
+ /**
35
+ * Re-index a single project. By default this is **incremental**: it resumes from
36
+ * the stored checkpoint and only fetches blocks added since — so re-indexing is
37
+ * fast no matter how far head has moved — yet yields state identical to a full
38
+ * replay. `{full: true}` forces a replay from the deploy block (the durability
39
+ * proof, and what runs automatically when there's no prior state). Idempotent.
40
+ */
41
+ async reindex(address, opts = {}) {
42
+ const reg = this.store.getRegistration(address);
43
+ // User-facing: this surfaces through `abx index`/`abx verify`. Name the real command a creator
44
+ // runs (`abx add`), never the internal `register()` (there is no `abx register` — a dead end).
45
+ if (!reg)
46
+ throw new Error(`${address} isn't registered on this node yet — add it first: abx add ${address}`);
47
+ const started = Date.now();
48
+ const factory = reg.factory ? reg.factory : undefined;
49
+ const prior = opts.full ? null : this.store.getProject(address);
50
+ let state;
51
+ let mode;
52
+ if (prior && prior.deployBlock && prior.events.length > 0) {
53
+ state = await reconstructIncremental(this.client(reg.chainKey), prior, { factory });
54
+ mode = 'incremental';
55
+ }
56
+ else {
57
+ state = await reconstructProject(this.client(reg.chainKey), {
58
+ address,
59
+ fromBlock: BigInt(reg.fromBlock),
60
+ factory,
61
+ });
62
+ mode = 'full';
63
+ }
64
+ this.store.putProject(state);
65
+ return { state, elapsedMs: Date.now() - started, mode };
66
+ }
67
+ /** Re-index every registered project. */
68
+ async reindexAll(opts = {}) {
69
+ const out = [];
70
+ for (const reg of this.store.listRegistrations()) {
71
+ out.push(await this.reindex(reg.address, opts));
72
+ }
73
+ return out;
74
+ }
75
+ getProject(address) {
76
+ return this.store.getProject(address);
77
+ }
78
+ listProjects() {
79
+ return this.store.listProjects();
80
+ }
81
+ }
82
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import type { ProjectState } from '@artblocks/abx-sdk';
2
+ /** How a project was registered for indexing — the minimum to replay it. */
3
+ export interface ProjectRegistration {
4
+ address: string;
5
+ chainKey: string;
6
+ fromBlock: string;
7
+ factory: string | null;
8
+ label?: string;
9
+ /** Operator display metadata served in the token's ERC-721 JSON (the creator's words). */
10
+ description?: string;
11
+ externalUrl?: string;
12
+ /** Operator's off-chain OpenSea attributes (JSON array), stitched UNDER any on-chain `attributes`.
13
+ * Collection-scope: a 1/1's traits, or a Series' shared/fallback traits. */
14
+ attributes?: string;
15
+ /** Operator's off-chain PER-TOKEN attributes (JSON `{ "<tokenId>": OpenSeaAttribute[] }`) — a Series'
16
+ * editable, resolver-served traits (the per-token twin of `attributes`; a token's entry wins over
17
+ * the collection-scope `attributes`, and any on-chain `attributes` still wins over both). */
18
+ tokenAttributes?: string;
19
+ /** Durable content locators keyed by on-chain hash (JSON `{ "0x<keccak>": "ipfs://<cid>" }`) —
20
+ * bridged from the deployer so this store can point `image` at IPFS/Arweave without the bytes. */
21
+ contentLocators?: string;
22
+ registeredAt: string;
23
+ }
24
+ /** One producer-published effect artifact — a row in the data plane's enumeration registry
25
+ * (`specs/protocol/data-plane.md`). The resolver lists a token's rows and keeps only those whose
26
+ * `key` matches the recomputed address at the CURRENT settled inputsHash, so stale rows go
27
+ * silently unlisted (self-invalidation). `locator === null` means the bytes live in custody
28
+ * (the shared backend at `key`, or resolver-held published bytes). Producer-published, NOT
29
+ * chain-derived: rows survive a projection wipe and self-heal from a runner's next sweep. */
30
+ export interface EffectArtifactRow {
31
+ /** renderArtifactKey (keccak hex; encodes effectKey + settled inputsHash). */
32
+ key: string;
33
+ address: string;
34
+ tokenId: string;
35
+ effectKey: string;
36
+ outputKey: string;
37
+ inputsHash: string;
38
+ /** The effect's DECLARED output mimeType — what the manifest and byte route serve. */
39
+ contentType: string | null;
40
+ locator: string | null;
41
+ updatedAt?: string;
42
+ }
43
+ /** Transient per-(artifact key) effect observability — `rendering`/`failed` between triggers.
44
+ * Rebuildable state ONLY: "up to date" is always artifact-presence at the current settled
45
+ * inputsHash, never a row here; a lost table costs history, not correctness. */
46
+ export interface EffectStatusRow {
47
+ /** The artifact key (renderArtifactKey at the settled inputsHash) this run is producing. */
48
+ key: string;
49
+ address: string;
50
+ tokenId: string;
51
+ effectKey: string;
52
+ status: 'rendering' | 'failed';
53
+ error?: string | null;
54
+ attempts?: number;
55
+ updatedAt?: string;
56
+ }
57
+ /**
58
+ * The projection store contract. Two responsibilities, kept distinct:
59
+ *
60
+ * - **registrations** — the minimum needed to replay a project (operator input).
61
+ * - **projects** — the reconstructed state, the *disposable, replay-rebuildable
62
+ * projection*. `wipeProjections()` clears only this; registrations survive.
63
+ *
64
+ * The reference implementation is {@link SqliteStore}. A platform-scale deploy
65
+ * swaps in a Postgres-backed implementation behind this same interface — nothing
66
+ * upstream (indexer, token API) changes.
67
+ */
68
+ export interface Store {
69
+ /** Where the projection lives on disk (for display / ops). */
70
+ readonly path: string;
71
+ register(reg: ProjectRegistration): void;
72
+ listRegistrations(): ProjectRegistration[];
73
+ getRegistration(address: string): ProjectRegistration | null;
74
+ /** Forget a project entirely — drop its registration and its projection (on-chain data is untouched). */
75
+ deregister(address: string): void;
76
+ /** Register one effect artifact (the data plane's enumeration registry). Effect-agnostic —
77
+ * producers declare the (effectKey, outputKey, mimeType); the store never interprets them.
78
+ * Idempotent — last write wins per key. */
79
+ putEffectArtifact(row: EffectArtifactRow): void;
80
+ /** The registered artifact row for an effect artifact key, or null. */
81
+ getEffectArtifact(key: string): EffectArtifactRow | null;
82
+ /** Every registered artifact row for (project, token) — the manifest's effect-source listing.
83
+ * Callers filter by recomputing the current-inputsHash key per row (stale rows unlisted). */
84
+ listEffectArtifacts(address: string, tokenId: string): EffectArtifactRow[];
85
+ /** Node-level key/value metadata (e.g. the chain watcher's persisted watermark). */
86
+ putMeta(key: string, value: string): void;
87
+ getMeta(key: string): string | null;
88
+ /** Upsert transient effect observability (`rendering` / `failed`) for an artifact key. */
89
+ putEffectStatus(row: EffectStatusRow): void;
90
+ /** Clear one artifact key's status — the run finished; artifact presence takes over as truth. */
91
+ clearEffectStatus(key: string): void;
92
+ listEffectStatuses(address: string): EffectStatusRow[];
93
+ putProject(state: ProjectState): void;
94
+ getProject(address: string): ProjectState | null;
95
+ listProjects(): ProjectState[];
96
+ /** Drop the rebuildable projection (keeps registrations). Proves replay. */
97
+ wipeProjections(): void;
98
+ /** Close and remove the underlying store entirely. */
99
+ destroy(): void;
100
+ }
101
+ /**
102
+ * The reference store: a single SQLite file (`.abx-self-host/index.db`).
103
+ *
104
+ * It keeps the elegant property of the file-based projection — *one disposable
105
+ * artifact you can delete and replay* — while adding real indexes, queries, and
106
+ * transactional writes. No server, no second container, no connection string:
107
+ * SQLite is embedded, the indexer is the only writer, and the token API is
108
+ * read-heavy, so WAL mode fits the access pattern exactly.
109
+ *
110
+ * The reconstructed state is normalized across `projects` / `tokens` /
111
+ * `commitments` / `extensions` / `events`. Wiping those tables (keeping
112
+ * `registrations`) and replaying yields identical state — that's the whole point.
113
+ */
114
+ export declare class SqliteStore implements Store {
115
+ readonly path: string;
116
+ private db;
117
+ constructor(dataDir?: string);
118
+ /** Shape changes that must land BEFORE the schema exec (its indexes reference new columns).
119
+ * effect_artifacts pre-data-plane shape (key/address/locator only) → drop; the schema recreates
120
+ * it. Dropping is safe pre-release: rows are producer-published and self-heal from a runner's
121
+ * next sweep (record-on-skip / republish) — no chain data is lost. */
122
+ private premigrate;
123
+ /** Idempotently add columns introduced after a DB was first created (CREATE IF NOT
124
+ * EXISTS won't backfill them). Keeps an existing projection working across upgrades. */
125
+ private migrate;
126
+ register(reg: ProjectRegistration): void;
127
+ listRegistrations(): ProjectRegistration[];
128
+ getRegistration(address: string): ProjectRegistration | null;
129
+ deregister(address: string): void;
130
+ putEffectArtifact(row: EffectArtifactRow): void;
131
+ getEffectArtifact(key: string): EffectArtifactRow | null;
132
+ listEffectArtifacts(address: string, tokenId: string): EffectArtifactRow[];
133
+ putMeta(key: string, value: string): void;
134
+ getMeta(key: string): string | null;
135
+ putEffectStatus(row: EffectStatusRow): void;
136
+ clearEffectStatus(key: string): void;
137
+ listEffectStatuses(address: string): EffectStatusRow[];
138
+ putProject(state: ProjectState): void;
139
+ getProject(address: string): ProjectState | null;
140
+ listProjects(): ProjectState[];
141
+ wipeProjections(): void;
142
+ destroy(): void;
143
+ private deleteProjection;
144
+ private hydrate;
145
+ }
146
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/dist/store.js ADDED
@@ -0,0 +1,484 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import { existsSync, mkdirSync, rmSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ // The data plane's effect-artifact registry (`specs/protocol/data-plane.md`): one row per declared
5
+ // output a runner produced, keyed by renderArtifactKey at the CURRENT settled inputsHash (a param
6
+ // change re-addresses → old rows go silently unlisted). Effect-agnostic — producers declare the
7
+ // (effect_key, output_key, content_type); the store never interprets them. locator NULL = the bytes
8
+ // live in custody (shared backend, or published bytes at `key`). Producer-published, NOT chain-
9
+ // derived, so like registrations rows survive a projection wipe/replay — and a lost table self-heals
10
+ // from a runner's next sweep (record-on-skip / republish).
11
+ const EFFECT_ARTIFACTS_DDL = `
12
+ CREATE TABLE IF NOT EXISTS effect_artifacts (
13
+ key TEXT PRIMARY KEY, -- renderArtifactKey (keccak hex; encodes effectKey + settled inputsHash)
14
+ address TEXT NOT NULL, -- lowercased project address
15
+ token_id TEXT NOT NULL,
16
+ effect_key TEXT NOT NULL, -- 'render' | any registered effect
17
+ output_key TEXT NOT NULL, -- 'image' | 'traits' | any declared output
18
+ inputs_hash TEXT NOT NULL, -- the settled inputsHash this row was produced at
19
+ locator TEXT, -- ipfs://<cid> | ar://<txid> | https://… | NULL (bytes in custody)
20
+ content_type TEXT, -- the effect's DECLARED output mimeType
21
+ updated_at TEXT NOT NULL
22
+ );
23
+ CREATE INDEX IF NOT EXISTS idx_effect_artifacts_token ON effect_artifacts(address, token_id);
24
+ `;
25
+ const SCHEMA = `
26
+ PRAGMA journal_mode = WAL;
27
+ PRAGMA foreign_keys = ON;
28
+ -- Cross-process co-located writes (a local effect runner records artifact rows into this same
29
+ -- file while the resolver serves): wait out a writer instead of failing fast. WAL keeps readers
30
+ -- unblocked; artifact writes are rare (one per rendered output) and touch a table the indexer
31
+ -- never writes.
32
+ PRAGMA busy_timeout = 5000;
33
+
34
+ CREATE TABLE IF NOT EXISTS registrations (
35
+ address TEXT PRIMARY KEY, -- lowercased
36
+ chain_key TEXT NOT NULL,
37
+ from_block TEXT NOT NULL,
38
+ factory TEXT,
39
+ label TEXT,
40
+ description TEXT,
41
+ external_url TEXT,
42
+ attributes TEXT, -- JSON OpenSeaAttribute[] (off-chain operator traits, collection-scope)
43
+ token_attributes TEXT, -- JSON { "<tokenId>": OpenSeaAttribute[] } (off-chain per-token traits)
44
+ content_locators TEXT, -- JSON { "0x<keccak>": "ipfs://<cid>" }
45
+ registered_at TEXT NOT NULL
46
+ );
47
+
48
+ CREATE TABLE IF NOT EXISTS projects (
49
+ address TEXT PRIMARY KEY, -- lowercased
50
+ address_original TEXT NOT NULL, -- checksummed, as reconstructed
51
+ chain_id INTEGER NOT NULL,
52
+ abx_version INTEGER,
53
+ deploy_block TEXT,
54
+ deploy_tx TEXT,
55
+ factory TEXT,
56
+ implementation TEXT,
57
+ is_canonical INTEGER, -- 0 | 1 | NULL
58
+ name TEXT,
59
+ symbol TEXT,
60
+ owner TEXT,
61
+ contract_uri TEXT,
62
+ token_uri_renderer TEXT, -- non-null => tokenURI resolves on-chain
63
+ token_uri_locked INTEGER, -- 0 | 1 | NULL
64
+ contract_uri_renderer TEXT,
65
+ contract_uri_locked INTEGER,
66
+ royalty_receiver TEXT, -- NULL => no royalty
67
+ royalty_bps INTEGER,
68
+ collection_fields TEXT, -- JSON MetadataField[] (collection scope)
69
+ locked_collection_fields TEXT, -- JSON string[]
70
+ contract_type TEXT, -- '1of1' | 'series' (from enabled extensions)
71
+ max_invocations TEXT, -- Series supply cap (decimal string) or NULL
72
+ minter TEXT, -- the single authorized minter or NULL
73
+ paused INTEGER, -- Paused extension: 1 | 0 | NULL (NULL/0 ⇒ unpaused)
74
+ primary_payee TEXT, -- Primary Payee destination or NULL
75
+ from_block TEXT NOT NULL,
76
+ to_block TEXT NOT NULL,
77
+ event_count INTEGER NOT NULL,
78
+ reconstructed_at TEXT NOT NULL,
79
+ rpc_url TEXT
80
+ );
81
+
82
+ CREATE TABLE IF NOT EXISTS tokens (
83
+ project_address TEXT NOT NULL,
84
+ token_id TEXT NOT NULL,
85
+ minted INTEGER NOT NULL DEFAULT 0,
86
+ owner TEXT,
87
+ token_uri TEXT,
88
+ fields TEXT, -- JSON MetadataField[] (on-chain token fields)
89
+ locked_fields TEXT, -- JSON string[] (locked field names)
90
+ PRIMARY KEY (project_address, token_id)
91
+ );
92
+
93
+ CREATE TABLE IF NOT EXISTS extensions (
94
+ project_address TEXT NOT NULL,
95
+ id TEXT NOT NULL,
96
+ name TEXT NOT NULL,
97
+ version INTEGER NOT NULL,
98
+ PRIMARY KEY (project_address, id)
99
+ );
100
+
101
+ CREATE TABLE IF NOT EXISTS events (
102
+ project_address TEXT NOT NULL,
103
+ seq INTEGER NOT NULL, -- chain order (block, logIndex)
104
+ name TEXT NOT NULL,
105
+ register INTEGER NOT NULL,
106
+ what TEXT NOT NULL,
107
+ block_number TEXT NOT NULL,
108
+ log_index INTEGER NOT NULL,
109
+ tx_hash TEXT NOT NULL,
110
+ args TEXT NOT NULL, -- JSON
111
+ PRIMARY KEY (project_address, seq)
112
+ );
113
+
114
+ CREATE INDEX IF NOT EXISTS idx_tokens_project ON tokens(project_address);
115
+ CREATE INDEX IF NOT EXISTS idx_extensions_project ON extensions(project_address);
116
+ CREATE INDEX IF NOT EXISTS idx_events_project ON events(project_address);
117
+
118
+ ${EFFECT_ARTIFACTS_DDL}
119
+
120
+ -- Node-level key/value metadata: the chain watcher's persisted watermark, etc. NOT chain-derived
121
+ -- (survives a projection wipe; losing it merely re-notifies once, which idempotency absorbs).
122
+ CREATE TABLE IF NOT EXISTS meta (
123
+ key TEXT PRIMARY KEY,
124
+ value TEXT NOT NULL
125
+ );
126
+
127
+ -- Transient effect observability: 'rendering' / 'failed' between triggers, reported by a runner.
128
+ -- REBUILDABLE ONLY — "up to date" is artifact-presence at the current settled inputsHash, never a
129
+ -- row here. A wiped table loses history (attempt counts, error text), not correctness.
130
+ CREATE TABLE IF NOT EXISTS effect_status (
131
+ key TEXT PRIMARY KEY, -- the artifact key this run produces
132
+ address TEXT NOT NULL, -- lowercased project address
133
+ token_id TEXT NOT NULL,
134
+ effect_key TEXT NOT NULL, -- 'render' | any registered effect
135
+ status TEXT NOT NULL, -- 'rendering' | 'failed'
136
+ error TEXT,
137
+ attempts INTEGER,
138
+ updated_at TEXT NOT NULL
139
+ );
140
+ CREATE INDEX IF NOT EXISTS idx_effect_status_address ON effect_status(address);
141
+ `;
142
+ const b = (v) => v === null || v === undefined ? null : v ? 1 : 0;
143
+ const lc = (address) => address.toLowerCase();
144
+ /**
145
+ * The reference store: a single SQLite file (`.abx-self-host/index.db`).
146
+ *
147
+ * It keeps the elegant property of the file-based projection — *one disposable
148
+ * artifact you can delete and replay* — while adding real indexes, queries, and
149
+ * transactional writes. No server, no second container, no connection string:
150
+ * SQLite is embedded, the indexer is the only writer, and the token API is
151
+ * read-heavy, so WAL mode fits the access pattern exactly.
152
+ *
153
+ * The reconstructed state is normalized across `projects` / `tokens` /
154
+ * `commitments` / `extensions` / `events`. Wiping those tables (keeping
155
+ * `registrations`) and replaying yields identical state — that's the whole point.
156
+ */
157
+ export class SqliteStore {
158
+ path;
159
+ db;
160
+ constructor(dataDir) {
161
+ const dir = dataDir ?? process.env.ABX_DATA_DIR ?? resolve(process.cwd(), '.abx-self-host');
162
+ mkdirSync(dir, { recursive: true });
163
+ this.path = resolve(dir, 'index.db');
164
+ this.db = new DatabaseSync(this.path);
165
+ this.premigrate();
166
+ this.db.exec(SCHEMA);
167
+ this.migrate();
168
+ }
169
+ /** Shape changes that must land BEFORE the schema exec (its indexes reference new columns).
170
+ * effect_artifacts pre-data-plane shape (key/address/locator only) → drop; the schema recreates
171
+ * it. Dropping is safe pre-release: rows are producer-published and self-heal from a runner's
172
+ * next sweep (record-on-skip / republish) — no chain data is lost. */
173
+ premigrate() {
174
+ const cols = this.db.prepare(`PRAGMA table_info(effect_artifacts)`).all();
175
+ if (cols.length > 0 && !cols.some((c) => c.name === 'token_id')) {
176
+ this.db.exec(`DROP TABLE effect_artifacts`);
177
+ }
178
+ }
179
+ /** Idempotently add columns introduced after a DB was first created (CREATE IF NOT
180
+ * EXISTS won't backfill them). Keeps an existing projection working across upgrades. */
181
+ migrate() {
182
+ const add = (table, col) => {
183
+ try {
184
+ this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${col}`);
185
+ }
186
+ catch {
187
+ /* column already exists */
188
+ }
189
+ };
190
+ add('registrations', 'description TEXT');
191
+ add('registrations', 'external_url TEXT');
192
+ add('registrations', 'attributes TEXT');
193
+ add('registrations', 'token_attributes TEXT');
194
+ add('registrations', 'content_locators TEXT');
195
+ add('tokens', 'minted INTEGER NOT NULL DEFAULT 0');
196
+ add('tokens', 'fields TEXT');
197
+ add('tokens', 'locked_fields TEXT');
198
+ add('projects', 'collection_fields TEXT');
199
+ add('projects', 'locked_collection_fields TEXT');
200
+ add('projects', 'token_uri_renderer TEXT');
201
+ add('projects', 'token_uri_locked INTEGER');
202
+ add('projects', 'contract_uri_renderer TEXT');
203
+ add('projects', 'contract_uri_locked INTEGER');
204
+ add('projects', 'contract_type TEXT');
205
+ add('projects', 'max_invocations TEXT');
206
+ add('projects', 'minter TEXT');
207
+ add('projects', 'paused INTEGER');
208
+ add('projects', 'primary_payee TEXT');
209
+ // code-project state (params, schemas, hooks, seed source, script, dependencies) —
210
+ // one JSON column; the shape is the ProjectState fields, spread back on hydrate.
211
+ add('projects', 'code_state TEXT');
212
+ add('tokens', 'params TEXT');
213
+ }
214
+ // ── registrations ──────────────────────────────────────────────────────────
215
+ register(reg) {
216
+ this.db
217
+ .prepare(`INSERT INTO registrations (address, chain_key, from_block, factory, label, description, external_url, attributes, token_attributes, content_locators, registered_at)
218
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
219
+ ON CONFLICT(address) DO UPDATE SET
220
+ chain_key=excluded.chain_key, from_block=excluded.from_block,
221
+ factory=excluded.factory, label=excluded.label,
222
+ description=excluded.description, external_url=excluded.external_url,
223
+ attributes=excluded.attributes, token_attributes=excluded.token_attributes,
224
+ content_locators=excluded.content_locators,
225
+ registered_at=excluded.registered_at`)
226
+ .run(lc(reg.address), reg.chainKey, reg.fromBlock, reg.factory, reg.label ?? null, reg.description ?? null, reg.externalUrl ?? null, reg.attributes ?? null, reg.tokenAttributes ?? null, reg.contentLocators ?? null, reg.registeredAt);
227
+ }
228
+ listRegistrations() {
229
+ return this.db
230
+ .prepare(`SELECT * FROM registrations ORDER BY registered_at`)
231
+ .all()
232
+ .map(rowToRegistration);
233
+ }
234
+ getRegistration(address) {
235
+ const row = this.db.prepare(`SELECT * FROM registrations WHERE address = ?`).get(lc(address));
236
+ return row ? rowToRegistration(row) : null;
237
+ }
238
+ deregister(address) {
239
+ const key = lc(address);
240
+ this.deleteProjection(key);
241
+ this.db.prepare(`DELETE FROM effect_artifacts WHERE address = ?`).run(key);
242
+ this.db.prepare(`DELETE FROM effect_status WHERE address = ?`).run(key);
243
+ this.db.prepare(`DELETE FROM registrations WHERE address = ?`).run(key);
244
+ }
245
+ // ── effect artifacts (the data plane's registry; producer-published) ──────────
246
+ putEffectArtifact(row) {
247
+ this.db
248
+ .prepare(`INSERT INTO effect_artifacts (key, address, token_id, effect_key, output_key, inputs_hash, locator, content_type, updated_at)
249
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
250
+ ON CONFLICT(key) DO UPDATE SET
251
+ address=excluded.address, token_id=excluded.token_id, effect_key=excluded.effect_key,
252
+ output_key=excluded.output_key, inputs_hash=excluded.inputs_hash,
253
+ locator=excluded.locator, content_type=excluded.content_type, updated_at=excluded.updated_at`)
254
+ .run(row.key.toLowerCase(), lc(row.address), row.tokenId, row.effectKey, row.outputKey, row.inputsHash.toLowerCase(), row.locator, row.contentType, row.updatedAt ?? new Date().toISOString());
255
+ }
256
+ getEffectArtifact(key) {
257
+ const row = this.db
258
+ .prepare(`SELECT * FROM effect_artifacts WHERE key = ?`)
259
+ .get(key.toLowerCase());
260
+ return row ? rowToArtifact(row) : null;
261
+ }
262
+ listEffectArtifacts(address, tokenId) {
263
+ return this.db
264
+ .prepare(`SELECT * FROM effect_artifacts WHERE address = ? AND token_id = ? ORDER BY effect_key, output_key`)
265
+ .all(lc(address), tokenId).map(rowToArtifact);
266
+ }
267
+ // ── node metadata (watcher watermark, …) ─────────────────────────────────────
268
+ putMeta(key, value) {
269
+ this.db
270
+ .prepare(`INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`)
271
+ .run(key, value);
272
+ }
273
+ getMeta(key) {
274
+ const row = this.db.prepare(`SELECT value FROM meta WHERE key = ?`).get(key);
275
+ return row?.value ?? null;
276
+ }
277
+ // ── transient effect status (runner-reported observability; rebuildable) ─────
278
+ putEffectStatus(row) {
279
+ this.db
280
+ .prepare(`INSERT INTO effect_status (key, address, token_id, effect_key, status, error, attempts, updated_at)
281
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
282
+ ON CONFLICT(key) DO UPDATE SET
283
+ address=excluded.address, token_id=excluded.token_id, effect_key=excluded.effect_key,
284
+ status=excluded.status, error=excluded.error, attempts=excluded.attempts, updated_at=excluded.updated_at`)
285
+ .run(row.key.toLowerCase(), lc(row.address), row.tokenId, row.effectKey, row.status, row.error ?? null, row.attempts ?? null, row.updatedAt ?? new Date().toISOString());
286
+ }
287
+ clearEffectStatus(key) {
288
+ this.db.prepare(`DELETE FROM effect_status WHERE key = ?`).run(key.toLowerCase());
289
+ }
290
+ listEffectStatuses(address) {
291
+ const rows = this.db
292
+ .prepare(`SELECT key, address, token_id, effect_key, status, error, attempts, updated_at FROM effect_status WHERE address = ?`)
293
+ .all(lc(address));
294
+ return rows.map((r) => ({
295
+ key: r.key,
296
+ address: r.address,
297
+ tokenId: r.token_id,
298
+ effectKey: r.effect_key,
299
+ status: r.status,
300
+ error: r.error,
301
+ attempts: r.attempts ?? undefined,
302
+ updatedAt: r.updated_at,
303
+ }));
304
+ }
305
+ // ── projection ───────────────────────────────────────────────────────────--
306
+ putProject(state) {
307
+ const key = lc(state.address);
308
+ this.db.exec('BEGIN');
309
+ try {
310
+ this.deleteProjection(key);
311
+ this.db
312
+ .prepare(`INSERT INTO projects (
313
+ address, address_original, chain_id, abx_version, deploy_block, deploy_tx,
314
+ factory, implementation, is_canonical, name, symbol, owner, contract_uri,
315
+ token_uri_renderer, token_uri_locked, contract_uri_renderer, contract_uri_locked,
316
+ royalty_receiver, royalty_bps, collection_fields, locked_collection_fields,
317
+ contract_type, max_invocations, minter, paused, primary_payee, code_state,
318
+ from_block, to_block, event_count, reconstructed_at, rpc_url
319
+ ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`)
320
+ .run(key, state.address, state.chainId, state.abxVersion, state.deployBlock, state.deployTx, state.factory, state.implementation, b(state.isCanonical), state.name, state.symbol, state.owner, state.contractURI, state.tokenURIRenderer, b(state.tokenURILocked), state.contractURIRenderer, b(state.contractURILocked), state.royalty?.receiver ?? null, state.royalty?.bps ?? null, JSON.stringify(state.collectionFields), JSON.stringify(state.lockedCollectionFields), state.contractType ?? null, state.maxInvocations ?? null, state.minter ?? null, b(state.paused), state.primaryPayee ?? null, JSON.stringify({
321
+ contractParams: state.contractParams ?? null,
322
+ paramSchemas: state.paramSchemas ?? null,
323
+ paramHooks: state.paramHooks ?? null,
324
+ delegateRegistry: state.delegateRegistry ?? null,
325
+ seedSource: state.seedSource ?? null,
326
+ script: state.script ?? null,
327
+ dependencies: state.dependencies ?? null,
328
+ }), state.fromBlock, state.toBlock, state.eventCount, state.reconstructedAt, state.rpcUrl ?? null);
329
+ const insToken = this.db.prepare(`INSERT INTO tokens (project_address, token_id, minted, owner, token_uri, fields, locked_fields, params)
330
+ VALUES (?,?,?,?,?,?,?,?)`);
331
+ for (const t of state.tokens) {
332
+ insToken.run(key, t.tokenId, b(t.minted), t.owner, t.tokenURI, JSON.stringify(t.fields), JSON.stringify(t.lockedFields), t.params?.length ? JSON.stringify(t.params) : null);
333
+ }
334
+ const insExt = this.db.prepare(`INSERT INTO extensions (project_address, id, name, version) VALUES (?,?,?,?)`);
335
+ for (const e of state.extensions)
336
+ insExt.run(key, e.id, e.name, e.version);
337
+ const insEvent = this.db.prepare(`INSERT INTO events (project_address, seq, name, register, what, block_number, log_index, tx_hash, args)
338
+ VALUES (?,?,?,?,?,?,?,?,?)`);
339
+ state.events.forEach((ev, i) => {
340
+ insEvent.run(key, i, ev.name, ev.register, ev.what, ev.blockNumber, ev.logIndex, ev.txHash, JSON.stringify(ev.args));
341
+ });
342
+ this.db.exec('COMMIT');
343
+ }
344
+ catch (err) {
345
+ this.db.exec('ROLLBACK');
346
+ throw err;
347
+ }
348
+ }
349
+ getProject(address) {
350
+ const row = this.db.prepare(`SELECT * FROM projects WHERE address = ?`).get(lc(address));
351
+ return row ? this.hydrate(row) : null;
352
+ }
353
+ listProjects() {
354
+ return this.db
355
+ .prepare(`SELECT * FROM projects ORDER BY reconstructed_at`)
356
+ .all()
357
+ .map((r) => this.hydrate(r));
358
+ }
359
+ wipeProjections() {
360
+ this.db.exec(`DELETE FROM events; DELETE FROM extensions; DELETE FROM tokens; DELETE FROM projects;`);
361
+ }
362
+ destroy() {
363
+ this.db.close();
364
+ for (const suffix of ['', '-wal', '-shm']) {
365
+ const f = this.path + suffix;
366
+ if (existsSync(f))
367
+ rmSync(f);
368
+ }
369
+ }
370
+ deleteProjection(key) {
371
+ for (const table of ['events', 'extensions', 'tokens', 'projects']) {
372
+ this.db.prepare(`DELETE FROM ${table} WHERE ${table === 'projects' ? 'address' : 'project_address'} = ?`).run(key);
373
+ }
374
+ }
375
+ hydrate(p) {
376
+ const key = p.address;
377
+ const tokens = this.db.prepare(`SELECT * FROM tokens WHERE project_address = ? ORDER BY CAST(token_id AS INTEGER)`).all(key).map((t) => ({
378
+ tokenId: t.token_id,
379
+ minted: !!t.minted,
380
+ owner: t.owner ?? null,
381
+ tokenURI: t.token_uri ?? null,
382
+ fields: JSON.parse(t.fields ?? '[]'),
383
+ lockedFields: JSON.parse(t.locked_fields ?? '[]'),
384
+ ...(t.params ? { params: JSON.parse(t.params) } : {}),
385
+ }));
386
+ const extensions = this.db.prepare(`SELECT * FROM extensions WHERE project_address = ? ORDER BY name`).all(key).map((e) => ({ id: e.id, name: e.name, version: e.version }));
387
+ const events = this.db.prepare(`SELECT * FROM events WHERE project_address = ? ORDER BY seq`).all(key).map((e) => ({
388
+ name: e.name,
389
+ register: e.register,
390
+ what: e.what,
391
+ blockNumber: e.block_number,
392
+ logIndex: e.log_index,
393
+ txHash: e.tx_hash,
394
+ args: JSON.parse(e.args),
395
+ }));
396
+ return {
397
+ address: p.address_original,
398
+ chainId: p.chain_id,
399
+ abxVersion: p.abx_version,
400
+ deployBlock: p.deploy_block,
401
+ deployTx: p.deploy_tx ?? null,
402
+ factory: p.factory ?? null,
403
+ implementation: p.implementation ?? null,
404
+ isCanonical: p.is_canonical === null ? null : !!p.is_canonical,
405
+ name: p.name,
406
+ symbol: p.symbol,
407
+ owner: p.owner ?? null,
408
+ contractURI: p.contract_uri,
409
+ tokenURIRenderer: p.token_uri_renderer ?? null,
410
+ tokenURILocked: p.token_uri_locked === null ? null : !!p.token_uri_locked,
411
+ contractURIRenderer: p.contract_uri_renderer ?? null,
412
+ contractURILocked: p.contract_uri_locked === null ? null : !!p.contract_uri_locked,
413
+ royalty: p.royalty_receiver ? { receiver: p.royalty_receiver, bps: p.royalty_bps ?? 0 } : null,
414
+ collectionFields: JSON.parse(p.collection_fields ?? '[]'),
415
+ lockedCollectionFields: JSON.parse(p.locked_collection_fields ?? '[]'),
416
+ contractType: p.contract_type ?? undefined,
417
+ maxInvocations: p.max_invocations ?? null,
418
+ minter: p.minter ?? null,
419
+ paused: !!p.paused,
420
+ primaryPayee: p.primary_payee ?? null,
421
+ ...hydrateCodeState(p.code_state),
422
+ extensions,
423
+ tokens,
424
+ events,
425
+ fromBlock: p.from_block,
426
+ toBlock: p.to_block,
427
+ eventCount: p.event_count,
428
+ reconstructedAt: p.reconstructed_at,
429
+ rpcUrl: p.rpc_url ?? undefined,
430
+ };
431
+ }
432
+ }
433
+ /** Spread the code-project JSON column back into its ProjectState fields (see putProject). */
434
+ function hydrateCodeState(json) {
435
+ if (!json) {
436
+ return {
437
+ paramHooks: null,
438
+ delegateRegistry: null,
439
+ seedSource: null,
440
+ script: null,
441
+ dependencies: null,
442
+ };
443
+ }
444
+ const c = JSON.parse(json);
445
+ return {
446
+ contractParams: c.contractParams ?? undefined,
447
+ paramSchemas: c.paramSchemas ?? undefined,
448
+ paramHooks: c.paramHooks ?? null,
449
+ delegateRegistry: c.delegateRegistry ?? null,
450
+ seedSource: c.seedSource ?? null,
451
+ script: c.script ?? null,
452
+ dependencies: c.dependencies ?? null,
453
+ };
454
+ }
455
+ function rowToArtifact(row) {
456
+ return {
457
+ key: row.key,
458
+ address: row.address,
459
+ tokenId: row.token_id,
460
+ effectKey: row.effect_key,
461
+ outputKey: row.output_key,
462
+ inputsHash: row.inputs_hash,
463
+ contentType: row.content_type ?? null,
464
+ locator: row.locator ?? null,
465
+ updatedAt: row.updated_at,
466
+ };
467
+ }
468
+ function rowToRegistration(row) {
469
+ const r = row;
470
+ return {
471
+ address: r.address,
472
+ chainKey: r.chain_key,
473
+ fromBlock: r.from_block,
474
+ factory: r.factory,
475
+ label: r.label ?? undefined,
476
+ description: r.description ?? undefined,
477
+ externalUrl: r.external_url ?? undefined,
478
+ attributes: r.attributes ?? undefined,
479
+ tokenAttributes: r.token_attributes ?? undefined,
480
+ contentLocators: r.content_locators ?? undefined,
481
+ registeredAt: r.registered_at,
482
+ };
483
+ }
484
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@artblocks/abx-indexer",
3
+ "version": "0.1.0-alpha.0",
4
+ "license": "MIT",
5
+ "description": "ABX Self-Host Toolkit (Layer 3) — the reference indexer. Replays the event spine from chain into a disposable, rebuildable projection. The canonical re-index.",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "LICENSE"
17
+ ],
18
+ "sideEffects": false,
19
+ "engines": {
20
+ "node": ">=22.5.0"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/ArtBlocks/abx.git",
25
+ "directory": "packages/indexer"
26
+ },
27
+ "homepage": "https://github.com/ArtBlocks/abx#readme",
28
+ "bugs": "https://github.com/ArtBlocks/abx/issues",
29
+ "keywords": [
30
+ "abx",
31
+ "nft",
32
+ "indexer",
33
+ "ethereum",
34
+ "art-blocks"
35
+ ],
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "dependencies": {
40
+ "viem": "^2.21.0",
41
+ "@artblocks/abx-sdk": "0.1.0-alpha.0"
42
+ },
43
+ "scripts": {
44
+ "build": "tsc -b tsconfig.build.json"
45
+ },
46
+ "types": "./dist/index.d.ts"
47
+ }