@distrohelena/canton-typescript-sdk 0.1.0 → 0.1.2

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 (139) hide show
  1. package/README.md +76 -0
  2. package/dist/client/canton-client.d.ts +4 -0
  3. package/dist/client/canton-client.js +5 -0
  4. package/dist/client/canton-hashing-client.d.ts +8 -0
  5. package/dist/client/canton-hashing-client.js +16 -0
  6. package/dist/client/external-party-activation-client.d.ts +15 -0
  7. package/dist/client/external-party-activation-client.js +126 -0
  8. package/dist/client/external-party-activation-request.d.ts +15 -0
  9. package/dist/client/external-party-activation-request.js +14 -0
  10. package/dist/client/external-party-activation-response.d.ts +13 -0
  11. package/dist/client/external-party-activation-response.js +12 -0
  12. package/dist/client/service-registry.d.ts +2 -0
  13. package/dist/client/service-registry.js +124 -0
  14. package/dist/core/hashing/canton-hash.d.ts +3 -0
  15. package/dist/core/hashing/canton-hash.js +24 -0
  16. package/dist/core/transports/transport.interface.d.ts +48 -0
  17. package/dist/core/types/canton-hash-purpose.d.ts +4 -0
  18. package/dist/core/types/canton-hash-purpose.js +5 -0
  19. package/dist/core/types/external-party/external-party-crypto-key-format.d.ts +6 -0
  20. package/dist/core/types/external-party/external-party-crypto-key-format.js +7 -0
  21. package/dist/core/types/external-party/external-party-onboarding-transaction.d.ts +9 -0
  22. package/dist/core/types/external-party/external-party-onboarding-transaction.js +8 -0
  23. package/dist/core/types/external-party/external-party-signature-format.d.ts +7 -0
  24. package/dist/core/types/external-party/external-party-signature-format.js +8 -0
  25. package/dist/core/types/external-party/external-party-signature.d.ts +14 -0
  26. package/dist/core/types/external-party/external-party-signature.js +16 -0
  27. package/dist/core/types/external-party/external-party-signing-algorithm-spec.d.ts +7 -0
  28. package/dist/core/types/external-party/external-party-signing-algorithm-spec.js +8 -0
  29. package/dist/core/types/external-party/external-party-signing-key-spec.d.ts +8 -0
  30. package/dist/core/types/external-party/external-party-signing-key-spec.js +9 -0
  31. package/dist/core/types/external-party/external-party-signing-public-key.d.ts +12 -0
  32. package/dist/core/types/external-party/external-party-signing-public-key.js +12 -0
  33. package/dist/core/types/requests/add-party-async-request.d.ts +27 -0
  34. package/dist/core/types/requests/add-party-async-request.js +25 -0
  35. package/dist/core/types/requests/add-topology-transactions-request.d.ts +16 -0
  36. package/dist/core/types/requests/add-topology-transactions-request.js +12 -0
  37. package/dist/core/types/requests/allocate-external-party-request.d.ts +18 -0
  38. package/dist/core/types/requests/allocate-external-party-request.js +16 -0
  39. package/dist/core/types/requests/assemble-signed-topology-transactions-request.d.ts +10 -0
  40. package/dist/core/types/requests/assemble-signed-topology-transactions-request.js +8 -0
  41. package/dist/core/types/requests/authorize-topology-transactions-request.d.ts +37 -0
  42. package/dist/core/types/requests/authorize-topology-transactions-request.js +35 -0
  43. package/dist/core/types/requests/clear-party-onboarding-flag-request.d.ts +13 -0
  44. package/dist/core/types/requests/clear-party-onboarding-flag-request.js +12 -0
  45. package/dist/core/types/requests/create-temporary-topology-store-request.d.ts +8 -0
  46. package/dist/core/types/requests/create-temporary-topology-store-request.js +8 -0
  47. package/dist/core/types/requests/drop-temporary-topology-store-request.d.ts +7 -0
  48. package/dist/core/types/requests/drop-temporary-topology-store-request.js +6 -0
  49. package/dist/core/types/requests/generate-external-party-topology-request.d.ts +19 -0
  50. package/dist/core/types/requests/generate-external-party-topology-request.js +21 -0
  51. package/dist/core/types/requests/generate-topology-transactions-request.d.ts +26 -0
  52. package/dist/core/types/requests/generate-topology-transactions-request.js +22 -0
  53. package/dist/core/types/requests/get-active-contracts-page-request.d.ts +12 -0
  54. package/dist/core/types/requests/get-active-contracts-page-request.js +12 -0
  55. package/dist/core/types/requests/import-topology-snapshot-request.d.ts +12 -0
  56. package/dist/core/types/requests/import-topology-snapshot-request.js +10 -0
  57. package/dist/core/types/requests/import-topology-snapshot-v2-request.d.ts +12 -0
  58. package/dist/core/types/requests/import-topology-snapshot-v2-request.js +10 -0
  59. package/dist/core/types/requests/sign-topology-transactions-request.d.ts +15 -0
  60. package/dist/core/types/requests/sign-topology-transactions-request.js +12 -0
  61. package/dist/core/types/responses/add-party-async-response.d.ts +6 -0
  62. package/dist/core/types/responses/add-party-async-response.js +6 -0
  63. package/dist/core/types/responses/add-topology-transactions-response.d.ts +3 -0
  64. package/dist/core/types/responses/add-topology-transactions-response.js +5 -0
  65. package/dist/core/types/responses/allocate-external-party-response.d.ts +6 -0
  66. package/dist/core/types/responses/allocate-external-party-response.js +6 -0
  67. package/dist/core/types/responses/authorize-topology-transactions-response.d.ts +7 -0
  68. package/dist/core/types/responses/authorize-topology-transactions-response.js +6 -0
  69. package/dist/core/types/responses/clear-party-onboarding-flag-response.d.ts +8 -0
  70. package/dist/core/types/responses/clear-party-onboarding-flag-response.js +8 -0
  71. package/dist/core/types/responses/create-temporary-topology-store-response.d.ts +7 -0
  72. package/dist/core/types/responses/create-temporary-topology-store-response.js +6 -0
  73. package/dist/core/types/responses/drop-temporary-topology-store-response.d.ts +3 -0
  74. package/dist/core/types/responses/drop-temporary-topology-store-response.js +5 -0
  75. package/dist/core/types/responses/generate-external-party-topology-response.d.ts +12 -0
  76. package/dist/core/types/responses/generate-external-party-topology-response.js +12 -0
  77. package/dist/core/types/responses/generate-topology-transactions-response.d.ts +7 -0
  78. package/dist/core/types/responses/generate-topology-transactions-response.js +6 -0
  79. package/dist/core/types/responses/get-active-contracts-page-response.d.ts +4 -0
  80. package/dist/core/types/responses/get-active-contracts-page-response.js +4 -0
  81. package/dist/core/types/responses/import-topology-snapshot-response.d.ts +3 -0
  82. package/dist/core/types/responses/import-topology-snapshot-response.js +5 -0
  83. package/dist/core/types/responses/import-topology-snapshot-v2-response.d.ts +3 -0
  84. package/dist/core/types/responses/import-topology-snapshot-v2-response.js +5 -0
  85. package/dist/core/types/responses/sign-topology-transactions-response.d.ts +7 -0
  86. package/dist/core/types/responses/sign-topology-transactions-response.js +6 -0
  87. package/dist/core/types/topology/external-topology-signature.d.ts +18 -0
  88. package/dist/core/types/topology/external-topology-signature.js +16 -0
  89. package/dist/core/types/topology/generated-topology-transaction.d.ts +8 -0
  90. package/dist/core/types/topology/generated-topology-transaction.js +8 -0
  91. package/dist/core/types/topology/multi-topology-transaction-signature.d.ts +9 -0
  92. package/dist/core/types/topology/multi-topology-transaction-signature.js +8 -0
  93. package/dist/core/types/topology/prepared-topology-transaction.d.ts +10 -0
  94. package/dist/core/types/topology/prepared-topology-transaction.js +10 -0
  95. package/dist/core/types/topology/signed-topology-transaction.d.ts +14 -0
  96. package/dist/core/types/topology/signed-topology-transaction.js +14 -0
  97. package/dist/core/types/topology/topology-force-flag.d.ts +8 -0
  98. package/dist/core/types/topology/topology-force-flag.js +9 -0
  99. package/dist/core/types/topology/topology-mapping.d.ts +16 -0
  100. package/dist/core/types/topology/topology-mapping.js +1 -0
  101. package/dist/core/types/topology/topology-public-key.d.ts +4 -0
  102. package/dist/core/types/topology/topology-public-key.js +4 -0
  103. package/dist/core/types/topology/topology-signature-delegation.d.ts +18 -0
  104. package/dist/core/types/topology/topology-signature-delegation.js +20 -0
  105. package/dist/core/types/topology/topology-signature-format.d.ts +3 -0
  106. package/dist/core/types/topology/topology-signature-format.js +4 -0
  107. package/dist/core/types/topology/topology-transaction-signature.d.ts +15 -0
  108. package/dist/core/types/topology/topology-transaction-signature.js +14 -0
  109. package/dist/daml-lf/container/dar-archive-loader.js +9 -0
  110. package/dist/index.d.ts +51 -0
  111. package/dist/index.js +50 -0
  112. package/dist/services/participant-party-management/participant-party-management-service-client.d.ts +8 -0
  113. package/dist/services/participant-party-management/participant-party-management-service-client.js +8 -0
  114. package/dist/services/party-management/party-management-service-client.d.ts +8 -0
  115. package/dist/services/party-management/party-management-service-client.js +8 -0
  116. package/dist/services/state/state-service-client.d.ts +1 -1
  117. package/dist/services/state/state-service-client.js +1 -1
  118. package/dist/services/topology-manager-write/topology-manager-write-service-client.d.ts +42 -0
  119. package/dist/services/topology-manager-write/topology-manager-write-service-client.js +44 -0
  120. package/dist/services/topology-manager-write/topology-signed-transaction-assembler.d.ts +3 -0
  121. package/dist/services/topology-manager-write/topology-signed-transaction-assembler.js +78 -0
  122. package/dist/transports/grpc/grpc-channel-factory.d.ts +16 -2
  123. package/dist/transports/grpc/grpc-channel-factory.js +56 -0
  124. package/dist/transports/grpc/grpc-transport.d.ts +20 -0
  125. package/dist/transports/grpc/grpc-transport.js +72 -1
  126. package/dist/transports/grpc/mappers/contracts-mapper.d.ts +6 -0
  127. package/dist/transports/grpc/mappers/contracts-mapper.js +40 -19
  128. package/dist/transports/grpc/mappers/external-party-management-mapper.d.ts +9 -0
  129. package/dist/transports/grpc/mappers/external-party-management-mapper.js +126 -0
  130. package/dist/transports/grpc/mappers/participant-party-management-mapper.d.ts +9 -2
  131. package/dist/transports/grpc/mappers/participant-party-management-mapper.js +56 -1
  132. package/dist/transports/grpc/mappers/topology-common-mapper.js +3 -0
  133. package/dist/transports/grpc/mappers/topology-manager-write-mapper.d.ts +33 -0
  134. package/dist/transports/grpc/mappers/topology-manager-write-mapper.js +451 -0
  135. package/dist/transports/json/json-transport.d.ts +20 -0
  136. package/dist/transports/json/json-transport.js +59 -6
  137. package/dist/transports/json/mappers/parties-mapper.d.ts +13 -2
  138. package/dist/transports/json/mappers/parties-mapper.js +15 -1
  139. package/package.json +4 -2
