@distrohelena/canton-typescript-sdk 0.1.35 → 0.1.37

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 (102) hide show
  1. package/README.md +159 -51
  2. package/dist/cjs/core/types/requests/{submit-command-request.js → submit-commands-request.js} +10 -6
  3. package/dist/cjs/index.js +10 -8
  4. package/dist/cjs/query/canonical/in-memory-query-evaluator.js +291 -0
  5. package/dist/cjs/query/canonical/public-identity.js +41 -0
  6. package/dist/cjs/query/canonical/query-ast.js +2 -0
  7. package/dist/cjs/query/canonical/query-dataset.js +351 -0
  8. package/dist/cjs/query/canonical/query-normalizer.js +655 -0
  9. package/dist/cjs/query/canonical/query-schema.js +86 -0
  10. package/dist/cjs/query/canton-manager.js +14 -5
  11. package/dist/cjs/query/errors/query-snapshot-incomplete-error.js +19 -0
  12. package/dist/cjs/query/grpc/grpc-contract-cache.js +484 -0
  13. package/dist/cjs/query/grpc/grpc-package-relation-reader.js +218 -0
  14. package/dist/cjs/query/grpc/grpc-query-client.js +249 -0
  15. package/dist/cjs/query/grpc/grpc-query-snapshot-reader.js +238 -0
  16. package/dist/cjs/query/grpc/grpc-query-value-mapper.js +204 -0
  17. package/dist/cjs/query/grpc/grpc-relation-mapper.js +794 -0
  18. package/dist/cjs/query/pqs/pqs-query-client.js +151 -582
  19. package/dist/cjs/query/pqs/pqs-relational-sql-compiler.js +138 -95
  20. package/dist/cjs/query/pqs/pqs-result-shape.js +28 -0
  21. package/dist/cjs/query/pqs/pqs-schema-profile.js +49 -48
  22. package/dist/cjs/query/pqs/pqs-sql-compiler.js +343 -289
  23. package/dist/cjs/query/pqs/pqs-sql-syntax.js +10 -0
  24. package/dist/cjs/services/command/command-service-client.js +16 -3
  25. package/dist/cjs/services/commands/command-payload-builder.js +1 -1
  26. package/dist/cjs/services/commands/command-submission-pipeline.js +21 -6
  27. package/dist/cjs/services/state/state-service-client.js +56 -0
  28. package/dist/cjs/testing/runtime/declarative-action-executor.js +3 -3
  29. package/dist/cjs/transports/grpc/grpc-transport.js +2 -2
  30. package/dist/cjs/transports/grpc/mappers/commands-mapper.js +6 -6
  31. package/dist/cjs/transports/grpc/mappers/interactive-command-mapper.js +1 -1
  32. package/dist/cjs/transports/json/json-transport.js +1 -1
  33. package/dist/cjs/transports/json/mappers/commands-mapper.js +3 -3
  34. package/dist/core/transports/transport.interface.d.ts +4 -4
  35. package/dist/core/types/prepared-command-submission.d.ts +3 -3
  36. package/dist/core/types/requests/{submit-command-request.d.ts → submit-commands-request.d.ts} +8 -4
  37. package/dist/core/types/requests/{submit-command-request.js → submit-commands-request.js} +8 -4
  38. package/dist/index.d.ts +5 -2
  39. package/dist/index.js +2 -1
  40. package/dist/query/canonical/in-memory-query-evaluator.d.ts +22 -0
  41. package/dist/query/canonical/in-memory-query-evaluator.js +287 -0
  42. package/dist/query/canonical/public-identity.d.ts +14 -0
  43. package/dist/query/canonical/public-identity.js +35 -0
  44. package/dist/query/canonical/query-ast.d.ts +104 -0
  45. package/dist/query/canonical/query-ast.js +1 -0
  46. package/dist/query/canonical/query-dataset.d.ts +63 -0
  47. package/dist/query/canonical/query-dataset.js +343 -0
  48. package/dist/query/canonical/query-normalizer.d.ts +10 -0
  49. package/dist/query/canonical/query-normalizer.js +646 -0
  50. package/dist/query/canonical/query-schema.d.ts +25 -0
  51. package/dist/query/canonical/query-schema.js +83 -0
  52. package/dist/query/canton-manager.js +14 -5
  53. package/dist/query/errors/query-snapshot-incomplete-error.d.ts +14 -0
  54. package/dist/query/errors/query-snapshot-incomplete-error.js +15 -0
  55. package/dist/query/grpc/grpc-contract-cache.d.ts +27 -0
  56. package/dist/query/grpc/grpc-contract-cache.js +479 -0
  57. package/dist/query/grpc/grpc-package-relation-reader.d.ts +43 -0
  58. package/dist/query/grpc/grpc-package-relation-reader.js +213 -0
  59. package/dist/query/grpc/grpc-query-client.d.ts +42 -0
  60. package/dist/query/grpc/grpc-query-client.js +245 -0
  61. package/dist/query/grpc/grpc-query-snapshot-reader.d.ts +33 -0
  62. package/dist/query/grpc/grpc-query-snapshot-reader.js +233 -0
  63. package/dist/query/grpc/grpc-query-value-mapper.d.ts +15 -0
  64. package/dist/query/grpc/grpc-query-value-mapper.js +195 -0
  65. package/dist/query/grpc/grpc-relation-mapper.d.ts +67 -0
  66. package/dist/query/grpc/grpc-relation-mapper.js +789 -0
  67. package/dist/query/pqs/pqs-query-client.d.ts +10 -20
  68. package/dist/query/pqs/pqs-query-client.js +154 -585
  69. package/dist/query/pqs/pqs-relational-sql-compiler.d.ts +9 -17
  70. package/dist/query/pqs/pqs-relational-sql-compiler.js +136 -95
  71. package/dist/query/pqs/pqs-result-shape.d.ts +25 -0
  72. package/dist/query/pqs/pqs-result-shape.js +25 -0
  73. package/dist/query/pqs/pqs-schema-profile.js +49 -48
  74. package/dist/query/pqs/pqs-sql-compiler.d.ts +18 -3
  75. package/dist/query/pqs/pqs-sql-compiler.js +337 -288
  76. package/dist/query/pqs/pqs-sql-syntax.d.ts +2 -0
  77. package/dist/query/pqs/pqs-sql-syntax.js +6 -0
  78. package/dist/query/query-client.d.ts +15 -0
  79. package/dist/services/command/command-service-client.d.ts +9 -4
  80. package/dist/services/command/command-service-client.js +16 -3
  81. package/dist/services/command-submission/command-submission-service-client.d.ts +2 -2
  82. package/dist/services/commands/command-payload-builder.d.ts +2 -2
  83. package/dist/services/commands/command-payload-builder.js +1 -1
  84. package/dist/services/commands/command-submission-pipeline.d.ts +5 -4
  85. package/dist/services/commands/command-submission-pipeline.js +21 -6
  86. package/dist/services/state/state-service-client.d.ts +4 -0
  87. package/dist/services/state/state-service-client.js +56 -0
  88. package/dist/testing/runtime/declarative-action-executor.js +3 -3
  89. package/dist/transports/grpc/grpc-transport.d.ts +4 -4
  90. package/dist/transports/grpc/grpc-transport.js +3 -3
  91. package/dist/transports/grpc/mappers/commands-mapper.d.ts +3 -3
  92. package/dist/transports/grpc/mappers/commands-mapper.js +4 -4
  93. package/dist/transports/grpc/mappers/interactive-command-mapper.d.ts +3 -3
  94. package/dist/transports/grpc/mappers/interactive-command-mapper.js +1 -1
  95. package/dist/transports/json/json-transport.d.ts +2 -2
  96. package/dist/transports/json/json-transport.js +2 -2
  97. package/dist/transports/json/mappers/commands-mapper.d.ts +2 -2
  98. package/dist/transports/json/mappers/commands-mapper.js +2 -2
  99. package/package.json +8 -3
  100. package/dist/cjs/query/grpc/grpc-contract-query-client.js +0 -178
  101. package/dist/query/grpc/grpc-contract-query-client.d.ts +0 -33
  102. package/dist/query/grpc/grpc-contract-query-client.js +0 -174
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.queryRelationMetadata = exports.queryRelationEdges = exports.queryRelations = void 0;
4
+ exports.queryRelations = [
5
+ "contracts",
6
+ "contractTypes",
7
+ "events",
8
+ "exercises",
9
+ "exerciseTypes",
10
+ "packages",
11
+ "transactions",
12
+ "watermark",
13
+ ];
14
+ exports.queryRelationEdges = {
15
+ contracts: {
16
+ contractType: { target: "contractTypes", cardinality: "one", nullable: false },
17
+ createdTransaction: { target: "transactions", cardinality: "one", nullable: false },
18
+ archivedTransaction: { target: "transactions", cardinality: "one", nullable: true },
19
+ exercises: { target: "exercises", cardinality: "many", nullable: false },
20
+ },
21
+ contractTypes: {
22
+ contracts: { target: "contracts", cardinality: "many", nullable: false },
23
+ exercises: { target: "exercises", cardinality: "many", nullable: false },
24
+ },
25
+ events: {
26
+ transaction: { target: "transactions", cardinality: "one", nullable: false },
27
+ exercises: { target: "exercises", cardinality: "many", nullable: false },
28
+ },
29
+ exercises: {
30
+ exerciseType: { target: "exerciseTypes", cardinality: "one", nullable: false },
31
+ contractType: { target: "contractTypes", cardinality: "one", nullable: false },
32
+ event: { target: "events", cardinality: "one", nullable: true },
33
+ transaction: { target: "transactions", cardinality: "one", nullable: true },
34
+ package: { target: "packages", cardinality: "one", nullable: false },
35
+ contract: { target: "contracts", cardinality: "one", nullable: true },
36
+ },
37
+ exerciseTypes: { exercises: { target: "exercises", cardinality: "many", nullable: false } },
38
+ packages: { exercises: { target: "exercises", cardinality: "many", nullable: false } },
39
+ transactions: {
40
+ events: { target: "events", cardinality: "many", nullable: false },
41
+ createdContracts: { target: "contracts", cardinality: "many", nullable: false },
42
+ archivedContracts: { target: "contracts", cardinality: "many", nullable: false },
43
+ exercises: { target: "exercises", cardinality: "many", nullable: false },
44
+ },
45
+ };
46
+ exports.queryRelationMetadata = {
47
+ contracts: {
48
+ fields: ["contractId", "templateId", "packageId", "payload", "witnesses", "createdEventOffset", "createdAt", "archivedEventOffset", "archivedAt", "active"],
49
+ uniqueKeys: [["contractId"]], stableOrder: ["contractId"],
50
+ orderFields: ["contractId", "createdEventOffset", "createdAt", "archivedEventOffset", "archivedAt"],
51
+ groupFields: ["contractId", "createdEventOffset", "createdAt", "archivedEventOffset", "archivedAt", "witnesses"],
52
+ numericFields: ["createdEventOffset", "archivedEventOffset"], arrayFields: ["witnesses"], dateFields: ["createdAt", "archivedAt"], binaryFields: [], booleanFields: ["active"], nullableFields: ["packageId", "createdAt", "archivedEventOffset", "archivedAt"], stringFields: ["contractId", "packageId"], jsonFields: ["payload"], bucketFields: [],
53
+ },
54
+ contractTypes: {
55
+ fields: ["pk", "payloadType", "aliases", "packageName", "moduleName", "entityName", "templateFqn"],
56
+ uniqueKeys: [["pk"]], stableOrder: ["pk"], orderFields: ["pk", "payloadType", "aliases", "packageName", "moduleName", "entityName", "templateFqn"], groupFields: ["pk", "payloadType", "aliases", "packageName", "moduleName", "entityName", "templateFqn"],
57
+ numericFields: ["pk"], arrayFields: ["aliases"], dateFields: [], binaryFields: [], booleanFields: [], nullableFields: [], stringFields: ["payloadType", "packageName", "moduleName", "entityName", "templateFqn"], jsonFields: [], bucketFields: [],
58
+ },
59
+ events: {
60
+ fields: ["pk", "txIx", "eventId", "type"], uniqueKeys: [["pk"]], stableOrder: ["pk"], orderFields: ["pk", "txIx", "eventId", "type"], groupFields: ["pk", "txIx", "eventId", "type"],
61
+ numericFields: ["pk", "txIx"], arrayFields: [], dateFields: [], binaryFields: [], booleanFields: [], nullableFields: [], stringFields: ["eventId", "type"], jsonFields: [], bucketFields: [],
62
+ },
63
+ exercises: {
64
+ fields: ["tpePk", "contractTpePk", "exerciseEventPk", "exercisedAtIx", "contractId", "argument", "result", "redactionId", "packagePk", "controllers", "lastDescendantNodeId", "witnesses"],
65
+ uniqueKeys: [], stableOrder: ["tpePk", "contractTpePk", "exerciseEventPk", "contractId"], orderFields: ["tpePk", "contractTpePk", "exerciseEventPk", "exercisedAtIx", "contractId", "argument", "result", "redactionId", "packagePk", "controllers", "lastDescendantNodeId", "witnesses"], groupFields: ["tpePk", "contractTpePk", "exerciseEventPk", "exercisedAtIx", "contractId", "argument", "result", "redactionId", "packagePk", "controllers", "lastDescendantNodeId", "witnesses"],
66
+ numericFields: ["tpePk", "contractTpePk", "exerciseEventPk", "exercisedAtIx", "packagePk", "lastDescendantNodeId"], arrayFields: ["controllers", "witnesses"], dateFields: [], binaryFields: [], booleanFields: [], nullableFields: ["exerciseEventPk", "exercisedAtIx", "redactionId"], stringFields: ["contractId", "redactionId"], jsonFields: ["argument", "result"], bucketFields: [],
67
+ },
68
+ exerciseTypes: {
69
+ fields: ["pk", "choice", "consuming", "aliases", "packageName", "moduleName", "entityName", "templateFqn", "choiceFqn"],
70
+ uniqueKeys: [["pk"]], stableOrder: ["pk"], orderFields: ["pk", "choice", "consuming", "aliases", "packageName", "moduleName", "entityName", "templateFqn", "choiceFqn"], groupFields: ["pk", "choice", "consuming", "aliases", "packageName", "moduleName", "entityName", "templateFqn", "choiceFqn"],
71
+ numericFields: ["pk"], arrayFields: ["aliases"], dateFields: [], binaryFields: [], booleanFields: ["consuming"], nullableFields: [], stringFields: ["choice", "packageName", "moduleName", "entityName", "templateFqn", "choiceFqn"], jsonFields: [], bucketFields: [],
72
+ },
73
+ packages: {
74
+ fields: ["pk", "name", "version", "id"], uniqueKeys: [["pk"], ["id"]], stableOrder: ["pk"], orderFields: ["pk", "name", "version", "id"], groupFields: ["pk", "name", "version", "id"],
75
+ numericFields: ["pk"], arrayFields: [], dateFields: [], binaryFields: [], booleanFields: [], nullableFields: [], stringFields: ["name", "version", "id"], jsonFields: [], bucketFields: [],
76
+ },
77
+ transactions: {
78
+ fields: ["ix", "offset", "transactionId", "effectiveAt", "workflowId", "domainId", "traceContext", "externalTransactionHash", "paidTrafficCost"],
79
+ uniqueKeys: [["ix"], ["offset"]], stableOrder: ["ix"], orderFields: ["ix", "offset", "transactionId", "effectiveAt", "workflowId", "domainId", "traceContext", "externalTransactionHash", "paidTrafficCost"], groupFields: ["ix", "offset", "transactionId", "effectiveAt", "workflowId", "domainId", "traceContext", "externalTransactionHash", "paidTrafficCost"],
80
+ numericFields: ["ix", "offset", "paidTrafficCost"], arrayFields: [], dateFields: ["effectiveAt"], binaryFields: ["externalTransactionHash"], booleanFields: [], nullableFields: ["transactionId", "effectiveAt", "workflowId", "domainId", "traceContext", "externalTransactionHash", "paidTrafficCost"], stringFields: ["transactionId", "workflowId", "domainId"], jsonFields: ["traceContext"], bucketFields: ["effectiveAt"],
81
+ },
82
+ watermark: {
83
+ fields: ["singleton", "ix", "offset", "instanceId"], uniqueKeys: [["singleton"]], stableOrder: ["singleton"], orderFields: ["singleton", "ix", "offset", "instanceId"], groupFields: ["singleton", "ix", "offset", "instanceId"],
84
+ numericFields: ["ix", "offset"], arrayFields: [], dateFields: [], binaryFields: [], booleanFields: ["singleton"], nullableFields: ["ix", "offset", "instanceId"], stringFields: ["instanceId"], jsonFields: [], bucketFields: [],
85
+ },
86
+ };
@@ -4,7 +4,8 @@ exports.CantonManager = void 0;
4
4
  const canton_client_js_1 = require("../client/canton-client.js");
