@distrohelena/canton-typescript-sdk 0.1.36 → 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.
- package/README.md +104 -34
- package/dist/cjs/core/types/requests/{submit-command-request.js → submit-commands-request.js} +10 -6
- package/dist/cjs/index.js +10 -8
- package/dist/cjs/query/canonical/in-memory-query-evaluator.js +291 -0
- package/dist/cjs/query/canonical/public-identity.js +41 -0
- package/dist/cjs/query/canonical/query-ast.js +2 -0
- package/dist/cjs/query/canonical/query-dataset.js +351 -0
- package/dist/cjs/query/canonical/query-normalizer.js +655 -0
- package/dist/cjs/query/canonical/query-schema.js +86 -0
- package/dist/cjs/query/canton-manager.js +14 -5
- package/dist/cjs/query/errors/query-snapshot-incomplete-error.js +19 -0
- package/dist/cjs/query/grpc/grpc-contract-cache.js +484 -0
- package/dist/cjs/query/grpc/grpc-package-relation-reader.js +218 -0
- package/dist/cjs/query/grpc/grpc-query-client.js +249 -0
- package/dist/cjs/query/grpc/grpc-query-snapshot-reader.js +238 -0
- package/dist/cjs/query/grpc/grpc-query-value-mapper.js +204 -0
- package/dist/cjs/query/grpc/grpc-relation-mapper.js +794 -0
- package/dist/cjs/query/pqs/pqs-query-client.js +151 -582
- package/dist/cjs/query/pqs/pqs-relational-sql-compiler.js +138 -95
- package/dist/cjs/query/pqs/pqs-result-shape.js +28 -0
- package/dist/cjs/query/pqs/pqs-schema-profile.js +49 -48
- package/dist/cjs/query/pqs/pqs-sql-compiler.js +343 -289
- package/dist/cjs/query/pqs/pqs-sql-syntax.js +10 -0
- package/dist/cjs/services/command/command-service-client.js +16 -3
- package/dist/cjs/services/commands/command-payload-builder.js +1 -1
- package/dist/cjs/services/commands/command-submission-pipeline.js +21 -6
- package/dist/cjs/testing/runtime/declarative-action-executor.js +3 -3
- package/dist/cjs/transports/grpc/grpc-transport.js +2 -2
- package/dist/cjs/transports/grpc/mappers/commands-mapper.js +6 -6
- package/dist/cjs/transports/grpc/mappers/interactive-command-mapper.js +1 -1
- package/dist/cjs/transports/json/json-transport.js +1 -1
- package/dist/cjs/transports/json/mappers/commands-mapper.js +3 -3
- package/dist/core/transports/transport.interface.d.ts +4 -4
- package/dist/core/types/prepared-command-submission.d.ts +3 -3
- package/dist/core/types/requests/{submit-command-request.d.ts → submit-commands-request.d.ts} +8 -4
- package/dist/core/types/requests/{submit-command-request.js → submit-commands-request.js} +8 -4
- package/dist/index.d.ts +5 -2
- package/dist/index.js +2 -1
- package/dist/query/canonical/in-memory-query-evaluator.d.ts +22 -0
- package/dist/query/canonical/in-memory-query-evaluator.js +287 -0
- package/dist/query/canonical/public-identity.d.ts +14 -0
- package/dist/query/canonical/public-identity.js +35 -0
- package/dist/query/canonical/query-ast.d.ts +104 -0
- package/dist/query/canonical/query-ast.js +1 -0
- package/dist/query/canonical/query-dataset.d.ts +63 -0
- package/dist/query/canonical/query-dataset.js +343 -0
- package/dist/query/canonical/query-normalizer.d.ts +10 -0
- package/dist/query/canonical/query-normalizer.js +646 -0
- package/dist/query/canonical/query-schema.d.ts +25 -0
- package/dist/query/canonical/query-schema.js +83 -0
- package/dist/query/canton-manager.js +14 -5
- package/dist/query/errors/query-snapshot-incomplete-error.d.ts +14 -0
- package/dist/query/errors/query-snapshot-incomplete-error.js +15 -0
- package/dist/query/grpc/grpc-contract-cache.d.ts +27 -0
- package/dist/query/grpc/grpc-contract-cache.js +479 -0
- package/dist/query/grpc/grpc-package-relation-reader.d.ts +43 -0
- package/dist/query/grpc/grpc-package-relation-reader.js +213 -0
- package/dist/query/grpc/grpc-query-client.d.ts +42 -0
- package/dist/query/grpc/grpc-query-client.js +245 -0
- package/dist/query/grpc/grpc-query-snapshot-reader.d.ts +33 -0
- package/dist/query/grpc/grpc-query-snapshot-reader.js +233 -0
- package/dist/query/grpc/grpc-query-value-mapper.d.ts +15 -0
- package/dist/query/grpc/grpc-query-value-mapper.js +195 -0
- package/dist/query/grpc/grpc-relation-mapper.d.ts +67 -0
- package/dist/query/grpc/grpc-relation-mapper.js +789 -0
- package/dist/query/pqs/pqs-query-client.d.ts +10 -20
- package/dist/query/pqs/pqs-query-client.js +154 -585
- package/dist/query/pqs/pqs-relational-sql-compiler.d.ts +9 -17
- package/dist/query/pqs/pqs-relational-sql-compiler.js +136 -95
- package/dist/query/pqs/pqs-result-shape.d.ts +25 -0
- package/dist/query/pqs/pqs-result-shape.js +25 -0
- package/dist/query/pqs/pqs-schema-profile.js +49 -48
- package/dist/query/pqs/pqs-sql-compiler.d.ts +18 -3
- package/dist/query/pqs/pqs-sql-compiler.js +337 -288
- package/dist/query/pqs/pqs-sql-syntax.d.ts +2 -0
- package/dist/query/pqs/pqs-sql-syntax.js +6 -0
- package/dist/query/query-client.d.ts +15 -0
- package/dist/services/command/command-service-client.d.ts +9 -4
- package/dist/services/command/command-service-client.js +16 -3
- package/dist/services/command-submission/command-submission-service-client.d.ts +2 -2
- package/dist/services/commands/command-payload-builder.d.ts +2 -2
- package/dist/services/commands/command-payload-builder.js +1 -1
- package/dist/services/commands/command-submission-pipeline.d.ts +5 -4
- package/dist/services/commands/command-submission-pipeline.js +21 -6
- package/dist/testing/runtime/declarative-action-executor.js +3 -3
- package/dist/transports/grpc/grpc-transport.d.ts +4 -4
- package/dist/transports/grpc/grpc-transport.js +3 -3
- package/dist/transports/grpc/mappers/commands-mapper.d.ts +3 -3
- package/dist/transports/grpc/mappers/commands-mapper.js +4 -4
- package/dist/transports/grpc/mappers/interactive-command-mapper.d.ts +3 -3
- package/dist/transports/grpc/mappers/interactive-command-mapper.js +1 -1
- package/dist/transports/json/json-transport.d.ts +2 -2
- package/dist/transports/json/json-transport.js +2 -2
- package/dist/transports/json/mappers/commands-mapper.d.ts +2 -2
- package/dist/transports/json/mappers/commands-mapper.js +2 -2
- package/package.json +4 -3
- package/dist/cjs/query/grpc/grpc-contract-query-client.js +0 -178
- package/dist/query/grpc/grpc-contract-query-client.d.ts +0 -33
- package/dist/query/grpc/grpc-contract-query-client.js +0 -174
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GrpcPackageRelationReader = exports.GrpcPackageRelationError = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const canton_error_js_1 = require("../../core/errors/canton-error.js");
|
|
6
|
+
const daml_lf_package_loader_js_1 = require("../../daml-lf/daml-lf-package-loader.js");
|
|
7
|
+
const daml_lf_template_js_1 = require("../../daml-lf/model/daml-lf-template.js");
|
|
8
|
+
const lf_2_model_mapper_js_1 = require("../../daml-lf/model/lf-2-model-mapper.js");
|
|
9
|
+
const daml_lf_js_1 = require("../../transports/grpc/generated/canton/com/digitalasset/daml/lf/archive/daml_lf.js");
|
|
10
|
+
const package_service_js_1 = require("../../transports/grpc/generated/canton/com/daml/ledger/api/v2/package_service.js");
|
|
11
|
+
const grpc_query_value_mapper_js_1 = require("./grpc-query-value-mapper.js");
|
|
12
|
+
/** An explicit package-service/LF decoding failure; callers never receive partial package rows. */
|
|
13
|
+
class GrpcPackageRelationError extends canton_error_js_1.CantonError {
|
|
14
|
+
packageId;
|
|
15
|
+
constructor(packageId, message) {
|
|
16
|
+
super(`gRPC query package ${packageId} could not be materialized: ${message}`);
|
|
17
|
+
this.packageId = packageId;
|
|
18
|
+
Object.freeze(this);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.GrpcPackageRelationError = GrpcPackageRelationError;
|
|
22
|
+
/** Loads LF package metadata. Each call owns its promise map, so no package data enters QueryCacheStore. */
|
|
23
|
+
class GrpcPackageRelationReader {
|
|
24
|
+
packageService;
|
|
25
|
+
packageLoader;
|
|
26
|
+
constructor(packageService, packageLoader = new daml_lf_package_loader_js_1.DamlLfPackageLoader()) {
|
|
27
|
+
this.packageService = packageService;
|
|
28
|
+
this.packageLoader = packageLoader;
|
|
29
|
+
}
|
|
30
|
+
async readAllAsync() {
|
|
31
|
+
let packageIds;
|
|
32
|
+
try {
|
|
33
|
+
packageIds = packageIdsSnapshot(await this.packageService.listPackagesAsync({}));
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throw new GrpcPackageRelationError("<list>", errorMessage(error));
|
|
37
|
+
}
|
|
38
|
+
const packages = await this.readPackagesAsync(packageIds);
|
|
39
|
+
return Object.freeze(packages.filter((pkg) => pkg.templates.length > 0));
|
|
40
|
+
}
|
|
41
|
+
async readPackagesAsync(packageIds) {
|
|
42
|
+
const uniquePackageIds = new Set();
|
|
43
|
+
for (const packageId of packageIds) {
|
|
44
|
+
try {
|
|
45
|
+
validPackageDigest(packageId);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
throw new GrpcPackageRelationError(typeof packageId === "string" ? packageId : "<invalid>", errorMessage(error));
|
|
49
|
+
}
|
|
50
|
+
uniquePackageIds.add(packageId);
|
|
51
|
+
}
|
|
52
|
+
const packages = await Promise.all([...uniquePackageIds].map((packageId) => this.readPackageAsync(packageId)));
|
|
53
|
+
return Object.freeze(packages.slice().sort((left, right) => left.id.localeCompare(right.id)));
|
|
54
|
+
}
|
|
55
|
+
async readPackageAsync(packageId) {
|
|
56
|
+
let response;
|
|
57
|
+
try {
|
|
58
|
+
response = await this.packageService.getPackageAsync({ packageId });
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
throw new GrpcPackageRelationError(packageId, errorMessage(error));
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
if (response.hash !== packageId) {
|
|
65
|
+
throw new Error("Package Service response hash does not match its request");
|
|
66
|
+
}
|
|
67
|
+
else if (!(response.archivePayload instanceof Uint8Array) || response.archivePayload.length === 0) {
|
|
68
|
+
throw new Error("Package Service response archive payload is missing");
|
|
69
|
+
}
|
|
70
|
+
else if (response.hashFunction !== package_service_js_1.HashFunction.SHA256) {
|
|
71
|
+
throw new Error("Package Service response uses an unsupported hash function");
|
|
72
|
+
}
|
|
73
|
+
const digest = (0, node_crypto_1.createHash)("sha256").update(response.archivePayload).digest("hex");
|
|
74
|
+
if (digest !== packageId || digest !== response.hash) {
|
|
75
|
+
throw new Error("Package Service response archive payload does not match its SHA-256 hash");
|
|
76
|
+
}
|
|
77
|
+
const archive = daml_lf_js_1.Archive.toBinary({
|
|
78
|
+
hashFunction: daml_lf_js_1.HashFunction.SHA256,
|
|
79
|
+
payload: response.archivePayload,
|
|
80
|
+
hash: response.hash,
|
|
81
|
+
});
|
|
82
|
+
const result = this.packageLoader.loadRawPackageOrThrow(archive);
|
|
83
|
+
const pkg = lf_2_model_mapper_js_1.Lf2ModelMapper.mapPackage(result.packageId, result.rawPackage, result.languageVersion);
|
|
84
|
+
const packageName = requiredPackageText(pkg.packageName, "name");
|
|
85
|
+
const templates = [
|
|
86
|
+
...pkg.modules.flatMap((module) => module.definitions
|
|
87
|
+
.filter((definition) => definition instanceof daml_lf_template_js_1.DamlLfTemplate)
|
|
88
|
+
.map((template) => templateMetadata(packageId, packageName, module.name, template))),
|
|
89
|
+
...interfaceMetadata(packageId, packageName, result.rawPackage),
|
|
90
|
+
];
|
|
91
|
+
return Object.freeze({
|
|
92
|
+
id: packageId,
|
|
93
|
+
name: packageName,
|
|
94
|
+
version: requiredPackageText(pkg.packageVersion, "version"),
|
|
95
|
+
templates: Object.freeze(templates),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
throw isGrpcPackageRelationError(error) ? error : new GrpcPackageRelationError(packageId, errorMessage(error));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.GrpcPackageRelationReader = GrpcPackageRelationReader;
|
|
104
|
+
function packageIdsSnapshot(response) {
|
|
105
|
+
if (response === null || typeof response !== "object") {
|
|
106
|
+
throw new Error("Package Service returned no package IDs");
|
|
107
|
+
}
|
|
108
|
+
const descriptor = Object.getOwnPropertyDescriptor(response, "packageIds");
|
|
109
|
+
if (descriptor === undefined || !("value" in descriptor) || !Array.isArray(descriptor.value)) {
|
|
110
|
+
throw new Error("Package Service returned no package IDs");
|
|
111
|
+
}
|
|
112
|
+
const packageIds = Array.from(descriptor.value, validPackageDigest);
|
|
113
|
+
if (packageIds.length === 0) {
|
|
114
|
+
throw new Error("Package Service returned no package IDs");
|
|
115
|
+
}
|
|
116
|
+
return Object.freeze(packageIds);
|
|
117
|
+
}
|
|
118
|
+
function validPackageDigest(value) {
|
|
119
|
+
if (typeof value !== "string") {
|
|
120
|
+
throw new Error("Package Service package ID is invalid");
|
|
121
|
+
}
|
|
122
|
+
(0, grpc_query_value_mapper_js_1.validPackageIdString)(value, "package id");
|
|
123
|
+
if (!/^[0-9a-f]{64}$/.test(value)) {
|
|
124
|
+
throw new Error("Package Service package ID is not a lowercase SHA-256 digest");
|
|
125
|
+
}
|
|
126
|
+
return value;
|
|
127
|
+
}
|
|
128
|
+
function templateMetadata(packageId, packageName, moduleName, template) {
|
|
129
|
+
(0, grpc_query_value_mapper_js_1.validDottedNameString)(moduleName, "DAML-LF module name");
|
|
130
|
+
(0, grpc_query_value_mapper_js_1.validDottedNameString)(template.templateId.templateName, "DAML-LF template name");
|
|
131
|
+
const entityName = template.templateId.templateName;
|
|
132
|
+
const templateFqn = `${packageName}:${moduleName}:${entityName}`;
|
|
133
|
+
return Object.freeze({
|
|
134
|
+
moduleName,
|
|
135
|
+
entityName,
|
|
136
|
+
payloadType: "template",
|
|
137
|
+
aliases: contractTypeAliases(packageName, moduleName, entityName),
|
|
138
|
+
templateFqn,
|
|
139
|
+
choices: Object.freeze(template.choices.map((choice) => {
|
|
140
|
+
(0, grpc_query_value_mapper_js_1.validNameString)(choice.name, "DAML-LF choice name");
|
|
141
|
+
return Object.freeze({ choice: choice.name, consuming: choice.consuming, aliases: exerciseTypeAliases(packageName, moduleName, entityName, choice.name), choiceFqn: `${templateFqn}:${choice.name}` });
|
|
142
|
+
}).sort((left, right) => left.choice.localeCompare(right.choice))),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function interfaceMetadata(packageId, packageName, rawPackage) {
|
|
146
|
+
return rawPackage.modules.flatMap((module) => {
|
|
147
|
+
const moduleName = resolveInternedDottedName(rawPackage, module.nameInternedDname);
|
|
148
|
+
return module.interfaces.map((definition) => rawInterfaceMetadata(packageId, packageName, moduleName, definition, rawPackage));
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function rawInterfaceMetadata(packageId, packageName, moduleName, definition, rawPackage) {
|
|
152
|
+
(0, grpc_query_value_mapper_js_1.validDottedNameString)(moduleName, "DAML-LF module name");
|
|
153
|
+
const entityName = resolveInternedDottedName(rawPackage, definition.tyconInternedDname);
|
|
154
|
+
(0, grpc_query_value_mapper_js_1.validDottedNameString)(entityName, "DAML-LF interface name");
|
|
155
|
+
const templateFqn = `${packageName}:${moduleName}:${entityName}`;
|
|
156
|
+
return Object.freeze({
|
|
157
|
+
moduleName,
|
|
158
|
+
entityName,
|
|
159
|
+
payloadType: "interface",
|
|
160
|
+
aliases: contractTypeAliases(packageName, moduleName, entityName),
|
|
161
|
+
templateFqn,
|
|
162
|
+
choices: Object.freeze(definition.choices.map((choice) => rawInterfaceChoiceMetadata(packageId, packageName, moduleName, entityName, choice, rawPackage))
|
|
163
|
+
.sort((left, right) => left.choice.localeCompare(right.choice))),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function rawInterfaceChoiceMetadata(packageId, packageName, moduleName, entityName, choice, rawPackage) {
|
|
167
|
+
const choiceName = resolveInternedString(rawPackage, choice.nameInternedStr);
|
|
168
|
+
(0, grpc_query_value_mapper_js_1.validNameString)(choiceName, `DAML-LF package ${packageId} interface choice name`);
|
|
169
|
+
return Object.freeze({
|
|
170
|
+
choice: choiceName,
|
|
171
|
+
consuming: choice.consuming,
|
|
172
|
+
aliases: exerciseTypeAliases(packageName, moduleName, entityName, choiceName),
|
|
173
|
+
choiceFqn: `${packageName}:${moduleName}:${entityName}:${choiceName}`,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function contractTypeAliases(packageName, moduleName, entityName) {
|
|
177
|
+
return Object.freeze([`${packageName}:${moduleName}:${entityName}`, `${moduleName}:${entityName}`, entityName]);
|
|
178
|
+
}
|
|
179
|
+
function exerciseTypeAliases(packageName, moduleName, entityName, choiceName) {
|
|
180
|
+
return Object.freeze([`${packageName}:${moduleName}:${entityName}:${choiceName}`, `${moduleName}:${entityName}:${choiceName}`, `${entityName}:${choiceName}`, choiceName]);
|
|
181
|
+
}
|
|
182
|
+
function resolveInternedDottedName(rawPackage, index) {
|
|
183
|
+
const dottedName = rawPackage.internedDottedNames[index];
|
|
184
|
+
if (dottedName === undefined) {
|
|
185
|
+
throw new Error("DAML-LF interface references a missing interned dotted name");
|
|
186
|
+
}
|
|
187
|
+
return dottedName.segmentsInternedStr.map((segment) => resolveInternedString(rawPackage, segment)).join(".");
|
|
188
|
+
}
|
|
189
|
+
function resolveInternedString(rawPackage, index) {
|
|
190
|
+
const value = rawPackage.internedStrings[index];
|
|
191
|
+
if (value === undefined) {
|
|
192
|
+
throw new Error("DAML-LF interface references a missing interned string");
|
|
193
|
+
}
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
function requiredPackageText(value, name) {
|
|
197
|
+
if (value.length === 0) {
|
|
198
|
+
throw new Error(`DAML-LF package ${name} is missing`);
|
|
199
|
+
}
|
|
200
|
+
return value;
|
|
201
|
+
}
|
|
202
|
+
function errorMessage(error) {
|
|
203
|
+
try {
|
|
204
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
205
|
+
return typeof message === "string" ? message : "Unknown package service error";
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return "Unknown package service error";
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function isGrpcPackageRelationError(error) {
|
|
212
|
+
try {
|
|
213
|
+
return error instanceof GrpcPackageRelationError;
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GrpcQueryClient = void 0;
|
|
4
|
+
const validation_error_js_1 = require("../../core/errors/validation-error.js");
|
|
5
|
+
const query_capability_error_js_1 = require("../errors/query-capability-error.js");
|
|
6
|
+
const in_memory_query_evaluator_js_1 = require("../canonical/in-memory-query-evaluator.js");
|
|
7
|
+
const query_dataset_js_1 = require("../canonical/query-dataset.js");
|
|
8
|
+
const query_normalizer_js_1 = require("../canonical/query-normalizer.js");
|
|
9
|
+
const query_schema_js_1 = require("../canonical/query-schema.js");
|
|
10
|
+
const query_source_js_1 = require("../query-source.js");
|
|
11
|
+
const grpc_relation_mapper_js_1 = require("./grpc-relation-mapper.js");
|
|
12
|
+
const grpc_package_relation_reader_js_1 = require("./grpc-package-relation-reader.js");
|
|
13
|
+
const grpc_query_snapshot_reader_js_1 = require("./grpc-query-snapshot-reader.js");
|
|
14
|
+
class GrpcQueryClient {
|
|
15
|
+
options;
|
|
16
|
+
source = query_source_js_1.QuerySource.grpc;
|
|
17
|
+
evaluator = new in_memory_query_evaluator_js_1.InMemoryQueryEvaluator();
|
|
18
|
+
dataProvider;
|
|
19
|
+
contracts = this.delegate("contracts");
|
|
20
|
+
contractTypes = this.delegate("contractTypes");
|
|
21
|
+
events = this.delegate("events");
|
|
22
|
+
exercises = this.collectionDelegate("exercises");
|
|
23
|
+
exerciseTypes = this.delegate("exerciseTypes");
|
|
24
|
+
packages = this.delegate("packages");
|
|
25
|
+
transactions = this.delegate("transactions");
|
|
26
|
+
watermark = this.delegate("watermark");
|
|
27
|
+
constructor(options, dataProvider) {
|
|
28
|
+
this.options = options;
|
|
29
|
+
this.dataProvider = dataProvider ?? new DefaultGrpcQueryDataProvider(options);
|
|
30
|
+
}
|
|
31
|
+
async $queryRaw(_sql, _values = []) {
|
|
32
|
+
throw new query_capability_error_js_1.QueryCapabilityError(query_source_js_1.QuerySource.grpc, "query.$queryRaw");
|
|
33
|
+
}
|
|
34
|
+
async cacheContracts(args) {
|
|
35
|
+
if (this.options.contractCache === undefined) {
|
|
36
|
+
throw new validation_error_js_1.ValidationError("gRPC contract caching requires configured cache storage and ttlMs.");
|
|
37
|
+
}
|
|
38
|
+
return this.options.contractCache.cacheContracts(args);
|
|
39
|
+
}
|
|
40
|
+
async invalidateContractsCache(args) {
|
|
41
|
+
await this.options.contractCache?.invalidateContractsCache(args);
|
|
42
|
+
}
|
|
43
|
+
delegate(relation) {
|
|
44
|
+
return {
|
|
45
|
+
findMany: async (args = {}) => this.execute((0, query_normalizer_js_1.normalizeFindMany)(relation, args)),
|
|
46
|
+
findUnique: async (args) => this.execute((0, query_normalizer_js_1.normalizeFindUnique)(relation, args)),
|
|
47
|
+
count: async (args = {}) => this.execute((0, query_normalizer_js_1.normalizeCount)(relation, args)),
|
|
48
|
+
aggregate: async (args) => this.execute((0, query_normalizer_js_1.normalizeAggregate)(relation, args)),
|
|
49
|
+
groupBy: async (args) => this.execute((0, query_normalizer_js_1.normalizeGroupBy)(relation, args)),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
collectionDelegate(relation) {
|
|
53
|
+
const delegate = this.delegate(relation);
|
|
54
|
+
delete delegate.findUnique;
|
|
55
|
+
return delegate;
|
|
56
|
+
}
|
|
57
|
+
async execute(query) {
|
|
58
|
+
const dataset = await this.dataProvider.readDatasetAsync(query);
|
|
59
|
+
return this.evaluator.execute(dataset, query);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.GrpcQueryClient = GrpcQueryClient;
|
|
63
|
+
class DefaultGrpcQueryDataProvider {
|
|
64
|
+
options;
|
|
65
|
+
snapshots;
|
|
66
|
+
packages;
|
|
67
|
+
constructor(options) {
|
|
68
|
+
this.options = options;
|
|
69
|
+
this.snapshots = new grpc_query_snapshot_reader_js_1.GrpcQuerySnapshotReader(options.stateService, options.updateService);
|
|
70
|
+
this.packages = new grpc_package_relation_reader_js_1.GrpcPackageRelationReader(options.packageService);
|
|
71
|
+
}
|
|
72
|
+
async readDatasetAsync(query) {
|
|
73
|
+
const closure = relationClosure(query);
|
|
74
|
+
const needsHistory = requiresHistory(query);
|
|
75
|
+
const activeOnly = query.relation === "contracts" && isActiveOnly(query);
|
|
76
|
+
const cached = activeOnly && this.options.contractCache !== undefined
|
|
77
|
+
? await this.options.contractCache.readSnapshotAsync({ parties: partiesFor(query) })
|
|
78
|
+
: undefined;
|
|
79
|
+
if (cached !== undefined && !needsHistory && !requiresPackageMetadata(closure)) {
|
|
80
|
+
return cachedContractsDataset(cached.contracts, cached.activeAtOffset, this.options.endpointScope ?? "ledger");
|
|
81
|
+
}
|
|
82
|
+
else if (needsHistory) {
|
|
83
|
+
const endInclusive = cached?.activeAtOffset ?? (await this.options.stateService.getLedgerEndAsync({})).offset;
|
|
84
|
+
const history = await this.snapshots.readHistoryAsync(endInclusive);
|
|
85
|
+
const transactions = history.updates.flatMap((response) => response.update.oneofKind === "transaction" ? [response.update.transaction] : []);
|
|
86
|
+
const fragment = (0, grpc_relation_mapper_js_1.mapGrpcQueryRelationFragment)(transactions);
|
|
87
|
+
const packageMetadata = !requiresPackageMetadata(closure)
|
|
88
|
+
? []
|
|
89
|
+
: query.relation === "packages" || query.relation === "contractTypes" || query.relation === "exerciseTypes"
|
|
90
|
+
? await this.packages.readAllAsync()
|
|
91
|
+
: await this.packages.readPackagesAsync((0, grpc_relation_mapper_js_1.referencedGrpcPackageIds)(fragment));
|
|
92
|
+
return packageMetadata.length === 0
|
|
93
|
+
? fragmentDataset(fragment, endInclusive, this.options.endpointScope ?? "ledger")
|
|
94
|
+
: (0, grpc_relation_mapper_js_1.createGrpcQueryDataset)(fragment, packageMetadata, endInclusive, this.options.endpointScope ?? "ledger");
|
|
95
|
+
}
|
|
96
|
+
const endInclusive = cached?.activeAtOffset ?? (await this.options.stateService.getLedgerEndAsync({})).offset;
|
|
97
|
+
if (query.relation === "packages" || query.relation === "contractTypes" || query.relation === "exerciseTypes") {
|
|
98
|
+
return (0, grpc_relation_mapper_js_1.createGrpcQueryDataset)((0, grpc_relation_mapper_js_1.mapGrpcQueryRelationFragment)([]), await this.packages.readAllAsync(), endInclusive, this.options.endpointScope ?? "ledger");
|
|
99
|
+
}
|
|
100
|
+
else if (query.relation === "watermark") {
|
|
101
|
+
return (0, grpc_relation_mapper_js_1.createGrpcQueryDataset)((0, grpc_relation_mapper_js_1.mapGrpcQueryRelationFragment)([]), [], endInclusive, this.options.endpointScope ?? "ledger");
|
|
102
|
+
}
|
|
103
|
+
const active = await this.snapshots.readActiveContractsAsync(endInclusive, partiesFor(query));
|
|
104
|
+
const fragment = (0, grpc_relation_mapper_js_1.mapGrpcQueryRelationFragment)([], active.activeContracts);
|
|
105
|
+
return requiresPackageMetadata(closure)
|
|
106
|
+
? (0, grpc_relation_mapper_js_1.createGrpcQueryDataset)(fragment, await this.packages.readPackagesAsync((0, grpc_relation_mapper_js_1.referencedGrpcPackageIds)(fragment)), endInclusive, this.options.endpointScope ?? "ledger")
|
|
107
|
+
: fragmentDataset(fragment, endInclusive, this.options.endpointScope ?? "ledger", false);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function requiresHistory(query) {
|
|
111
|
+
if (query.relation === "transactions" || query.relation === "events" || query.relation === "exercises") {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
else if (query.relation === "contracts" && !isActiveOnly(query)) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
return predicateRequiresHistory(query.relation, query.predicate) || includesRequireHistory(query.relation, includesFor(query));
|
|
118
|
+
}
|
|
119
|
+
function partiesFor(query) {
|
|
120
|
+
return query.kind === "findMany" || query.kind === "count" ? query.parties : undefined;
|
|
121
|
+
}
|
|
122
|
+
function includesFor(query) {
|
|
123
|
+
return query.kind === "findMany" || query.kind === "findUnique" ? query.includes : [];
|
|
124
|
+
}
|
|
125
|
+
function isActiveOnly(query) {
|
|
126
|
+
if (query.kind === "findMany" || query.kind === "count") {
|
|
127
|
+
return query.activeOnly;
|
|
128
|
+
}
|
|
129
|
+
return predicateProvesActive(query.predicate);
|
|
130
|
+
}
|
|
131
|
+
function predicateProvesActive(predicate) {
|
|
132
|
+
if (predicate === undefined) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
else if (predicate.kind === "scalar") {
|
|
136
|
+
return predicate.path.length === 1 && predicate.path[0] === "active" && predicate.operator === "equals" && predicate.value === true;
|
|
137
|
+
}
|
|
138
|
+
else if (predicate.kind === "and") {
|
|
139
|
+
return predicate.children.some(predicateProvesActive);
|
|
140
|
+
}
|
|
141
|
+
else if (predicate.kind === "or") {
|
|
142
|
+
return predicate.children.length > 0 && predicate.children.every(predicateProvesActive);
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
function requiresPackageMetadata(closure) {
|
|
147
|
+
return closure.has("packages") || closure.has("contractTypes") || closure.has("exercises") || closure.has("exerciseTypes");
|
|
148
|
+
}
|
|
149
|
+
function predicateRequiresHistory(relation, predicate) {
|
|
150
|
+
if (predicate === undefined || predicate.kind === "scalar") {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
else if (predicate.kind === "not") {
|
|
154
|
+
return predicateRequiresHistory(relation, predicate.child);
|
|
155
|
+
}
|
|
156
|
+
else if (predicate.kind === "and" || predicate.kind === "or") {
|
|
157
|
+
return predicate.children.some((child) => predicateRequiresHistory(relation, child));
|
|
158
|
+
}
|
|
159
|
+
else if (predicate.kind !== "relation") {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
const target = query_schema_js_1.queryRelationEdges[relation]?.[predicate.edge]?.target;
|
|
163
|
+
return target === "contracts" || target === "transactions" || target === "events" || target === "exercises" || target !== undefined && predicateRequiresHistory(target, predicate.predicate);
|
|
164
|
+
}
|
|
165
|
+
function includesRequireHistory(relation, includes) {
|
|
166
|
+
return includes.some((include) => include.relation === "contracts" || include.relation === "transactions" || include.relation === "events" || include.relation === "exercises" || predicateRequiresHistory(include.relation, include.predicate) || includesRequireHistory(include.relation, include.includes));
|
|
167
|
+
}
|
|
168
|
+
function relationClosure(query) {
|
|
169
|
+
const relations = new Set([query.relation]);
|
|
170
|
+
const visitPredicate = (relation, predicate) => {
|
|
171
|
+
if (predicate === undefined || predicate.kind === "scalar") {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
else if (predicate.kind === "relation") {
|
|
175
|
+
const target = query_schema_js_1.queryRelationEdges[relation]?.[predicate.edge]?.target;
|
|
176
|
+
if (target !== undefined) {
|
|
177
|
+
relations.add(target);
|
|
178
|
+
visitPredicate(target, predicate.predicate);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else if (predicate.kind === "not") {
|
|
182
|
+
visitPredicate(relation, predicate.child);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
predicate.children.forEach((child) => visitPredicate(relation, child));
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const visitIncludes = (relation, includes) => {
|
|
189
|
+
for (const include of includes) {
|
|
190
|
+
relations.add(include.relation);
|
|
191
|
+
visitPredicate(include.relation, include.predicate);
|
|
192
|
+
visitIncludes(include.relation, include.includes);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
visitPredicate(query.relation, query.predicate);
|
|
196
|
+
visitIncludes(query.relation, includesFor(query));
|
|
197
|
+
if (query.kind === "groupBy") {
|
|
198
|
+
for (const group of query.by) {
|
|
199
|
+
addRelationPath(query.relation, group.path, relations);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
else if (query.kind === "findMany") {
|
|
203
|
+
for (const order of query.orderBy) {
|
|
204
|
+
addRelationPath(query.relation, order.path, relations);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return relations;
|
|
208
|
+
}
|
|
209
|
+
function addRelationPath(relation, path, relations) {
|
|
210
|
+
if (path.length > 1) {
|
|
211
|
+
const target = query_schema_js_1.queryRelationEdges[relation]?.[path[0]]?.target;
|
|
212
|
+
if (target !== undefined) {
|
|
213
|
+
relations.add(target);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function cachedContractsDataset(contracts, offset, instanceId) {
|
|
218
|
+
const empty = [];
|
|
219
|
+
return basicDataset({ contracts: contracts, transactions: empty, events: empty, exercises: empty }, offset, instanceId, false);
|
|
220
|
+
}
|
|
221
|
+
function fragmentDataset(fragment, offset, instanceId, completeHistoryEdges = true) {
|
|
222
|
+
return basicDataset(fragment, offset, instanceId, completeHistoryEdges);
|
|
223
|
+
}
|
|
224
|
+
function basicDataset(rows, offset, instanceId, completeHistoryEdges = true) {
|
|
225
|
+
const empty = [];
|
|
226
|
+
return (0, query_dataset_js_1.createQueryDataset)({
|
|
227
|
+
rows: { contracts: rows.contracts, contractTypes: empty, events: rows.events, exercises: rows.exercises, exerciseTypes: empty, packages: empty, transactions: rows.transactions, watermark: [{ singleton: true, ix: offset, offset, instanceId }] },
|
|
228
|
+
uniqueKeys: { contracts: [["contractId"]], contractTypes: [["pk"]], events: [["pk"]], exercises: [["tpePk", "contractTpePk", "exerciseEventPk", "contractId"]], exerciseTypes: [["pk"]], packages: [["pk"], ["id"]], transactions: [["ix"], ["offset"]], watermark: [["singleton"]] },
|
|
229
|
+
edges: Object.fromEntries(query_schema_js_1.queryRelations.map((relation) => [relation, Object.fromEntries(Object.keys(query_schema_js_1.queryRelationEdges[relation] ?? {}).map((edge) => [edge, { ...cachedEdgePaths(relation, edge), ...(completeHistoryEdges ? completeFragmentEdge(relation, edge) : { complete: false }) }]))])),
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
function completeFragmentEdge(relation, edge) {
|
|
233
|
+
const complete = new Set([
|
|
234
|
+
"contracts.createdTransaction", "contracts.archivedTransaction", "contracts.exercises",
|
|
235
|
+
"events.transaction", "events.exercises",
|
|
236
|
+
"exercises.event", "exercises.transaction", "exercises.contract",
|
|
237
|
+
"transactions.events", "transactions.createdContracts", "transactions.archivedContracts", "transactions.exercises",
|
|
238
|
+
]);
|
|
239
|
+
return complete.has(`${relation}.${edge}`) ? {} : { complete: false };
|
|
240
|
+
}
|
|
241
|
+
function cachedEdgePaths(relation, edge) {
|
|
242
|
+
const paths = {
|
|
243
|
+
"contracts.contractType": { from: ["contractId"], to: ["pk"] }, "contracts.createdTransaction": { from: ["createdEventOffset"], to: ["ix"] }, "contracts.archivedTransaction": { from: ["archivedEventOffset"], to: ["ix"] }, "contracts.exercises": { from: ["contractId"], to: ["contractId"] },
|
|
244
|
+
"contractTypes.contracts": { from: ["pk"], to: ["contractId"] }, "contractTypes.exercises": { from: ["pk"], to: ["contractTpePk"] }, "events.transaction": { from: ["txIx"], to: ["ix"] }, "events.exercises": { from: ["pk"], to: ["exerciseEventPk"] },
|
|
245
|
+
"exercises.exerciseType": { from: ["tpePk"], to: ["pk"] }, "exercises.contractType": { from: ["contractTpePk"], to: ["pk"] }, "exercises.event": { from: ["exerciseEventPk"], to: ["pk"] }, "exercises.transaction": { from: ["exercisedAtIx"], to: ["ix"] }, "exercises.package": { from: ["packagePk"], to: ["pk"] }, "exercises.contract": { from: ["contractId"], to: ["contractId"] },
|
|
246
|
+
"exerciseTypes.exercises": { from: ["pk"], to: ["tpePk"] }, "packages.exercises": { from: ["pk"], to: ["packagePk"] }, "transactions.events": { from: ["ix"], to: ["txIx"] }, "transactions.createdContracts": { from: ["ix"], to: ["createdEventOffset"] }, "transactions.archivedContracts": { from: ["ix"], to: ["archivedEventOffset"] }, "transactions.exercises": { from: ["ix"], to: ["exercisedAtIx"] },
|
|
247
|
+
};
|
|
248
|
+
return paths[`${relation}.${edge}`];
|
|
249
|
+
}
|