package/README.md CHANGED
@@ -13,6 +13,60 @@ TypeScript SDK for Canton with:
13
13
  npm install @distrohelena/canton-typescript-sdk
14
14
  ```
15
15
 
16
+ ## Live Integration Tests
17
+
18
+ The repository also supports a live SDK validation suite against an already-running CN quickstart localnet.
19
+
20
+ The live suite runs single-worker with an extended timeout because it mutates and reads a shared localnet.
21
+
22
+ Prerequisites:
23
+
24
+ - CN quickstart is already running on your machine
25
+ - the suite is expected to fail fast if the configured node is unreachable
26
+
27
+ Default local endpoints:
28
+
29
+ - gRPC ledger: `http://localhost:3901`
30
+ - gRPC ledger admin: `http://localhost:3901`
31
+ - gRPC participant admin: `http://localhost:3902`
32
+ - JSON ledger and ledger admin: `http://localhost:3975`
33
+
34
+ Override environment variables:
35
+
36
+ - `SDK_TEST_LEDGER_ENDPOINT`
37
+ - `SDK_TEST_LEDGER_ADMIN_ENDPOINT`
38
+ - `SDK_TEST_PARTICIPANT_ADMIN_ENDPOINT`
39
+ - `SDK_TEST_SECONDARY_LEDGER_ENDPOINT`
40
+ - `SDK_TEST_SECONDARY_LEDGER_ADMIN_ENDPOINT`
41
+ - `SDK_TEST_SECONDARY_PARTICIPANT_ADMIN_ENDPOINT`
42
+ - `SDK_TEST_TERTIARY_LEDGER_ENDPOINT`
43
+ - `SDK_TEST_TERTIARY_LEDGER_ADMIN_ENDPOINT`
44
+ - `SDK_TEST_TERTIARY_PARTICIPANT_ADMIN_ENDPOINT`
45
+
46
+ The live harness also supports bearer-token overrides:
47
+
48
+ - `SDK_TEST_LEDGER_BEARER_TOKEN`
49
+ - `SDK_TEST_LEDGER_ADMIN_BEARER_TOKEN`
50
+ - `SDK_TEST_PARTICIPANT_ADMIN_BEARER_TOKEN`
51
+
52
+ For CN quickstart shared-secret mode, the harness generates a default bearer token automatically using:
53
+
54
+ - subject `ledger-api-user`
55
+ - audience `https://canton.network.global`
56
+ - shared secret `unsafe`
57
+
58
+ Run:
59
+
60
+ ```bash
61
+ npm run test:live
62
+ ```
63
+
64
+ Experimental multi-host external-party coverage is opt-in:
65
+
66
+ - set `SDK_TEST_ENABLE_MULTI_HOST_EXTERNAL_PARTY=1` to enable the multi-host live spec
67
+ - the default quickstart assumptions cover 2 nodes (`390x` and `490x`)
68
+ - configure the tertiary endpoint variables above to enable the 3-host scenario
69
+
16
70
  ## Shared Client
