@umbra-privacy/indexer-read-service-client 0.1.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) 2025 Umbra Privacy
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.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # @umbra-privacy/indexer-read-service-client
2
+
3
+ TypeScript HTTP client for the Umbra Indexer Read Service. Provides typed methods for querying UTXO data, Merkle proofs, tree metadata, and health status from the Umbra indexer.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @umbra-privacy/indexer-read-service-client
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { ReadServiceClient } from "@umbra-privacy/indexer-read-service-client";
15
+
16
+ const client = new ReadServiceClient({
17
+ endpoint: "https://acqzie0a1h.execute-api.eu-central-1.amazonaws.com",
18
+ });
19
+
20
+ // Health checks
21
+ const health = await client.health();
22
+ const detailed = await client.healthDetailed();
23
+ const liveness = await client.liveness();
24
+ const readiness = await client.readiness();
25
+
26
+ // Global stats
27
+ const stats = await client.getStats();
28
+
29
+ // Tree metadata
30
+ const treeInfo = await client.getTreeInfo(0);
31
+
32
+ // Merkle proofs
33
+ const proof = await client.getProof(0, 42);
34
+
35
+ // UTXO queries
36
+ const utxos = await client.getUtxoData({ start: 0, limit: 100 });
37
+ const single = await client.getUtxo(42);
38
+ const treeUtxos = await client.getTreeUtxos(0, { cursor: 0, limit: 50 });
39
+
40
+ // Columnar format (better compression for large datasets)
41
+ const columnar = await client.getUtxoDataColumnar({ start: 0, limit: 1000 });
42
+
43
+ // Auto-paginated fetch
44
+ const allUtxos = await client.getAllUtxoData(0);
45
+ ```
46
+
47
+ ## API
48
+
49
+ ### `ReadServiceClient`
50
+
51
+ **Constructor**
52
+
53
+ - `new ReadServiceClient({ endpoint, fetch? })` — Create a client. Optionally provide a custom `fetch` implementation.
54
+
55
+ **Health**
56
+
57
+ - `health()` — Basic health check
58
+ - `healthDetailed()` — Detailed health with version, uptime, and storage status
59
+ - `liveness()` — Kubernetes-style liveness probe
60
+ - `readiness()` — Kubernetes-style readiness probe
61
+
62
+ **Stats & Trees**
63
+
64
+ - `getStats()` — Global UTXO count and latest index
65
+ - `getTreeInfo(treeIndex)` — Merkle tree metadata (root, leaf count)
66
+
67
+ **Proofs**
68
+
69
+ - `getProof(treeIndex, insertionIndex)` — Merkle inclusion proof for a specific leaf
70
+
71
+ **UTXOs**
72
+
73
+ - `getUtxoData(params?)` — Paginated UTXO query by absolute index range
74
+ - `getUtxoDataColumnar(params?)` — Same query in columnar layout for better compression
75
+ - `getUtxo(absoluteIndex)` — Single UTXO by absolute index (returns `null` on 404)
76
+ - `getTreeUtxos(treeIndex, params?)` — UTXOs scoped to a specific tree
77
+ - `getAllUtxoData(start?, end?, pageSize?)` — Auto-paginated fetch of all UTXOs
78
+
79
+ ### Error Handling
80
+
81
+ All methods throw `IndexerReadError` on failure:
82
+
83
+ ```typescript
84
+ import { IndexerReadError } from "@umbra-privacy/indexer-read-service-client";
85
+
86
+ try {
87
+ await client.getUtxo(999999);
88
+ } catch (err) {
89
+ if (err instanceof IndexerReadError) {
90
+ console.log(err.operation); // "getUtxo"
91
+ console.log(err.statusCode); // 404, 500, etc.
92
+ console.log(err.message);
93
+ }
94
+ }
95
+ ```
96
+
97
+ ## Transport
98
+
99
+ All responses are protobuf-encoded (`application/protobuf`). The client handles deserialization automatically using `@umbra-privacy/indexer-proto-gen` schemas.
100
+
101
+ ## Dependencies
102
+
103
+ - `@bufbuild/protobuf` ^2.0.0
104
+ - `@umbra-privacy/indexer-proto-gen`
105
+
106
+ ## License
107
+
108
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,428 @@
1
+ 'use strict';
2
+
3
+ var indexerProtoGen = require('@umbra-privacy/indexer-proto-gen');
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+
8
+ // src/errors.ts
9
+ var IndexerReadError = class extends Error {
10
+ static {
11
+ __name(this, "IndexerReadError");
12
+ }
13
+ operation;
14
+ statusCode;
15
+ constructor(operation, message, statusCode, cause) {
16
+ super(`Read service '${operation}' failed: ${message}`);
17
+ this.name = "IndexerReadError";
18
+ this.operation = operation;
19
+ this.statusCode = statusCode;
20
+ this.cause = cause;
21
+ }
22
+ };
23
+
24
+ // src/client.ts
25
+ var ACCEPT_PROTOBUF = "application/protobuf";
26
+ var ReadServiceClient = class {
27
+ static {
28
+ __name(this, "ReadServiceClient");
29
+ }
30
+ endpoint;
31
+ fetchFn;
32
+ constructor(config) {
33
+ this.endpoint = config.endpoint.replace(/\/+$/, "");
34
+ this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
35
+ }
36
+ // ===========================================================================
37
+ // Health
38
+ // ===========================================================================
39
+ async health() {
40
+ return this.get(
41
+ "/health",
42
+ "health",
43
+ indexerProtoGen.BasicHealthResponseSchema,
44
+ protoToBasicHealth
45
+ );
46
+ }
47
+ async healthDetailed() {
48
+ return this.get(
49
+ "/health/detailed",
50
+ "healthDetailed",
51
+ indexerProtoGen.DetailedHealthResponseSchema,
52
+ protoToDetailedHealth
53
+ );
54
+ }
55
+ async liveness() {
56
+ return this.get(
57
+ "/health/liveness",
58
+ "liveness",
59
+ indexerProtoGen.LivenessResponseSchema,
60
+ protoToLiveness
61
+ );
62
+ }
63
+ async readiness() {
64
+ return this.get(
65
+ "/health/readiness",
66
+ "readiness",
67
+ indexerProtoGen.ReadinessResponseSchema,
68
+ protoToReadiness
69
+ );
70
+ }
71
+ // ===========================================================================
72
+ // Stats
73
+ // ===========================================================================
74
+ /** Get global UTXO statistics. */
75
+ async getStats() {
76
+ return this.get(
77
+ "/v1/stats",
78
+ "getStats",
79
+ indexerProtoGen.StatsResponseSchema,
80
+ protoToStatsResponse
81
+ );
82
+ }
83
+ // ===========================================================================
84
+ // Tree Info
85
+ // ===========================================================================
86
+ /**
87
+ * Get metadata for a specific Merkle tree.
88
+ *
89
+ * @param treeIndex - The Merkle tree index.
90
+ */
91
+ async getTreeInfo(treeIndex) {
92
+ return this.get(
93
+ `/v1/trees/${treeIndex}`,
94
+ "getTreeInfo",
95
+ indexerProtoGen.TreeInfoResponseSchema,
96
+ protoToTreeInfoResponse
97
+ );
98
+ }
99
+ // ===========================================================================
100
+ // Merkle Proof
101
+ // ===========================================================================
102
+ /**
103
+ * Get a Merkle proof for a specific leaf in a tree.
104
+ *
105
+ * @param treeIndex - The Merkle tree index.
106
+ * @param insertionIndex - The leaf index within the tree.
107
+ */
108
+ async getProof(treeIndex, insertionIndex) {
109
+ return this.get(
110
+ `/v1/trees/${treeIndex}/proof/${insertionIndex}`,
111
+ "getProof",
112
+ indexerProtoGen.ProofResponseSchema,
113
+ protoToProofResponse
114
+ );
115
+ }
116
+ // ===========================================================================
117
+ // UTXO Data
118
+ // ===========================================================================
119
+ /**
120
+ * Fetch UTXO data by absolute index range with pagination.
121
+ *
122
+ * @param params - Query parameters (start, end, limit — all optional).
123
+ */
124
+ async getUtxoData(params = {}) {
125
+ const query = buildQuery(params);
126
+ return this.get(
127
+ `/v1/utxos${query}`,
128
+ "getUtxoData",
129
+ indexerProtoGen.UtxoResponseSchema,
130
+ protoToUtxoResponse
131
+ );
132
+ }
133
+ /**
134
+ * Fetch UTXO data in columnar layout for maximum compression.
135
+ *
136
+ * Sends `X-Response-Layout: columnar` header. Data is transposed into
137
+ * column arrays instead of row arrays for better compression ratios.
138
+ *
139
+ * @param params - Query parameters (start, end, limit — all optional).
140
+ */
141
+ async getUtxoDataColumnar(params = {}) {
142
+ const query = buildQuery(params);
143
+ return this.get(
144
+ `/v1/utxos${query}`,
145
+ "getUtxoDataColumnar",
146
+ indexerProtoGen.UtxoColumnarResponseSchema,
147
+ protoToUtxoColumnarResponse,
148
+ { "X-Response-Layout": "columnar" }
149
+ );
150
+ }
151
+ /**
152
+ * Fetch a single UTXO by its absolute index.
153
+ *
154
+ * Returns `null` if the UTXO does not exist (404).
155
+ *
156
+ * @param absoluteIndex - The global absolute index across all trees.
157
+ */
158
+ async getUtxo(absoluteIndex) {
159
+ try {
160
+ const proto = await this.get(
161
+ `/v1/utxos/${absoluteIndex}`,
162
+ "getUtxo",
163
+ indexerProtoGen.SingleUtxoResponseSchema,
164
+ (p) => p
165
+ );
166
+ return proto.utxo ? protoUtxoItemToJson(proto.utxo) : null;
167
+ } catch (err) {
168
+ if (err instanceof IndexerReadError && err.statusCode === 404) {
169
+ return null;
170
+ }
171
+ throw err;
172
+ }
173
+ }
174
+ /**
175
+ * Fetch UTXOs scoped to a specific Merkle tree with pagination.
176
+ *
177
+ * @param treeIndex - The Merkle tree index.
178
+ * @param params - Pagination params (cursor = absolute_index, limit optional).
179
+ */
180
+ async getTreeUtxos(treeIndex, params = {}) {
181
+ const parts = [];
182
+ if (params.cursor !== void 0) parts.push(`cursor=${params.cursor}`);
183
+ if (params.limit !== void 0) parts.push(`limit=${params.limit}`);
184
+ const query = parts.length > 0 ? `?${parts.join("&")}` : "";
185
+ return this.get(
186
+ `/v1/trees/${treeIndex}/utxos${query}`,
187
+ "getTreeUtxos",
188
+ indexerProtoGen.UtxoResponseSchema,
189
+ protoToUtxoResponse
190
+ );
191
+ }
192
+ /**
193
+ * Fetch all UTXO data with automatic pagination.
194
+ *
195
+ * Iterates through all pages starting from `start` up to an optional `end`.
196
+ *
197
+ * @param start - Starting absolute index (default: 0).
198
+ * @param end - Optional ending absolute index (inclusive). Omit to fetch everything.
199
+ * @param pageSize - Records per page (default: 1000, max: 5000).
200
+ */
201
+ async getAllUtxoData(start = 0, end, pageSize = 1e3) {
202
+ const allItems = [];
203
+ let cursor = start;
204
+ while (true) {
205
+ const response = await this.getUtxoData({ start: cursor, end, limit: pageSize });
206
+ allItems.push(...response.items);
207
+ if (!response.has_more || response.next_cursor === null) {
208
+ break;
209
+ }
210
+ cursor = response.next_cursor;
211
+ }
212
+ return allItems;
213
+ }
214
+ // ===========================================================================
215
+ // Internal helpers
216
+ // ===========================================================================
217
+ async get(path, operation, protoSchema, protoToJson, extraHeaders) {
218
+ const url = `${this.endpoint}${path}`;
219
+ let response;
220
+ try {
221
+ response = await this.fetchFn(url, {
222
+ method: "GET",
223
+ headers: { Accept: ACCEPT_PROTOBUF, ...extraHeaders }
224
+ });
225
+ } catch (err) {
226
+ throw new IndexerReadError(operation, `Network error: ${err}`, void 0, err);
227
+ }
228
+ return this.handleResponse(response, operation, protoSchema, protoToJson);
229
+ }
230
+ async handleResponse(response, operation, protoSchema, protoToJson) {
231
+ if (!response.ok) {
232
+ let errorMessage;
233
+ try {
234
+ const errorBody = await response.text();
235
+ errorMessage = errorBody || response.statusText;
236
+ } catch {
237
+ errorMessage = response.statusText;
238
+ }
239
+ throw new IndexerReadError(operation, errorMessage, response.status);
240
+ }
241
+ const contentType = response.headers.get("content-type") ?? "";
242
+ if (contentType.includes("protobuf")) {
243
+ try {
244
+ const buffer = await response.arrayBuffer();
245
+ const proto = indexerProtoGen.fromBinary(protoSchema, new Uint8Array(buffer));
246
+ return protoToJson(proto);
247
+ } catch (err) {
248
+ throw new IndexerReadError(
249
+ operation,
250
+ `Failed to decode protobuf response: ${err}`,
251
+ response.status,
252
+ err
253
+ );
254
+ }
255
+ }
256
+ try {
257
+ return await response.json();
258
+ } catch (err) {
259
+ throw new IndexerReadError(
260
+ operation,
261
+ `Failed to parse response: ${err}`,
262
+ response.status,
263
+ err
264
+ );
265
+ }
266
+ }
267
+ };
268
+ function buildQuery(params) {
269
+ const parts = [];
270
+ if (params.start !== void 0) parts.push(`start=${params.start}`);
271
+ if (params.end !== void 0) parts.push(`end=${params.end}`);
272
+ if (params.limit !== void 0) parts.push(`limit=${params.limit}`);
273
+ return parts.length > 0 ? `?${parts.join("&")}` : "";
274
+ }
275
+ __name(buildQuery, "buildQuery");
276
+ function bytesToBase64(bytes) {
277
+ if (typeof Buffer !== "undefined") {
278
+ return Buffer.from(bytes).toString("base64");
279
+ }
280
+ let binary = "";
281
+ for (let i = 0; i < bytes.length; i++) {
282
+ binary += String.fromCharCode(bytes[i]);
283
+ }
284
+ return btoa(binary);
285
+ }
286
+ __name(bytesToBase64, "bytesToBase64");
287
+ function protoToBasicHealth(p) {
288
+ return { status: p.status };
289
+ }
290
+ __name(protoToBasicHealth, "protoToBasicHealth");
291
+ function protoToDetailedHealth(p) {
292
+ return {
293
+ status: p.status,
294
+ version: p.version,
295
+ timestamp: p.timestamp,
296
+ uptime_seconds: Number(p.uptimeSeconds),
297
+ storage: p.storage ? { status: p.storage.status, connected: p.storage.connected } : { status: "unknown", connected: false }
298
+ };
299
+ }
300
+ __name(protoToDetailedHealth, "protoToDetailedHealth");
301
+ function protoToLiveness(p) {
302
+ return { alive: p.alive };
303
+ }
304
+ __name(protoToLiveness, "protoToLiveness");
305
+ function protoToReadiness(p) {
306
+ return { ready: p.ready, storage: p.storage };
307
+ }
308
+ __name(protoToReadiness, "protoToReadiness");
309
+ function protoToStatsResponse(p) {
310
+ return {
311
+ total_utxos: Number(p.totalUtxos),
312
+ latest_absolute_index: p.latestAbsoluteIndex !== void 0 ? Number(p.latestAbsoluteIndex) : null
313
+ };
314
+ }
315
+ __name(protoToStatsResponse, "protoToStatsResponse");
316
+ function protoToTreeInfoResponse(p) {
317
+ return {
318
+ tree_index: Number(p.treeIndex),
319
+ num_leaves: Number(p.numLeaves),
320
+ root: bytesToBase64(p.root),
321
+ utxo_count: Number(p.utxoCount)
322
+ };
323
+ }
324
+ __name(protoToTreeInfoResponse, "protoToTreeInfoResponse");
325
+ function protoToProofResponse(p) {
326
+ return {
327
+ root: bytesToBase64(p.root),
328
+ tree_index: Number(p.treeIndex),
329
+ insertion_index: Number(p.insertionIndex),
330
+ proof: p.proof.map(bytesToBase64),
331
+ leaf: bytesToBase64(p.leaf)
332
+ };
333
+ }
334
+ __name(protoToProofResponse, "protoToProofResponse");
335
+ function protoUtxoItemToJson(item) {
336
+ return {
337
+ absolute_index: Number(item.absoluteIndex),
338
+ tree_index: Number(item.treeIndex),
339
+ insertion_index: Number(item.insertionIndex),
340
+ final_commitment: bytesToBase64(item.finalCommitment),
341
+ h1_version: readU128LE(item.h1Version),
342
+ h1_commitment_index: readU128LE(item.h1CommitmentIndex),
343
+ h1_sender_address: bytesToBase64(item.h1SenderAddress),
344
+ h1_mint_address: bytesToBase64(item.h1MintAddress),
345
+ h1_relayer_fixed_sol_fees: Number(item.h1RelayerFixedSolFees),
346
+ h1_year: item.h1Year,
347
+ h1_month: item.h1Month,
348
+ h1_day: item.h1Day,
349
+ h1_hour: item.h1Hour,
350
+ h1_minute: item.h1Minute,
351
+ h1_second: item.h1Second,
352
+ h1_purpose: item.h1Purpose,
353
+ h1_circuit_provable_hash: bytesToBase64(item.h1CircuitProvableHash),
354
+ h1_smart_program_provable_hash: bytesToBase64(item.h1SmartProgramProvableHash),
355
+ h1_hash: bytesToBase64(item.h1Hash),
356
+ h2_hash: bytesToBase64(item.h2Hash),
357
+ aes_encrypted_data: bytesToBase64(item.aesEncryptedData),
358
+ depositor_x25519_public_key: bytesToBase64(item.depositorX25519PublicKey),
359
+ timestamp: Number(item.timestamp),
360
+ slot: Number(item.slot),
361
+ event_type: item.eventType
362
+ };
363
+ }
364
+ __name(protoUtxoItemToJson, "protoUtxoItemToJson");
365
+ function readU128LE(bytes) {
366
+ if (bytes.length < 16) return "0";
367
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
368
+ const lo = view.getBigUint64(0, true);
369
+ const hi = view.getBigUint64(8, true);
370
+ const value = hi << 64n | lo;
371
+ return value.toString();
372
+ }
373
+ __name(readU128LE, "readU128LE");
374
+ function protoToUtxoResponse(p) {
375
+ return {
376
+ items: p.items.map(protoUtxoItemToJson),
377
+ has_more: p.hasMore,
378
+ next_cursor: p.nextCursor !== void 0 ? Number(p.nextCursor) : null,
379
+ total_count: Number(p.totalCount),
380
+ start_index: Number(p.startIndex),
381
+ end_index: p.endIndex !== void 0 ? Number(p.endIndex) : null
382
+ };
383
+ }
384
+ __name(protoToUtxoResponse, "protoToUtxoResponse");
385
+ function protoToUtxoColumnarResponse(p) {
386
+ const cols = p.columns;
387
+ return {
388
+ columns: cols ? {
389
+ absolute_index: cols.absoluteIndex.map(Number),
390
+ tree_index: cols.treeIndex.map(Number),
391
+ insertion_index: cols.insertionIndex.map(Number),
392
+ final_commitment: cols.finalCommitment.map(bytesToBase64),
393
+ h1_version: cols.h1Version.map(bytesToBase64),
394
+ h1_commitment_index: cols.h1CommitmentIndex.map(bytesToBase64),
395
+ h1_sender_address: cols.h1SenderAddress.map(bytesToBase64),
396
+ h1_mint_address: cols.h1MintAddress.map(bytesToBase64),
397
+ h1_relayer_fixed_sol_fees: cols.h1RelayerFixedSolFees.map(Number),
398
+ h1_year: cols.h1Year.slice(),
399
+ h1_month: cols.h1Month.slice(),
400
+ h1_day: cols.h1Day.slice(),
401
+ h1_hour: cols.h1Hour.slice(),
402
+ h1_minute: cols.h1Minute.slice(),
403
+ h1_second: cols.h1Second.slice(),
404
+ h1_purpose: cols.h1Purpose.slice(),
405
+ h1_circuit_provable_hash: cols.h1CircuitProvableHash.map(bytesToBase64),
406
+ h1_smart_program_provable_hash: cols.h1SmartProgramProvableHash.map(bytesToBase64),
407
+ h1_hash: cols.h1Hash.map(bytesToBase64),
408
+ h2_hash: cols.h2Hash.map(bytesToBase64),
409
+ aes_encrypted_data: cols.aesEncryptedData.map(bytesToBase64),
410
+ depositor_x25519_public_key: cols.depositorX25519PublicKey.map(bytesToBase64),
411
+ timestamp: cols.timestamp.map(Number),
412
+ slot: cols.slot.map(Number),
413
+ event_type: cols.eventType.slice()
414
+ } : null,
415
+ count: p.count,
416
+ has_more: p.hasMore,
417
+ next_cursor: p.nextCursor !== void 0 ? Number(p.nextCursor) : null,
418
+ total_count: Number(p.totalCount),
419
+ start_index: Number(p.startIndex),
420
+ end_index: p.endIndex !== void 0 ? Number(p.endIndex) : null
421
+ };
422
+ }
423
+ __name(protoToUtxoColumnarResponse, "protoToUtxoColumnarResponse");
424
+
425
+ exports.IndexerReadError = IndexerReadError;
426
+ exports.ReadServiceClient = ReadServiceClient;
427
+ //# sourceMappingURL=index.cjs.map
428
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/client.ts"],"names":["BasicHealthResponseSchema","DetailedHealthResponseSchema","LivenessResponseSchema","ReadinessResponseSchema","StatsResponseSchema","TreeInfoResponseSchema","ProofResponseSchema","UtxoResponseSchema","UtxoColumnarResponseSchema","SingleUtxoResponseSchema","fromBinary"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Error class for Indexer Read Service client operations.\n */\nexport class IndexerReadError extends Error {\n public readonly operation: string;\n public readonly statusCode: number | undefined;\n\n constructor(operation: string, message: string, statusCode?: number, cause?: Error) {\n super(`Read service '${operation}' failed: ${message}`);\n this.name = \"IndexerReadError\";\n this.operation = operation;\n this.statusCode = statusCode;\n this.cause = cause;\n }\n}\n","/**\n * ReadServiceClient — typed HTTP client for the Umbra Indexer Read Service.\n *\n * All responses are protobuf-encoded binary.\n *\n * @example\n * ```typescript\n * const client = new ReadServiceClient({ endpoint: \"http://localhost:8082\" });\n * const stats = await client.getStats();\n * const proof = await client.getProof(0, 42);\n * const utxos = await client.getUtxoData({ start: 0, limit: 100 });\n * ```\n */\n\nimport {\n fromBinary,\n type BasicHealthResponse as ProtoBasicHealth,\n BasicHealthResponseSchema,\n type DetailedHealthResponse as ProtoDetailedHealth,\n DetailedHealthResponseSchema,\n type LivenessResponse as ProtoLiveness,\n LivenessResponseSchema,\n type ReadinessResponse as ProtoReadiness,\n ReadinessResponseSchema,\n type ProofResponse as ProtoProof,\n ProofResponseSchema,\n type UtxoResponse as ProtoUtxo,\n UtxoResponseSchema,\n type UtxoColumnarResponse as ProtoUtxoColumnar,\n UtxoColumnarResponseSchema,\n type StatsResponse as ProtoStats,\n StatsResponseSchema,\n type TreeInfoResponse as ProtoTreeInfo,\n TreeInfoResponseSchema,\n type SingleUtxoResponse as ProtoSingleUtxo,\n SingleUtxoResponseSchema,\n} from \"@umbra-privacy/indexer-proto-gen\";\nimport type { GenMessage } from \"@bufbuild/protobuf/codegenv2\";\nimport type { Message } from \"@bufbuild/protobuf\";\n\nimport { IndexerReadError } from \"./errors.js\";\nimport type {\n BasicHealthResponse,\n DetailedHealthResponse,\n LivenessResponse,\n ProofResponse,\n ReadServiceClientConfig,\n ReadinessResponse,\n StatsResponse,\n TreeInfoResponse,\n UtxoColumnarResponse,\n UtxoDataResponse,\n UtxoRequest,\n UtxoResponse,\n} from \"./types.js\";\n\nconst ACCEPT_PROTOBUF = \"application/protobuf\";\n\nexport class ReadServiceClient {\n private readonly endpoint: string;\n private readonly fetchFn: typeof globalThis.fetch;\n\n constructor(config: ReadServiceClientConfig) {\n this.endpoint = config.endpoint.replace(/\\/+$/, \"\");\n this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n // ===========================================================================\n // Health\n // ===========================================================================\n\n async health(): Promise<BasicHealthResponse> {\n return this.get<BasicHealthResponse, ProtoBasicHealth>(\n \"/health\",\n \"health\",\n BasicHealthResponseSchema,\n protoToBasicHealth,\n );\n }\n\n async healthDetailed(): Promise<DetailedHealthResponse> {\n return this.get<DetailedHealthResponse, ProtoDetailedHealth>(\n \"/health/detailed\",\n \"healthDetailed\",\n DetailedHealthResponseSchema,\n protoToDetailedHealth,\n );\n }\n\n async liveness(): Promise<LivenessResponse> {\n return this.get<LivenessResponse, ProtoLiveness>(\n \"/health/liveness\",\n \"liveness\",\n LivenessResponseSchema,\n protoToLiveness,\n );\n }\n\n async readiness(): Promise<ReadinessResponse> {\n return this.get<ReadinessResponse, ProtoReadiness>(\n \"/health/readiness\",\n \"readiness\",\n ReadinessResponseSchema,\n protoToReadiness,\n );\n }\n\n // ===========================================================================\n // Stats\n // ===========================================================================\n\n /** Get global UTXO statistics. */\n async getStats(): Promise<StatsResponse> {\n return this.get<StatsResponse, ProtoStats>(\n \"/v1/stats\",\n \"getStats\",\n StatsResponseSchema,\n protoToStatsResponse,\n );\n }\n\n // ===========================================================================\n // Tree Info\n // ===========================================================================\n\n /**\n * Get metadata for a specific Merkle tree.\n *\n * @param treeIndex - The Merkle tree index.\n */\n async getTreeInfo(treeIndex: number): Promise<TreeInfoResponse> {\n return this.get<TreeInfoResponse, ProtoTreeInfo>(\n `/v1/trees/${treeIndex}`,\n \"getTreeInfo\",\n TreeInfoResponseSchema,\n protoToTreeInfoResponse,\n );\n }\n\n // ===========================================================================\n // Merkle Proof\n // ===========================================================================\n\n /**\n * Get a Merkle proof for a specific leaf in a tree.\n *\n * @param treeIndex - The Merkle tree index.\n * @param insertionIndex - The leaf index within the tree.\n */\n async getProof(treeIndex: number, insertionIndex: number): Promise<ProofResponse> {\n return this.get<ProofResponse, ProtoProof>(\n `/v1/trees/${treeIndex}/proof/${insertionIndex}`,\n \"getProof\",\n ProofResponseSchema,\n protoToProofResponse,\n );\n }\n\n // ===========================================================================\n // UTXO Data\n // ===========================================================================\n\n /**\n * Fetch UTXO data by absolute index range with pagination.\n *\n * @param params - Query parameters (start, end, limit — all optional).\n */\n async getUtxoData(params: UtxoRequest = {}): Promise<UtxoResponse> {\n const query = buildQuery(params);\n return this.get<UtxoResponse, ProtoUtxo>(\n `/v1/utxos${query}`,\n \"getUtxoData\",\n UtxoResponseSchema,\n protoToUtxoResponse,\n );\n }\n\n /**\n * Fetch UTXO data in columnar layout for maximum compression.\n *\n * Sends `X-Response-Layout: columnar` header. Data is transposed into\n * column arrays instead of row arrays for better compression ratios.\n *\n * @param params - Query parameters (start, end, limit — all optional).\n */\n async getUtxoDataColumnar(params: UtxoRequest = {}): Promise<UtxoColumnarResponse> {\n const query = buildQuery(params);\n return this.get<UtxoColumnarResponse, ProtoUtxoColumnar>(\n `/v1/utxos${query}`,\n \"getUtxoDataColumnar\",\n UtxoColumnarResponseSchema,\n protoToUtxoColumnarResponse,\n { \"X-Response-Layout\": \"columnar\" },\n );\n }\n\n /**\n * Fetch a single UTXO by its absolute index.\n *\n * Returns `null` if the UTXO does not exist (404).\n *\n * @param absoluteIndex - The global absolute index across all trees.\n */\n async getUtxo(absoluteIndex: number): Promise<UtxoDataResponse | null> {\n try {\n const proto = await this.get<ProtoSingleUtxo, ProtoSingleUtxo>(\n `/v1/utxos/${absoluteIndex}`,\n \"getUtxo\",\n SingleUtxoResponseSchema,\n (p) => p,\n );\n return proto.utxo ? protoUtxoItemToJson(proto.utxo) : null;\n } catch (err) {\n if (err instanceof IndexerReadError && err.statusCode === 404) {\n return null;\n }\n throw err;\n }\n }\n\n /**\n * Fetch UTXOs scoped to a specific Merkle tree with pagination.\n *\n * @param treeIndex - The Merkle tree index.\n * @param params - Pagination params (cursor = absolute_index, limit optional).\n */\n async getTreeUtxos(\n treeIndex: number,\n params: { cursor?: number; limit?: number } = {},\n ): Promise<UtxoResponse> {\n const parts: string[] = [];\n if (params.cursor !== undefined) parts.push(`cursor=${params.cursor}`);\n if (params.limit !== undefined) parts.push(`limit=${params.limit}`);\n const query = parts.length > 0 ? `?${parts.join(\"&\")}` : \"\";\n return this.get<UtxoResponse, ProtoUtxo>(\n `/v1/trees/${treeIndex}/utxos${query}`,\n \"getTreeUtxos\",\n UtxoResponseSchema,\n protoToUtxoResponse,\n );\n }\n\n /**\n * Fetch all UTXO data with automatic pagination.\n *\n * Iterates through all pages starting from `start` up to an optional `end`.\n *\n * @param start - Starting absolute index (default: 0).\n * @param end - Optional ending absolute index (inclusive). Omit to fetch everything.\n * @param pageSize - Records per page (default: 1000, max: 5000).\n */\n async getAllUtxoData(\n start: number = 0,\n end?: number,\n pageSize: number = 1000,\n ): Promise<UtxoDataResponse[]> {\n const allItems: UtxoDataResponse[] = [];\n let cursor = start;\n\n while (true) {\n const response = await this.getUtxoData({ start: cursor, end, limit: pageSize });\n\n allItems.push(...response.items);\n\n if (!response.has_more || response.next_cursor === null) {\n break;\n }\n\n cursor = response.next_cursor;\n }\n\n return allItems;\n }\n\n // ===========================================================================\n // Internal helpers\n // ===========================================================================\n\n protected async get<T, P extends Message>(\n path: string,\n operation: string,\n protoSchema: GenMessage<P>,\n protoToJson: (proto: P) => T,\n extraHeaders?: Record<string, string>,\n ): Promise<T> {\n const url = `${this.endpoint}${path}`;\n\n let response: Response;\n try {\n response = await this.fetchFn(url, {\n method: \"GET\",\n headers: { Accept: ACCEPT_PROTOBUF, ...extraHeaders },\n });\n } catch (err) {\n throw new IndexerReadError(operation, `Network error: ${err}`, undefined, err as Error);\n }\n\n return this.handleResponse<T, P>(response, operation, protoSchema, protoToJson);\n }\n\n protected async handleResponse<T, P extends Message>(\n response: Response,\n operation: string,\n protoSchema: GenMessage<P>,\n protoToJson: (proto: P) => T,\n ): Promise<T> {\n if (!response.ok) {\n let errorMessage: string;\n try {\n const errorBody = await response.text();\n errorMessage = errorBody || response.statusText;\n } catch {\n errorMessage = response.statusText;\n }\n throw new IndexerReadError(operation, errorMessage, response.status);\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n\n if (contentType.includes(\"protobuf\")) {\n try {\n const buffer = await response.arrayBuffer();\n const proto = fromBinary(protoSchema, new Uint8Array(buffer));\n return protoToJson(proto);\n } catch (err) {\n throw new IndexerReadError(\n operation,\n `Failed to decode protobuf response: ${err}`,\n response.status,\n err as Error,\n );\n }\n }\n\n // Fallback to JSON (e.g. error responses)\n try {\n return (await response.json()) as T;\n } catch (err) {\n throw new IndexerReadError(\n operation,\n `Failed to parse response: ${err}`,\n response.status,\n err as Error,\n );\n }\n }\n}\n\n// =============================================================================\n// Query string builder\n// =============================================================================\n\nfunction buildQuery(params: UtxoRequest): string {\n const parts: string[] = [];\n if (params.start !== undefined) parts.push(`start=${params.start}`);\n if (params.end !== undefined) parts.push(`end=${params.end}`);\n if (params.limit !== undefined) parts.push(`limit=${params.limit}`);\n return parts.length > 0 ? `?${parts.join(\"&\")}` : \"\";\n}\n\n// =============================================================================\n// Proto-to-JSON conversion helpers\n// =============================================================================\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n }\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\nfunction protoToBasicHealth(p: ProtoBasicHealth): BasicHealthResponse {\n return { status: p.status };\n}\n\nfunction protoToDetailedHealth(p: ProtoDetailedHealth): DetailedHealthResponse {\n return {\n status: p.status,\n version: p.version,\n timestamp: p.timestamp,\n uptime_seconds: Number(p.uptimeSeconds),\n storage: p.storage\n ? { status: p.storage.status, connected: p.storage.connected }\n : { status: \"unknown\", connected: false },\n };\n}\n\nfunction protoToLiveness(p: ProtoLiveness): LivenessResponse {\n return { alive: p.alive };\n}\n\nfunction protoToReadiness(p: ProtoReadiness): ReadinessResponse {\n return { ready: p.ready, storage: p.storage };\n}\n\nfunction protoToStatsResponse(p: ProtoStats): StatsResponse {\n return {\n total_utxos: Number(p.totalUtxos),\n latest_absolute_index:\n p.latestAbsoluteIndex !== undefined ? Number(p.latestAbsoluteIndex) : null,\n };\n}\n\nfunction protoToTreeInfoResponse(p: ProtoTreeInfo): TreeInfoResponse {\n return {\n tree_index: Number(p.treeIndex),\n num_leaves: Number(p.numLeaves),\n root: bytesToBase64(p.root),\n utxo_count: Number(p.utxoCount),\n };\n}\n\nfunction protoToProofResponse(p: ProtoProof): ProofResponse {\n return {\n root: bytesToBase64(p.root),\n tree_index: Number(p.treeIndex),\n insertion_index: Number(p.insertionIndex),\n proof: p.proof.map(bytesToBase64),\n leaf: bytesToBase64(p.leaf),\n };\n}\n\nfunction protoUtxoItemToJson(item: ProtoUtxo[\"items\"][number]): UtxoDataResponse {\n return {\n absolute_index: Number(item.absoluteIndex),\n tree_index: Number(item.treeIndex),\n insertion_index: Number(item.insertionIndex),\n final_commitment: bytesToBase64(item.finalCommitment),\n h1_version: readU128LE(item.h1Version),\n h1_commitment_index: readU128LE(item.h1CommitmentIndex),\n h1_sender_address: bytesToBase64(item.h1SenderAddress),\n h1_mint_address: bytesToBase64(item.h1MintAddress),\n h1_relayer_fixed_sol_fees: Number(item.h1RelayerFixedSolFees),\n h1_year: item.h1Year,\n h1_month: item.h1Month,\n h1_day: item.h1Day,\n h1_hour: item.h1Hour,\n h1_minute: item.h1Minute,\n h1_second: item.h1Second,\n h1_purpose: item.h1Purpose,\n h1_circuit_provable_hash: bytesToBase64(item.h1CircuitProvableHash),\n h1_smart_program_provable_hash: bytesToBase64(item.h1SmartProgramProvableHash),\n h1_hash: bytesToBase64(item.h1Hash),\n h2_hash: bytesToBase64(item.h2Hash),\n aes_encrypted_data: bytesToBase64(item.aesEncryptedData),\n depositor_x25519_public_key: bytesToBase64(item.depositorX25519PublicKey),\n timestamp: Number(item.timestamp),\n slot: Number(item.slot),\n event_type: item.eventType,\n };\n}\n\n/** Read a u128 from 16 little-endian bytes and return as decimal string. */\nfunction readU128LE(bytes: Uint8Array): string {\n if (bytes.length < 16) return \"0\";\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const lo = view.getBigUint64(0, true);\n const hi = view.getBigUint64(8, true);\n const value = (hi << 64n) | lo;\n return value.toString();\n}\n\nfunction protoToUtxoResponse(p: ProtoUtxo): UtxoResponse {\n return {\n items: p.items.map(protoUtxoItemToJson),\n has_more: p.hasMore,\n next_cursor: p.nextCursor !== undefined ? Number(p.nextCursor) : null,\n total_count: Number(p.totalCount),\n start_index: Number(p.startIndex),\n end_index: p.endIndex !== undefined ? Number(p.endIndex) : null,\n };\n}\n\nfunction protoToUtxoColumnarResponse(p: ProtoUtxoColumnar): UtxoColumnarResponse {\n const cols = p.columns;\n return {\n columns: cols\n ? {\n absolute_index: cols.absoluteIndex.map(Number),\n tree_index: cols.treeIndex.map(Number),\n insertion_index: cols.insertionIndex.map(Number),\n final_commitment: cols.finalCommitment.map(bytesToBase64),\n h1_version: cols.h1Version.map(bytesToBase64),\n h1_commitment_index: cols.h1CommitmentIndex.map(bytesToBase64),\n h1_sender_address: cols.h1SenderAddress.map(bytesToBase64),\n h1_mint_address: cols.h1MintAddress.map(bytesToBase64),\n h1_relayer_fixed_sol_fees: cols.h1RelayerFixedSolFees.map(Number),\n h1_year: cols.h1Year.slice(),\n h1_month: cols.h1Month.slice(),\n h1_day: cols.h1Day.slice(),\n h1_hour: cols.h1Hour.slice(),\n h1_minute: cols.h1Minute.slice(),\n h1_second: cols.h1Second.slice(),\n h1_purpose: cols.h1Purpose.slice(),\n h1_circuit_provable_hash: cols.h1CircuitProvableHash.map(bytesToBase64),\n h1_smart_program_provable_hash: cols.h1SmartProgramProvableHash.map(bytesToBase64),\n h1_hash: cols.h1Hash.map(bytesToBase64),\n h2_hash: cols.h2Hash.map(bytesToBase64),\n aes_encrypted_data: cols.aesEncryptedData.map(bytesToBase64),\n depositor_x25519_public_key: cols.depositorX25519PublicKey.map(bytesToBase64),\n timestamp: cols.timestamp.map(Number),\n slot: cols.slot.map(Number),\n event_type: cols.eventType.slice(),\n }\n : null,\n count: p.count,\n has_more: p.hasMore,\n next_cursor: p.nextCursor !== undefined ? Number(p.nextCursor) : null,\n total_count: Number(p.totalCount),\n start_index: Number(p.startIndex),\n end_index: p.endIndex !== undefined ? Number(p.endIndex) : null,\n };\n}\n"]}