5
5
  const transport_kind_js_1 = require("../core/types/transport-kind.js");
6
6
  const validation_error_js_1 = require("../core/errors/validation-error.js");
7
- const grpc_contract_query_client_js_1 = require("./grpc/grpc-contract-query-client.js");
7
+ const grpc_query_client_js_1 = require("./grpc/grpc-query-client.js");
8
+ const grpc_contract_cache_js_1 = require("./grpc/grpc-contract-cache.js");
8
9
  const pqs_pool_js_1 = require("./pqs/pqs-pool.js");
9
10
  const pqs_query_client_js_1 = require("./pqs/pqs-query-client.js");
10
11
  const pqs_schema_profile_js_1 = require("./pqs/pqs-schema-profile.js");
@@ -18,12 +19,12 @@ class CantonManager {
18
19
  if (options.grpc.transportKind !== transport_kind_js_1.TransportKind.grpc) {
19
20
  throw new validation_error_js_1.ValidationError("CantonManager requires grpc transport for writes.");
20
21
  }
21
- else if (options.querySource === query_source_js_1.QuerySource.grpc && options.pqs !== undefined) {
22
- throw new validation_error_js_1.ValidationError("PQS options require QuerySource.pqs.");
23
- }
24
22
  else if (options.querySource === query_source_js_1.QuerySource.pqs && options.pqs === undefined) {
25
23
  throw new validation_error_js_1.ValidationError("QuerySource.pqs requires PQS options.");
26
24
  }
25
+ else if (options.cache !== undefined && (!Number.isFinite(options.cache.ttlMs) || options.cache.ttlMs <= 0)) {
26
+ throw new validation_error_js_1.ValidationError("CantonManager cache ttlMs must be a positive finite number.");
27
+ }
27
28
  this.grpc = new canton_client_js_1.CantonClient(options.grpc);
28
29
  if (options.querySource === query_source_js_1.QuerySource.pqs) {
29
30
  this.pqsPool = pqs_pool_js_1.PqsPool.create(options.pqs.connectionString);
@@ -31,7 +32,15 @@ class CantonManager {
31
32
  this.query = new pqs_query_client_js_1.PqsQueryClient(this.pqsPool.pool, profile, (0, pqs_schema_profile_js_1.validatePqsSchemaAsync)(this.pqsPool.pool, profile));
32
33
  }
33
34
  else {
34
- this.query = new grpc_contract_query_client_js_1.GrpcContractQueryClient(this.grpc.stateService, options.cache?.store, options.cache?.ttlMs, options.grpc.ledgerEndpoint ?? "ledger");
35
+ this.query = new grpc_query_client_js_1.GrpcQueryClient({
36
+ stateService: this.grpc.stateService,
37
+ updateService: this.grpc.updateService,
38
+ packageService: this.grpc.packageService,
39
+ endpointScope: options.grpc.ledgerEndpoint ?? "ledger",
40
+ contractCache: options.cache === undefined
41
+ ? undefined
42
+ : new grpc_contract_cache_js_1.GrpcContractCache(this.grpc.stateService, options.cache.store, options.cache.ttlMs, options.grpc.ledgerEndpoint ?? "ledger"),
43
+ });
35
44
  }
36
45
  }
37
46
  async disposeAsync() {
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QuerySnapshotIncompleteError = void 0;
4
+ const canton_error_js_1 = require("../../core/errors/canton-error.js");
5
+ class QuerySnapshotIncompleteError extends canton_error_js_1.CantonError {
6
+ beginExclusive;
7
+ endInclusive;
8
+ activeAtOffset;
9
+ reason;
10
+ constructor(init) {
11
+ super(`gRPC query snapshot is incomplete: ${init.reason}.`);
12
+ this.beginExclusive = init.beginExclusive;
13
+ this.endInclusive = init.endInclusive;
14
+ this.activeAtOffset = init.activeAtOffset;
15
+ this.reason = init.reason;
16
+ Object.freeze(this);
17
+ }
18
+ }
19
+ exports.QuerySnapshotIncompleteError = QuerySnapshotIncompleteError;
@@ -0,0 +1,484 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GrpcContractCache = void 0;
4
+ exports.normalizeParties = normalizeParties;
5
+ const types_1 = require("node:util/types");
6
+ const validation_error_js_1 = require("../../core/errors/validation-error.js");
7
+ const contracts_mapper_js_1 = require("../../transports/grpc/mappers/contracts-mapper.js");
8
+ const query_source_js_1 = require("../query-source.js");
9
+ const grpc_relation_mapper_js_1 = require("./grpc-relation-mapper.js");
10
+ const grpc_query_snapshot_reader_js_1 = require("./grpc-query-snapshot-reader.js");
11
+ class GrpcContractCache {
12
+ stateService;
13
+ store;
14
+ ttlMs;
15
+ endpointScope;
16
+ now;
17
+ inflight = new Map();
18
+ constructor(stateService, store, ttlMs, endpointScope, now = Date.now) {
19
+ this.stateService = stateService;
20
+ this.store = store;
21
+ this.ttlMs = ttlMs;
22
+ this.endpointScope = endpointScope;
23
+ this.now = now;
24
+ if (!Number.isFinite(ttlMs) || ttlMs <= 0) {
25
+ throw new validation_error_js_1.ValidationError("Contract cache ttlMs must be a positive finite number.");
26
+ }
27
+ }
28
+ async cacheContracts(args) {
29
+ const parties = normalizeParties(args);
30
+ const key = cacheKey(this.endpointScope, parties);
31
+ const current = this.inflight.get(key);
32
+ if (current !== undefined) {
33
+ return current;
34
+ }
35
+ const promise = this.populateAsync(parties, key);
36
+ this.inflight.set(key, promise);
37
+ void promise.then(() => this.clearInflight(key, promise), () => this.clearInflight(key, promise));
38
+ return promise;
39
+ }
40
+ async readContractsAsync(args) {
41
+ const snapshot = await this.readSnapshotAsync(args);
42
+ return snapshot?.contracts;
43
+ }
44
+ async readSnapshotAsync(args) {
45
+ const parties = normalizeParties(args);
46
+ const cached = await this.store.getAsync(cacheKey(this.endpointScope, parties));
47
+ const nowEpochMs = currentEpochMs(this.now);
48
+ const snapshot = asCompatibleSnapshot(cached, this.endpointScope, parties, nowEpochMs);
49
+ if (snapshot === undefined) {
50
+ return undefined;
51
+ }
52
+ return Object.freeze({ activeAtOffset: snapshot.activeAtOffset, contracts: snapshot.contracts });
53
+ }
54
+ async invalidateContractsCache(args) {
55
+ const parties = normalizeParties(args);
56
+ const key = cacheKey(this.endpointScope, parties);
57
+ try {
58
+ await this.inflight.get(key);
59
+ }
60
+ catch {
61
+ // A failed prewarm leaves no completed snapshot to preserve.
62
+ }
63
+ await this.store.deleteAsync(key);
64
+ }
65
+ async populateAsync(parties, key) {
66
+ const activeContracts = [];
67
+ const seenPageTokens = new Set();
68
+ let activeAtOffset;
69
+ let pageToken;
70
+ do {
71
+ const page = materializeActiveContractsPage(await this.stateService.getActiveContractsPageAsync((0, contracts_mapper_js_1.mapGrpcQueryContractsRequest)(parties === undefined
72
+ ? { allParties: true, activeAtOffset, pageToken }
73
+ : { parties, activeAtOffset, pageToken })));
74
+ if (activeAtOffset === undefined) {
75
+ activeAtOffset = page.activeAtOffset;
76
+ }
77
+ else if (activeAtOffset !== page.activeAtOffset) {
78
+ throw new Error("Active-contracts response activeAtOffset changed during traversal.");
79
+ }
80
+ activeContracts.push(...page.activeContracts);
81
+ pageToken = page.nextPageToken;
82
+ if (pageToken !== undefined && pageToken.length > 0) {
83
+ const tokenKey = Array.from(pageToken).join(",");
84
+ if (seenPageTokens.has(tokenKey)) {
85
+ throw new Error("Active-contracts response repeated a page token.");
86
+ }
87
+ seenPageTokens.add(tokenKey);
88
+ }
89
+ } while (pageToken !== undefined && pageToken.length > 0);
90
+ const contracts = (0, grpc_relation_mapper_js_1.mapGrpcQueryRelationFragment)([], activeContracts).contracts;
91
+ const expiresAtEpochMs = effectiveExpiryEpochMs(this.now, this.ttlMs);
92
+ const result = {
93
+ source: query_source_js_1.QuerySource.grpc,
94
+ cached: true,
95
+ activeAtOffset: activeAtOffset,
96
+ contractCount: contracts.length,
97
+ expiresAt: new Date(expiresAtEpochMs),
98
+ };
99
+ const snapshot = {
100
+ version: 1,
101
+ endpointScope: this.endpointScope,
102
+ parties,
103
+ activeAtOffset: activeAtOffset,
104
+ expiresAtEpochMs,
105
+ contracts: copyRows(contracts),
106
+ };
107
+ await this.store.setAsync(key, snapshot, this.ttlMs);
108
+ return result;
109
+ }
110
+ clearInflight(key, promise) {
111
+ if (this.inflight.get(key) === promise) {
112
+ this.inflight.delete(key);
113
+ }
114
+ }
115
+ }
116
+ exports.GrpcContractCache = GrpcContractCache;
117
+ function normalizeParties(args) {
118
+ try {
119
+ if (args === undefined) {
120
+ return undefined;
121
+ }
122
+ const candidate = args.parties;
123
+ if (candidate === undefined) {
124
+ return undefined;
125
+ }
126
+ else if (!Array.isArray(candidate)) {
127
+ throw new validation_error_js_1.ValidationError("Contract cache parties must contain non-empty strings.");
128
+ }
129
+ const values = materializeIndexedArray(candidate);
130
+ if (values === undefined || values.length === 0) {
131
+ throw new validation_error_js_1.ValidationError("Contract cache parties must contain non-empty strings.");
132
+ }
133
+ const parties = values.map((party) => {
134
+ if (typeof party !== "string" || party.trim().length === 0) {
135
+ throw new validation_error_js_1.ValidationError("Contract cache parties must contain non-empty strings.");
136
+ }
137
+ return party;
138
+ });
139
+ return Object.freeze([...new Set(parties)].sort());
140
+ }
141
+ catch (error) {
142
+ if (isValidationError(error)) {
143
+ throw error;
144
+ }
145
+ throw new validation_error_js_1.ValidationError("Contract cache parties must be a non-empty array of strings when provided.");
146
+ }
147
+ }
148
+ function cacheKey(endpointScope, parties) {
149
+ return `grpc-contract-cache:v1:${JSON.stringify([endpointScope, parties])}`;
150
+ }
151
+ function asCompatibleSnapshot(value, endpointScope, parties, nowEpochMs) {
152
+ try {
153
+ if (value === null || typeof value !== "object") {
154
+ return undefined;
155
+ }
156
+ const candidate = value;
157
+ const version = candidate.version;
158
+ const storedEndpointScope = candidate.endpointScope;
159
+ const rawParties = candidate.parties;
160
+ const storedParties = rawParties === undefined ? undefined : materializeStringArray(rawParties);
161
+ const activeAtOffset = candidate.activeAtOffset;
162
+ const expiresAtEpochMs = candidate.expiresAtEpochMs;
163
+ const contracts = materializeContractRows(candidate.contracts);
164
+ if (version !== 1
165
+ || storedEndpointScope !== endpointScope
166
+ || (rawParties !== undefined && storedParties === undefined)
167
+ || !sameParties(storedParties, parties)
168
+ || typeof nowEpochMs !== "number"
169
+ || !Number.isFinite(nowEpochMs)
170
+ || !Number.isFinite(new Date(nowEpochMs).getTime())
171
+ || !(0, grpc_query_snapshot_reader_js_1.isCanonicalGrpcOffset)(activeAtOffset)
172
+ || typeof expiresAtEpochMs !== "number"
173
+ || !Number.isFinite(expiresAtEpochMs)
174
+ || !Number.isFinite(new Date(expiresAtEpochMs).getTime())
175
+ || expiresAtEpochMs <= nowEpochMs
176
+ || contracts === undefined) {
177
+ return undefined;
178
+ }
179
+ return {
180
+ version,
181
+ endpointScope: storedEndpointScope,
182
+ parties: storedParties,
183
+ activeAtOffset,
184
+ expiresAtEpochMs,
185
+ contracts,
186
+ };
187
+ }
188
+ catch {
189
+ return undefined;
190
+ }
191
+ }
192
+ function sameParties(left, right) {
193
+ return left === undefined
194
+ ? right === undefined
195
+ : Array.isArray(left)
196
+ && right !== undefined
197
+ && left.length === right.length
198
+ && left.every((party, index) => typeof party === "string" && party === right[index]);
199
+ }
200
+ function materializeActiveContractsPage(value) {
201
+ try {
202
+ if (value === null || typeof value !== "object") {
203
+ throw new Error("Active-contracts response is invalid.");
204
+ }
205
+ const candidate = value;
206
+ const activeAtOffset = candidate.activeAtOffset;
207
+ if (!(0, grpc_query_snapshot_reader_js_1.isCanonicalGrpcOffset)(activeAtOffset)) {
208
+ throw new Error("Active-contracts response is missing activeAtOffset.");
209
+ }
210
+ const activeContracts = materializeIndexedValues(candidate.activeContracts, materializeActiveContractResponse);
211
+ if (activeContracts === undefined) {
212
+ throw new Error("Active-contracts response activeContracts is invalid.");
213
+ }
214
+ const nextPageToken = materializePageToken(candidate.nextPageToken);
215
+ return {
216
+ activeAtOffset,
217
+ activeContracts,
218
+ nextPageToken,
219
+ };
220
+ }
221
+ catch (error) {
222
+ if (isError(error)) {
223
+ throw error;
224
+ }
225
+ throw new Error("Active-contracts response is invalid.");
226
+ }
227
+ }
228
+ function materializeActiveContractResponse(value) {
229
+ const copy = copyValue(value);
230
+ if (copy === null || typeof copy !== "object") {
231
+ throw new Error("Active-contracts response contains an invalid contract entry.");
232
+ }
233
+ return copy;
234
+ }
235
+ function materializePageToken(value) {
236
+ if (value === undefined) {
237
+ return undefined;
238
+ }
239
+ else if ((0, types_1.isProxy)(value) || !isUint8Array(value)) {
240
+ throw new Error("Active-contracts response nextPageToken is invalid.");
241
+ }
242
+ try {
243
+ return new Uint8Array(value);
244
+ }
245
+ catch {
246
+ throw new Error("Active-contracts response nextPageToken is invalid.");
247
+ }
248
+ }
249
+ function materializeContractRows(value) {
250
+ const rows = materializeIndexedValues(value, materializeContractRow);
251
+ if (rows === undefined) {
252
+ return undefined;
253
+ }
254
+ return rows.every((row) => row !== undefined) ? rows : undefined;
255
+ }
256
+ function materializeContractRow(value) {
257
+ if (value === null || typeof value !== "object") {
258
+ return undefined;
259
+ }
260
+ const candidate = value;
261
+ const contractId = candidate.contractId;
262
+ const templateId = materializeTemplateId(candidate.templateId);
263
+ const packageId = candidate.packageId;
264
+ const payload = copyValue(candidate.payload);
265
+ const witnesses = materializeStringArray(candidate.witnesses);
266
+ const createdEventOffset = candidate.createdEventOffset;
267
+ const createdAt = materializeOptionalDate(candidate.createdAt);
268
+ const archivedEventOffset = candidate.archivedEventOffset;
269
+ const archivedAt = candidate.archivedAt;
270
+ const active = candidate.active;
271
+ if (typeof contractId !== "string"
272
+ || templateId === undefined
273
+ || (typeof packageId !== "string" && packageId !== null)
274
+ || witnesses === undefined
275
+ || typeof createdEventOffset !== "string"
276
+ || createdAt === undefined
277
+ || archivedEventOffset !== null
278
+ || archivedAt !== null
279
+ || active !== true) {
280
+ return undefined;
281
+ }
282
+ return {
283
+ contractId,
284
+ templateId,
285
+ packageId,
286
+ payload,
287
+ witnesses,
288
+ createdEventOffset,
289
+ createdAt,
290
+ archivedEventOffset,
291
+ archivedAt,
292
+ active,
293
+ };
294
+ }
295
+ function materializeTemplateId(value) {
296
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
297
+ return undefined;
298
+ }
299
+ const candidate = value;
300
+ const packageId = candidate.packageId;
301
+ const moduleName = candidate.moduleName;
302
+ const entityName = candidate.entityName;
303
+ return typeof packageId === "string" && typeof moduleName === "string" && typeof entityName === "string"
304
+ ? { packageId, moduleName, entityName }
305
+ : undefined;
306
+ }
307
+ function materializeStringArray(value) {
308
+ const values = materializeIndexedArray(value);
309
+ if (values === undefined) {
310
+ return undefined;
311
+ }
312
+ return values.every((entry) => typeof entry === "string") ? values : undefined;
313
+ }
314
+ function materializeIndexedArray(value) {
315
+ return materializeIndexedValues(value, (entry) => entry);
316
+ }
317
+ function materializeIndexedValues(value, materialize) {
318
+ if ((0, types_1.isProxy)(value) || !Array.isArray(value)) {
319
+ return undefined;
320
+ }
321
+ const length = value.length;
322
+ if (!Number.isSafeInteger(length) || length < 0) {
323
+ return undefined;
324
+ }
325
+ const values = [];
326
+ for (let index = 0; index < length; index += 1) {
327
+ values.push(materialize(value[index]));
328
+ }
329
+ return values;
330
+ }
331
+ function materializeOptionalDate(value) {
332
+ if (value === null) {
333
+ return null;
334
+ }
335
+ else if (!isDate(value)) {
336
+ return undefined;
337
+ }
338
+ const epochMs = value.getTime();
339
+ return Number.isFinite(epochMs) ? new Date(epochMs) : undefined;
340
+ }
341
+ function copyRows(rows) {
342
+ return rows.map((row) => ({
343
+ ...row,
344
+ templateId: { ...row.templateId },
345
+ payload: copyValue(row.payload),
346
+ witnesses: [...row.witnesses],
347
+ createdAt: row.createdAt === null ? null : new Date(row.createdAt.getTime()),
348
+ archivedAt: row.archivedAt === null ? null : new Date(row.archivedAt.getTime()),
349
+ }));
350
+ }
351
+ function copyValue(value) {
352
+ if (value === undefined || value === null || typeof value !== "object") {
353
+ return value;
354
+ }
355
+ const copy = structuredClone(value);
356
+ if (containsSharedMemory(copy, new Set())) {
357
+ throw new Error("Contract payload must not contain shared memory.");
358
+ }
359
+ return copy;
360
+ }
361
+ function containsSharedMemory(value, seen) {
362
+ if (value === null || typeof value !== "object") {
363
+ return false;
364
+ }
365
+ else if (isSharedArrayBuffer(value)) {
366
+ return true;
367
+ }
368
+ else if (seen.has(value)) {
369
+ return false;
370
+ }
371
+ seen.add(value);
372
+ if (ArrayBuffer.isView(value)) {
373
+ return isSharedArrayBuffer(value.buffer);
374
+ }
375
+ else if (isMap(value)) {
376
+ for (const [key, entry] of value) {
377
+ if (containsSharedMemory(key, seen) || containsSharedMemory(entry, seen)) {
378
+ return true;
379
+ }
380
+ }
381
+ return false;
382
+ }
383
+ else if (isSet(value)) {
384
+ for (const entry of value) {
385
+ if (containsSharedMemory(entry, seen)) {
386
+ return true;
387
+ }
388
+ }
389
+ return false;
390
+ }
391
+ return Reflect.ownKeys(value).some((key) => containsSharedMemory(Reflect.get(value, key), seen));
392
+ }
393
+ function effectiveExpiryEpochMs(now, ttlMs) {
394
+ try {
395
+ const nowEpochMs = currentEpochMs(now);
396
+ const expiresAtEpochMs = nowEpochMs + ttlMs;
397
+ if (typeof nowEpochMs !== "number"
398
+ || !Number.isFinite(nowEpochMs)
399
+ || !Number.isFinite(expiresAtEpochMs)
400
+ || !Number.isFinite(new Date(expiresAtEpochMs).getTime())) {
401
+ throw new validation_error_js_1.ValidationError("Contract cache expiry must be a finite valid date.");
402
+ }
403
+ return expiresAtEpochMs;
404
+ }
405
+ catch (error) {
406
+ if (isValidationError(error)) {
407
+ throw error;
408
+ }
409
+ throw new validation_error_js_1.ValidationError("Contract cache expiry must be a finite valid date.");
410
+ }
411
+ }
412
+ function currentEpochMs(now) {
413
+ try {
414
+ const nowEpochMs = now();
415
+ if (typeof nowEpochMs !== "number"
416
+ || !Number.isFinite(nowEpochMs)
417
+ || !Number.isFinite(new Date(nowEpochMs).getTime())) {
418
+ throw new validation_error_js_1.ValidationError("Contract cache clock must return a finite valid date.");
419
+ }
420
+ return nowEpochMs;
421
+ }
422
+ catch (error) {
423
+ if (isValidationError(error)) {
424
+ throw error;
425
+ }
426
+ throw new validation_error_js_1.ValidationError("Contract cache clock must return a finite valid date.");
427
+ }
428
+ }
429
+ function isValidationError(value) {
430
+ try {
431
+ return value instanceof validation_error_js_1.ValidationError;
432
+ }
433
+ catch {
434
+ return false;
435
+ }
436
+ }
437
+ function isError(value) {
438
+ try {
439
+ return value instanceof Error;
440
+ }
441
+ catch {
442
+ return false;
443
+ }
444
+ }
445
+ function isUint8Array(value) {
446
+ try {
447
+ return value instanceof Uint8Array;
448
+ }
449
+ catch {
450
+ return false;
451
+ }
452
+ }
453
+ function isDate(value) {
454
+ try {
455
+ return value instanceof Date;
456
+ }
457
+ catch {
458
+ return false;
459
+ }
460
+ }
461
+ function isSharedArrayBuffer(value) {
462
+ try {
463
+ return typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer;
464
+ }
465
+ catch {
466
+ return false;
467
+ }
468
+ }
469
+ function isMap(value) {
470
+ try {
471
+ return value instanceof Map;
472
+ }
473
+ catch {
474
+ return false;
475
+ }
476
+ }
477
+ function isSet(value) {
478
+ try {
479
+ return value instanceof Set;
480
+ }
481
+ catch {
482
+ return false;
483
+ }
484
+ }