17
71
 
18
72
  ```ts
@@ -65,6 +119,10 @@ const contracts = await client.stateService.getActiveContractsPageAsync(
65
119
  );
66
120
  ```
67
121
 
122
+ `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.
123
+
124
+ For interface views, do not use `contractService.getContractAsync(...)`. That contract lookup surface cannot return interface views; use `stateService` or `updateService` instead.
125
+
68
126
  `CantonClient` now splits its public surface across the real API boundaries:
69
127
 
70
128
  - ledger services use `ledgerEndpoint`
@@ -98,6 +156,10 @@ For gRPC, channel security resolves per surface:
98
156
  - Ledger Admin endpoint:
99
157
  - `partyManagementService.allocatePartyAsync(...)`: `json`, `grpc`
100
158
  - `partyManagementService.listKnownPartiesAsync(...)`: `json`, `grpc`
159
+ - `partyManagementService.getParticipantIdAsync(...)`: `grpc` only
160
+ - `partyManagementService.getPartiesAsync(...)`: `grpc` only
161
+ - `partyManagementService.generateExternalPartyTopologyAsync(...)`: `grpc` only
162
+ - `partyManagementService.allocateExternalPartyAsync(...)`: `grpc` only
101
163
  - `userManagementService.grantUserRightsAsync(...)`: `json`, `grpc`
102
164
  - `packageManagementService.uploadDarFileAsync(...)`: `json`, `grpc`
103
165
 
@@ -106,6 +168,19 @@ For gRPC, channel security resolves per surface:
106
168
  - `participantPackageService.getPackageContentsAsync(...)`: `grpc` only
107
169
  - `participantPackageService.getPackageReferencesAsync(...)`: `grpc` only
108
170
  - `participantStatusService.getParticipantStatusAsync(...)`: `grpc` only
171
+ - `topologyManagerReadService.*`: `grpc` only
172
+ - `topologyAggregationService.*`: `grpc` only
173
+ - `topologyManagerWriteService.authorizeAsync(...)`: `grpc` only
174
+ - `topologyManagerWriteService.addTransactionsAsync(...)`: `grpc` only
175
+ - `topologyManagerWriteService.importTopologySnapshotAsync(...)`: `grpc` only
176
+ - `topologyManagerWriteService.importTopologySnapshotV2Async(...)`: `grpc` only
177
+ - `topologyManagerWriteService.signTransactionsAsync(...)`: `grpc` only
178
+ - `topologyManagerWriteService.generateTransactionsAsync(...)`: `grpc` only
179
+ - `topologyManagerWriteService.createTemporaryTopologyStoreAsync(...)`: `grpc` only
180
+ - `topologyManagerWriteService.dropTemporaryTopologyStoreAsync(...)`: `grpc` only
181
+ - `topologyManagerWriteService.assembleSignedTransactions(...)`: SDK-local on any client
182
+
183
+ Raw topology-write mapping support currently starts with `PartyToParticipant`. The detached-signature assembler is transport-independent, but the actual participant-admin write RPCs are `grpc` only and JSON rejects them with `NotSupportedError`.
109
184
 
110
185
  ## Protocol-Specific Clients
111
186
 
@@ -120,6 +195,7 @@ Subpath exports are available when you want to construct directly over a transpo
120
195
 
121
196
  JSON does not provide a `grpc.health.v1.Health.Check` equivalent. The shared SDK still exposes `healthService`, but JSON rejects calls with `NotSupportedError`.
122
197
  JSON also does not provide a participant-admin status equivalent, so `participantStatusService` is currently `grpc` only.
198
+ JSON also does not expose the ledger-admin external-party RPCs, so `partyManagementService.generateExternalPartyTopologyAsync(...)` and `partyManagementService.allocateExternalPartyAsync(...)` are `grpc` only.
123
199
 
124
200
  ## DAML-LF Parser
125
201
 
@@ -20,11 +20,13 @@ import { ResourceManagementServiceClient } from "../services/resource-management
20
20
  import { StateServiceClient } from "../services/state/state-service-client.js";
21
21
  import { TopologyAggregationServiceClient } from "../services/topology-aggregation/topology-aggregation-service-client.js";
22
22
  import { TopologyManagerReadServiceClient } from "../services/topology-manager-read/topology-manager-read-service-client.js";
23
+ import { TopologyManagerWriteServiceClient } from "../services/topology-manager-write/topology-manager-write-service-client.js";
23
24
  import { TrafficControlServiceClient } from "../services/traffic-control/traffic-control-service-client.js";
24
25
  import { UpdateServiceClient } from "../services/update/update-service-client.js";
25
26
  import { UserManagementServiceClient } from "../services/user-management/user-management-service-client.js";
26
27
  import { VersionServiceClient } from "../services/version/version-service-client.js";
27
28
  import { SynchronizerConnectivityServiceClient } from "../services/synchronizer-connectivity/synchronizer-connectivity-service-client.js";
29
+ import { CantonHashingClient } from "./canton-hashing-client.js";
28
30
  import { CantonClientOptions } from "./canton-client-options.js";
29
31
  export declare class CantonClient {
30
32
  private readonly options;
@@ -48,6 +50,7 @@ export declare class CantonClient {
48
50
  readonly identityInitializationService: IdentityInitializationServiceClient;
49
51
  readonly synchronizerConnectivityService: SynchronizerConnectivityServiceClient;
50
52
  readonly topologyManagerReadService: TopologyManagerReadServiceClient;
53
+ readonly topologyManagerWriteService: TopologyManagerWriteServiceClient;
51
54
  readonly trafficControlService: TrafficControlServiceClient;
52
55
  readonly topologyAggregationService: TopologyAggregationServiceClient;
53
56
  readonly commandService: CommandServiceClient;
@@ -57,6 +60,7 @@ export declare class CantonClient {
57
60
  readonly updateService: UpdateServiceClient;
58
61
  readonly eventQueryService: EventQueryServiceClient;
59
62
  readonly contractService: ContractServiceClient;
63
+ readonly hashing: CantonHashingClient;
60
64
  constructor(options: CantonClientOptions);
61
65
  /** Disposes transport-owned resources for this client instance. */
62
66
  disposeAsync(): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  import { NotSupportedError } from "../core/errors/not-supported-error.js";
2
2
  import { TransportKind } from "../core/types/transport-kind.js";
3
+ import { CantonHashingClient } from "./canton-hashing-client.js";
3
4
  import { createServiceRegistry } from "./service-registry.js";
4
5
  export class CantonClient {
5
6
  options;
@@ -23,6 +24,7 @@ export class CantonClient {
23
24
  identityInitializationService;
24
25
  synchronizerConnectivityService;
25
26
  topologyManagerReadService;
27
+ topologyManagerWriteService;
26
28
  trafficControlService;
27
29
  topologyAggregationService;
28
30
  commandService;
@@ -32,6 +34,7 @@ export class CantonClient {
32
34
  updateService;
33
35
  eventQueryService;
34
36
  contractService;
37
+ hashing;
35
38
  constructor(options) {
36
39
  this.options = options;
37
40
  if (options.transportKind === TransportKind.json &&
@@ -61,6 +64,7 @@ export class CantonClient {
61
64
  this.synchronizerConnectivityService =
62
65
  services.synchronizerConnectivityService;
63
66
  this.topologyManagerReadService = services.topologyManagerReadService;
67
+ this.topologyManagerWriteService = services.topologyManagerWriteService;
64
68
  this.trafficControlService = services.trafficControlService;
65
69
  this.topologyAggregationService = services.topologyAggregationService;
66
70
  this.commandService = services.commandService;
@@ -70,6 +74,7 @@ export class CantonClient {
70
74
  this.updateService = services.updateService;
71
75
  this.eventQueryService = services.eventQueryService;
72
76
  this.contractService = services.contractService;
77
+ this.hashing = new CantonHashingClient();
73
78
  }
74
79
  /** Disposes transport-owned resources for this client instance. */
75
80
  async disposeAsync() {
@@ -0,0 +1,8 @@
1
+ export declare class CantonHashingClient {
2
+ /** Computes a Canton multihash for the provided content and hash purpose. */
3
+ computeHash(content: Uint8Array, purpose: number): Uint8Array;
4
+ /** Computes a Canton multihash as lowercase hexadecimal for the provided content and hash purpose. */
5
+ computeHashHex(content: Uint8Array, purpose: number): string;
6
+ /** Computes the canonical Canton public-key fingerprint from serialized public key bytes. */
7
+ computePublicKeyFingerprint(publicKey: Uint8Array): string;
8
+ }
@@ -0,0 +1,16 @@
1
+ import { computeCantonHash, computeCantonHashHex, } from "../core/hashing/canton-hash.js";
2
+ import { CantonHashPurpose } from "../core/types/canton-hash-purpose.js";
3
+ export class CantonHashingClient {
4
+ /** Computes a Canton multihash for the provided content and hash purpose. */
5
+ computeHash(content, purpose) {
6
+ return computeCantonHash(content, purpose);
7
+ }
8
+ /** Computes a Canton multihash as lowercase hexadecimal for the provided content and hash purpose. */
9
+ computeHashHex(content, purpose) {
10
+ return computeCantonHashHex(content, purpose);
11
+ }
12
+ /** Computes the canonical Canton public-key fingerprint from serialized public key bytes. */
13
+ computePublicKeyFingerprint(publicKey) {
14
+ return computeCantonHashHex(publicKey, CantonHashPurpose.publicKeyFingerprint);
15
+ }
16
+ }
@@ -0,0 +1,15 @@
1
+ import { RequestOptions } from "../core/types/request-options.js";
2
+ import { CantonClient } from "./canton-client.js";
3
+ import { ExternalPartyActivationRequest } from "./external-party-activation-request.js";
4
+ import { ExternalPartyActivationResponse } from "./external-party-activation-response.js";
5
+ /** Coordinates multi-host external-party activation across participant-admin topology reads and writes. gRPC only. */
6
+ export declare class ExternalPartyActivationClient {
7
+ private readonly sourceClient;
8
+ constructor(sourceClient: CantonClient);
9
+ /** Waits for a PartyToParticipant proposal, asks additional participants to co-authorize it, and waits for activation. gRPC only. */
10
+ activateAsync(request: ExternalPartyActivationRequest, options?: RequestOptions): Promise<ExternalPartyActivationResponse>;
11
+ private waitForProposalOrActivationAsync;
12
+ private waitForActivationAsync;
13
+ private readStateAsync;
14
+ private createActivationResponse;
15
+ }
@@ -0,0 +1,126 @@
1
+ import { AuthorizeTopologyTransactionsRequest } from "../core/types/requests/authorize-topology-transactions-request.js";
2
+ import { ListPartyToParticipantRequest } from "../core/types/requests/list-party-to-participant-request.js";
3
+ import { TopologyBaseQuery } from "../core/types/topology/topology-base-query.js";
4
+ import { TopologyStoreId, TopologyStoreKind, TopologyStoreSynchronizer } from "../core/types/topology/topology-store-id.js";
5
+ import { ExternalPartyActivationResponse } from "./external-party-activation-response.js";
6
+ /** Coordinates multi-host external-party activation across participant-admin topology reads and writes. gRPC only. */
7
+ export class ExternalPartyActivationClient {
8
+ sourceClient;
9
+ constructor(sourceClient) {
10
+ this.sourceClient = sourceClient;
11
+ }
12
+ /** Waits for a PartyToParticipant proposal, asks additional participants to co-authorize it, and waits for activation. gRPC only. */
13
+ async activateAsync(request, options) {
14
+ if (request.activationTimeoutMs <= 0) {
15
+ throw new Error(`External party activation timeout must be greater than zero, received ${request.activationTimeoutMs}.`);
16
+ }
17
+ if (request.pollIntervalMs < 0) {
18
+ throw new Error(`External party activation poll interval must be zero or greater, received ${request.pollIntervalMs}.`);
19
+ }
20
+ const initialState = await this.waitForProposalOrActivationAsync(request, options);
21
+ if (initialState.active !== undefined) {
22
+ return this.createActivationResponse(request, initialState.active.context, initialState.active.mapping);
23
+ }
24
+ if (initialState.proposal === undefined) {
25
+ throw new Error(`External party activation did not find an active or proposed PartyToParticipant mapping for '${request.partyId}'.`);
26
+ }
27
+ const transactionHash = convertBytesToHex(initialState.proposal.context.transactionHash);
28
+ if (transactionHash.length === 0) {
29
+ throw new Error(`External party activation could not read a transaction hash for '${request.partyId}'.`);
30
+ }
31
+ const authorizeRequest = new AuthorizeTopologyTransactionsRequest({
32
+ transactionHash,
33
+ mustFullyAuthorize: false,
34
+ store: createSynchronizerStoreId(request.synchronizerId),
35
+ });
36
+ for (const client of request.authorizingClients) {
37
+ await client.topologyManagerWriteService.authorizeAsync(authorizeRequest, options);
38
+ }
39
+ const activatedState = await this.waitForActivationAsync(request, options);
40
+ return this.createActivationResponse(request, activatedState.context, activatedState.mapping);
41
+ }
42
+ async waitForProposalOrActivationAsync(request, options) {
43
+ const startedAt = Date.now();
44
+ while (Date.now() - startedAt <= request.activationTimeoutMs) {
45
+ const state = await this.readStateAsync(request, options);
46
+ if (state.active !== undefined || state.proposal !== undefined) {
47
+ return state;
48
+ }
49
+ await delayAsync(request.pollIntervalMs);
50
+ }
51
+ throw new Error(`External party activation timed out while waiting for a PartyToParticipant proposal for '${request.partyId}' on synchronizer '${request.synchronizerId}'.`);
52
+ }
53
+ async waitForActivationAsync(request, options) {
54
+ const startedAt = Date.now();
55
+ while (Date.now() - startedAt <= request.activationTimeoutMs) {
56
+ const state = await this.readStateAsync(request, options);
57
+ if (state.active !== undefined) {
58
+ return state.active;
59
+ }
60
+ await delayAsync(request.pollIntervalMs);
61
+ }
62
+ throw new Error(`External party activation timed out while waiting for '${request.partyId}' to become active on synchronizer '${request.synchronizerId}'.`);
63
+ }
64
+ async readStateAsync(request, options) {
65
+ const [activeResponse, proposalResponse] = await Promise.all([
66
+ this.sourceClient.topologyManagerReadService.listPartyToParticipantAsync(new ListPartyToParticipantRequest({
67
+ baseQuery: createSynchronizerQuery(request.synchronizerId, false),
68
+ filterParty: request.partyId,
69
+ }), options),
70
+ this.sourceClient.topologyManagerReadService.listPartyToParticipantAsync(new ListPartyToParticipantRequest({
71
+ baseQuery: createSynchronizerQuery(request.synchronizerId, true),
72
+ filterParty: request.partyId,
73
+ }), options),
74
+ ]);
75
+ const active = activeResponse.results.find((item) => item.item.party === request.partyId);
76
+ const proposal = proposalResponse.results.find((item) => item.item.party === request.partyId);
77
+ return {
78
+ active: active === undefined || active.context === undefined
79
+ ? undefined
80
+ : {
81
+ context: active.context,
82
+ mapping: active.item,
83
+ },
84
+ proposal: proposal === undefined || proposal.context === undefined
85
+ ? undefined
86
+ : {
87
+ context: proposal.context,
88
+ mapping: proposal.item,
89
+ },
90
+ };
91
+ }
92
+ createActivationResponse(request, context, mapping) {
93
+ return new ExternalPartyActivationResponse({
94
+ partyId: request.partyId,
95
+ synchronizerId: request.synchronizerId,
96
+ transactionHash: convertBytesToHex(context.transactionHash),
97
+ mapping,
98
+ });
99
+ }
100
+ }
101
+ function createSynchronizerStoreId(synchronizerId) {
102
+ return new TopologyStoreId({
103
+ kind: TopologyStoreKind.synchronizer,
104
+ synchronizer: new TopologyStoreSynchronizer({
105
+ id: synchronizerId,
106
+ }),
107
+ });
108
+ }
109
+ function createSynchronizerQuery(synchronizerId, includeProposals) {
110
+ return new TopologyBaseQuery({
111
+ storeId: createSynchronizerStoreId(synchronizerId),
112
+ includeProposals,
113
+ headState: true,
114
+ });
115
+ }
116
+ function convertBytesToHex(value) {
117
+ return Array.from(value, (item) => item.toString(16).padStart(2, "0")).join("");
118
+ }
119
+ async function delayAsync(durationMs) {
120
+ if (durationMs <= 0) {
121
+ return;
122
+ }
123
+ await new Promise((resolve) => {
124
+ setTimeout(resolve, durationMs);
125
+ });
126
+ }
@@ -0,0 +1,15 @@
1
+ import type { CantonClient } from "./canton-client.js";
2
+ export declare class ExternalPartyActivationRequest {
3
+ readonly partyId: string;
4
+ readonly synchronizerId: string;
5
+ readonly authorizingClients: readonly CantonClient[];
6
+ readonly activationTimeoutMs: number;
7
+ readonly pollIntervalMs: number;
8
+ constructor(init: {
9
+ partyId: string;
10
+ synchronizerId: string;
11
+ authorizingClients?: readonly CantonClient[];
12
+ activationTimeoutMs?: number;
13
+ pollIntervalMs?: number;
14
+ });
15
+ }
@@ -0,0 +1,14 @@
1
+ export class ExternalPartyActivationRequest {
2
+ partyId;
3
+ synchronizerId;
4
+ authorizingClients;
5
+ activationTimeoutMs;
6
+ pollIntervalMs;
7
+ constructor(init) {
8
+ this.partyId = init.partyId;
9
+ this.synchronizerId = init.synchronizerId;
10
+ this.authorizingClients = [...(init.authorizingClients ?? [])];
11
+ this.activationTimeoutMs = init.activationTimeoutMs ?? 45_000;
12
+ this.pollIntervalMs = init.pollIntervalMs ?? 500;
13
+ }
14
+ }
@@ -0,0 +1,13 @@
1
+ import { PartyToParticipant } from "../core/types/topology/party-to-participant.js";
2
+ export declare class ExternalPartyActivationResponse {
3
+ readonly partyId: string;
4
+ readonly synchronizerId: string;
5
+ readonly transactionHash: string;
6
+ readonly mapping: PartyToParticipant;
7
+ constructor(init: {
8
+ partyId: string;
9
+ synchronizerId: string;
10
+ transactionHash: string;
11
+ mapping: PartyToParticipant;
12
+ });
13
+ }
@@ -0,0 +1,12 @@
1
+ export class ExternalPartyActivationResponse {
2
+ partyId;
3
+ synchronizerId;
4
+ transactionHash;
5
+ mapping;
6
+ constructor(init) {
7
+ this.partyId = init.partyId;
8
+ this.synchronizerId = init.synchronizerId;
9
+ this.transactionHash = init.transactionHash;
10
+ this.mapping = init.mapping;
11
+ }
12
+ }
@@ -22,6 +22,7 @@ import { ResourceManagementServiceClient } from "../services/resource-management
22
22
  import { StateServiceClient } from "../services/state/state-service-client.js";
23
23
  import { TopologyAggregationServiceClient } from "../services/topology-aggregation/topology-aggregation-service-client.js";
24
24
  import { TopologyManagerReadServiceClient } from "../services/topology-manager-read/topology-manager-read-service-client.js";
25
+ import { TopologyManagerWriteServiceClient } from "../services/topology-manager-write/topology-manager-write-service-client.js";
25
26
  import { TrafficControlServiceClient } from "../services/traffic-control/traffic-control-service-client.js";
26
27
  import { UpdateServiceClient } from "../services/update/update-service-client.js";
27
28
  import { UserManagementServiceClient } from "../services/user-management/user-management-service-client.js";
@@ -47,6 +48,7 @@ export interface ServiceRegistry {
47
48
  readonly identityInitializationService: IdentityInitializationServiceClient;
48
49
  readonly synchronizerConnectivityService: SynchronizerConnectivityServiceClient;
49
50
  readonly topologyManagerReadService: TopologyManagerReadServiceClient;
51
+ readonly topologyManagerWriteService: TopologyManagerWriteServiceClient;
50
52
  readonly trafficControlService: TrafficControlServiceClient;
51
53
  readonly topologyAggregationService: TopologyAggregationServiceClient;
52
54
  readonly commandService: CommandServiceClient;
@@ -25,6 +25,7 @@ import { ResourceManagementServiceClient } from "../services/resource-management
25
25
  import { StateServiceClient } from "../services/state/state-service-client.js";
26
26
  import { TopologyAggregationServiceClient } from "../services/topology-aggregation/topology-aggregation-service-client.js";
27
27
  import { TopologyManagerReadServiceClient } from "../services/topology-manager-read/topology-manager-read-service-client.js";
28
+ import { TopologyManagerWriteServiceClient } from "../services/topology-manager-write/topology-manager-write-service-client.js";
28
29
  import { TrafficControlServiceClient } from "../services/traffic-control/traffic-control-service-client.js";
29
30
  import { UpdateServiceClient } from "../services/update/update-service-client.js";
30
31
  import { UserManagementServiceClient } from "../services/user-management/user-management-service-client.js";
@@ -55,6 +56,14 @@ class PlaceholderTransport {
55
56
  this.throwIfDisposed();
56
57
  throw new TransportError("party allocation is not available yet");
57
58
  }
59
+ async generateExternalPartyTopologyAsync(_request, _options) {
60
+ this.throwIfDisposed();
61
+ throw new TransportError("external party topology generation is not available yet");
62
+ }
63
+ async allocateExternalPartyAsync(_request, _options) {
64
+ this.throwIfDisposed();
65
+ throw new TransportError("external party allocation is not available yet");
66
+ }
58
67
  async listKnownPartiesAsync(_request, _options) {
59
68
  this.throwIfDisposed();
60
69
  throw new TransportError("known party listing is not available yet");
@@ -179,6 +188,14 @@ class PlaceholderTransport {
179
188
  this.throwIfDisposed();
180
189
  throw new TransportError("received ACS commitment inspection is not available yet");
181
190
  }
191
+ async addPartyAsync(_request, _options) {
192
+ this.throwIfDisposed();
193
+ throw new TransportError("participant party replication is not available yet");
194
+ }
195
+ async clearPartyOnboardingFlagAsync(_request, _options) {
196
+ this.throwIfDisposed();
197
+ throw new TransportError("party onboarding flag clearing is not available yet");
198
+ }
182
199
  async getHighestOffsetByTimestampAsync(_request, _options) {
183
200
  this.throwIfDisposed();
184
201
  throw new TransportError("highest offset by timestamp is not available yet");
@@ -263,6 +280,38 @@ class PlaceholderTransport {
263
280
  this.throwIfDisposed();
264
281
  throw new TransportError("topology participant synchronizer permissions are not available yet");
265
282
  }
283
+ async authorizeTopologyTransactionsAsync(_request, _options) {
284
+ this.throwIfDisposed();
285
+ throw new TransportError("topology transaction authorization is not available yet");
286
+ }
287
+ async addTopologyTransactionsAsync(_request, _options) {
288
+ this.throwIfDisposed();
289
+ throw new TransportError("topology transaction writes are not available yet");
290
+ }
291
+ async importTopologySnapshotAsync(_request, _options) {
292
+ this.throwIfDisposed();
293
+ throw new TransportError("topology snapshot import is not available yet");
294
+ }
295
+ async importTopologySnapshotV2Async(_request, _options) {
296
+ this.throwIfDisposed();
297
+ throw new TransportError("topology snapshot import v2 is not available yet");
298
+ }
299
+ async signTopologyTransactionsAsync(_request, _options) {
300
+ this.throwIfDisposed();
301
+ throw new TransportError("topology transaction signing is not available yet");
302
+ }
303
+ async generateTopologyTransactionsAsync(_request, _options) {
304
+ this.throwIfDisposed();
305
+ throw new TransportError("topology transaction generation is not available yet");
306
+ }
307
+ async createTemporaryTopologyStoreAsync(_request, _options) {
308
+ this.throwIfDisposed();
309
+ throw new TransportError("temporary topology stores are not available yet");
310
+ }
311
+ async dropTemporaryTopologyStoreAsync(_request, _options) {
312
+ this.throwIfDisposed();
313
+ throw new TransportError("temporary topology store deletion is not available yet");
314
+ }
266
315
  async listPartyHostingLimitsAsync(_request, _options) {
267
316
  this.throwIfDisposed();
268
317
  throw new TransportError("topology party hosting limits are not available yet");
@@ -396,6 +445,12 @@ class MissingEndpointTransport {
396
445
  async allocatePartyAsync() {
397
446
  this.throwMissingEndpoint();
398
447
  }
448
+ async generateExternalPartyTopologyAsync() {
449
+ this.throwMissingEndpoint();
450
+ }
451
+ async allocateExternalPartyAsync() {
452
+ this.throwMissingEndpoint();
453
+ }
399
454
  async listKnownPartiesAsync() {
400
455
  this.throwMissingEndpoint();
401
456
  }
@@ -489,6 +544,12 @@ class MissingEndpointTransport {
489
544
  async lookupReceivedAcsCommitmentsAsync() {
490
545
  this.throwMissingEndpoint();
491
546
  }
547
+ async addPartyAsync() {
548
+ this.throwMissingEndpoint();
549
+ }
550
+ async clearPartyOnboardingFlagAsync() {
551
+ this.throwMissingEndpoint();
552
+ }
492
553
  async getHighestOffsetByTimestampAsync() {
493
554
  this.throwMissingEndpoint();
494
555
  }
@@ -552,6 +613,30 @@ class MissingEndpointTransport {
552
613
  async listParticipantSynchronizerPermissionAsync() {
553
614
  this.throwMissingEndpoint();
554
615
  }
616
+ async authorizeTopologyTransactionsAsync() {
617
+ this.throwMissingEndpoint();
618
+ }
619
+ async addTopologyTransactionsAsync() {
620
+ this.throwMissingEndpoint();
621
+ }
622
+ async importTopologySnapshotAsync() {
623
+ this.throwMissingEndpoint();
624
+ }
625
+ async importTopologySnapshotV2Async() {
626
+ this.throwMissingEndpoint();
627
+ }
628
+ async signTopologyTransactionsAsync() {
629
+ this.throwMissingEndpoint();
630
+ }
631
+ async generateTopologyTransactionsAsync() {
632
+ this.throwMissingEndpoint();
633
+ }
634
+ async createTemporaryTopologyStoreAsync() {
635
+ this.throwMissingEndpoint();
636
+ }
637
+ async dropTemporaryTopologyStoreAsync() {
638
+ this.throwMissingEndpoint();
639
+ }
555
640
  async listPartyHostingLimitsAsync() {
556
641
  this.throwMissingEndpoint();
557
642
  }
@@ -655,6 +740,12 @@ class CompositeTransport {
655
740
  async allocatePartyAsync() {
656
741
  throw new TransportError("Composite transport does not forward service calls.");
657
742
  }
743
+ async generateExternalPartyTopologyAsync() {
744
+ throw new TransportError("Composite transport does not forward service calls.");
745
+ }
746
+ async allocateExternalPartyAsync() {
747
+ throw new TransportError("Composite transport does not forward service calls.");
748
+ }
658
749
  async listKnownPartiesAsync() {
659
750
  throw new TransportError("Composite transport does not forward service calls.");
660
751
  }
@@ -748,6 +839,12 @@ class CompositeTransport {
748
839
  async lookupReceivedAcsCommitmentsAsync() {
749
840
  throw new TransportError("Composite transport does not forward service calls.");
750
841
  }
842
+ async addPartyAsync() {
843
+ throw new TransportError("Composite transport does not forward service calls.");
844
+ }
845
+ async clearPartyOnboardingFlagAsync() {
846
+ throw new TransportError("Composite transport does not forward service calls.");
847
+ }
751
848
  async getHighestOffsetByTimestampAsync() {
752
849
  throw new TransportError("Composite transport does not forward service calls.");
753
850
  }
@@ -811,6 +908,30 @@ class CompositeTransport {
811
908
  async listParticipantSynchronizerPermissionAsync() {
812
909
  throw new TransportError("Composite transport does not forward service calls.");
813
910
  }
911
+ async authorizeTopologyTransactionsAsync() {
912
+ throw new TransportError("Composite transport does not forward service calls.");
913
+ }
914
+ async addTopologyTransactionsAsync() {
915
+ throw new TransportError("Composite transport does not forward service calls.");
916
+ }
917
+ async importTopologySnapshotAsync() {
918
+ throw new TransportError("Composite transport does not forward service calls.");
919
+ }
920
+ async importTopologySnapshotV2Async() {
921
+ throw new TransportError("Composite transport does not forward service calls.");
922
+ }
923
+ async signTopologyTransactionsAsync() {
924
+ throw new TransportError("Composite transport does not forward service calls.");
925
+ }
926
+ async generateTopologyTransactionsAsync() {
927
+ throw new TransportError("Composite transport does not forward service calls.");
928
+ }
929
+ async createTemporaryTopologyStoreAsync() {
930
+ throw new TransportError("Composite transport does not forward service calls.");
931
+ }
932
+ async dropTemporaryTopologyStoreAsync() {
933
+ throw new TransportError("Composite transport does not forward service calls.");
934
+ }
814
935
  async listPartyHostingLimitsAsync() {
815
936
  throw new TransportError("Composite transport does not forward service calls.");
816
937
  }
@@ -989,6 +1110,8 @@ export function createServiceRegistry(options) {
989
1110
  ?? createMissingParticipantAdminTransport(options, "trafficControlService");
990
1111
  const topologyManagerReadTransport = participantAdminTransport
991
1112
  ?? createMissingParticipantAdminTransport(options, "topologyManagerReadService");
1113
+ const topologyManagerWriteTransport = participantAdminTransport
1114
+ ?? createMissingParticipantAdminTransport(options, "topologyManagerWriteService");
992
1115
  const topologyAggregationTransport = participantAdminTransport
993
1116
  ?? createMissingParticipantAdminTransport(options, "topologyAggregationService");
994
1117
  const transport = new CompositeTransport([
@@ -1016,6 +1139,7 @@ export function createServiceRegistry(options) {
1016
1139
  identityInitializationService: new IdentityInitializationServiceClient(identityInitializationTransport),
1017
1140
  synchronizerConnectivityService: new SynchronizerConnectivityServiceClient(synchronizerConnectivityTransport),
1018
1141
  topologyManagerReadService: new TopologyManagerReadServiceClient(topologyManagerReadTransport),
1142
+ topologyManagerWriteService: new TopologyManagerWriteServiceClient(topologyManagerWriteTransport),
1019
1143
  trafficControlService: new TrafficControlServiceClient(trafficControlTransport),
1020
1144
  topologyAggregationService: new TopologyAggregationServiceClient(topologyAggregationTransport),
1021
1145
  commandService: new CommandServiceClient(commandTransport, options.commandSigner),
@@ -0,0 +1,3 @@
1
+ export declare function computeCantonHash(content: Uint8Array, purpose: number): Uint8Array;
2
+ export declare function computeCantonHashHex(content: Uint8Array, purpose: number): string;
3
+ export declare function computeCantonPublicKeyFingerprint(publicKey: Uint8Array | undefined): string | undefined;
@@ -0,0 +1,24 @@
1
+ import { createHash } from "node:crypto";
2
+ import { CantonHashPurpose } from "../types/canton-hash-purpose.js";
3
+ const sha256MultihashPrefix = new Uint8Array([0x12, 0x20]);
4
+ export function computeCantonHash(content, purpose) {
5
+ const purposePrefix = Buffer.alloc(4);
6
+ purposePrefix.writeUInt32BE(purpose, 0);
7
+ const digest = createHash("sha256")
8
+ .update(purposePrefix)
9
+ .update(content)
10
+ .digest();
11
+ return new Uint8Array(Buffer.concat([
12
+ Buffer.from(sha256MultihashPrefix),
13
+ digest,
14
+ ]));
15
+ }
16
+ export function computeCantonHashHex(content, purpose) {
17
+ return Buffer.from(computeCantonHash(content, purpose)).toString("hex");
18
+ }
19
+ export function computeCantonPublicKeyFingerprint(publicKey) {
20
+ if (publicKey === undefined || publicKey.length === 0) {
21
+ return undefined;
22
+ }
23
+ return computeCantonHashHex(publicKey, CantonHashPurpose.publicKeyFingerprint);
24
+ }