@distrohelena/canton-typescript-sdk 0.1.36 → 0.1.38

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 (116) hide show
  1. package/README.md +143 -34
  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 +657 -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/testing/runtime/declarative-action-executor.js +3 -3
  28. package/dist/cjs/transports/grpc/grpc-transport.js +2 -2
  29. package/dist/cjs/transports/grpc/mappers/commands-mapper.js +6 -6
  30. package/dist/cjs/transports/grpc/mappers/interactive-command-mapper.js +1 -1
  31. package/dist/cjs/transports/json/json-transport.js +1 -1
  32. package/dist/cjs/transports/json/mappers/commands-mapper.js +3 -3
  33. package/dist/core/transports/transport.interface.d.ts +4 -4
  34. package/dist/core/types/prepared-command-submission.d.ts +3 -3
  35. package/dist/core/types/requests/{submit-command-request.d.ts → submit-commands-request.d.ts} +8 -4
  36. package/dist/core/types/requests/{submit-command-request.js → submit-commands-request.js} +8 -4
  37. package/dist/index.d.ts +5 -2
  38. package/dist/index.js +2 -1
  39. package/dist/query/canonical/in-memory-query-evaluator.d.ts +22 -0
  40. package/dist/query/canonical/in-memory-query-evaluator.js +287 -0
  41. package/dist/query/canonical/public-identity.d.ts +14 -0
  42. package/dist/query/canonical/public-identity.js +35 -0
  43. package/dist/query/canonical/query-ast.d.ts +104 -0
  44. package/dist/query/canonical/query-ast.js +1 -0
  45. package/dist/query/canonical/query-dataset.d.ts +63 -0
  46. package/dist/query/canonical/query-dataset.js +343 -0
  47. package/dist/query/canonical/query-normalizer.d.ts +10 -0
  48. package/dist/query/canonical/query-normalizer.js +648 -0
  49. package/dist/query/canonical/query-schema.d.ts +25 -0
  50. package/dist/query/canonical/query-schema.js +83 -0
  51. package/dist/query/canton-manager.js +14 -5
  52. package/dist/query/errors/query-snapshot-incomplete-error.d.ts +14 -0
  53. package/dist/query/errors/query-snapshot-incomplete-error.js +15 -0
  54. package/dist/query/grpc/grpc-contract-cache.d.ts +27 -0
  55. package/dist/query/grpc/grpc-contract-cache.js +479 -0
  56. package/dist/query/grpc/grpc-package-relation-reader.d.ts +43 -0
  57. package/dist/query/grpc/grpc-package-relation-reader.js +213 -0
  58. package/dist/query/grpc/grpc-query-client.d.ts +42 -0
  59. package/dist/query/grpc/grpc-query-client.js +245 -0
  60. package/dist/query/grpc/grpc-query-snapshot-reader.d.ts +33 -0
  61. package/dist/query/grpc/grpc-query-snapshot-reader.js +233 -0
  62. package/dist/query/grpc/grpc-query-value-mapper.d.ts +15 -0
  63. package/dist/query/grpc/grpc-query-value-mapper.js +195 -0
  64. package/dist/query/grpc/grpc-relation-mapper.d.ts +67 -0
  65. package/dist/query/grpc/grpc-relation-mapper.js +789 -0
  66. package/dist/query/model-types.d.ts +2 -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 +16 -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/testing/runtime/declarative-action-executor.js +3 -3
  87. package/dist/transports/grpc/grpc-transport.d.ts +4 -4
  88. package/dist/transports/grpc/grpc-transport.js +3 -3
  89. package/dist/transports/grpc/mappers/commands-mapper.d.ts +3 -3
  90. package/dist/transports/grpc/mappers/commands-mapper.js +4 -4
  91. package/dist/transports/grpc/mappers/interactive-command-mapper.d.ts +3 -3
  92. package/dist/transports/grpc/mappers/interactive-command-mapper.js +1 -1
  93. package/dist/transports/json/json-transport.d.ts +2 -2
  94. package/dist/transports/json/json-transport.js +2 -2
  95. package/dist/transports/json/mappers/commands-mapper.d.ts +2 -2
  96. package/dist/transports/json/mappers/commands-mapper.js +2 -2
  97. package/node/start-local-splice-0.6.12.sh +6 -0
  98. package/node/start-local-splice-0.6.13.sh +6 -0
  99. package/node/start-local-splice-0.6.14.sh +6 -0
  100. package/node/start-local-splice-0.7.0.sh +6 -0
  101. package/node/stop-local-splice-0.6.12.sh +6 -0
  102. package/node/stop-local-splice-0.6.13.sh +6 -0
  103. package/node/stop-local-splice-0.6.14.sh +6 -0
  104. package/node/stop-local-splice-0.7.0.sh +6 -0
  105. package/node/test-start-local-splice-0.6.12.sh +28 -0
  106. package/node/test-start-local-splice-0.6.13.sh +28 -0
  107. package/node/test-start-local-splice-0.6.14.sh +28 -0
  108. package/node/test-start-local-splice-0.7.0.sh +28 -0
  109. package/node/test-stop-local-splice-0.6.12.sh +28 -0
  110. package/node/test-stop-local-splice-0.6.13.sh +28 -0
  111. package/node/test-stop-local-splice-0.6.14.sh +28 -0
  112. package/node/test-stop-local-splice-0.7.0.sh +28 -0
  113. package/package.json +29 -4
  114. package/dist/cjs/query/grpc/grpc-contract-query-client.js +0 -178
  115. package/dist/query/grpc/grpc-contract-query-client.d.ts +0 -33
  116. package/dist/query/grpc/grpc-contract-query-client.js +0 -174
