@distrohelena/canton-typescript-sdk 0.1.32 → 0.1.35

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 (121) hide show
  1. package/README.md +220 -9
  2. package/dist/cjs/client/external-party-activation-client.js +20 -10
  3. package/dist/cjs/core/errors/active-contracts-traversal-error.js +12 -0
  4. package/dist/cjs/core/polling/poll-until-async.js +26 -0
  5. package/dist/cjs/core/types/active-contracts-traversal-options.js +26 -0
  6. package/dist/cjs/core/types/command-deduplication-period.js +2 -0
  7. package/dist/cjs/core/types/operation-deadline.js +42 -0
  8. package/dist/cjs/core/types/requests/allocate-party-request.js +2 -0
  9. package/dist/cjs/core/types/requests/finalize-decentralized-party-request.js +6 -0
  10. package/dist/cjs/core/types/requests/submit-command-request.js +43 -0
  11. package/dist/cjs/core/types/requests/wait-for-party-hosting-request.js +40 -0
  12. package/dist/cjs/index.js +13 -27
  13. package/dist/cjs/query/grpc/grpc-contract-query-client.js +33 -16
  14. package/dist/cjs/services/party-management/decentralized-party-lifecycle.js +28 -3
  15. package/dist/cjs/services/party-management/party-management-service-client.js +3 -0
  16. package/dist/cjs/services/state/state-service-client.js +1 -1
  17. package/dist/cjs/services/topology-aggregation/topology-aggregation-service-client.js +36 -0
  18. package/dist/cjs/transports/grpc/grpc-channel-factory.js +5 -7
  19. package/dist/cjs/transports/grpc/grpc-transport.js +31 -15
  20. package/dist/cjs/transports/grpc/mappers/command-deduplication-mapper.js +22 -0
  21. package/dist/cjs/transports/grpc/mappers/commands-mapper.js +3 -4
  22. package/dist/cjs/transports/grpc/mappers/interactive-command-mapper.js +5 -3
  23. package/dist/cjs/transports/grpc/mappers/parties-mapper.js +1 -12
  24. package/dist/cjs/transports/json/mappers/commands-mapper.js +5 -1
  25. package/dist/cjs/transports/json/mappers/parties-mapper.js +1 -0
  26. package/dist/client/external-party-activation-client.js +20 -10
  27. package/dist/client/external-party-activation-response.d.ts +1 -1
  28. package/dist/core/errors/active-contracts-traversal-error.d.ts +5 -0
  29. package/dist/core/errors/active-contracts-traversal-error.js +8 -0
  30. package/dist/core/polling/poll-until-async.d.ts +10 -0
  31. package/dist/core/polling/poll-until-async.js +23 -0
  32. package/dist/core/transports/transport.interface.d.ts +11 -3
  33. package/dist/core/types/active-contracts-traversal-options.d.ts +11 -0
  34. package/dist/core/types/active-contracts-traversal-options.js +22 -0
  35. package/dist/core/types/command-deduplication-period.d.ts +7 -0
  36. package/dist/core/types/command-deduplication-period.js +1 -0
  37. package/dist/core/types/operation-deadline.d.ts +13 -0
  38. package/dist/core/types/operation-deadline.js +38 -0
  39. package/dist/core/types/requests/allocate-party-request.d.ts +2 -0
  40. package/dist/core/types/requests/allocate-party-request.js +2 -0
  41. package/dist/core/types/requests/finalize-decentralized-party-request.d.ts +6 -0
  42. package/dist/core/types/requests/finalize-decentralized-party-request.js +6 -0
  43. package/dist/core/types/requests/submit-command-request.d.ts +5 -0
  44. package/dist/core/types/requests/submit-command-request.js +43 -0
  45. package/dist/core/types/requests/wait-for-party-hosting-request.d.ts +14 -0
  46. package/dist/core/types/requests/wait-for-party-hosting-request.js +36 -0
  47. package/dist/index.d.ts +5 -11
  48. package/dist/index.js +4 -11
  49. package/dist/query/grpc/grpc-contract-query-client.js +33 -16
  50. package/dist/services/party-management/decentralized-party-lifecycle.d.ts +1 -1
  51. package/dist/services/party-management/decentralized-party-lifecycle.js +28 -3
  52. package/dist/services/party-management/party-management-service-client.js +3 -0
  53. package/dist/services/state/state-service-client.d.ts +1 -1
  54. package/dist/services/state/state-service-client.js +1 -1
  55. package/dist/services/topology-aggregation/topology-aggregation-service-client.d.ts +4 -1
  56. package/dist/services/topology-aggregation/topology-aggregation-service-client.js +36 -0
  57. package/dist/services/topology-manager-read/topology-manager-read-service-client.d.ts +3 -1
  58. package/dist/services/user-management/user-management-service-client.d.ts +7 -1
  59. package/dist/transports/grpc/grpc-channel-factory.d.ts +0 -1
  60. package/dist/transports/grpc/grpc-channel-factory.js +5 -7
  61. package/dist/transports/grpc/grpc-transport.d.ts +10 -3
  62. package/dist/transports/grpc/grpc-transport.js +31 -15
  63. package/dist/transports/grpc/mappers/command-deduplication-mapper.d.ts +5 -0
  64. package/dist/transports/grpc/mappers/command-deduplication-mapper.js +19 -0
  65. package/dist/transports/grpc/mappers/commands-mapper.js +3 -4
  66. package/dist/transports/grpc/mappers/interactive-command-mapper.js +5 -3
  67. package/dist/transports/grpc/mappers/parties-mapper.d.ts +3 -7
  68. package/dist/transports/grpc/mappers/parties-mapper.js +1 -10
  69. package/dist/transports/json/json-transport.d.ts +10 -5
  70. package/dist/transports/json/mappers/commands-mapper.js +5 -1
  71. package/dist/transports/json/mappers/parties-mapper.d.ts +1 -0
  72. package/dist/transports/json/mappers/parties-mapper.js +1 -0
  73. package/node/participant-358-synchronizer.mjs +174 -0
  74. package/node/start-local-participant-358.sh +214 -0
  75. package/node/stop-local-participant-358.sh +18 -0
  76. package/node/test-participant-358-sidecar-smoke.sh +19 -0
  77. package/node/test-participant-358-sidecar.sh +113 -0
  78. package/package.json +18 -2
  79. package/dist/cjs/core/types/health-check-status.js +0 -10
  80. package/dist/cjs/core/types/requests/get-ledger-api-version-request.js +0 -6
  81. package/dist/cjs/core/types/requests/get-package-references-request.js +0 -10
  82. package/dist/cjs/core/types/requests/get-participant-id-request.js +0 -7
  83. package/dist/cjs/core/types/requests/get-participant-status-request.js +0 -6
  84. package/dist/cjs/core/types/requests/health-check-request.js +0 -10
  85. package/dist/cjs/core/types/responses/get-ledger-api-version-response.js +0 -12
  86. package/dist/cjs/core/types/responses/get-package-references-response.js +0 -10
  87. package/dist/cjs/core/types/responses/get-participant-id-response.js +0 -10
  88. package/dist/cjs/core/types/responses/get-participant-status-response.js +0 -12
  89. package/dist/cjs/core/types/responses/health-check-response.js +0 -10
  90. package/dist/cjs/transports/grpc/mappers/health-mapper.js +0 -24
  91. package/dist/cjs/transports/grpc/mappers/participant-status-mapper.js +0 -58
  92. package/dist/core/types/health-check-status.d.ts +0 -6
  93. package/dist/core/types/health-check-status.js +0 -7
  94. package/dist/core/types/requests/get-ledger-api-version-request.d.ts +0 -2
  95. package/dist/core/types/requests/get-ledger-api-version-request.js +0 -2
  96. package/dist/core/types/requests/get-package-references-request.d.ts +0 -6
  97. package/dist/core/types/requests/get-package-references-request.js +0 -6
  98. package/dist/core/types/requests/get-participant-id-request.d.ts +0 -3
  99. package/dist/core/types/requests/get-participant-id-request.js +0 -3
  100. package/dist/core/types/requests/get-participant-status-request.d.ts +0 -2
  101. package/dist/core/types/requests/get-participant-status-request.js +0 -2
  102. package/dist/core/types/requests/health-check-request.d.ts +0 -6
  103. package/dist/core/types/requests/health-check-request.js +0 -6
  104. package/dist/core/types/responses/get-ledger-api-version-response.d.ts +0 -8
  105. package/dist/core/types/responses/get-ledger-api-version-response.js +0 -8
  106. package/dist/core/types/responses/get-package-references-response.d.ts +0 -7
  107. package/dist/core/types/responses/get-package-references-response.js +0 -6
  108. package/dist/core/types/responses/get-participant-id-response.d.ts +0 -6
  109. package/dist/core/types/responses/get-participant-id-response.js +0 -6
  110. package/dist/core/types/responses/get-participant-status-response.d.ts +0 -10
  111. package/dist/core/types/responses/get-participant-status-response.js +0 -8
  112. package/dist/core/types/responses/health-check-response.d.ts +0 -7
  113. package/dist/core/types/responses/health-check-response.js +0 -6
  114. package/dist/transports/grpc/mappers/health-mapper.d.ts +0 -5
  115. package/dist/transports/grpc/mappers/health-mapper.js +0 -21
  116. package/dist/transports/grpc/mappers/participant-status-mapper.d.ts +0 -5
  117. package/dist/transports/grpc/mappers/participant-status-mapper.js +0 -54
  118. package/node/.generated/start-local/additional-config.extra-participants.conf +0 -72
  119. package/node/.generated/start-local/additional-config.extra-validators.conf +0 -105
  120. package/node/.generated/start-local/compose-extra-participants.yaml +0 -366
  121. package/node/.generated/start-local/extra-participants.env +0 -88
