opacity-issuer-core 0.2.1

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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -0
  3. package/dist/chunk-2STMWRIV.js +164 -0
  4. package/dist/chunk-2STMWRIV.js.map +1 -0
  5. package/dist/chunk-3L7NNVUV.cjs +184 -0
  6. package/dist/chunk-3L7NNVUV.cjs.map +1 -0
  7. package/dist/chunk-54Q3MU62.js +29 -0
  8. package/dist/chunk-54Q3MU62.js.map +1 -0
  9. package/dist/chunk-7ODYBEZH.js +889 -0
  10. package/dist/chunk-7ODYBEZH.js.map +1 -0
  11. package/dist/chunk-GMPQFX25.cjs +923 -0
  12. package/dist/chunk-GMPQFX25.cjs.map +1 -0
  13. package/dist/chunk-HJQZWNZJ.cjs +33 -0
  14. package/dist/chunk-HJQZWNZJ.cjs.map +1 -0
  15. package/dist/documents/index.cjs +170 -0
  16. package/dist/documents/index.cjs.map +1 -0
  17. package/dist/documents/index.d.cts +1370 -0
  18. package/dist/documents/index.d.ts +1370 -0
  19. package/dist/documents/index.js +5 -0
  20. package/dist/documents/index.js.map +1 -0
  21. package/dist/documents/validate.cjs +53 -0
  22. package/dist/documents/validate.cjs.map +1 -0
  23. package/dist/documents/validate.d.cts +70 -0
  24. package/dist/documents/validate.d.ts +70 -0
  25. package/dist/documents/validate.js +4 -0
  26. package/dist/documents/validate.js.map +1 -0
  27. package/dist/index.cjs +8917 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.d.cts +11088 -0
  30. package/dist/index.d.ts +11088 -0
  31. package/dist/index.js +8647 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/subgraph.cjs +891 -0
  34. package/dist/subgraph.cjs.map +1 -0
  35. package/dist/subgraph.d.cts +456 -0
  36. package/dist/subgraph.d.ts +456 -0
  37. package/dist/subgraph.js +882 -0
  38. package/dist/subgraph.js.map +1 -0
  39. package/dist/transport-0_X4HTI6.d.ts +39 -0
  40. package/dist/transport-uaC5Yl3p.d.cts +39 -0
  41. package/dist/types-B4Yi7WA4.d.cts +108 -0
  42. package/dist/types-B4Yi7WA4.d.ts +108 -0
  43. package/package.json +75 -0