@@ -0,0 +1,789 @@
1
+ import { ValidationError } from "../../core/errors/validation-error.js";
2
+ import { createQueryDataset, immutableQueryValue } from "../canonical/query-dataset.js";
3
+ import { canonicalPublicNumericIdentity, canonicalPublicNumericIdentityParts } from "../canonical/public-identity.js";
4
+ import { mapGrpcQueryValue, validDottedNameString, validLedgerString, validNameString, validPackageIdString, validPartyId } from "./grpc-query-value-mapper.js";
5
+ /** Materializes ledger-effects transactions and optionally seeds still-active ACS contracts. */
6
+ export function mapGrpcQueryRelationFragment(source, activeContracts = []) {
7
+ const transactions = [...source].sort((left, right) => compareOffset(left.offset, right.offset));
8
+ const activeEntries = activeContractEntries(activeContracts);
9
+ const seenOffsets = new Set();
10
+ const pending = [];
11
+ for (const transaction of transactions) {
12
+ validOffset(transaction.offset, "transaction offset");
13
+ validateTransaction(transaction);
14
+ if (seenOffsets.has(transaction.offset)) {
15
+ throw new ValidationError(`gRPC query has duplicate transaction offset ${transaction.offset}`);
16
+ }
17
+ seenOffsets.add(transaction.offset);
18
+ for (const event of transaction.events) {
19
+ pending.push(pendingEvent(transaction, event));
20
+ }
21
+ }
22
+ const eventIdentities = new Set();
23
+ for (const event of pending) {
24
+ if (eventIdentities.has(event.identity)) {
25
+ throw new ValidationError(`gRPC query has duplicate event ${eventId(event.event)}`);
26
+ }
27
+ eventIdentities.add(event.identity);
28
+ }
29
+ const registry = keyRegistry([
30
+ ...pending.map((item) => item.identity),
31
+ ...pending.flatMap((item) => identitiesFor(item.event)),
32
+ ...activeEntries.map((entry) => entry.event).flatMap(identitiesFor),
33
+ ]);
34
+ const transactionRows = transactions.map(mapTransaction);
35
+ const eventRows = pending
36
+ .slice()
37
+ .sort((left, right) => compareOffset(left.transaction.offset, right.transaction.offset) || nodeId(left.event) - nodeId(right.event))
38
+ .map((item) => ({ pk: canonicalPublicNumericIdentity(eventId(item.event)), txIx: item.transaction.offset, eventId: eventId(item.event), type: item.kind }));
39
+ const eventPkByIdentity = new Map(pending.map((item) => [item.identity, canonicalPublicNumericIdentity(eventId(item.event))]));
40
+ const contracts = new Map();
41
+ const creations = new Map();
42
+ const exerciseRows = [];
43
+ for (const item of pending.sort((left, right) => compareOffset(left.transaction.offset, right.transaction.offset) || nodeId(left.event) - nodeId(right.event))) {
44
+ if (item.kind === "created") {
45
+ addCreatedContract(contracts, creations, item.event, item.transaction.offset);
46
+ }
47
+ else {
48
+ const target = contracts.get(item.event.contractId);
49
+ if (target !== undefined && !target.active) {
50
+ throw new ValidationError(`gRPC query exercise archives already archived contract ${item.event.contractId}`);
51
+ }
52
+ const template = requiredTemplate(item.event.templateId, "exercise template");
53
+ const owner = exerciseOwner(item.event);
54
+ exerciseRows.push({
55
+ tpePk: registry.get(exerciseIdentity(owner, item.event.choice, item.event.consuming)),
56
+ contractTpePk: registry.get(contractIdentity(target?.templateId ?? template)),
57
+ exerciseEventPk: eventPkByIdentity.get(item.identity),
58
+ exercisedAtIx: item.transaction.offset,
59
+ contractId: item.event.contractId,
60
+ argument: mapRequiredValue(item.event.choiceArgument, "exercise argument"),
61
+ result: item.event.exerciseResult === undefined ? null : mapGrpcQueryValue(item.event.exerciseResult),
62
+ redactionId: null,
63
+ packagePk: canonicalPublicNumericIdentity(template.packageId),
64
+ controllers: immutableStrings(item.event.actingParties, "exercise acting parties", true),
65
+ lastDescendantNodeId: String(validNodeId(item.event.lastDescendantNodeId, "last descendant node id")),
66
+ witnesses: immutableStrings(item.event.witnessParties, "exercise witnesses", true),
67
+ });
68
+ if (item.event.consuming && target !== undefined) {
69
+ contracts.set(target.contractId, { ...target, archivedEventOffset: item.transaction.offset, archivedAt: timestamp(item.transaction.effectiveAt, "transaction effective time", true), active: false });
70
+ }
71
+ }
72
+ }
73
+ reconcileActiveContracts(contracts, creations, activeEntries);
74
+ const typeIdentities = [...new Map([...pending.map((item) => item.event), ...activeEntries.map((entry) => entry.event)].flatMap((event) => typeIdentityRows(event, registry).map((item) => [item.pk, item]))).values()].sort((left, right) => left.pk.localeCompare(right.pk));
75
+ const packageIdentities = [...new Set([...pending.flatMap((item) => packageIdsFor(item.event)), ...activeEntries.map((entry) => entry.event).flatMap(packageIdsFor)])]
76
+ .sort()
77
+ .map((id) => ({ pk: canonicalPublicNumericIdentity(id), id }));
78
+ return immutableQueryValue({
79
+ contracts: [...contracts.values()].sort((left, right) => left.contractId.localeCompare(right.contractId)),
80
+ transactions: transactionRows,
81
+ events: eventRows,
82
+ exercises: exerciseRows.sort((left, right) => compareOffset(left.exercisedAtIx ?? "1", right.exercisedAtIx ?? "1") || (left.exerciseEventPk ?? "").localeCompare(right.exerciseEventPk ?? "") || left.contractId.localeCompare(right.contractId)),
83
+ typeIdentities,
84
+ packageIdentities,
85
+ creationIdentities: [...creations.values()].sort((left, right) => left.contractId.localeCompare(right.contractId)),
86
+ activeContractIdentities: activeEntries.map((entry) => ({ contractId: entry.event.contractId, synchronizerId: entry.synchronizerId, reassignmentCounter: entry.reassignmentCounter, activationOffset: entry.event.offset, activationNodeId: entry.event.nodeId }))
87
+ .sort((left, right) => left.contractId.localeCompare(right.contractId) || left.synchronizerId.localeCompare(right.synchronizerId)),
88
+ });
89
+ }
90
+ /**
91
+ * Combines the Task 5 ledger fragment with decoded LF package metadata into the
92
+ * complete immutable eight-relation snapshot. Private edge keys retain the
93
+ * creation template identity without exposing a synthetic field in contract rows.
94
+ */
95
+ export function createGrpcQueryDataset(fragment, packages, endInclusive, instanceId) {
96
+ validSnapshotOffset(endInclusive);
97
+ if (instanceId.length === 0) {
98
+ throw new ValidationError("gRPC query snapshot instance id is missing");
99
+ }
100
+ const normalizedPackages = normalizeGrpcPackageMetadata(packages);
101
+ const packageById = new Map();
102
+ for (const pkg of normalizedPackages) {
103
+ if (packageById.has(pkg.id)) {
104
+ throw new ValidationError(`gRPC query has duplicate package metadata ${pkg.id}`);
105
+ }
106
+ packageById.set(pkg.id, pkg);
107
+ }
108
+ const templates = normalizedPackages.flatMap((pkg) => pkg.templates.map((template) => ({ package: pkg, template })));
109
+ const templateByIdentity = new Map();
110
+ for (const entry of templates) {
111
+ const identity = templateIdentity(entry.package.id, entry.template.moduleName, entry.template.entityName);
112
+ if (templateByIdentity.has(identity)) {
113
+ throw new ValidationError(`gRPC query has duplicate DAML-LF template ${identity}`);
114
+ }
115
+ templateByIdentity.set(identity, entry);
116
+ }
117
+ const packagePublicKeys = new Map(normalizedPackages.map((pkg) => [pkg.id, canonicalPublicNumericIdentity(pkg.id)]));
118
+ const contractTypePublicKeys = new Map(templates.map(({ package: pkg, template }) => [templateIdentity(pkg.id, template.moduleName, template.entityName), canonicalContractTypeKey(template.payloadType, template.templateFqn)]));
119
+ const exerciseTypePublicKeys = new Map(templates.flatMap(({ package: pkg, template }) => template.choices.map((choice) => [exerciseIdentity({ packageId: pkg.id, moduleName: template.moduleName, entityName: template.entityName }, choice.choice, choice.consuming), canonicalPublicNumericIdentity(choice.choiceFqn)])));
120
+ const packageRows = [...normalizedPackages]
121
+ .sort((left, right) => left.id.localeCompare(right.id))
122
+ .map((pkg) => ({ pk: packagePublicKeys.get(pkg.id), name: pkg.name, version: pkg.version, id: pkg.id }));
123
+ const contractTypeRows = deduplicateCanonicalRows([...templates]
124
+ .sort(compareTemplateMetadata)
125
+ .map(({ package: pkg, template }) => ({
126
+ pk: contractTypePublicKeys.get(templateIdentity(pkg.id, template.moduleName, template.entityName)),
127
+ payloadType: template.payloadType,
128
+ aliases: template.aliases,
129
+ packageName: pkg.name,
130
+ moduleName: template.moduleName,
131
+ entityName: template.entityName,
132
+ templateFqn: template.templateFqn,
133
+ })));
134
+ const exerciseTypeRows = deduplicateCanonicalRows([...templates]
135
+ .flatMap(({ package: pkg, template }) => template.choices.map((choice) => ({ package: pkg, template, choice })))
136
+ .sort((left, right) => compareTemplateMetadata(left, right) || left.choice.choice.localeCompare(right.choice.choice) || Number(left.choice.consuming) - Number(right.choice.consuming))
137
+ .map(({ package: pkg, template, choice }) => ({
138
+ pk: exerciseTypePublicKeys.get(exerciseIdentity({ packageId: pkg.id, moduleName: template.moduleName, entityName: template.entityName }, choice.choice, choice.consuming)),
139
+ choice: choice.choice,
140
+ consuming: choice.consuming,
141
+ aliases: choice.aliases,
142
+ packageName: pkg.name,
143
+ moduleName: template.moduleName,
144
+ entityName: template.entityName,
145
+ templateFqn: template.templateFqn,
146
+ choiceFqn: choice.choiceFqn,
147
+ })));
148
+ const typeIdentityByOldPk = new Map(fragment.typeIdentities.map((identity) => [identity.pk, identity]));
149
+ const packageIdByOldPk = new Map(fragment.packageIdentities.map((identity) => [identity.pk, identity.id]));
150
+ const creationByContract = new Map(fragment.creationIdentities.map((identity) => [identity.contractId, identity]));
151
+ const exercises = fragment.exercises.map((exercise) => ({
152
+ ...exercise,
153
+ tpePk: canonicalExerciseTypeKeyForIdentity(typeIdentityByOldPk.get(exercise.tpePk), templateByIdentity, exerciseTypePublicKeys),
154
+ contractTpePk: canonicalContractTypeKeyForExercise(exercise.contractId, typeIdentityByOldPk.get(exercise.contractTpePk), creationByContract, templateByIdentity, contractTypePublicKeys),
155
+ packagePk: canonicalPackageKeyForId(packageIdByOldPk.get(exercise.packagePk), packagePublicKeys),
156
+ }));
157
+ const contractPrivateKeys = fragment.contracts.map((contract) => {
158
+ const creation = creationByContract.get(contract.contractId);
159
+ if (creation === undefined) {
160
+ throw new ValidationError(`gRPC query creation identity is missing ${contract.contractId}`);
161
+ }
162
+ const key = contractTypePublicKeys.get(templateIdentity(creation.representativePackageId ?? creation.creationPackageId, creation.templateId.moduleName, creation.templateId.entityName));
163
+ if (key === undefined) {
164
+ throw new ValidationError(`gRPC query representative contract type metadata is missing ${creation.contractId}`);
165
+ }
166
+ return [key];
167
+ });
168
+ const templatePrivateKeys = contractTypeRows.map((row) => [row.pk]);
169
+ const watermark = [{ singleton: true, ix: endInclusive, offset: endInclusive, instanceId }];
170
+ const transactionOffsets = new Set(fragment.transactions.map((transaction) => transaction.ix));
171
+ const activeContractIds = new Set(fragment.activeContractIdentities.map((identity) => identity.contractId));
172
+ const contractsWithoutCreatedTransaction = fragment.contracts.filter((contract) => !transactionOffsets.has(contract.createdEventOffset));
173
+ const createdTransactionIncomplete = contractsWithoutCreatedTransaction.length > 0 && contractsWithoutCreatedTransaction.every((contract) => activeContractIds.has(contract.contractId));
174
+ const eventPrivateKeys = fragment.events.map((event) => [event.eventId]);
175
+ const eventTransactionPrivateKeys = fragment.events.map((event) => [event.txIx]);
176
+ const transactionPrivateKeys = fragment.transactions.map((transaction) => [transaction.offset]);
177
+ const eventPrivateKeyByPk = new Map(fragment.events.map((event) => [event.pk, event.eventId]));
178
+ const packagePrivateKeys = packageRows.map((pkg) => [pkg.id]);
179
+ const packagePrivateKeyByPk = new Map(fragment.packageIdentities.map((pkg) => [pkg.pk, pkg.id]));
180
+ const contractTypePrivateKeys = contractTypeRows.map((row) => [row.pk]);
181
+ const exerciseTypePrivateKeys = exerciseTypeRows.map((row) => [row.pk]);
182
+ const exerciseEventPrivateKeys = fragment.exercises.map((exercise) => [exercise.exerciseEventPk === null ? null : eventPrivateKeyByPk.get(exercise.exerciseEventPk) ?? null]);
183
+ const exerciseTransactionPrivateKeys = exercises.map((exercise) => [exercise.exercisedAtIx]);
184
+ const exercisePackagePrivateKeys = fragment.exercises.map((exercise) => [packagePrivateKeyByPk.get(exercise.packagePk)]);
185
+ const exerciseContractTypePrivateKeys = exercises.map((exercise) => [exercise.contractTpePk]);
186
+ const exerciseTypePrivateKeysByExercise = exercises.map((exercise) => [exercise.tpePk]);
187
+ return createQueryDataset({
188
+ rows: {
189
+ contracts: fragment.contracts,
190
+ contractTypes: contractTypeRows,
191
+ events: fragment.events,
192
+ exercises: exercises,
193
+ exerciseTypes: exerciseTypeRows,
194
+ packages: packageRows,
195
+ transactions: fragment.transactions,
196
+ watermark: watermark,
197
+ },
198
+ uniqueKeys: {
199
+ contracts: [["contractId"]], contractTypes: [["pk"]], events: [["pk"]], exercises: [["tpePk", "contractTpePk", "exerciseEventPk", "contractId"]], exerciseTypes: [["pk"]], packages: [["pk"], ["id"]], transactions: [["ix"], ["offset"]], watermark: [["singleton"]],
200
+ },
201
+ edges: {
202
+ contracts: {
203
+ contractType: { privateKeys: { source: contractPrivateKeys, target: templatePrivateKeys } },
204
+ createdTransaction: { from: ["createdEventOffset"], to: ["ix"], ...(createdTransactionIncomplete ? { complete: false } : {}) },
205
+ archivedTransaction: { from: ["archivedEventOffset"], to: ["ix"] },
206
+ exercises: { from: ["contractId"], to: ["contractId"] },
207
+ },
208
+ contractTypes: {
209
+ contracts: { privateKeys: { source: templatePrivateKeys, target: contractPrivateKeys } },
210
+ exercises: { privateKeys: { source: contractTypePrivateKeys, target: exerciseContractTypePrivateKeys } },
211
+ },
212
+ events: { transaction: { privateKeys: { source: eventTransactionPrivateKeys, target: transactionPrivateKeys } }, exercises: { privateKeys: { source: eventPrivateKeys, target: exerciseEventPrivateKeys } } },
213
+ exercises: {
214
+ exerciseType: { privateKeys: { source: exerciseTypePrivateKeysByExercise, target: exerciseTypePrivateKeys } }, contractType: { privateKeys: { source: exerciseContractTypePrivateKeys, target: contractTypePrivateKeys } }, event: { privateKeys: { source: exerciseEventPrivateKeys, target: eventPrivateKeys } }, transaction: { privateKeys: { source: exerciseTransactionPrivateKeys, target: transactionPrivateKeys } }, package: { privateKeys: { source: exercisePackagePrivateKeys, target: packagePrivateKeys } }, contract: { from: ["contractId"], to: ["contractId"] },
215
+ },
216
+ exerciseTypes: { exercises: { privateKeys: { source: exerciseTypePrivateKeys, target: exerciseTypePrivateKeysByExercise } } },
217
+ packages: { exercises: { privateKeys: { source: packagePrivateKeys, target: exercisePackagePrivateKeys } } },
218
+ transactions: {
219
+ events: { privateKeys: { source: transactionPrivateKeys, target: eventTransactionPrivateKeys } }, createdContracts: { from: ["ix"], to: ["createdEventOffset"] }, archivedContracts: { from: ["ix"], to: ["archivedEventOffset"] }, exercises: { privateKeys: { source: transactionPrivateKeys, target: exerciseTransactionPrivateKeys } },
220
+ },
221
+ watermark: {},
222
+ },
223
+ });
224
+ }
225
+ /** Package payloads required for a contract/history relation plan, excluding creation-only provenance. */
226
+ export function referencedGrpcPackageIds(fragment) {
227
+ const packageIdByPk = new Map(fragment.packageIdentities.map((identity) => [identity.pk, identity.id]));
228
+ const concreteExercisePackages = fragment.exercises.map((exercise) => {
229
+ const packageId = packageIdByPk.get(exercise.packagePk);
230
+ if (packageId === undefined) {
231
+ throw new ValidationError("gRPC query relation package identity is missing");
232
+ }
233
+ return packageId;
234
+ });
235
+ return Object.freeze([...new Set([
236
+ ...fragment.creationIdentities.map((creation) => creation.representativePackageId ?? creation.creationPackageId),
237
+ ...concreteExercisePackages,
238
+ ...fragment.typeIdentities.filter((identity) => identity.choice !== undefined).map((identity) => identity.packageId),
239
+ ])].sort());
240
+ }
241
+ function compareTemplateMetadata(left, right) {
242
+ return left.package.id.localeCompare(right.package.id) || left.template.moduleName.localeCompare(right.template.moduleName) || left.template.entityName.localeCompare(right.template.entityName);
243
+ }
244
+ function normalizeGrpcPackageMetadata(packages) {
245
+ try {
246
+ return normalizeGrpcPackageMetadataUnsafe(packages);
247
+ }
248
+ catch (error) {
249
+ if (isValidationError(error)) {
250
+ throw error;
251
+ }
252
+ throw new ValidationError("gRPC query package metadata is invalid");
253
+ }
254
+ }
255
+ function normalizeGrpcPackageMetadataUnsafe(packages) {
256
+ if (!Array.isArray(packages)) {
257
+ throw new ValidationError("gRPC query package metadata is not an array");
258
+ }
259
+ const packageValues = Array.from(packages);
260
+ const packageIds = new Set();
261
+ const packageNameVersions = new Set();
262
+ const normalized = [];
263
+ for (const pkg of packageValues) {
264
+ if (pkg === null || typeof pkg !== "object") {
265
+ throw new ValidationError("gRPC query package metadata is invalid");
266
+ }
267
+ const value = pkg;
268
+ const packageId = packageText(value.id, "id");
269
+ validPackageIdString(packageId, "package metadata id");
270
+ const packageName = packageText(value.name, "name");
271
+ const packageVersion = packageText(value.version, "version");
272
+ if (packageIds.has(packageId)) {
273
+ throw new ValidationError(`gRPC query has duplicate package metadata ${packageId}`);
274
+ }
275
+ packageIds.add(packageId);
276
+ const nameVersion = `${packageName}\u0000${packageVersion}`;
277
+ if (packageNameVersions.has(nameVersion)) {
278
+ throw new ValidationError(`gRPC query has duplicate package metadata ${packageName}@${packageVersion}`);
279
+ }
280
+ packageNameVersions.add(nameVersion);
281
+ const templatesValue = value.templates;
282
+ if (!Array.isArray(templatesValue)) {
283
+ throw new ValidationError(`gRPC query package ${packageId} templates are invalid`);
284
+ }
285
+ const templateValues = Array.from(templatesValue);
286
+ const templateIdentities = new Set();
287
+ const templates = Object.freeze(templateValues.map((template) => normalizePackageTemplate(packageId, packageName, template, templateIdentities)));
288
+ normalized.push(Object.freeze({ id: packageId, name: packageName, version: packageVersion, templates }));
289
+ }
290
+ return Object.freeze(normalized);
291
+ }
292
+ function normalizePackageTemplate(packageId, packageName, template, identities) {
293
+ if (template === null || typeof template !== "object") {
294
+ throw new ValidationError(`gRPC query package ${packageId} template is invalid`);
295
+ }
296
+ const value = template;
297
+ const moduleName = dottedPackageName(value.moduleName, `package ${packageId} template module`);
298
+ const entityName = dottedPackageName(value.entityName, `package ${packageId} template entity`);
299
+ const identity = templateIdentity(packageId, moduleName, entityName);
300
+ if (identities.has(identity)) {
301
+ throw new ValidationError(`gRPC query has duplicate DAML-LF template ${identity}`);
302
+ }
303
+ identities.add(identity);
304
+ const payloadType = value.payloadType;
305
+ if (payloadType !== "template" && payloadType !== "interface") {
306
+ throw new ValidationError(`gRPC query package ${packageId} template payload type is invalid`);
307
+ }
308
+ const aliases = exactAliases(value.aliases, [`${packageName}:${moduleName}:${entityName}`, `${moduleName}:${entityName}`, entityName], `package ${packageId} template`);
309
+ const templateFqn = exactText(value.templateFqn, `${packageName}:${moduleName}:${entityName}`, `package ${packageId} template FQN`);
310
+ const choicesValue = value.choices;
311
+ if (!Array.isArray(choicesValue)) {
312
+ throw new ValidationError(`gRPC query package ${packageId} template choices are invalid`);
313
+ }
314
+ const choiceValues = Array.from(choicesValue);
315
+ const choiceNames = new Set();
316
+ const choices = Object.freeze(choiceValues.map((choice) => normalizePackageChoice(packageId, packageName, moduleName, entityName, choice, choiceNames)));
317
+ return Object.freeze({ moduleName, entityName, payloadType, aliases, templateFqn, choices });
318
+ }
319
+ function normalizePackageChoice(packageId, packageName, moduleName, entityName, choice, choiceNames) {
320
+ if (choice === null || typeof choice !== "object") {
321
+ throw new ValidationError(`gRPC query package ${packageId} choice is invalid`);
322
+ }
323
+ const value = choice;
324
+ const choiceName = value.choice;
325
+ if (typeof choiceName !== "string") {
326
+ throw new ValidationError(`gRPC query package ${packageId} choice name is invalid`);
327
+ }
328
+ validNameString(choiceName, `package ${packageId} choice name`);
329
+ if (choiceNames.has(choiceName)) {
330
+ throw new ValidationError(`gRPC query has duplicate DAML-LF choice ${packageId}:${moduleName}:${entityName}:${choiceName}`);
331
+ }
332
+ choiceNames.add(choiceName);
333
+ const consuming = value.consuming;
334
+ if (typeof consuming !== "boolean") {
335
+ throw new ValidationError(`gRPC query package ${packageId} choice consuming flag is invalid`);
336
+ }
337
+ const aliases = exactAliases(value.aliases, [
338
+ `${packageName}:${moduleName}:${entityName}:${choiceName}`,
339
+ `${moduleName}:${entityName}:${choiceName}`,
340
+ `${entityName}:${choiceName}`,
341
+ choiceName,
342
+ ], `package ${packageId} choice`);
343
+ const choiceFqn = exactText(value.choiceFqn, `${packageName}:${moduleName}:${entityName}:${choiceName}`, `package ${packageId} choice FQN`);
344
+ return Object.freeze({ choice: choiceName, consuming, aliases, choiceFqn });
345
+ }
346
+ function packageText(value, name) {
347
+ if (typeof value !== "string" || value.length === 0 || /[:\u0000-\u001F\u007F]/.test(value)) {
348
+ throw new ValidationError(`gRPC query package metadata ${name} is invalid`);
349
+ }
350
+ return value;
351
+ }
352
+ function dottedPackageName(value, name) {
353
+ if (typeof value !== "string") {
354
+ throw new ValidationError(`gRPC query ${name} is invalid`);
355
+ }
356
+ return validDottedNameString(value, name);
357
+ }
358
+ function exactAliases(value, expected, name) {
359
+ if (!Array.isArray(value)) {
360
+ throw new ValidationError(`gRPC query ${name} aliases are invalid`);
361
+ }
362
+ const aliases = Array.from(value);
363
+ if (aliases.length !== expected.length || aliases.some((alias, index) => alias !== expected[index])) {
364
+ throw new ValidationError(`gRPC query ${name} aliases are invalid`);
365
+ }
366
+ return Object.freeze([...expected]);
367
+ }
368
+ function exactText(value, expected, name) {
369
+ if (value !== expected) {
370
+ throw new ValidationError(`gRPC query ${name} is invalid`);
371
+ }
372
+ return expected;
373
+ }
374
+ function isValidationError(error) {
375
+ try {
376
+ return error instanceof ValidationError;
377
+ }
378
+ catch {
379
+ return false;
380
+ }
381
+ }
382
+ function templateIdentity(packageId, moduleName, entityName) {
383
+ return `${packageId}\u0000${moduleName}\u0000${entityName}`;
384
+ }
385
+ function templateKey(packageId, moduleName, entityName) {
386
+ return [packageId, moduleName, entityName];
387
+ }
388
+ function canonicalContractTypeKey(payloadType, templateFqn) {
389
+ return canonicalPublicNumericIdentityParts([payloadType, templateFqn]);
390
+ }
391
+ function deduplicateCanonicalRows(rows) {
392
+ const byPk = new Map();
393
+ for (const row of rows) {
394
+ const existing = byPk.get(row.pk);
395
+ if (existing === undefined) {
396
+ byPk.set(row.pk, row);
397
+ }
398
+ else if (JSON.stringify(existing) !== JSON.stringify(row)) {
399
+ throw new ValidationError(`gRPC query canonical public key ${row.pk} has conflicting metadata`);
400
+ }
401
+ }
402
+ return [...byPk.values()];
403
+ }
404
+ function canonicalExerciseTypeKeyForIdentity(identity, templates, keys) {
405
+ if (identity === undefined) {
406
+ throw new ValidationError("gRPC query relation type identity is missing");
407
+ }
408
+ if (identity.choice === undefined) {
409
+ throw new ValidationError("gRPC query relation exercise type identity is invalid");
410
+ }
411
+ const template = templates.get(templateIdentity(identity.templateId.packageId, identity.templateId.moduleName, identity.templateId.entityName));
412
+ const key = template === undefined ? undefined : keys.get(exerciseIdentity(identity.templateId, identity.choice, identity.consuming));
413
+ if (key === undefined) {
414
+ throw new ValidationError("gRPC query relation type metadata is missing");
415
+ }
416
+ return key;
417
+ }
418
+ function canonicalContractTypeKeyForExercise(contractId, orphanIdentity, creations, templates, keys) {
419
+ const creation = creations.get(contractId);
420
+ if (creation === undefined) {
421
+ if (orphanIdentity === undefined || orphanIdentity.choice !== undefined) {
422
+ throw new ValidationError("gRPC query orphan contract type identity is invalid");
423
+ }
424
+ const orphan = templates.get(templateIdentity(orphanIdentity.templateId.packageId, orphanIdentity.templateId.moduleName, orphanIdentity.templateId.entityName));
425
+ const key = orphan === undefined ? undefined : keys.get(templateIdentity(orphanIdentity.templateId.packageId, orphanIdentity.templateId.moduleName, orphanIdentity.templateId.entityName));
426
+ if (key === undefined) {
427
+ throw new ValidationError("gRPC query orphan contract type metadata is missing");
428
+ }
429
+ return key;
430
+ }
431
+ const packageId = creation.representativePackageId ?? creation.creationPackageId;
432
+ const key = keys.get(templateIdentity(packageId, creation.templateId.moduleName, creation.templateId.entityName));
433
+ if (key === undefined) {
434
+ throw new ValidationError(`gRPC query representative contract type metadata is missing ${packageId}:${creation.templateId.moduleName}:${creation.templateId.entityName}`);
435
+ }
436
+ return key;
437
+ }
438
+ function canonicalPackageKeyForId(packageId, keys) {
439
+ const key = packageId === undefined ? undefined : keys.get(packageId);
440
+ if (key === undefined) {
441
+ throw new ValidationError("gRPC query relation package metadata is missing");
442
+ }
443
+ return key;
444
+ }
445
+ function pendingEvent(transaction, event) {
446
+ switch (event.event.oneofKind) {
447
+ case "created":
448
+ validatePending(transaction, event.event.created, "created");
449
+ return { transaction, event: event.event.created, kind: "created", identity: eventIdentity(event.event.created) };
450
+ case "exercised":
451
+ validatePending(transaction, event.event.exercised, "exercised");
452
+ return { transaction, event: event.event.exercised, kind: "exercised", identity: eventIdentity(event.event.exercised) };
453
+ default: throw new ValidationError("gRPC query history contains a non-ledger-effects event");
454
+ }
455
+ }
456
+ function validatePending(transaction, event, kind) {
457
+ validOffset(event.offset, `${kind} event offset`);
458
+ validNodeId(event.nodeId, `${kind} node id`);
459
+ if (event.offset !== transaction.offset) {
460
+ throw new ValidationError(`gRPC query ${kind} event offset differs from its transaction`);
461
+ }
462
+ validLedgerString(event.contractId, `${kind} event contract id`);
463
+ requiredTemplate(event.templateId, `${kind} event template`);
464
+ if (isExercised(event)) {
465
+ exerciseOwner(event);
466
+ if (event.packageName.length === 0) {
467
+ throw new ValidationError("gRPC query exercise package name is missing");
468
+ }
469
+ else if (event.choiceArgument === undefined) {
470
+ throw new ValidationError("gRPC query exercise argument is missing");
471
+ }
472
+ validNameString(event.choice, "exercise choice");
473
+ immutableStrings(event.actingParties, "exercise acting parties", true);
474
+ immutableStrings(event.witnessParties, "exercise witnesses", true);
475
+ validNodeId(event.lastDescendantNodeId, "last descendant node id");
476
+ if (event.lastDescendantNodeId < event.nodeId) {
477
+ throw new ValidationError("gRPC query exercise last descendant node id precedes its node id");
478
+ }
479
+ }
480
+ else {
481
+ creationDescriptor(event, event.offset);
482
+ }
483
+ }
484
+ function addCreatedContract(contracts, creations, event, offset) {
485
+ const creation = creationDescriptor(event, offset);
486
+ if (contracts.has(event.contractId)) {
487
+ throw new ValidationError(`gRPC query has duplicate contract creation ${event.contractId}`);
488
+ }
489
+ contracts.set(event.contractId, {
490
+ contractId: creation.contractId,
491
+ templateId: creation.templateId,
492
+ packageId: creation.creationPackageId,
493
+ payload: creation.payload,
494
+ witnesses: creation.witnesses,
495
+ createdEventOffset: creation.offset,
496
+ createdAt: creation.createdAt,
497
+ archivedEventOffset: null,
498
+ archivedAt: null,
499
+ active: true,
500
+ });
501
+ creations.set(event.contractId, creation);
502
+ }
503
+ function mapTransaction(transaction) {
504
+ return {
505
+ ix: transaction.offset,
506
+ offset: transaction.offset,
507
+ transactionId: transaction.updateId,
508
+ effectiveAt: timestamp(transaction.effectiveAt, "transaction effective time", true),
509
+ workflowId: nullableString(transaction.workflowId),
510
+ domainId: null,
511
+ traceContext: transaction.traceContext === undefined ? null : transaction.traceContext,
512
+ externalTransactionHash: transaction.transactionHash === undefined
513
+ ? transaction.externalTransactionHash === undefined ? null : Uint8Array.from(transaction.externalTransactionHash)
514
+ : Uint8Array.from(transaction.transactionHash),
515
+ paidTrafficCost: transaction.paidTrafficCost === undefined ? null : signedInt64(transaction.paidTrafficCost, "paid traffic cost"),
516
+ };
517
+ }
518
+ function identitiesFor(event) {
519
+ const template = requiredTemplate(event.templateId, "event template");
520
+ return isExercised(event)
521
+ ? [eventIdentity(event), contractIdentity(template), ...packageIdsFor(event).map(packageIdentity), exerciseIdentity(exerciseOwner(event), event.choice, event.consuming)]
522
+ : [eventIdentity(event), contractIdentity(template), ...packageIdsFor(event).map(packageIdentity)];
523
+ }
524
+ function typeIdentityRows(event, registry) {
525
+ const template = requiredTemplate(event.templateId, "event template");
526
+ const contract = { pk: registry.get(contractIdentity(template)), templateId: copyTemplate(template), packageId: template.packageId };
527
+ if (!isExercised(event)) {
528
+ return [contract];
529
+ }
530
+ const owner = exerciseOwner(event);
531
+ return [contract, { pk: registry.get(exerciseIdentity(owner, event.choice, event.consuming)), templateId: copyTemplate(owner), packageId: owner.packageId, choice: event.choice, consuming: event.consuming }];
532
+ }
533
+ function activeContractEntries(responses) {
534
+ const entries = responses.map((response) => {
535
+ const contractEntry = response.contractEntry;
536
+ if (contractEntry.oneofKind !== "activeContract") {
537
+ throw new ValidationError("gRPC query ACS contains incomplete assigned or unassigned contract data");
538
+ }
539
+ const active = contractEntry.activeContract;
540
+ const event = active.createdEvent;
541
+ if (event === undefined) {
542
+ throw new ValidationError("gRPC query ACS contains incomplete assigned or unassigned contract data");
543
+ }
544
+ else if (active.synchronizerId.length === 0) {
545
+ throw new ValidationError("gRPC query ACS active contract synchronizer id is missing");
546
+ }
547
+ creationDescriptor(event, event.offset);
548
+ return { event, synchronizerId: active.synchronizerId, reassignmentCounter: uint64(active.reassignmentCounter, "ACS active contract reassignment counter") };
549
+ });
550
+ const seen = new Set();
551
+ for (const entry of entries) {
552
+ const key = `${entry.event.contractId}\u0000${entry.synchronizerId}`;
553
+ if (seen.has(key)) {
554
+ throw new ValidationError(`gRPC query has duplicate ACS activation for ${entry.event.contractId} on ${entry.synchronizerId}`);
555
+ }
556
+ seen.add(key);
557
+ }
558
+ return entries;
559
+ }
560
+ function reconcileActiveContracts(contracts, creations, entries) {
561
+ const grouped = new Map();
562
+ for (const entry of entries) {
563
+ let bucket = grouped.get(entry.event.contractId);
564
+ if (bucket === undefined) {
565
+ bucket = [];
566
+ grouped.set(entry.event.contractId, bucket);
567
+ }
568
+ bucket.push(entry);
569
+ }
570
+ for (const [contractId, group] of grouped) {
571
+ const descriptors = group.map((entry) => creationDescriptor(entry.event, entry.event.offset));
572
+ const facts = canonicalCreationFacts(descriptors[0]);
573
+ if (descriptors.some((descriptor) => canonicalCreationFacts(descriptor) !== facts)) {
574
+ throw new ValidationError(`gRPC query ACS conflicts within activations for contract ${contractId}`);
575
+ }
576
+ const existing = contracts.get(contractId);
577
+ const historical = creations.get(contractId);
578
+ if (existing !== undefined && existing.active === false) {
579
+ throw new ValidationError(`gRPC query ACS contains archived contract ${contractId}`);
580
+ }
581
+ else if (historical !== undefined && canonicalCreationFacts(historical) !== facts) {
582
+ throw new ValidationError(`gRPC query ACS conflicts with history for contract ${contractId}`);
583
+ }
584
+ const witnesses = partyUnion([...(historical?.witnesses ?? []), ...descriptors.flatMap((descriptor) => descriptor.witnesses)], "created event witnesses", true);
585
+ if (existing === undefined) {
586
+ const representative = [...group].sort(compareActivation)[0];
587
+ addCreatedContract(contracts, creations, representative.event, representative.event.offset);
588
+ }
589
+ const creation = creations.get(contractId);
590
+ const updatedCreation = { ...creation, witnesses };
591
+ creations.set(contractId, updatedCreation);
592
+ contracts.set(contractId, { ...contracts.get(contractId), witnesses });
593
+ }
594
+ }
595
+ function compareActivation(left, right) {
596
+ const counter = BigInt(left.reassignmentCounter) - BigInt(right.reassignmentCounter);
597
+ return counter < 0n ? -1 : counter > 0n ? 1 : compareOffset(left.event.offset, right.event.offset) || left.synchronizerId.localeCompare(right.synchronizerId);
598
+ }
599
+ function creationDescriptor(event, offset) {
600
+ validOffset(offset, "created event offset");
601
+ validNodeId(event.nodeId, "created node id");
602
+ validLedgerString(event.contractId, "created event contract id");
603
+ if (event.packageName.length === 0) {
604
+ throw new ValidationError("gRPC query created event package name is missing");
605
+ }
606
+ validPackageIdString(event.representativePackageId, "created event representative package id");
607
+ const template = requiredTemplate(event.templateId, "created event template");
608
+ if (event.createArguments === undefined) {
609
+ throw new ValidationError("gRPC query created event has no create arguments");
610
+ }
611
+ const createdAt = requiredTimestamp(event.createdAt, "created event time");
612
+ immutableStrings(event.signatories, "created event signatories", true);
613
+ immutableStrings(event.observers, "created event observers");
614
+ return {
615
+ contractId: event.contractId,
616
+ offset,
617
+ templateId: copyTemplate(template),
618
+ creationPackageId: template.packageId,
619
+ representativePackageId: nullableString(event.representativePackageId),
620
+ payload: mapGrpcQueryValue({ sum: { oneofKind: "record", record: event.createArguments } }),
621
+ witnesses: immutableStrings(event.witnessParties, "created event witnesses", true),
622
+ createdAt,
623
+ };
624
+ }
625
+ function validateTransaction(transaction) {
626
+ if (transaction.events.length === 0) {
627
+ throw new ValidationError("gRPC query transaction has no events");
628
+ }
629
+ else if (transaction.synchronizerId.length === 0) {
630
+ throw new ValidationError("gRPC query transaction synchronizer id is missing");
631
+ }
632
+ validLedgerString(transaction.updateId, "transaction update id");
633
+ if (transaction.workflowId.length > 0) {
634
+ validLedgerString(transaction.workflowId, "transaction workflow id");
635
+ }
636
+ timestamp(transaction.effectiveAt, "transaction effective time", true);
637
+ timestamp(transaction.recordTime, "transaction record time", true);
638
+ }
639
+ function packageIdsFor(event) {
640
+ const template = requiredTemplate(event.templateId, "event template");
641
+ if (!isExercised(event)) {
642
+ return [template.packageId, ...event.representativePackageId.length === 0 ? [] : [event.representativePackageId]];
643
+ }
644
+ const owner = exerciseOwner(event);
645
+ return owner.packageId === template.packageId ? [template.packageId] : [template.packageId, owner.packageId];
646
+ }
647
+ function keyRegistry(identities) {
648
+ return new Map([...new Set(identities)].map((identity) => [identity, canonicalPublicNumericIdentity(identity)]));
649
+ }
650
+ function contractIdentity(template) {
651
+ return `contract-type\u0000${template.packageId}\u0000${template.moduleName}\u0000${template.entityName}`;
652
+ }
653
+ function packageIdentity(id) {
654
+ return `package\u0000${id}`;
655
+ }
656
+ function exerciseIdentity(template, choice, consuming) {
657
+ return `exercise-type\u0000${template.packageId}\u0000${template.moduleName}\u0000${template.entityName}\u0000${choice}\u0000${consuming}`;
658
+ }
659
+ function eventIdentity(event) {
660
+ return `event\u0000${event.offset}\u0000${event.nodeId}`;
661
+ }
662
+ function eventId(event) {
663
+ return `${event.offset}:${event.nodeId}`;
664
+ }
665
+ function nodeId(event) {
666
+ return validNodeId(event.nodeId, "event node id");
667
+ }
668
+ function isExercised(event) {
669
+ return typeof event.choice === "string";
670
+ }
671
+ function requiredTemplate(template, name) {
672
+ if (template === undefined) {
673
+ throw new ValidationError(`gRPC query ${name} is missing`);
674
+ }
675
+ validPackageIdString(template.packageId, `${name} package id`);
676
+ validDottedNameString(template.moduleName, `${name} module name`);
677
+ validDottedNameString(template.entityName, `${name} entity name`);
678
+ return template;
679
+ }
680
+ function exerciseOwner(event) {
681
+ return event.interfaceId === undefined
682
+ ? requiredTemplate(event.templateId, "exercise template")
683
+ : requiredTemplate(event.interfaceId, "exercise interface");
684
+ }
685
+ function copyTemplate(template) {
686
+ return { packageId: template.packageId, moduleName: template.moduleName, entityName: template.entityName };
687
+ }
688
+ function mapRequiredValue(value, name) {
689
+ if (value === undefined) {
690
+ throw new ValidationError(`gRPC query ${name} is missing`);
691
+ }
692
+ return mapGrpcQueryValue(value);
693
+ }
694
+ function immutableStrings(value, name, required = false) {
695
+ if (required && value.length === 0) {
696
+ throw new ValidationError(`gRPC query ${name} is missing`);
697
+ }
698
+ return Object.freeze([...new Set(value.map(validPartyId))].sort());
699
+ }
700
+ function partyUnion(value, name, required = false) {
701
+ return immutableStrings(value, name, required);
702
+ }
703
+ function nullableString(value) {
704
+ return value.length === 0 ? null : value;
705
+ }
706
+ function validNodeId(value, name) {
707
+ if (!Number.isSafeInteger(value) || value < 0) {
708
+ throw new ValidationError(`gRPC query ${name} is invalid`);
709
+ }
710
+ return value;
711
+ }
712
+ function validOffset(value, name) {
713
+ if (!/^[1-9]\d*$/.test(value)) {
714
+ throw new ValidationError(`gRPC query ${name} is invalid`);
715
+ }
716
+ else if (BigInt(value) > 9223372036854775807n) {
717
+ throw new ValidationError(`gRPC query ${name} is outside the int64 range`);
718
+ }
719
+ return value;
720
+ }
721
+ function validSnapshotOffset(value) {
722
+ if (!/^(?:0|[1-9]\d*)$/.test(value)) {
723
+ throw new ValidationError("gRPC query snapshot end offset is invalid");
724
+ }
725
+ else if (BigInt(value) > 9223372036854775807n) {
726
+ throw new ValidationError("gRPC query snapshot end offset is outside the int64 range");
727
+ }
728
+ return value;
729
+ }
730
+ function signedInt64(value, name) {
731
+ if (!/^-?(?:0|[1-9]\d*)$/.test(value)) {
732
+ throw new ValidationError(`gRPC query ${name} is invalid`);
733
+ }
734
+ else if (BigInt(value) < -9223372036854775808n || BigInt(value) > 9223372036854775807n) {
735
+ throw new ValidationError(`gRPC query ${name} is outside the int64 range`);
736
+ }
737
+ return value;
738
+ }
739
+ function uint64(value, name) {
740
+ if (!/^(?:0|[1-9]\d*)$/.test(value)) {
741
+ throw new ValidationError(`gRPC query ${name} is invalid`);
742
+ }
743
+ else if (BigInt(value) > 18446744073709551615n) {
744
+ throw new ValidationError(`gRPC query ${name} is outside the uint64 range`);
745
+ }
746
+ return value;
747
+ }
748
+ function compareOffset(left, right) {
749
+ validOffset(left, "transaction offset");
750
+ validOffset(right, "transaction offset");
751
+ const first = BigInt(left);
752
+ const second = BigInt(right);
753
+ return first < second ? -1 : first > second ? 1 : 0;
754
+ }
755
+ function timestamp(value, name, required = false) {
756
+ if (value === undefined) {
757
+ if (required) {
758
+ throw new ValidationError(`gRPC query ${name} is missing`);
759
+ }
760
+ return null;
761
+ }
762
+ else if (!/^-?(?:0|[1-9]\d*)$/.test(value.seconds) || !Number.isInteger(value.nanos) || value.nanos < 0 || value.nanos > 999_999_999) {
763
+ throw new ValidationError(`gRPC query ${name} is invalid`);
764
+ }
765
+ const milliseconds = BigInt(value.seconds) * 1000n + BigInt(Math.trunc(value.nanos / 1_000_000));
766
+ if (milliseconds < -62135596800000n || milliseconds > 253402300799999n) {
767
+ throw new ValidationError(`gRPC query ${name} is outside the Ledger API range`);
768
+ }
769
+ return new Date(Number(milliseconds));
770
+ }
771
+ function requiredTimestamp(value, name) {
772
+ const mapped = timestamp(value, name, true);
773
+ if (mapped === null) {
774
+ throw new ValidationError(`gRPC query ${name} is missing`);
775
+ }
776
+ return mapped;
777
+ }
778
+ function canonicalCreationFacts(value) {
779
+ return JSON.stringify({ contractId: value.contractId, templateId: value.templateId, creationPackageId: value.creationPackageId, representativePackageId: value.representativePackageId, createdAt: value.createdAt.toISOString(), payload: canonicalJson(value.payload) });
780
+ }
781
+ function canonicalJson(value) {
782
+ if (Array.isArray(value)) {
783
+ return value.map(canonicalJson);
784
+ }
785
+ else if (value !== null && typeof value === "object") {
786
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalJson(value[key])]));
787
+ }
788
+ return value;
789
+ }