package/README.md CHANGED
@@ -86,6 +86,151 @@ Participant 3.5.7. In particular, external-party allocation signs the generated
86
86
  combined topology hash (`multi_hash`) rather than each topology transaction
87
87
  individually.
88
88
 
89
+ The decentralized Ed25519 example was also run end-to-end against an isolated
90
+ Canton Participant 3.5.8 sidecar. On both 3.5.7 and 3.5.8 it creates the same
91
+ topology shape: a serial-1 decentralized namespace definition, one self-root
92
+ namespace certificate per owner, and a PartyToParticipant containing the party
93
+ signing key. No deprecated PartyToKeyMapping is created.
94
+
95
+ The SDK preserves `identityProviderId`, `userId`, and `waitForAllocation`
96
+ through decentralized prepare/finalize. Canton ignores `waitForAllocation` for
97
+ decentralized parties, so the example explicitly calls
98
+ `topologyAggregationService.waitForPartyHostingAsync(...)` to prove that the
99
+ expected participant is hosting the party on the expected synchronizer. That
100
+ aggregate topology check is the same on Participant 3.5.7 and 3.5.8.
101
+
102
+ ## Standalone TypeScript examples
103
+
104
+ The repository includes runnable TypeScript examples for a local Canton
105
+ participant. Check them before running a lifecycle:
106
+
107
+ ```bash
108
+ npm run examples:check
109
+ ```
110
+
111
+ The setup and party examples are available individually:
112
+
113
+ ```bash
114
+ npm run example:init
115
+ npm run example:tls
116
+ npm run example:jwt
117
+ npm run example:party:hosted
118
+ npm run example:party:external
119
+ npm run example:party:decentralized
120
+ ```
121
+
122
+ For the application lifecycle, run these in order:
123
+
124
+ ```bash
125
+ npm run example:dar:upload
126
+ npm run example:contract:create-exercise
127
+ npm run example:contract:query
128
+ npm run example:updates:stream
129
+ npm run example:user:rights
130
+ npm run example:topology:party-hosting
131
+ ```
132
+
133
+ ### Workflow examples
134
+
135
+ The four workflow examples are standalone proofs, not a sequence: each uploads
136
+ or verifies the fixture DAR, resolves a party, reads the participant status,
137
+ and creates its own run-scoped data. First make a Canton participant available
138
+ and verify the source with `npm run examples:check`; the default endpoints and
139
+ authentication environment variables are documented below. Run any example
140
+ independently:
141
+
142
+ ```bash
143
+ npm run example:workflow:atomic
144
+ npm run example:workflow:retry
145
+ npm run example:workflow:resume
146
+ npm run example:workflow:stale-contract
147
+ ```
148
+
149
+ They intentionally leave durable state behind. A missing `SDK_EXAMPLE_PARTY`
150
+ causes fallback party allocation, which creates durable topology state; every
151
+ workflow also creates durable contracts. Set `SDK_EXAMPLE_PARTY` to an existing
152
+ party to rerun all four against that party and avoid fallback allocation. The
153
+ fixture DAR remains installed after a run.
154
+
155
+ Each program prints its actor plus the full participant version returned by the
156
+ authenticated status API, its parsed release core, and its selected path:
157
+ `Participant version:`, `Release core:`, and `Compatibility path:`. The current
158
+ implementation uses one common-code path for release cores 3.5.7 and 3.5.8. It
159
+ adds a version-specific behavioral difference only after live evidence proves
160
+ one; it does not infer compatibility from a container tag or endpoint.
161
+
162
+ - `example:workflow:atomic` first proves that an invalid choice is rejected,
163
+ then proves an atomic create-and-exercise by reading the created replacement
164
+ and its exact text.
165
+ - `example:workflow:retry` submits a caller-controlled command ID with a
166
+ deduplication duration, retries the exact same request, classifies the
167
+ duplicate outcome, and proves that exactly one matching contract is active.
168
+ - `example:workflow:resume` saves the ledger end before its post-offset create,
169
+ proves the intentionally idle stream timeout, then resumes exclusively after
170
+ that saved offset and rejects a pre-offset contract if it appears.
171
+ - `example:workflow:stale-contract` proves archive/replacement state and then
172
+ proves that exercising the archived contract is rejected.
173
+
174
+ Expected failures are accepted only through structured error classification:
175
+ gRPC status code, decoded status, operation, and the selected compatibility
176
+ path—not prose matching. The retry example uses one explicit command ID and
177
+ deduplication period for the exact same request; changing either value is a new
178
+ request and is not a retry proof. The resume example treats the saved offset as
179
+ exclusive, so its resumed stream must observe only updates after the saved
180
+ ledger end.
181
+
182
+ The workflow source and unit contracts were developed and live-tested against
183
+ authenticated Participant 3.5.7 and the isolated Participant 3.5.8. Both
184
+ final-tree matrices selected the same unchanged implementation and common
185
+ compatibility path. The normalized outcome comparison is identical: atomic
186
+ reports `invalidChoice` before its replacement proof, retry reports
187
+ `duplicateCommand` with one active contract, resume reports `idle-timeout` and
188
+ a post-offset update, and stale-contract reports `staleContract`.
189
+
190
+ The best multi-version path reads the authenticated full version, parses its
191
+ release core, and uses data-only structured compatibility for observed
192
+ outcomes. A behavioral difference is introduced only after live proof; it is
193
+ never inferred from a container tag, endpoint, or prose error message. For the
194
+ isolated 3.5.8 sidecar, use the SDK sidecar launcher's protected documented
195
+ credential refresh flow in a local child shell and refresh before expiry. Never
196
+ log its output or expose refreshed credentials beyond that child. Use the
197
+ documented `SDK_EXAMPLE_*` environment variables when running the workflow
198
+ commands.
199
+
200
+ By default, Ledger and Ledger Admin use `localhost:3901`; Participant Admin
201
+ uses `localhost:3902`. Override them with
202
+ `SDK_EXAMPLE_LEDGER_ENDPOINT`, `SDK_EXAMPLE_LEDGER_ADMIN_ENDPOINT`, and
203
+ `SDK_EXAMPLE_PARTICIPANT_ADMIN_ENDPOINT`. Use `SDK_EXAMPLE_BEARER_TOKEN` for a
204
+ shared bearer token, or set `SDK_EXAMPLE_LEDGER_BEARER_TOKEN`,
205
+ `SDK_EXAMPLE_LEDGER_ADMIN_BEARER_TOKEN`, and
206
+ `SDK_EXAMPLE_PARTICIPANT_ADMIN_BEARER_TOKEN` per surface. The examples also
207
+ accept `SDK_EXAMPLE_PARTY`, `SDK_EXAMPLE_USER_ID`, `SDK_EXAMPLE_SYNCHRONIZER`,
208
+ and `SDK_EXAMPLE_TIMEOUT_MS`; generated fallback party names use
209
+ `SDK_EXAMPLE_PARTY_PREFIX` when supplied. For TLS, set
210
+ `SDK_EXAMPLE_TLS_ROOT_CERTIFICATE` to a custom CA certificate path.
211
+
212
+ Some commands intentionally create durable localnet state: DAR upload installs
213
+ a package; create/exercise, query, and stream may allocate a fallback party and
214
+ create contracts; topology inspection may allocate a fallback party. User-rights
215
+ is read-only. These examples do not clean up durable state.
216
+
217
+ The uploaded asset is
218
+ `canton-explorer-debug-playground-0.1.0.dar`, the normal (not debug) Canton
219
+ Explorer Debug Playground DAR from
220
+ `/home/helena/dev/daml/canton-explorer/debug-playground/.daml/dist/canton-explorer-debug-playground-0.1.0.dar`.
221
+ Its Canton Explorer checkout commit is `750b28dd0ce4674e4368c12a6da1b5b5cbb00f88`,
222
+ its package-introduction commit is `abde077`, it is Apache-2.0 licensed, and
223
+ its SHA-256 is
224
+ `307cf7c52ac2770d1d1a2c5e1ec56a78ab7c70e7809c0cfb419abadb93cc6e29`.
225
+
226
+ The examples and their DAR are repository-only and excluded from the npm
227
+ tarball. The existing setup and decentralized-party examples were developed
228
+ and live-tested against Participant 3.5.7, then live-tested unchanged against
229
+ the isolated [Participant 3.5.8 sidecar](#optional-canton-358-participant-sidecar).
230
+ The workflow examples have completed 3.5.7 and 3.5.8 workflow matrices with
231
+ authenticated status evidence, the same unchanged implementation, and the
232
+ common compatibility path.
233
+
89
234
  ## Localnet launchers
90
235
 
91
236
  The published package includes launchers for an existing CN Quickstart checkout.
@@ -110,6 +255,67 @@ npm exec --package @distrohelena/canton-typescript-sdk canton-localnet-stop
110
255
  These commands launch and stop CN Quickstart; they do not provision a
111
256
  Quickstart checkout.
112
257
 
258
+ ### Optional Canton 3.5.8 participant sidecar
259
+
260
+ For SDK compatibility work, an isolated Canton 3.5.8 participant can join an
261
+ already-running CN Quickstart localnet without changing its files or Compose
262
+ project:
263
+
264
+ ```bash
265
+ canton-localnet-participant-358-start
266
+ canton-localnet-participant-358-stop
267
+ ```
268
+
269
+ The sidecar owns `.generated/participant-358`, its `canton-participant-358`
270
+ Compose project, its Postgres container, and host ports `8901` (Ledger), `8902`
271
+ (Admin), and `8975` (JSON). The start launcher reads the existing localnet's
272
+ registered synchronizer via its Admin API, stores the exported connection
273
+ configuration in the sidecar runtime directory, and connects the sidecar with
274
+ its own Admin API. It generates a five-minute 3.5.8-compatible development JWT
275
+ at `.generated/participant-358/ledger-api-user.token`. When the connection is
276
+ healthy, use the protected child-shell credential flow below to make the
277
+ live-test and example endpoint/token variables available without logging them.
278
+ Canton 3.5.8 enforces this short lifetime for the unsafe development JWT.
279
+ `cn-quickstart` is strictly read-only: this launcher never writes to, starts,
280
+ or stops the normal Quickstart stack.
281
+
282
+ Refresh short-lived credentials before expiry without restarting or otherwise
283
+ touching the running containers. Use the launcher's protected documented
284
+ credential refresh flow only in a local child shell; do not log its output or
285
+ expose refreshed credentials beyond that child. The runtime credential file
286
+ remains protected with mode `0600`.
287
+
288
+ After the protected credential flow completes, run the example inside that same
289
+ short-lived credential-scoped child shell:
290
+
291
+ ```bash
292
+ npm run example:party:decentralized
293
+ ```
294
+
295
+ The defaults target the normal insecure shared-secret localnet at
296
+ `localhost:3902` on its `quickstart` Docker network. Override them when your
297
+ localnet differs:
298
+
299
+ ```bash
300
+ PARTICIPANT_358_SOURCE_ADMIN_ENDPOINT=localhost:3902 \
301
+ PARTICIPANT_358_NETWORK=quickstart \
302
+ canton-localnet-participant-358-start
303
+ ```
304
+
305
+ Provide any required source-admin credential only through the protected
306
+ child-scoped credential mechanism described above; do not place credentials in
307
+ command lines or logs.
308
+
309
+ Use `PARTICIPANT_358_CANTON_IMAGE`, `PARTICIPANT_358_PROJECT_NAME`,
310
+ `PARTICIPANT_358_RUNTIME_DIR`, `PARTICIPANT_358_LEDGER_PORT`,
311
+ `PARTICIPANT_358_ADMIN_PORT`, and `PARTICIPANT_358_JSON_PORT` to make an
312
+ explicitly isolated variant. The opt-in Docker check requires a running
313
+ localnet and is never part of the normal test suite:
314
+
315
+ ```bash
316
+ PARTICIPANT_358_SMOKE_TEST=1 npm run test:participant-358-sidecar-smoke
317
+ ```
318
+
113
319
  ### Optional ES256 bearer tokens
114
320
 
115
321
  Set `LOCALNET_ES256_JWT=1` when starting the localnet to add ES256 JWT
@@ -123,11 +329,12 @@ a self-signed certificate in `.generated/localnet-es256` at the package root. Se
123
329
  use your own matching PEM private key and certificate.
124
330
 
125
331
  The launcher writes a short-lived (ten-minute) token for `ledger-api-user` to
126
- `ledger-api-user.token` in that runtime directory and prints its path. Use it
127
- with the live SDK suite:
332
+ `ledger-api-user.token` in that runtime directory and prints its path. In a
333
+ short-lived child shell, use a protected local credential mechanism to make the
334
+ token available without placing its value or a token-file read in a command
335
+ line or log. From within that same child shell, run the live SDK suite:
128
336
 
129
337
  ```bash
130
- SDK_TEST_LEDGER_BEARER_TOKEN="$(cat .generated/localnet-es256/ledger-api-user.token)" \
131
338
  npm run test:live
132
339
  ```
133
340
 
@@ -300,11 +507,11 @@ import {
300
507
  BearerTokenAuthProvider,
301
508
  CantonClient,
302
509
  CantonClientOptions,
303
- GetActiveContractsPageRequest,
304
510
  HealthCheckRequest,
305
511
  GetLedgerApiVersionRequest,
306
512
  TransportKind,
307
513
  } from "@distrohelena/canton-typescript-sdk";
514
+ import { ledgerApiV2 } from "@distrohelena/canton-typescript-sdk/protobuf";
308
515
 
309
516
  const client = new CantonClient(
310
517
  new CantonClientOptions({
@@ -337,14 +544,18 @@ const party = await client.partyManagementService.allocatePartyAsync(
337
544
  }),
338
545
  );
339
546
  const contracts = await client.stateService.getActiveContractsPageAsync(
340
- new GetActiveContractsPageRequest({
341
- party: "Alice",
342
- templateId: "Main:Iou",
547
+ ledgerApiV2.GetActiveContractsPageRequest.create({
548
+ eventFormat: {
549
+ filtersByParty: {
550
+ Alice: { cumulative: [] },
551
+ },
552
+ verbose: true,
553
+ },
343
554
  }),
344
555
  );
345
556
  ```
346
557
 
347
- `stateService.getActiveContractsPageAsync(...)` keeps `templateId` as the simple helper path, and on gRPC also supports interface-based ACS reads with `interfaceId`, `includeInterfaceView`, `includeCreatedEventBlob`, `activeAtOffset`, `maxPageSize`, and `pageToken`. JSON remains template-query only.
558
+ `stateService.getActiveContractsPageAsync(...)` accepts the generated Ledger API request on gRPC, including its `eventFormat`, `activeAtOffset`, `maxPageSize`, and `pageToken` fields. Build party, template, and interface filters in `eventFormat`. JSON does not implement this paginated RPC; use `getActiveContractsAsync(...)` for JSON streaming reads.
348
559
 
349
560
  For interface views, do not use `contractService.getContractAsync(...)`. That contract lookup surface cannot return interface views; use `stateService` or `updateService` instead.
350
561
 
@@ -491,7 +702,7 @@ unsupported query features reject with `QueryCapabilityError`.
491
702
  - `packageService.listVettedPackagesAsync(...)`: `grpc` only
492
703
  - `commandService.submitAndWaitAsync(...)`: `json`, `grpc`
493
704
  - `commandSubmissionService.submitAsync(...)`: reserved, currently unsupported
494
- - `stateService.getActiveContractsPageAsync(...)`: `json`, `grpc`
705
+ - `stateService.getActiveContractsPageAsync(...)`: `grpc` only
495
706
  - `stateService.getActiveContractsAsync(...)`: `json` only
496
707
  - `updateService.getUpdatesAsync(...)`: `grpc` only
497
708
  - `commandCompletionService`: placeholder, no methods yet
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ExternalPartyActivationClient = void 0;
4
+ const list_party_to_participant_request_js_1 = require("../core/types/requests/list-party-to-participant-request.js");
5
+ const topology_base_query_js_1 = require("../core/types/topology/topology-base-query.js");
4
6
  const topology_store_id_js_1 = require("../core/types/topology/topology-store-id.js");
5
7
  const topology_js_1 = require("../transports/grpc/generated/canton/com/digitalasset/canton/protocol/v30/topology.js");
6
8
  const external_party_activation_response_js_1 = require("./external-party-activation-response.js");
@@ -66,27 +68,35 @@ class ExternalPartyActivationClient {
66
68
  }
67
69
  async readStateAsync(request, options) {
68
70
  const [activeResponse, proposalResponse] = await Promise.all([
69
- this.sourceClient.topologyManagerReadService.listPartyToParticipantAsync({
70
- baseQuery: createSynchronizerQuery(request.synchronizerId, false),
71
+ this.sourceClient.topologyManagerReadService.listPartyToParticipantAsync(new list_party_to_participant_request_js_1.ListPartyToParticipantRequest({
72
+ baseQuery: new topology_base_query_js_1.TopologyBaseQuery({
73
+ storeId: createSynchronizerStoreId(request.synchronizerId),
74
+ headState: true,
75
+ includeProposals: false,
76
+ }),
71
77
  filterParty: request.partyId,
72
78
  filterParticipant: "",
73
- }, options),
74
- this.sourceClient.topologyManagerReadService.listPartyToParticipantAsync({
75
- baseQuery: createSynchronizerQuery(request.synchronizerId, true),
79
+ }), options),
80
+ this.sourceClient.topologyManagerReadService.listPartyToParticipantAsync(new list_party_to_participant_request_js_1.ListPartyToParticipantRequest({
81
+ baseQuery: new topology_base_query_js_1.TopologyBaseQuery({
82
+ storeId: createSynchronizerStoreId(request.synchronizerId),
83
+ headState: true,
84
+ includeProposals: true,
85
+ }),
76
86
  filterParty: request.partyId,
77
87
  filterParticipant: "",
78
- }, options),
88
+ }), options),
79
89
  ]);
80
- const active = activeResponse.results.find((item) => item.item?.party === request.partyId);
81
- const proposal = proposalResponse.results.find((item) => item.item?.party === request.partyId);
90
+ const active = activeResponse.results.find((item) => item.item.party === request.partyId);
91
+ const proposal = proposalResponse.results.find((item) => item.item.party === request.partyId);
82
92
  return {
83
- active: active === undefined || active.context === undefined || active.item === undefined
93
+ active: active === undefined || active.context === undefined
84
94
  ? undefined
85
95
  : {
86
96
  context: active.context,
87
97
  mapping: active.item,
88
98
  },
89
- proposal: proposal === undefined || proposal.context === undefined || proposal.item === undefined
99
+ proposal: proposal === undefined || proposal.context === undefined
90
100
  ? undefined
91
101
  : {
92
102
  context: proposal.context,
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ActiveContractsTraversalError = void 0;
4
+ const canton_error_js_1 = require("./canton-error.js");
5
+ class ActiveContractsTraversalError extends canton_error_js_1.CantonError {
6
+ code;
7
+ constructor(code, message) {
8
+ super(message);
9
+ this.code = code;
10
+ }
11
+ }
12
+ exports.ActiveContractsTraversalError = ActiveContractsTraversalError;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pollUntilAsync = pollUntilAsync;
4
+ async function pollUntilAsync(init) {
5
+ const now = init.now ?? Date.now;
6
+ const sleepAsync = init.sleepAsync ?? defaultSleepAsync;
7
+ const deadline = now() + init.timeoutMs;
8
+ let lastObserved;
9
+ let firstRead = true;
10
+ while (firstRead || now() < deadline) {
11
+ firstRead = false;
12
+ lastObserved = await init.readAsync();
13
+ if (init.match(lastObserved)) {
14
+ return lastObserved;
15
+ }
16
+ const remainingMs = deadline - now();
17
+ if (remainingMs <= 0) {
18
+ throw init.createTimeoutError(lastObserved);
19
+ }
20
+ await sleepAsync(Math.min(init.pollIntervalMs, remainingMs));
21
+ }
22
+ throw init.createTimeoutError(lastObserved);
23
+ }
24
+ async function defaultSleepAsync(milliseconds) {
25
+ await new Promise(resolve => setTimeout(resolve, milliseconds));
26
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ActiveContractsTraversalOptions = void 0;
4
+ const validation_error_js_1 = require("../errors/validation-error.js");
5
+ const operation_deadline_js_1 = require("./operation-deadline.js");
6
+ class ActiveContractsTraversalOptions {
7
+ deadline;
8
+ maxPages;
9
+ maxContracts;
10
+ constructor(init) {
11
+ if (!(init.deadline instanceof operation_deadline_js_1.OperationDeadline)) {
12
+ throw new validation_error_js_1.ValidationError("active contracts traversal deadline must be an OperationDeadline");
13
+ }
14
+ else if (!Number.isSafeInteger(init.maxPages) || init.maxPages <= 0) {
15
+ throw new validation_error_js_1.ValidationError("active contracts traversal maxPages must be a positive safe integer");
16
+ }
17
+ else if (!Number.isSafeInteger(init.maxContracts) || init.maxContracts <= 0) {
18
+ throw new validation_error_js_1.ValidationError("active contracts traversal maxContracts must be a positive safe integer");
19
+ }
20
+ this.deadline = init.deadline;
21
+ this.maxPages = init.maxPages;
22
+ this.maxContracts = init.maxContracts;
23
+ Object.freeze(this);
24
+ }
25
+ }
26
+ exports.ActiveContractsTraversalOptions = ActiveContractsTraversalOptions;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OperationDeadline = void 0;
4
+ const timeout_error_js_1 = require("../errors/timeout-error.js");
5
+ const validation_error_js_1 = require("../errors/validation-error.js");
6
+ const request_options_js_1 = require("./request-options.js");
7
+ class OperationDeadline {
8
+ endsAtMs;
9
+ now;
10
+ remainingMs;
11
+ constructor(init) {
12
+ if (!Number.isSafeInteger(init.timeoutMs) || init.timeoutMs <= 0) {
13
+ throw new validation_error_js_1.ValidationError("operation deadline timeout must be a positive safe integer");
14
+ }
15
+ this.now = init.now ?? Date.now;
16
+ const startedAtMs = this.safeNow();
17
+ this.endsAtMs = startedAtMs + init.timeoutMs;
18
+ if (!Number.isSafeInteger(this.endsAtMs)) {
19
+ throw new validation_error_js_1.ValidationError("operation deadline end time must be a safe integer");
20
+ }
21
+ this.remainingMs = init.timeoutMs;
22
+ }
23
+ remainingTimeoutMs() {
24
+ const computedRemainingMs = Math.max(0, this.endsAtMs - this.safeNow());
25
+ this.remainingMs = Math.min(this.remainingMs, computedRemainingMs);
26
+ if (this.remainingMs === 0) {
27
+ throw new timeout_error_js_1.TimeoutError("operation deadline has expired");
28
+ }
29
+ return this.remainingMs;
30
+ }
31
+ createRequestOptions() {
32
+ return new request_options_js_1.RequestOptions({ timeoutMs: this.remainingTimeoutMs() });
33
+ }
34
+ safeNow() {
35
+ const now = this.now();
36
+ if (!Number.isSafeInteger(now)) {
37
+ throw new validation_error_js_1.ValidationError("operation deadline clock must return a safe integer");
38
+ }
39
+ return now;
40
+ }
41
+ }
42
+ exports.OperationDeadline = OperationDeadline;
@@ -4,9 +4,11 @@ exports.AllocatePartyRequest = void 0;
4
4
  class AllocatePartyRequest {
5
5
  partyIdHint;
6
6
  displayName;
7
+ userId;
7
8
  constructor(init = {}) {
8
9
  this.partyIdHint = init.partyIdHint;
9
10
  this.displayName = init.displayName;
11
+ this.userId = init.userId;
10
12
  }
11
13
  }
12
14
  exports.AllocatePartyRequest = AllocatePartyRequest;
@@ -8,6 +8,9 @@ class PreparedDecentralizedParty {
8
8
  decentralizedNamespace;
9
9
  ownerThreshold;
10
10
  partySigningThreshold;
11
+ identityProviderId;
12
+ waitForAllocation;
13
+ userId;
11
14
  transactions;
12
15
  signingRequests;
13
16
  constructor(init) {
@@ -16,6 +19,9 @@ class PreparedDecentralizedParty {
16
19
  this.decentralizedNamespace = init.decentralizedNamespace;
17
20
  this.ownerThreshold = init.ownerThreshold;
18
21
  this.partySigningThreshold = init.partySigningThreshold;
22
+ this.identityProviderId = init.identityProviderId;
23
+ this.waitForAllocation = init.waitForAllocation;
24
+ this.userId = init.userId;
19
25
  this.transactions = [...(init.transactions ?? [])].map((transaction) => new prepared_topology_transaction_js_1.PreparedTopologyTransaction({
20
26
  serializedTransaction: transaction.serializedTransaction,
21
27
  transactionHash: transaction.transactionHash,
@@ -2,25 +2,68 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SubmitCommandRequest = void 0;
4
4
  const validation_error_js_1 = require("../../errors/validation-error.js");
5
+ const ledgerStringPattern = /^[A-Za-z0-9#:\-_/ ]+$/;
6
+ const canonicalOffsetPattern = /^(0|[1-9][0-9]*)$/;
7
+ const maximumInt64Offset = "9223372036854775807";
5
8
  class SubmitCommandRequest {
6
9
  applicationId;
7
10
  userId;
8
11
  actAs;
9
12
  readAs;
10
13
  command;
14
+ commandId;
15
+ deduplicationPeriod;
11
16
  disclosedContracts;
12
17
  synchronizerId;
13
18
  constructor(init) {
14
19
  if (init.actAs.length === 0) {
15
20
  throw new validation_error_js_1.ValidationError("submit requests require at least one actAs party");
16
21
  }
22
+ else if (init.commandId !== undefined &&
23
+ (typeof init.commandId !== "string" ||
24
+ init.commandId.length > 255 ||
25
+ !ledgerStringPattern.test(init.commandId))) {
26
+ throw new validation_error_js_1.ValidationError("submit request command ID must be a LedgerString");
27
+ }
28
+ const deduplicationPeriod = freezeDeduplicationPeriod(init.deduplicationPeriod);
17
29
  this.applicationId = init.applicationId;
18
30
  this.userId = init.userId;
19
31
  this.actAs = init.actAs;
20
32
  this.readAs = init.readAs ?? [];
21
33
  this.command = init.command;
34
+ this.commandId = init.commandId;
35
+ this.deduplicationPeriod = deduplicationPeriod;
22
36
  this.disclosedContracts = init.disclosedContracts ?? [];
23
37
  this.synchronizerId = init.synchronizerId;
24
38
  }
25
39
  }
26
40
  exports.SubmitCommandRequest = SubmitCommandRequest;
41
+ function freezeDeduplicationPeriod(value) {
42
+ if (value === undefined) {
43
+ return undefined;
44
+ }
45
+ else if (typeof value !== "object" ||
46
+ value === null ||
47
+ Array.isArray(value)) {
48
+ throw new validation_error_js_1.ValidationError("submit request deduplication period is invalid");
49
+ }
50
+ else if (value.kind === "duration") {
51
+ if (typeof value.seconds !== "number" ||
52
+ !Number.isSafeInteger(value.seconds) ||
53
+ value.seconds <= 0) {
54
+ throw new validation_error_js_1.ValidationError("submit request duration deduplication seconds must be a positive safe integer");
55
+ }
56
+ return Object.freeze({ kind: "duration", seconds: value.seconds });
57
+ }
58
+ else if (value.kind !== "offset") {
59
+ throw new validation_error_js_1.ValidationError("submit request deduplication period is invalid");
60
+ }
61
+ if (typeof value.offset !== "string" ||
62
+ !canonicalOffsetPattern.test(value.offset) ||
63
+ value.offset.length > maximumInt64Offset.length ||
64
+ (value.offset.length === maximumInt64Offset.length &&
65
+ value.offset > maximumInt64Offset)) {
66
+ throw new validation_error_js_1.ValidationError("submit request offset deduplication period must be a canonical unsigned int64");
67
+ }
68
+ return Object.freeze({ kind: "offset", offset: value.offset });
69
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WaitForPartyHostingRequest = void 0;
4
+ const validation_error_js_1 = require("../../errors/validation-error.js");
5
+ class WaitForPartyHostingRequest {
6
+ partyId;
7
+ participantId;
8
+ synchronizerId;
9
+ pollIntervalMs;
10
+ timeoutMs;
11
+ constructor(init) {
12
+ const partyId = init.partyId.trim();
13
+ const participantId = init.participantId.trim();
14
+ const synchronizerId = init.synchronizerId.trim();
15
+ const pollIntervalMs = init.pollIntervalMs ?? 500;
16
+ const timeoutMs = init.timeoutMs ?? 30_000;
17
+ if (!partyId) {
18
+ throw new validation_error_js_1.ValidationError("party hosting wait requires a party ID");
19
+ }
20
+ else if (!participantId) {
21
+ throw new validation_error_js_1.ValidationError("party hosting wait requires a participant ID");
22
+ }
23
+ else if (!synchronizerId) {
24
+ throw new validation_error_js_1.ValidationError("party hosting wait requires a synchronizer ID");
25
+ }
26
+ else if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) {
27
+ throw new validation_error_js_1.ValidationError("party hosting wait timeout must be a positive safe integer");
28
+ }
29
+ else if (!Number.isSafeInteger(pollIntervalMs) ||
30
+ pollIntervalMs < 0) {
31
+ throw new validation_error_js_1.ValidationError("party hosting wait poll interval must be a non-negative safe integer");
32
+ }
33
+ this.partyId = partyId;
34
+ this.participantId = participantId;
35
+ this.synchronizerId = synchronizerId;
36
+ this.pollIntervalMs = pollIntervalMs;
37
+ this.timeoutMs = timeoutMs;
38
+ }
39
+ }
40
+ exports.WaitForPartyHostingRequest = WaitForPartyHostingRequest;