@@ -0,0 +1,882 @@
1
+ import { OpacityIssuerError } from './chunk-54Q3MU62.js';
2
+
3
+ // src/indexer/errors.ts
4
+ var OpacityIndexerError = class extends OpacityIssuerError {
5
+ constructor(code, message, options2) {
6
+ super(message, options2);
7
+ this.code = code;
8
+ this.name = "OpacityIndexerError";
9
+ }
10
+ code;
11
+ };
12
+
13
+ // src/indexer/executor.ts
14
+ function validateSubgraphUrl(url) {
15
+ try {
16
+ const parsed = new URL(url);
17
+ if (!["http:", "https:"].includes(parsed.protocol) || parsed.username || parsed.password)
18
+ throw new Error("Invalid URL");
19
+ } catch (cause) {
20
+ throw new OpacityIndexerError(
21
+ "INVALID_ARGUMENT",
22
+ "Subgraph URL must use HTTP(S) without embedded credentials.",
23
+ { cause }
24
+ );
25
+ }
26
+ }
27
+ function createGraphqlExecutor(config) {
28
+ const fetchImpl = config.fetch ?? globalThis.fetch?.bind(globalThis);
29
+ if (config.url) validateSubgraphUrl(config.url);
30
+ return async (query, variables = {}, options2 = {}) => {
31
+ if (!config.url)
32
+ throw new OpacityIndexerError(
33
+ "NOT_CONFIGURED",
34
+ "Configure a subgraph URL to use indexed reads."
35
+ );
36
+ if (!fetchImpl)
37
+ throw new OpacityIndexerError("NOT_CONFIGURED", "A fetch implementation is required.");
38
+ const timeoutMs = options2.timeoutMs ?? config.timeoutMs ?? 3e4;
39
+ if (!Number.isInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647)
40
+ throw new OpacityIndexerError(
41
+ "INVALID_ARGUMENT",
42
+ "timeoutMs must be a positive 32-bit integer."
43
+ );
44
+ if (options2.signal?.aborted)
45
+ throw new OpacityIndexerError("ABORTED", "Subgraph request cancelled before it started.");
46
+ const controller = new AbortController();
47
+ let timedOut = false;
48
+ const onAbort = () => controller.abort();
49
+ options2.signal?.addEventListener("abort", onAbort, { once: true });
50
+ const timer = setTimeout(() => {
51
+ timedOut = true;
52
+ controller.abort();
53
+ }, timeoutMs);
54
+ let cancellation;
55
+ const cancellationError = (cause) => new OpacityIndexerError(
56
+ timedOut ? "TIMEOUT" : "ABORTED",
57
+ timedOut ? "Subgraph request timed out." : "Subgraph request cancelled.",
58
+ { cause }
59
+ );
60
+ const aborted = new Promise((_, reject) => {
61
+ cancellation = () => reject(cancellationError());
62
+ controller.signal.addEventListener("abort", cancellation, { once: true });
63
+ });
64
+ try {
65
+ return await Promise.race([
66
+ (async () => {
67
+ const response = await fetchImpl(config.url, {
68
+ method: "POST",
69
+ headers: {
70
+ accept: "application/json",
71
+ "content-type": "application/json",
72
+ ...config.headers
73
+ },
74
+ credentials: "omit",
75
+ signal: controller.signal,
76
+ body: JSON.stringify({ query, variables })
77
+ });
78
+ if (!response.ok)
79
+ throw new OpacityIndexerError("HTTP", `Subgraph returned HTTP ${response.status}.`);
80
+ const payload = await response.json();
81
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
82
+ throw new OpacityIndexerError("INVALID_RESPONSE", "Malformed subgraph response.");
83
+ const envelope = payload;
84
+ if (envelope["errors"] !== void 0) {
85
+ if (!Array.isArray(envelope["errors"]))
86
+ throw new OpacityIndexerError("INVALID_RESPONSE", "Malformed subgraph errors.");
87
+ if (envelope["errors"].length > 0)
88
+ throw new OpacityIndexerError(
89
+ "GRAPHQL",
90
+ "Subgraph returned GraphQL errors; partial data was discarded.",
91
+ { cause: envelope["errors"] }
92
+ );
93
+ }
94
+ if (!envelope["data"] || typeof envelope["data"] !== "object" || Array.isArray(envelope["data"]))
95
+ throw new OpacityIndexerError("INVALID_RESPONSE", "Subgraph returned no data object.");
96
+ return envelope["data"];
97
+ })(),
98
+ aborted
99
+ ]);
100
+ } catch (cause) {
101
+ if (cause instanceof OpacityIndexerError) throw cause;
102
+ if (controller.signal.aborted) throw cancellationError(cause);
103
+ throw new OpacityIndexerError("TRANSPORT", "Subgraph request or response decoding failed.", {
104
+ cause
105
+ });
106
+ } finally {
107
+ clearTimeout(timer);
108
+ options2.signal?.removeEventListener("abort", onAbort);
109
+ if (cancellation) controller.signal.removeEventListener("abort", cancellation);
110
+ controller.abort();
111
+ }
112
+ };
113
+ }
114
+
115
+ // src/indexer/arguments.ts
116
+ function invalid(path) {
117
+ throw new OpacityIndexerError("INVALID_ARGUMENT", `Invalid indexer argument at ${path}.`);
118
+ }
119
+ var optional = (rule) => (value, path) => {
120
+ if (value !== void 0) rule(value, path);
121
+ };
122
+ var string = (pattern, min = 0, max = Infinity) => (value, path) => {
123
+ if (typeof value !== "string" || value.length < min || value.length > max || !pattern.test(value))
124
+ invalid(path);
125
+ };
126
+ var address = string(/^0x[0-9a-fA-F]{40}$/);
127
+ var bytes32 = string(/^0x[0-9a-fA-F]{64}$/);
128
+ var uint = (max) => (value, path) => {
129
+ if (typeof value !== "bigint" || value < 0n || value > max) invalid(path);
130
+ };
131
+ var uint256 = uint((1n << 256n) - 1n);
132
+ var blockNumber = uint(2147483647n);
133
+ var integer = (min, max) => (value, path) => {
134
+ if (typeof value !== "number" || !Number.isInteger(value) || value < min || value > max)
135
+ invalid(path);
136
+ };
137
+ var boolean = (value, path) => {
138
+ if (typeof value !== "boolean") invalid(path);
139
+ };
140
+ var object = (fields, refine) => (value, path) => {
141
+ if (!value || typeof value !== "object" || Array.isArray(value)) invalid(path);
142
+ const prototype = Object.getPrototypeOf(value);
143
+ if (prototype !== Object.prototype && prototype !== null) invalid(path);
144
+ const input = value;
145
+ for (const key of Object.keys(input)) {
146
+ if (!Object.hasOwn(fields, key)) invalid(`${path}.${key}`);
147
+ }
148
+ for (const [key, rule] of Object.entries(fields)) rule(input[key], `${path}.${key}`);
149
+ refine?.(input, path);
150
+ };
151
+ var snapshot = {
152
+ blockNumber: optional(blockNumber),
153
+ blockHash: optional(bytes32),
154
+ timeoutMs: optional(integer(1, 2147483647)),
155
+ // Signals are local request controls. JSON objects cannot impersonate an AbortSignal.
156
+ signal: optional((value, path) => {
157
+ if (typeof AbortSignal === "undefined" || !(value instanceof AbortSignal)) invalid(path);
158
+ })
159
+ };
160
+ var page = {
161
+ ...snapshot,
162
+ pageSize: optional(integer(1, 999)),
163
+ cursor: optional(
164
+ object({
165
+ after: string(/^0x(?:[0-9a-fA-F]{2})*$/, 2, 1024),
166
+ blockNumber,
167
+ blockHash: (value, path) => {
168
+ if (value !== null) bytes32(value, path);
169
+ },
170
+ deployment: string(/[\s\S]*/, 1, 512),
171
+ scope: string(/[\s\S]*/, 1, 4096)
172
+ })
173
+ )
174
+ };
175
+ var options = optional(object(snapshot));
176
+ var list = (fields, required = false, refine) => {
177
+ const params = object({ ...page, ...fields }, refine);
178
+ return [required ? params : optional(params)];
179
+ };
180
+ var vault = { token: optional(address), vault: optional(address) };
181
+ var operationArguments = {
182
+ getMetadata: [options],
183
+ getRegistry: [options],
184
+ getToken: [address, options],
185
+ getAccount: [address, options],
186
+ getUser: [bytes32, options],
187
+ getVault: [address, options],
188
+ listTokens: list({ issuer: optional(address), registry: optional(address) }),
189
+ listTokenIds: list({ token: address }, true),
190
+ listTokenURIs: list({ token: address }, true),
191
+ listPolicies: list({ token: address, active: optional(boolean) }, true),
192
+ listUserAccounts: list({ userId: bytes32 }, true),
193
+ listGlobalTraits: list({ userId: bytes32 }, true),
194
+ listTokenTraits: list({ userId: bytes32, token: optional(address) }, true),
195
+ listBalances: list(
196
+ {
197
+ wallet: optional(address),
198
+ userId: optional(bytes32),
199
+ token: optional(address),
200
+ tokenId: optional(uint256),
201
+ positiveOnly: optional(boolean)
202
+ },
203
+ false,
204
+ (value, path) => {
205
+ const input = value;
206
+ if (input["wallet"] !== void 0 && input["userId"] !== void 0)
207
+ invalid(`${path}.wallet/userId`);
208
+ }
209
+ ),
210
+ listTransfers: list({
211
+ wallet: optional(address),
212
+ token: optional(address),
213
+ tokenId: optional(uint256)
214
+ }),
215
+ listDocumentAttestations: list({
216
+ wallet: optional(address),
217
+ userId: optional(bytes32),
218
+ traitId: optional(bytes32)
219
+ }),
220
+ listVaults: list({ token: optional(address) }),
221
+ listVaultDeposits: list({ ...vault, wallet: optional(address) }),
222
+ listVaultWithdrawals: list({ ...vault, wallet: optional(address) }),
223
+ listVaultAdminExecutions: list({ ...vault, owner: optional(address), target: optional(address) })
224
+ };
225
+ var INDEXER_OPERATIONS = Object.freeze(
226
+ Object.keys(operationArguments)
227
+ );
228
+ function validateIndexerOperationArgs(operation, args) {
229
+ if (!Object.hasOwn(operationArguments, operation) || !Array.isArray(args)) invalid("args");
230
+ const rules = operationArguments[operation];
231
+ if (args.length > rules.length) invalid("args.length");
232
+ rules.forEach((rule, index) => rule(args[index], `args[${index}]`));
233
+ return [...args];
234
+ }
235
+
236
+ // src/indexer/index.ts
237
+ function invalid2(path) {
238
+ throw new OpacityIndexerError("INVALID_RESPONSE", `Malformed indexer response at ${path}.`);
239
+ }
240
+ function record(value, path) {
241
+ if (typeof value !== "object" || value === null || Array.isArray(value)) invalid2(path);
242
+ return value;
243
+ }
244
+ var stringField = {
245
+ parse: (v, p) => typeof v === "string" ? v : invalid2(p)
246
+ };
247
+ var bool = {
248
+ parse: (v, p) => typeof v === "boolean" ? v : invalid2(p)
249
+ };
250
+ var uint2 = {
251
+ parse: (v, p, domain) => domain ? typeof v === "bigint" && v >= 0n ? v : invalid2(p) : typeof v === "string" && /^(0|[1-9][0-9]*)$/.test(v) ? BigInt(v) : invalid2(p)
252
+ };
253
+ var graphInt = {
254
+ parse: (v, p, domain) => domain ? typeof v === "bigint" && v >= 0n && v <= BigInt(Number.MAX_SAFE_INTEGER) ? v : invalid2(p) : typeof v === "number" && Number.isSafeInteger(v) && v >= 0 ? BigInt(v) : invalid2(p)
255
+ };
256
+ function hex(bytes) {
257
+ return {
258
+ parse: (v, p) => {
259
+ if (typeof v !== "string" || !/^0x(?:[0-9a-fA-F]{2})*$/.test(v)) invalid2(p);
260
+ if (bytes !== void 0 && v.length !== 2 + bytes * 2) invalid2(p);
261
+ return v.toLowerCase();
262
+ }
263
+ };
264
+ }
265
+ var address2 = hex(20);
266
+ var bytes322 = hex(32);
267
+ function nullable(field) {
268
+ return {
269
+ ...field.selection === void 0 ? {} : { selection: field.selection },
270
+ parse: (v, p, domain) => v === null ? null : field.parse(v, p, domain)
271
+ };
272
+ }
273
+ function array(field) {
274
+ return {
275
+ parse: (v, p, domain) => {
276
+ if (!Array.isArray(v)) invalid2(p);
277
+ return v.map((item, i) => field.parse(item, `${p}[${i}]`, domain));
278
+ }
279
+ };
280
+ }
281
+ function enumeration(values) {
282
+ return {
283
+ parse: (v, p) => typeof v === "string" && values.includes(v) ? v : invalid2(p)
284
+ };
285
+ }
286
+ function object2(fields) {
287
+ return {
288
+ selection: Object.entries(fields).map(([key, field]) => `${key}${field.selection ? ` { ${field.selection} }` : ""}`).join(" "),
289
+ parse: (v, p, domain) => {
290
+ const input = record(v, p);
291
+ return Object.fromEntries(
292
+ Object.entries(fields).map(([key, field]) => [
293
+ key,
294
+ field.parse(input[key], `${p}.${key}`, domain)
295
+ ])
296
+ );
297
+ }
298
+ };
299
+ }
300
+ var addressRef = object2({ id: address2 });
301
+ var userRef = object2({ id: bytes322 });
302
+ var metaField = object2({
303
+ deployment: stringField,
304
+ hasIndexingErrors: bool,
305
+ block: object2({ number: graphInt, hash: nullable(bytes322), timestamp: nullable(graphInt) })
306
+ });
307
+ var tokenField = object2({
308
+ id: address2,
309
+ issuer: addressRef,
310
+ issuerAdmin: nullable(address2),
311
+ allowlistRegistry: address2,
312
+ name: nullable(stringField),
313
+ symbol: nullable(stringField),
314
+ paused: bool,
315
+ mintingPaused: bool,
316
+ policyEngine: nullable(address2),
317
+ transferOperator: nullable(address2),
318
+ tokenTraitRegistry: nullable(address2),
319
+ maxPolicies: nullable(uint2),
320
+ activePolicyCount: uint2,
321
+ activeRuleSetSnapshot: nullable(bytes322),
322
+ ruleSetDeploymentCount: uint2,
323
+ deployedAtBlock: uint2,
324
+ deployedAtTimestamp: uint2,
325
+ deployTxHash: bytes322,
326
+ beaconVariant: nullable(object2({ id: bytes322, beacon: address2, isActive: bool }))
327
+ });
328
+ var supplyField = object2({
329
+ id: hex(),
330
+ token: addressRef,
331
+ tokenId: uint2,
332
+ totalSupply: uint2,
333
+ maxSupply: uint2,
334
+ holderCount: uint2
335
+ });
336
+ var policyType = enumeration([
337
+ "TRADING_DISABLED_V1",
338
+ "ALLOWED_TRANSFEREE_V1",
339
+ "HOLDER_COUNT_CAP_V1",
340
+ "CEILING_BALANCE_V1",
341
+ "FLOOR_BALANCE_V1",
342
+ "DENYLIST_V1",
343
+ "INSIDER_FREEZE_V1",
344
+ "SELF_TRANSFER_ONLY_V1",
345
+ "UNKNOWN"
346
+ ]);
347
+ var guardMode = enumeration([
348
+ "NONE",
349
+ "ONLY_IF_FROM_HAS",
350
+ "ONLY_IF_TO_HAS",
351
+ "ONLY_IF_EITHER_HAS"
352
+ ]);
353
+ var policyField = object2({
354
+ id: hex(),
355
+ token: addressRef,
356
+ implementation: object2({
357
+ id: address2,
358
+ status: enumeration(["UNKNOWN", "PENDING", "APPROVED", "REVOKED", "CANCELLED"])
359
+ }),
360
+ policyType,
361
+ scopeKey: bytes322,
362
+ active: bool,
363
+ rawConfig: hex(),
364
+ guardTrait: bytes322,
365
+ guardMode,
366
+ guardTraitIsGlobal: bool,
367
+ configEnabled: nullable(bool),
368
+ configMaxHolders: nullable(uint2),
369
+ configIsPercentage: nullable(bool),
370
+ configCeiling: nullable(uint2),
371
+ configDenominatorMode: nullable(enumeration(["CURRENT_SUPPLY", "MAX_SUPPLY"])),
372
+ configTraitList: nullable(array(bytes322)),
373
+ configRequireAll: nullable(bool),
374
+ attachedAtBlock: uint2,
375
+ lastReconfiguredAtBlock: nullable(uint2)
376
+ });
377
+ var entryField = object2({
378
+ id: address2,
379
+ status: enumeration(["VERIFIED", "COMPLIANCE_REMOVAL", "USER_REMOVAL", "MIGRATED"]),
380
+ user: nullable(userRef),
381
+ expiresAt: nullable(uint2),
382
+ addedBy: nullable(address2),
383
+ migratedTo: nullable(address2),
384
+ migratedFrom: nullable(address2),
385
+ lastUpdatedBlock: uint2,
386
+ lastUpdatedTimestamp: uint2
387
+ });
388
+ var accountField = object2({
389
+ id: address2,
390
+ isAuthorizedIssuer: bool,
391
+ allowlistEntry: nullable(entryField)
392
+ });
393
+ var globalTraitField = object2({
394
+ id: hex(),
395
+ user: userRef,
396
+ traitId: bytes322,
397
+ enabled: bool,
398
+ lastUpdatedBy: address2,
399
+ lastUpdatedBlock: uint2,
400
+ lastUpdatedTimestamp: uint2,
401
+ traitConfig: object2({ expiryDuration: uint2, teeEnableable: bool, writerEnableable: bool })
402
+ });
403
+ var tokenTraitField = object2({
404
+ id: hex(),
405
+ token: addressRef,
406
+ user: userRef,
407
+ traitId: bytes322,
408
+ enabled: bool,
409
+ lastUpdatedBlock: uint2,
410
+ lastUpdatedTimestamp: uint2
411
+ });
412
+ var walletBalanceField = object2({
413
+ id: hex(),
414
+ token: addressRef,
415
+ account: addressRef,
416
+ tokenId: uint2,
417
+ balance: uint2,
418
+ frozenAmount: uint2
419
+ });
420
+ var userBalanceField = object2({
421
+ id: hex(),
422
+ token: addressRef,
423
+ user: userRef,
424
+ tokenId: uint2,
425
+ balance: uint2,
426
+ openIntervalId: nullable(hex())
427
+ });
428
+ var transferField = object2({
429
+ id: hex(),
430
+ token: addressRef,
431
+ operator: address2,
432
+ from: addressRef,
433
+ to: addressRef,
434
+ tokenId: uint2,
435
+ value: uint2,
436
+ isBatch: bool,
437
+ batchIndex: graphInt,
438
+ blockNumber: uint2,
439
+ blockTimestamp: uint2,
440
+ transactionHash: bytes322,
441
+ logIndex: uint2
442
+ });
443
+ var attestationField = object2({
444
+ id: bytes322,
445
+ attestor: addressRef,
446
+ document: object2({ id: bytes322 }),
447
+ user: userRef,
448
+ wallet: address2,
449
+ traitId: bytes322,
450
+ docHash: bytes322,
451
+ nonce: bytes322,
452
+ globalTrait: object2({ id: hex(), enabled: bool }),
453
+ blockNumber: uint2,
454
+ blockTimestamp: uint2,
455
+ transactionHash: bytes322,
456
+ logIndex: uint2
457
+ });
458
+ var registryField = object2({
459
+ id: stringField,
460
+ contractAddress: address2,
461
+ paused: bool,
462
+ defaultExpiryDuration: nullable(uint2),
463
+ authorizedSigner: nullable(address2),
464
+ teeTraitAllowlistEnforced: bool
465
+ });
466
+ var uriField = object2({
467
+ id: hex(),
468
+ token: addressRef,
469
+ tokenId: uint2,
470
+ uri: stringField,
471
+ lastUpdatedBlock: uint2
472
+ });
473
+ var vaultField = object2({
474
+ id: address2,
475
+ token: addressRef,
476
+ tokenId: uint2,
477
+ stablecoin: address2,
478
+ firstObservedAtBlock: uint2,
479
+ firstObservedAtTimestamp: uint2,
480
+ firstObservedTxHash: bytes322,
481
+ depositCount: uint2,
482
+ withdrawalCount: uint2,
483
+ totalDeposited: uint2,
484
+ totalWithdrawn: uint2,
485
+ adminExecutionCount: uint2
486
+ });
487
+ var vaultEventFields = {
488
+ id: hex(),
489
+ vault: addressRef,
490
+ token: addressRef,
491
+ blockNumber: uint2,
492
+ blockTimestamp: uint2,
493
+ transactionHash: bytes322
494
+ };
495
+ var vaultMovementField = object2({ ...vaultEventFields, user: addressRef, amount: uint2 });
496
+ var vaultAdminField = object2({
497
+ ...vaultEventFields,
498
+ owner: address2,
499
+ target: address2,
500
+ selector: hex(4)
501
+ });
502
+ function argument(field, value, name) {
503
+ try {
504
+ return field.parse(value, name);
505
+ } catch (cause) {
506
+ throw new OpacityIndexerError("INVALID_ARGUMENT", `Invalid ${name}.`, { cause });
507
+ }
508
+ }
509
+ function bigintArgument(value, name) {
510
+ if (typeof value !== "bigint" || value < 0n) {
511
+ throw new OpacityIndexerError("INVALID_ARGUMENT", `${name} must be a nonnegative bigint.`);
512
+ }
513
+ return value.toString();
514
+ }
515
+ function blockVariable(value, hash) {
516
+ if (value !== void 0) bigintArgument(value, "blockNumber");
517
+ if (value !== void 0 && value > 2147483647n) {
518
+ throw new OpacityIndexerError("INVALID_ARGUMENT", "blockNumber exceeds the GraphQL Int range.");
519
+ }
520
+ if (hash !== void 0) return { hash: argument(bytes322, hash, "blockHash") };
521
+ return value === void 0 ? null : { number: Number(value) };
522
+ }
523
+ function validateSnapshot(meta, blockNumber2, blockHash) {
524
+ if (blockNumber2 !== void 0 && meta.block.number !== blockNumber2) invalid2("_meta.block.number");
525
+ if (blockHash !== void 0 && meta.block.hash !== null && meta.block.hash !== blockHash.toLowerCase()) {
526
+ throw new OpacityIndexerError(
527
+ "SNAPSHOT_CHANGED",
528
+ "Indexed block hash changed; restart the snapshot."
529
+ );
530
+ }
531
+ }
532
+ function requireHealthyIndex(meta) {
533
+ if (meta.hasIndexingErrors) {
534
+ throw new OpacityIndexerError(
535
+ "INDEXING_ERROR",
536
+ "Subgraph reports indexing errors; indexed entity data was discarded."
537
+ );
538
+ }
539
+ }
540
+ function createIndexerNamespace(config) {
541
+ const request = createGraphqlExecutor(config);
542
+ async function single(entity, id, field, options2 = {}) {
543
+ const data = await request(
544
+ `query IndexedSingle($id:ID!,$block:Block_height){item:${entity}(id:$id,block:$block){${field.selection}} _meta(block:$block){${metaField.selection}}}`,
545
+ { id, block: blockVariable(options2.blockNumber, options2.blockHash) },
546
+ options2
547
+ );
548
+ const item = nullable(field).parse(data.item, "item");
549
+ if (item !== null && record(item, "item").id !== id) invalid2("item.id");
550
+ const meta = metaField.parse(data._meta, "_meta");
551
+ validateSnapshot(meta, options2.blockNumber, options2.blockHash);
552
+ requireHealthyIndex(meta);
553
+ return { item, meta };
554
+ }
555
+ async function page2(entity, filterType, field, filters, options2) {
556
+ const size = options2.pageSize ?? 100;
557
+ if (!Number.isInteger(size) || size < 1 || size > 999) {
558
+ throw new OpacityIndexerError("INVALID_ARGUMENT", "pageSize must be an integer from 1\u2013999.");
559
+ }
560
+ const scope = `${entity}:${JSON.stringify(filters)}`;
561
+ const cursor = options2.cursor;
562
+ if (cursor) {
563
+ argument(hex(), cursor.after, "cursor.after");
564
+ bigintArgument(cursor.blockNumber, "cursor.blockNumber");
565
+ argument(stringField, cursor.deployment, "cursor.deployment");
566
+ argument(nullable(bytes322), cursor.blockHash, "cursor.blockHash");
567
+ if (cursor.scope !== scope || options2.blockNumber !== void 0 && options2.blockNumber !== cursor.blockNumber || options2.blockHash !== void 0 && options2.blockHash.toLowerCase() !== cursor.blockHash) {
568
+ throw new OpacityIndexerError(
569
+ "INVALID_ARGUMENT",
570
+ "Cursor does not match the query filters or block."
571
+ );
572
+ }
573
+ }
574
+ const after = cursor?.after ?? "0x";
575
+ const blockNumber2 = cursor?.blockNumber ?? options2.blockNumber;
576
+ const blockHash = cursor?.blockHash ?? options2.blockHash;
577
+ const block = blockVariable(blockNumber2, blockHash);
578
+ const where = Array.isArray(filters.or) ? { or: filters.or.map((branch) => ({ ...record(branch, "filter"), id_gt: after })) } : { ...filters, id_gt: after };
579
+ const data = await request(
580
+ `query IndexedPage($first:Int!,$where:${filterType}!,$block:Block_height){items:${entity}(first:$first,orderBy:id,orderDirection:asc,where:$where,block:$block){${field.selection}} _meta(block:$block){${metaField.selection}}}`,
581
+ { first: size + 1, where, block },
582
+ options2
583
+ );
584
+ const meta = metaField.parse(data._meta, "_meta");
585
+ requireHealthyIndex(meta);
586
+ if (cursor && cursor.deployment !== meta.deployment) {
587
+ throw new OpacityIndexerError(
588
+ "DEPLOYMENT_CHANGED",
589
+ "Subgraph deployment changed; restart pagination."
590
+ );
591
+ }
592
+ validateSnapshot(meta, blockNumber2, blockHash);
593
+ const rows = array(field).parse(data.items, "items");
594
+ if (rows.length > size + 1) invalid2("items.length");
595
+ let previous = after;
596
+ for (const row of rows) {
597
+ if (row.id <= previous) invalid2("items.id order");
598
+ previous = row.id;
599
+ }
600
+ const items = rows.slice(0, size);
601
+ return {
602
+ items,
603
+ meta,
604
+ nextCursor: rows.length > size ? {
605
+ after: items[items.length - 1].id,
606
+ blockNumber: meta.block.number,
607
+ blockHash: blockHash ?? meta.block.hash,
608
+ deployment: meta.deployment,
609
+ scope
610
+ } : null
611
+ };
612
+ }
613
+ const tokenFilters = (p) => ({ token: argument(address2, p.token, "token") });
614
+ const userFilters = (p) => ({ user: argument(bytes322, p.userId, "userId") });
615
+ const vaultFilters = (p) => ({
616
+ ...p.token === void 0 ? {} : tokenFilters({ token: p.token }),
617
+ ...p.vault === void 0 ? {} : { vault: argument(address2, p.vault, "vault") }
618
+ });
619
+ const vaultMovementFilters = (p) => ({
620
+ ...vaultFilters(p),
621
+ ...p.wallet === void 0 ? {} : { user: argument(address2, p.wallet, "wallet") }
622
+ });
623
+ const namespace = {
624
+ async getMetadata(options2 = {}) {
625
+ const data = await request(
626
+ `query IndexingMetadata($block:Block_height){_meta(block:$block){${metaField.selection}}}`,
627
+ { block: blockVariable(options2.blockNumber, options2.blockHash) },
628
+ options2
629
+ );
630
+ const meta = metaField.parse(data._meta, "_meta");
631
+ validateSnapshot(meta, options2.blockNumber, options2.blockHash);
632
+ return meta;
633
+ },
634
+ getRegistry: (options2) => single("allowlistRegistryState", "registry", registryField, options2),
635
+ getVault: (vault2, options2) => single("issuerVault", argument(address2, vault2, "vault"), vaultField, options2),
636
+ listVaults: (p = {}) => page2("issuerVaults", "IssuerVault_filter", vaultField, vaultFilters(p), p),
637
+ listVaultDeposits: (p = {}) => page2(
638
+ "vaultDepositEvents",
639
+ "VaultDepositEvent_filter",
640
+ vaultMovementField,
641
+ vaultMovementFilters(p),
642
+ p
643
+ ),
644
+ listVaultWithdrawals: (p = {}) => page2(
645
+ "vaultWithdrawalEvents",
646
+ "VaultWithdrawalEvent_filter",
647
+ vaultMovementField,
648
+ vaultMovementFilters(p),
649
+ p
650
+ ),
651
+ listVaultAdminExecutions: (p = {}) => page2(
652
+ "vaultAdminExecutedEvents",
653
+ "VaultAdminExecutedEvent_filter",
654
+ vaultAdminField,
655
+ {
656
+ ...vaultFilters(p),
657
+ ...p.owner === void 0 ? {} : { owner: argument(address2, p.owner, "owner") },
658
+ ...p.target === void 0 ? {} : { target: argument(address2, p.target, "target") }
659
+ },
660
+ p
661
+ ),
662
+ listTokens: (p = {}) => page2(
663
+ "tokens",
664
+ "Token_filter",
665
+ tokenField,
666
+ {
667
+ ...p.issuer === void 0 ? {} : { issuer: argument(address2, p.issuer, "issuer") },
668
+ ...p.registry === void 0 ? {} : { allowlistRegistry: argument(address2, p.registry, "registry") }
669
+ },
670
+ p
671
+ ),
672
+ getToken: (token, options2) => single("token", argument(address2, token, "token"), tokenField, options2),
673
+ listTokenIds: (p) => page2("tokenSupplies", "TokenSupply_filter", supplyField, tokenFilters(p), p),
674
+ listTokenURIs: (p) => page2("tokenURIs", "TokenURI_filter", uriField, tokenFilters(p), p),
675
+ listPolicies: (p) => page2(
676
+ "attachedPolicies",
677
+ "AttachedPolicy_filter",
678
+ policyField,
679
+ { ...tokenFilters(p), active: argument(bool, p.active ?? true, "active") },
680
+ p
681
+ ),
682
+ getAccount: (wallet, options2) => single("account", argument(address2, wallet, "wallet"), accountField, options2),
683
+ getUser: (userId, options2) => single("user", argument(bytes322, userId, "userId"), userRef, options2),
684
+ listUserAccounts: (p) => page2("allowlistEntries", "AllowlistEntry_filter", entryField, userFilters(p), p),
685
+ listGlobalTraits: (p) => page2("globalTraits", "GlobalTrait_filter", globalTraitField, userFilters(p), p),
686
+ listTokenTraits: (p) => page2(
687
+ "tokenTraits",
688
+ "TokenTrait_filter",
689
+ tokenTraitField,
690
+ { ...userFilters(p), ...p.token === void 0 ? {} : tokenFilters({ token: p.token }) },
691
+ p
692
+ ),
693
+ listBalances(p = {}) {
694
+ if (p.wallet !== void 0 && p.userId !== void 0) {
695
+ throw new OpacityIndexerError(
696
+ "INVALID_ARGUMENT",
697
+ "Choose wallet or userId for balances, not both."
698
+ );
699
+ }
700
+ const filters = {
701
+ ...p.token === void 0 ? {} : tokenFilters({ token: p.token }),
702
+ ...p.tokenId === void 0 ? {} : { tokenId: bigintArgument(p.tokenId, "tokenId") },
703
+ ...argument(bool, p.positiveOnly ?? true, "positiveOnly") ? { balance_gt: "0" } : {}
704
+ };
705
+ if (p.userId !== void 0) {
706
+ return page2(
707
+ "userBalances",
708
+ "UserBalance_filter",
709
+ userBalanceField,
710
+ { ...filters, ...userFilters({ userId: p.userId }) },
711
+ p
712
+ );
713
+ }
714
+ return page2(
715
+ "tokenBalances",
716
+ "TokenBalance_filter",
717
+ walletBalanceField,
718
+ {
719
+ ...filters,
720
+ ...p.wallet === void 0 ? {} : { account: argument(address2, p.wallet, "wallet") }
721
+ },
722
+ p
723
+ );
724
+ },
725
+ listTransfers(p = {}) {
726
+ const filters = {
727
+ ...p.token === void 0 ? {} : tokenFilters({ token: p.token }),
728
+ ...p.tokenId === void 0 ? {} : { tokenId: bigintArgument(p.tokenId, "tokenId") }
729
+ };
730
+ const where = p.wallet === void 0 ? filters : {
731
+ or: [
732
+ { ...filters, from: argument(address2, p.wallet, "wallet") },
733
+ { ...filters, to: argument(address2, p.wallet, "wallet") }
734
+ ]
735
+ };
736
+ return page2("transferEvents", "TransferEvent_filter", transferField, where, p);
737
+ },
738
+ listDocumentAttestations: (p = {}) => page2(
739
+ "documentAttestations",
740
+ "DocumentAttestation_filter",
741
+ attestationField,
742
+ {
743
+ ...p.wallet === void 0 ? {} : { wallet: argument(address2, p.wallet, "wallet") },
744
+ ...p.userId === void 0 ? {} : userFilters({ userId: p.userId }),
745
+ ...p.traitId === void 0 ? {} : { traitId: argument(bytes322, p.traitId, "traitId") }
746
+ },
747
+ p
748
+ )
749
+ };
750
+ return Object.fromEntries(
751
+ INDEXER_OPERATIONS.map((operation) => [
752
+ operation,
753
+ async (...args) => {
754
+ const validated = validateIndexerOperationArgs(operation, args);
755
+ const invoke = namespace[operation];
756
+ return invoke(...validated);
757
+ }
758
+ ])
759
+ );
760
+ }
761
+ function validateIndexerOperationResult(operation, value, args = []) {
762
+ const last = args.at(-1);
763
+ const options2 = last && typeof last === "object" && !Array.isArray(last) ? last : {};
764
+ const requestedBlock = options2.cursor?.blockNumber ?? options2.blockNumber;
765
+ const requestedHash = options2.cursor?.blockHash ?? options2.blockHash;
766
+ if (operation === "getMetadata") {
767
+ const meta2 = metaField.parse(value, "metadata", true);
768
+ validateSnapshot(meta2, requestedBlock, requestedHash ?? void 0);
769
+ return meta2;
770
+ }
771
+ const result = record(value, "result");
772
+ const meta = metaField.parse(result["meta"], "meta", true);
773
+ requireHealthyIndex(meta);
774
+ validateSnapshot(meta, requestedBlock, requestedHash ?? void 0);
775
+ if (options2.cursor && options2.cursor.deployment !== meta.deployment)
776
+ throw new OpacityIndexerError(
777
+ "DEPLOYMENT_CHANGED",
778
+ "Subgraph deployment changed; restart pagination."
779
+ );
780
+ const fields = {
781
+ getRegistry: registryField,
782
+ getToken: tokenField,
783
+ getAccount: accountField,
784
+ getUser: userRef,
785
+ getVault: vaultField,
786
+ listTokens: tokenField,
787
+ listTokenIds: supplyField,
788
+ listTokenURIs: uriField,
789
+ listPolicies: policyField,
790
+ listUserAccounts: entryField,
791
+ listGlobalTraits: globalTraitField,
792
+ listTokenTraits: tokenTraitField,
793
+ listBalances: args[0] && typeof args[0] === "object" && args[0]["userId"] !== void 0 ? userBalanceField : walletBalanceField,
794
+ listTransfers: transferField,
795
+ listDocumentAttestations: attestationField,
796
+ listVaults: vaultField,
797
+ listVaultDeposits: vaultMovementField,
798
+ listVaultWithdrawals: vaultMovementField,
799
+ listVaultAdminExecutions: vaultAdminField
800
+ };
801
+ const field = fields[operation];
802
+ if (operation.startsWith("get")) {
803
+ const item = nullable(field).parse(result["item"], "item", true);
804
+ const id = operation === "getRegistry" ? "registry" : typeof args[0] === "string" ? args[0].toLowerCase() : void 0;
805
+ if (item !== null && record(item, "item")["id"] !== id) invalid2("item.id");
806
+ return { item, meta };
807
+ }
808
+ const items = array(field).parse(result["items"], "items", true);
809
+ if (items.length > (options2.pageSize ?? 100)) invalid2("items.length");
810
+ const cursorField = object2({
811
+ after: hex(),
812
+ blockNumber: uint2,
813
+ blockHash: nullable(bytes322),
814
+ deployment: stringField,
815
+ scope: stringField
816
+ });
817
+ const nextCursor = nullable(cursorField).parse(result["nextCursor"], "nextCursor", true);
818
+ if (nextCursor && (nextCursor.deployment !== meta.deployment || nextCursor.blockNumber !== meta.block.number || meta.block.hash !== null && nextCursor.blockHash !== meta.block.hash))
819
+ invalid2("nextCursor.snapshot");
820
+ if (nextCursor && options2.cursor && nextCursor.scope !== options2.cursor.scope)
821
+ invalid2("nextCursor.scope");
822
+ let previous = options2.cursor?.after ?? "";
823
+ for (const item of items) {
824
+ const id = record(item, "item")["id"];
825
+ if (typeof id !== "string" || id <= previous) invalid2("items.id order");
826
+ previous = id;
827
+ }
828
+ if (nextCursor && nextCursor.after !== previous) invalid2("nextCursor.after");
829
+ return { items, meta, nextCursor };
830
+ }
831
+
832
+ // src/indexer/wire.ts
833
+ function encodeWireValue(value) {
834
+ if (typeof value === "bigint") return { __bigint: value.toString() };
835
+ if (value === null || typeof value === "boolean" || typeof value === "string") return value;
836
+ if (typeof value === "number" && Number.isFinite(value)) return value;
837
+ if (Array.isArray(value)) return value.map(encodeWireValue);
838
+ if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === Object.prototype) {
839
+ if ("__bigint" in value)
840
+ throw new OpacityIndexerError("INVALID_ARGUMENT", "__bigint is reserved.");
841
+ return Object.fromEntries(
842
+ Object.entries(value).filter(([, item]) => item !== void 0).map(([key, item]) => [key, encodeWireValue(item)])
843
+ );
844
+ }
845
+ throw new OpacityIndexerError(
846
+ "INVALID_ARGUMENT",
847
+ "Indexer arguments must be JSON values or bigint."
848
+ );
849
+ }
850
+ function decodeWireValue(value) {
851
+ if (Array.isArray(value)) return value.map(decodeWireValue);
852
+ if (typeof value === "object" && value !== null) {
853
+ const record2 = value;
854
+ if ("__bigint" in record2) {
855
+ if (Object.keys(record2).length !== 1 || typeof record2["__bigint"] !== "string" || !/^-?(0|[1-9]\d*)$/.test(record2["__bigint"])) {
856
+ throw new OpacityIndexerError("INVALID_RESPONSE", "Malformed bigint in indexer response.");
857
+ }
858
+ return BigInt(record2["__bigint"]);
859
+ }
860
+ return Object.fromEntries(
861
+ Object.entries(record2).map(([key, item]) => [key, decodeWireValue(item)])
862
+ );
863
+ }
864
+ if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value))
865
+ return value;
866
+ throw new OpacityIndexerError("INVALID_RESPONSE", "Malformed indexer wire value.");
867
+ }
868
+
869
+ // src/indexer/client.ts
870
+ function createSubgraphClient(config) {
871
+ validateSubgraphUrl(config.url);
872
+ const request = createGraphqlExecutor(config);
873
+ return {
874
+ async query(query, variables, options2) {
875
+ return await request(query, variables, options2);
876
+ }
877
+ };
878
+ }
879
+
880
+ export { INDEXER_OPERATIONS, OpacityIndexerError, createIndexerNamespace, createSubgraphClient, decodeWireValue, encodeWireValue, validateIndexerOperationArgs, validateIndexerOperationResult };
881
+ //# sourceMappingURL=subgraph.js.map
882
+ //# sourceMappingURL=subgraph.js.map