@distrohelena/canton-typescript-sdk 0.1.3 → 0.1.5

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 (34) hide show
  1. package/dist/client/service-registry.js +1 -1
  2. package/dist/core/signing/sign-command-request.d.ts +4 -0
  3. package/dist/core/signing/sign-command-request.js +4 -0
  4. package/dist/core/signing/sign-command-result.d.ts +2 -0
  5. package/dist/core/signing/sign-command-result.js +9 -0
  6. package/dist/core/transports/transport.interface.d.ts +2 -2
  7. package/dist/core/types/commands/create-and-exercise-command.d.ts +12 -0
  8. package/dist/core/types/commands/create-and-exercise-command.js +19 -0
  9. package/dist/core/types/commands/create-command.js +4 -0
  10. package/dist/core/types/commands/exercise-by-key-command.d.ts +12 -0
  11. package/dist/core/types/commands/exercise-by-key-command.js +22 -0
  12. package/dist/core/types/commands/exercise-command.d.ts +12 -0
  13. package/dist/core/types/commands/exercise-command.js +22 -0
  14. package/dist/core/types/commands/ledger-command.d.ts +5 -0
  15. package/dist/core/types/commands/ledger-command.js +1 -0
  16. package/dist/core/types/requests/submit-command-request.d.ts +5 -3
  17. package/dist/core/types/requests/submit-command-request.js +2 -0
  18. package/dist/index.d.ts +4 -0
  19. package/dist/index.js +3 -0
  20. package/dist/services/commands/command-payload-builder.js +42 -4
  21. package/dist/services/commands/command-submission-pipeline.js +1 -7
  22. package/dist/transports/grpc/grpc-channel-factory.d.ts +4 -0
  23. package/dist/transports/grpc/grpc-channel-factory.js +11 -0
  24. package/dist/transports/grpc/grpc-transport.d.ts +2 -2
  25. package/dist/transports/grpc/grpc-transport.js +40 -3
  26. package/dist/transports/grpc/mappers/commands-mapper.d.ts +10 -2
  27. package/dist/transports/grpc/mappers/commands-mapper.js +58 -9
  28. package/dist/transports/grpc/mappers/interactive-command-mapper.d.ts +15 -0
  29. package/dist/transports/grpc/mappers/interactive-command-mapper.js +54 -0
  30. package/dist/transports/json/json-transport.d.ts +2 -2
  31. package/dist/transports/json/json-transport.js +4 -10
  32. package/dist/transports/json/mappers/commands-mapper.d.ts +11 -0
  33. package/dist/transports/json/mappers/commands-mapper.js +60 -1
  34. package/package.json +1 -1
@@ -412,7 +412,7 @@ class PlaceholderTransport {
412
412
  this.throwIfDisposed();
413
413
  throw new TransportError("CommandCompletionService.GetCompletions is not available yet");
414
414
  }
415
- async submitCommandAsync(_request, _signed, _options) {
415
+ async submitCommandAsync(_request, _signer, _options) {
416
416
  this.throwIfDisposed();
417
417
  throw new TransportError("command submission is not available yet");
418
418
  }
@@ -1,8 +1,12 @@
1
1
  export declare class SignCommandRequest {
2
2
  readonly payload: Uint8Array;
3
3
  readonly keyId?: string;
4
+ readonly party?: string;
5
+ readonly algorithmHint?: string;
4
6
  constructor(init: {
5
7
  payload: Uint8Array;
6
8
  keyId?: string;
9
+ party?: string;
10
+ algorithmHint?: string;
7
11
  });
8
12
  }
@@ -1,8 +1,12 @@
1
1
  export class SignCommandRequest {
2
2
  payload;
3
3
  keyId;
4
+ party;
5
+ algorithmHint;
4
6
  constructor(init) {
5
7
  this.payload = init.payload;
6
8
  this.keyId = init.keyId;
9
+ this.party = init.party;
10
+ this.algorithmHint = init.algorithmHint;
7
11
  }
8
12
  }
@@ -1,10 +1,12 @@
1
1
  export declare class SignCommandResult {
2
2
  readonly algorithm: string;
3
3
  readonly signature: Uint8Array;
4
+ readonly signedBy: string;
4
5
  readonly keyId?: string;
5
6
  constructor(init: {
6
7
  algorithm: string;
7
8
  signature: Uint8Array;
9
+ signedBy: string;
8
10
  keyId?: string;
9
11
  });
10
12
  }
@@ -1,10 +1,19 @@
1
+ import { ValidationError } from "../errors/validation-error.js";
1
2
  export class SignCommandResult {
2
3
  algorithm;
3
4
  signature;
5
+ signedBy;
4
6
  keyId;
5
7
  constructor(init) {
8
+ if (init.signature.length === 0) {
9
+ throw new ValidationError("command signatures require signature bytes");
10
+ }
11
+ else if (!init.signedBy) {
12
+ throw new ValidationError("command signatures require signedBy");
13
+ }
6
14
  this.algorithm = init.algorithm;
7
15
  this.signature = init.signature;
16
+ this.signedBy = init.signedBy;
8
17
  this.keyId = init.keyId;
9
18
  }
10
19
  }
@@ -185,7 +185,7 @@ import { CompletionObserver } from "../../services/command-completion/completion
185
185
  import { CommitmentChunkObserver } from "../../services/participant-inspection/commitment-chunk-observer.interface.js";
186
186
  import { ContractObserver } from "../../services/contracts/contract-observer.interface.js";
187
187
  import { TransactionObserver } from "../../services/events/transaction-observer.interface.js";
188
- import { SignCommandResult } from "../signing/sign-command-result.js";
188
+ import { ICommandSigner } from "../signing/command-signer.interface.js";
189
189
  import { RequestOptions } from "../types/request-options.js";
190
190
  import { SubmitCommandRequest } from "../types/requests/submit-command-request.js";
191
191
  export interface ITransport {
@@ -380,5 +380,5 @@ export interface ITransport {
380
380
  * Submits a command.
381
381
  * Supported on JSON and gRPC. External signing is gRPC-only.
382
382
  */
383
- submitCommandAsync(request: SubmitCommandRequest, signed?: SignCommandResult, options?: RequestOptions): Promise<SubmitCommandResponse>;
383
+ submitCommandAsync(request: SubmitCommandRequest, signer?: ICommandSigner, options?: RequestOptions): Promise<SubmitCommandResponse>;
384
384
  }
@@ -0,0 +1,12 @@
1
+ export declare class CreateAndExerciseCommand {
2
+ readonly templateId: string;
3
+ readonly payload: Record<string, unknown>;
4
+ readonly choice: string;
5
+ readonly argument: unknown;
6
+ constructor(init: {
7
+ templateId: string;
8
+ payload: Record<string, unknown>;
9
+ choice: string;
10
+ argument: unknown;
11
+ });
12
+ }
@@ -0,0 +1,19 @@
1
+ import { ValidationError } from "../../errors/validation-error.js";
2
+ export class CreateAndExerciseCommand {
3
+ templateId;
4
+ payload;
5
+ choice;
6
+ argument;
7
+ constructor(init) {
8
+ if (!init.templateId) {
9
+ throw new ValidationError("create-and-exercise commands require a templateId");
10
+ }
11
+ else if (!init.choice) {
12
+ throw new ValidationError("create-and-exercise commands require a choice");
13
+ }
14
+ this.templateId = init.templateId;
15
+ this.payload = init.payload;
16
+ this.choice = init.choice;
17
+ this.argument = init.argument;
18
+ }
19
+ }
@@ -1,7 +1,11 @@
1
+ import { ValidationError } from "../../errors/validation-error.js";
1
2
  export class CreateCommand {
2
3
  templateId;
3
4
  payload;
4
5
  constructor(init) {
6
+ if (!init.templateId) {
7
+ throw new ValidationError("create commands require a templateId");
8
+ }
5
9
  this.templateId = init.templateId;
6
10
  this.payload = init.payload;
7
11
  }
@@ -0,0 +1,12 @@
1
+ export declare class ExerciseByKeyCommand {
2
+ readonly templateId: string;
3
+ readonly contractKey: unknown;
4
+ readonly choice: string;
5
+ readonly argument: unknown;
6
+ constructor(init: {
7
+ templateId: string;
8
+ contractKey: unknown;
9
+ choice: string;
10
+ argument: unknown;
11
+ });
12
+ }
@@ -0,0 +1,22 @@
1
+ import { ValidationError } from "../../errors/validation-error.js";
2
+ export class ExerciseByKeyCommand {
3
+ templateId;
4
+ contractKey;
5
+ choice;
6
+ argument;
7
+ constructor(init) {
8
+ if (!init.templateId) {
9
+ throw new ValidationError("exercise-by-key commands require a templateId");
10
+ }
11
+ else if (init.contractKey === undefined) {
12
+ throw new ValidationError("exercise-by-key commands require a contractKey");
13
+ }
14
+ else if (!init.choice) {
15
+ throw new ValidationError("exercise-by-key commands require a choice");
16
+ }
17
+ this.templateId = init.templateId;
18
+ this.contractKey = init.contractKey;
19
+ this.choice = init.choice;
20
+ this.argument = init.argument;
21
+ }
22
+ }
@@ -0,0 +1,12 @@
1
+ export declare class ExerciseCommand {
2
+ readonly templateId: string;
3
+ readonly contractId: string;
4
+ readonly choice: string;
5
+ readonly argument: unknown;
6
+ constructor(init: {
7
+ templateId: string;
8
+ contractId: string;
9
+ choice: string;
10
+ argument: unknown;
11
+ });
12
+ }
@@ -0,0 +1,22 @@
1
+ import { ValidationError } from "../../errors/validation-error.js";
2
+ export class ExerciseCommand {
3
+ templateId;
4
+ contractId;
5
+ choice;
6
+ argument;
7
+ constructor(init) {
8
+ if (!init.templateId) {
9
+ throw new ValidationError("exercise commands require a templateId");
10
+ }
11
+ else if (!init.contractId) {
12
+ throw new ValidationError("exercise commands require a contractId");
13
+ }
14
+ else if (!init.choice) {
15
+ throw new ValidationError("exercise commands require a choice");
16
+ }
17
+ this.templateId = init.templateId;
18
+ this.contractId = init.contractId;
19
+ this.choice = init.choice;
20
+ this.argument = init.argument;
21
+ }
22
+ }
@@ -0,0 +1,5 @@
1
+ import { CreateAndExerciseCommand } from "./create-and-exercise-command.js";
2
+ import { CreateCommand } from "./create-command.js";
3
+ import { ExerciseByKeyCommand } from "./exercise-by-key-command.js";
4
+ import { ExerciseCommand } from "./exercise-command.js";
5
+ export type LedgerCommand = CreateCommand | ExerciseCommand | ExerciseByKeyCommand | CreateAndExerciseCommand;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,13 +1,15 @@
1
- import { CreateCommand } from "../commands/create-command.js";
1
+ import { LedgerCommand } from "../commands/ledger-command.js";
2
2
  export declare class SubmitCommandRequest {
3
3
  readonly applicationId: string;
4
+ readonly userId?: string;
4
5
  readonly actAs: readonly string[];
5
6
  readonly readAs: readonly string[];
6
- readonly command: CreateCommand;
7
+ readonly command: LedgerCommand;
7
8
  constructor(init: {
8
9
  applicationId: string;
10
+ userId?: string;
9
11
  actAs: readonly string[];
10
12
  readAs?: readonly string[];
11
- command: CreateCommand;
13
+ command: LedgerCommand;
12
14
  });
13
15
  }
@@ -1,6 +1,7 @@
1
1
  import { ValidationError } from "../../errors/validation-error.js";
2
2
  export class SubmitCommandRequest {
3
3
  applicationId;
4
+ userId;
4
5
  actAs;
5
6
  readAs;
6
7
  command;
@@ -9,6 +10,7 @@ export class SubmitCommandRequest {
9
10
  throw new ValidationError("submit requests require at least one actAs party");
10
11
  }
11
12
  this.applicationId = init.applicationId;
13
+ this.userId = init.userId;
12
14
  this.actAs = init.actAs;
13
15
  this.readAs = init.readAs ?? [];
14
16
  this.command = init.command;
package/dist/index.d.ts CHANGED
@@ -180,7 +180,11 @@ export { VettedPackage } from "./core/types/vetted-package.js";
180
180
  export { VettedPackages } from "./core/types/vetted-packages.js";
181
181
  export { PreparedTopologyTransaction } from "./core/types/topology/prepared-topology-transaction.js";
182
182
  export { SignedTopologyTransaction } from "./core/types/topology/signed-topology-transaction.js";
183
+ export { CreateAndExerciseCommand } from "./core/types/commands/create-and-exercise-command.js";
183
184
  export { CreateCommand } from "./core/types/commands/create-command.js";
185
+ export { ExerciseByKeyCommand } from "./core/types/commands/exercise-by-key-command.js";
186
+ export { ExerciseCommand } from "./core/types/commands/exercise-command.js";
187
+ export type { LedgerCommand } from "./core/types/commands/ledger-command.js";
184
188
  export { AddTopologyTransactionsRequest } from "./core/types/requests/add-topology-transactions-request.js";
185
189
  export { AllocateExternalPartyRequest } from "./core/types/requests/allocate-external-party-request.js";
186
190
  export { AllocatePartyRequest } from "./core/types/requests/allocate-party-request.js";
package/dist/index.js CHANGED
@@ -175,7 +175,10 @@ export { VettedPackage } from "./core/types/vetted-package.js";
175
175
  export { VettedPackages } from "./core/types/vetted-packages.js";
176
176
  export { PreparedTopologyTransaction } from "./core/types/topology/prepared-topology-transaction.js";
177
177
  export { SignedTopologyTransaction } from "./core/types/topology/signed-topology-transaction.js";
178
+ export { CreateAndExerciseCommand } from "./core/types/commands/create-and-exercise-command.js";
178
179
  export { CreateCommand } from "./core/types/commands/create-command.js";
180
+ export { ExerciseByKeyCommand } from "./core/types/commands/exercise-by-key-command.js";
181
+ export { ExerciseCommand } from "./core/types/commands/exercise-command.js";
179
182
  export { AddTopologyTransactionsRequest } from "./core/types/requests/add-topology-transactions-request.js";
180
183
  export { AllocateExternalPartyRequest } from "./core/types/requests/allocate-external-party-request.js";
181
184
  export { AllocatePartyRequest } from "./core/types/requests/allocate-party-request.js";
@@ -1,11 +1,49 @@
1
+ import { CreateAndExerciseCommand } from "../../core/types/commands/create-and-exercise-command.js";
2
+ import { CreateCommand } from "../../core/types/commands/create-command.js";
3
+ import { ExerciseByKeyCommand } from "../../core/types/commands/exercise-by-key-command.js";
4
+ import { ExerciseCommand } from "../../core/types/commands/exercise-command.js";
1
5
  export function buildCanonicalCommandPayload(request) {
2
6
  return new TextEncoder().encode(JSON.stringify({
3
7
  applicationId: request.applicationId,
4
8
  actAs: request.actAs,
5
9
  readAs: request.readAs,
6
- command: {
7
- templateId: request.command.templateId,
8
- payload: request.command.payload,
9
- },
10
+ command: mapCanonicalCommand(request.command),
10
11
  }));
11
12
  }
13
+ function mapCanonicalCommand(command) {
14
+ if (command instanceof CreateCommand) {
15
+ return {
16
+ kind: "create",
17
+ templateId: command.templateId,
18
+ payload: command.payload,
19
+ };
20
+ }
21
+ else if (command instanceof ExerciseCommand) {
22
+ return {
23
+ kind: "exercise",
24
+ templateId: command.templateId,
25
+ contractId: command.contractId,
26
+ choice: command.choice,
27
+ argument: command.argument,
28
+ };
29
+ }
30
+ else if (command instanceof ExerciseByKeyCommand) {
31
+ return {
32
+ kind: "exerciseByKey",
33
+ templateId: command.templateId,
34
+ contractKey: command.contractKey,
35
+ choice: command.choice,
36
+ argument: command.argument,
37
+ };
38
+ }
39
+ else if (command instanceof CreateAndExerciseCommand) {
40
+ return {
41
+ kind: "createAndExercise",
42
+ templateId: command.templateId,
43
+ payload: command.payload,
44
+ choice: command.choice,
45
+ argument: command.argument,
46
+ };
47
+ }
48
+ return {};
49
+ }
@@ -1,21 +1,15 @@
1
1
  import { NotSupportedError } from "../../core/errors/not-supported-error.js";
2
- import { SignCommandRequest } from "../../core/signing/sign-command-request.js";
3
- import { buildCanonicalCommandPayload } from "./command-payload-builder.js";
4
2
  export class CommandSubmissionPipeline {
5
3
  dependencies;
6
4
  constructor(dependencies) {
7
5
  this.dependencies = dependencies;
8
6
  }
9
7
  async submitAsync(request, options) {
10
- let signed;
11
8
  if (this.dependencies.signer) {
12
9
  if (!this.dependencies.transport.features.supportsCommandSigning) {
13
10
  throw new NotSupportedError("command signing is not supported by the selected transport");
14
11
  }
15
- signed = await this.dependencies.signer.signAsync(new SignCommandRequest({
16
- payload: buildCanonicalCommandPayload(request),
17
- }));
18
12
  }
19
- return this.dependencies.transport.submitCommandAsync(request, signed, options);
13
+ return this.dependencies.transport.submitCommandAsync(request, this.dependencies.signer, options);
20
14
  }
21
15
  }
@@ -20,6 +20,7 @@ import { IPartyManagementServiceClient } from "./generated/canton/com/daml/ledge
20
20
  import { IUserManagementServiceClient } from "./generated/canton/com/daml/ledger/api/v2/admin/user_management_service.client.js";
21
21
  import { IVersionServiceClient } from "./generated/canton/com/daml/ledger/api/v2/version_service.client.js";
22
22
  import { ICommandServiceClient } from "./generated/canton/com/daml/ledger/api/v2/command_service.client.js";
23
+ import { IInteractiveSubmissionServiceClient } from "./generated/canton/com/daml/ledger/api/v2/interactive/interactive_submission_service.client.js";
23
24
  import { ICommandCompletionServiceClient } from "./generated/canton/com/daml/ledger/api/v2/command_completion_service.client.js";
24
25
  import { IContractServiceClient } from "./generated/canton/com/daml/ledger/api/v2/contract_service.client.js";
25
26
  import { IEventQueryServiceClient } from "./generated/canton/com/daml/ledger/api/v2/event_query_service.client.js";
@@ -121,6 +122,8 @@ export interface GrpcOperations {
121
122
  getUpdateByHashAsync?(request: unknown, options?: RequestOptions): Promise<unknown>;
122
123
  getUpdatesPageAsync?(request: unknown, options?: RequestOptions): Promise<unknown>;
123
124
  getCompletionsAsync?(request: unknown, options?: RequestOptions): Promise<unknown>;
125
+ prepareSubmissionAsync?(request: unknown, options?: RequestOptions): Promise<unknown>;
126
+ executeSubmissionAndWaitAsync?(request: unknown, options?: RequestOptions): Promise<unknown>;
124
127
  submitCommandAsync(request: unknown, options?: RequestOptions): Promise<unknown>;
125
128
  }
126
129
  export interface GrpcOperationDependencies {
@@ -150,6 +153,7 @@ export interface GrpcOperationDependencies {
150
153
  stateServiceClient?: Pick<IStateServiceClient, "getActiveContractsPage" | "getConnectedSynchronizers" | "getLedgerEnd" | "getLatestPrunedOffsets">;
151
154
  updateServiceClient?: Pick<IUpdateServiceClient, "getUpdates" | "getUpdateByOffset" | "getUpdateById" | "getUpdateByHash" | "getUpdatesPage">;
152
155
  commandCompletionServiceClient?: Pick<ICommandCompletionServiceClient, "getCompletions">;
156
+ interactiveSubmissionServiceClient?: Pick<IInteractiveSubmissionServiceClient, "prepareSubmission" | "executeSubmissionAndWait">;
153
157
  commandServiceClient?: Pick<ICommandServiceClient, "submitAndWait">;
154
158
  }
155
159
  export declare function createGrpcOperations(options: CantonClientOptions, endpoint: string, grpcChannelSecurity: GrpcChannelSecurity, dependencies?: GrpcOperationDependencies): GrpcOperations;
@@ -20,6 +20,7 @@ import { PartyManagementServiceClient, } from "./generated/canton/com/daml/ledge
20
20
  import { UserManagementServiceClient, } from "./generated/canton/com/daml/ledger/api/v2/admin/user_management_service.client.js";
21
21
  import { VersionServiceClient, } from "./generated/canton/com/daml/ledger/api/v2/version_service.client.js";
22
22
  import { CommandServiceClient, } from "./generated/canton/com/daml/ledger/api/v2/command_service.client.js";
23
+ import { InteractiveSubmissionServiceClient, } from "./generated/canton/com/daml/ledger/api/v2/interactive/interactive_submission_service.client.js";
23
24
  import { CommandCompletionServiceClient, } from "./generated/canton/com/daml/ledger/api/v2/command_completion_service.client.js";
24
25
  import { ContractServiceClient, } from "./generated/canton/com/daml/ledger/api/v2/contract_service.client.js";
25
26
  import { EventQueryServiceClient, } from "./generated/canton/com/daml/ledger/api/v2/event_query_service.client.js";
@@ -85,6 +86,8 @@ export function createGrpcOperations(options, endpoint, grpcChannelSecurity, dep
85
86
  const updateServiceClient = dependencies.updateServiceClient ?? new UpdateServiceClient(rpcTransport);
86
87
  const commandCompletionServiceClient = dependencies.commandCompletionServiceClient
87
88
  ?? new CommandCompletionServiceClient(rpcTransport);
89
+ const interactiveSubmissionServiceClient = dependencies.interactiveSubmissionServiceClient
90
+ ?? new InteractiveSubmissionServiceClient(rpcTransport);
88
91
  const commandServiceClient = dependencies.commandServiceClient
89
92
  ?? new CommandServiceClient(rpcTransport);
90
93
  return {
@@ -459,6 +462,14 @@ export function createGrpcOperations(options, endpoint, grpcChannelSecurity, dep
459
462
  const callOptions = await buildCallOptionsForLedgerSurfaceAsync(options, requestOptions);
460
463
  return await unwrapUnaryResponse(commandServiceClient.submitAndWait(request, callOptions));
461
464
  },
465
+ async prepareSubmissionAsync(request, requestOptions) {
466
+ const callOptions = await buildCallOptionsForLedgerSurfaceAsync(options, requestOptions);
467
+ return await unwrapUnaryResponse(interactiveSubmissionServiceClient.prepareSubmission(request, callOptions));
468
+ },
469
+ async executeSubmissionAndWaitAsync(request, requestOptions) {
470
+ const callOptions = await buildCallOptionsForLedgerSurfaceAsync(options, requestOptions);
471
+ return await unwrapUnaryResponse(interactiveSubmissionServiceClient.executeSubmissionAndWait(request, callOptions));
472
+ },
462
473
  };
463
474
  }
464
475
  async function buildCallOptionsForLedgerSurfaceAsync(options, requestOptions) {
@@ -84,7 +84,7 @@ import { TopologyListPartiesRequest } from "../../core/types/requests/topology-l
84
84
  import { TopologyListVettedPackagesRequest } from "../../core/types/requests/topology-list-vetted-packages-request.js";
85
85
  import { TrafficControlStateRequest } from "../../core/types/requests/traffic-control-state-request.js";
86
86
  import { UploadDarFileRequest } from "../../core/types/requests/upload-dar-file-request.js";
87
- import { SignCommandResult } from "../../core/signing/sign-command-result.js";
87
+ import { ICommandSigner } from "../../core/signing/command-signer.interface.js";
88
88
  import { AllocatePartyResponse as SdkAllocatePartyResponse } from "../../core/types/responses/allocate-party-response.js";
89
89
  import { AllocateExternalPartyResponse } from "../../core/types/responses/allocate-external-party-response.js";
90
90
  import { AddPartyAsyncResponse } from "../../core/types/responses/add-party-async-response.js";
@@ -275,7 +275,7 @@ export declare class GrpcTransport implements ITransport {
275
275
  getUpdateByHashAsync(request: GetUpdateByHashRequest, options?: RequestOptions): Promise<GetUpdateByHashResponse>;
276
276
  getUpdatesPageAsync(request: GetUpdatesPageRequest, options?: RequestOptions): Promise<GetUpdatesPageResponse>;
277
277
  getCompletionsAsync(request: GetCompletionsRequest, observer: CompletionObserver, options?: RequestOptions): Promise<void>;
278
- submitCommandAsync(request: SubmitCommandRequest, signed?: SignCommandResult, options?: RequestOptions): Promise<SubmitCommandResponse>;
278
+ submitCommandAsync(request: SubmitCommandRequest, signer?: ICommandSigner, options?: RequestOptions): Promise<SubmitCommandResponse>;
279
279
  private throwIfDisposed;
280
280
  private throwPartyTopologyReadCompatibilityError;
281
281
  private isProtobufDeserializationFailure;
@@ -1,3 +1,6 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { ValidationError } from "../../core/errors/validation-error.js";
3
+ import { SignCommandRequest } from "../../core/signing/sign-command-request.js";
1
4
  import { AllocatePartyResponse as SdkAllocatePartyResponse } from "../../core/types/responses/allocate-party-response.js";
2
5
  import { GetActiveContractsPageResponse } from "../../core/types/responses/get-active-contracts-page-response.js";
3
6
  import { GetLedgerApiVersionResponse as SdkGetLedgerApiVersionResponse } from "../../core/types/responses/get-ledger-api-version-response.js";
@@ -8,6 +11,7 @@ import { TransportError } from "../../core/errors/transport-error.js";
8
11
  import { PackageFormat } from "../../core/types/package-format.js";
9
12
  import { createGrpcOperations, } from "./grpc-channel-factory.js";
10
13
  import { mapGrpcSubmitCommand, mapGrpcSubmitCommandRequest, } from "./mappers/commands-mapper.js";
14
+ import { mapGrpcExecuteSubmissionAndWaitRequest, mapGrpcInteractiveSubmitCommand, mapGrpcPrepareSubmissionRequest, } from "./mappers/interactive-command-mapper.js";
11
15
  import { mapGrpcGetContract, mapGrpcGetContractRequest, mapGrpcQueryContracts, mapGrpcQueryContractsRequest, } from "./mappers/contracts-mapper.js";
12
16
  import { mapGrpcCompletionStreamResponse, mapGrpcGetCompletionsRequest, } from "./mappers/command-completion-mapper.js";
13
17
  import { mapGrpcGetCommandStatus, mapGrpcGetCommandStatusRequest, } from "./mappers/command-inspection-mapper.js";
@@ -571,10 +575,43 @@ export class GrpcTransport {
571
575
  await observer.nextAsync(mapGrpcCompletionStreamResponse(response));
572
576
  }
573
577
  }
574
- async submitCommandAsync(request, signed, options) {
578
+ async submitCommandAsync(request, signer, options) {
575
579
  this.throwIfDisposed();
576
- const payload = await this.operations.submitCommandAsync(mapGrpcSubmitCommandRequest(request, signed), options);
577
- return mapGrpcSubmitCommand(payload);
580
+ if (!signer) {
581
+ const payload = await this.operations.submitCommandAsync(mapGrpcSubmitCommandRequest(request), options);
582
+ return mapGrpcSubmitCommand(payload);
583
+ }
584
+ if (request.actAs.length !== 1) {
585
+ throw new ValidationError("interactive gRPC command signing currently requires exactly one actAs party");
586
+ }
587
+ if (!this.operations.prepareSubmissionAsync) {
588
+ throw new NotSupportedError("interactive gRPC command signing is not available on this transport");
589
+ }
590
+ if (!this.operations.executeSubmissionAndWaitAsync) {
591
+ throw new NotSupportedError("interactive gRPC command signing is not available on this transport");
592
+ }
593
+ const commandId = randomUUID();
594
+ const submissionId = randomUUID();
595
+ const prepared = await this.operations.prepareSubmissionAsync(mapGrpcPrepareSubmissionRequest(request, commandId), options);
596
+ if (!prepared.preparedTransaction) {
597
+ throw new ValidationError("interactive prepare submission did not return a preparedTransaction");
598
+ }
599
+ else if (prepared.preparedTransactionHash.length === 0) {
600
+ throw new ValidationError("interactive prepare submission did not return a preparedTransactionHash");
601
+ }
602
+ const signerResult = await signer.signAsync(new SignCommandRequest({
603
+ payload: prepared.preparedTransactionHash,
604
+ party: request.actAs[0],
605
+ algorithmHint: "ed25519",
606
+ }));
607
+ const executed = await this.operations.executeSubmissionAndWaitAsync(mapGrpcExecuteSubmissionAndWaitRequest({
608
+ request,
609
+ preparedTransaction: prepared.preparedTransaction,
610
+ hashingSchemeVersion: prepared.hashingSchemeVersion,
611
+ submissionId,
612
+ signerResult,
613
+ }), options);
614
+ return mapGrpcInteractiveSubmitCommand(executed);
578
615
  }
579
616
  throwIfDisposed() {
580
617
  if (this.disposed) {
@@ -1,10 +1,18 @@
1
- import { SignCommandResult } from "../../../core/signing/sign-command-result.js";
1
+ import { CreateCommand } from "../../../core/types/commands/create-command.js";
2
+ import { LedgerCommand } from "../../../core/types/commands/ledger-command.js";
2
3
  import { SubmitCommandRequest } from "../../../core/types/requests/submit-command-request.js";
3
4
  import { SubmitCommandResponse } from "../../../core/types/responses/submit-command-response.js";
5
+ import { Command } from "../generated/canton/com/daml/ledger/api/v2/commands.js";
4
6
  import { SubmitAndWaitRequest, SubmitAndWaitResponse } from "../generated/canton/com/daml/ledger/api/v2/command_service.js";
5
- export declare function mapGrpcSubmitCommandRequest(request: SubmitCommandRequest, _signed?: SignCommandResult): SubmitAndWaitRequest;
7
+ import { Identifier, Record as GrpcRecord, Value } from "../generated/canton/com/daml/ledger/api/v2/value.js";
8
+ export declare function mapGrpcSubmitCommandRequest(request: SubmitCommandRequest): SubmitAndWaitRequest;
6
9
  export declare function mapGrpcSubmitCommand(payload: {
7
10
  commandId?: string;
8
11
  transactionId?: string;
9
12
  updateId?: string;
10
13
  } | SubmitAndWaitResponse): SubmitCommandResponse;
14
+ export declare function mapGrpcLedgerCommand(command: LedgerCommand): Command;
15
+ export declare function mapGrpcCreateCommand(command: CreateCommand): Command;
16
+ export declare function mapRecord(payload: Record<string, unknown>): GrpcRecord;
17
+ export declare function mapValue(value: unknown): Value;
18
+ export declare function parseTemplateIdentifier(templateId: string): Identifier;
@@ -1,13 +1,17 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { ValidationError } from "../../../core/errors/validation-error.js";
3
+ import { CreateAndExerciseCommand } from "../../../core/types/commands/create-and-exercise-command.js";
4
+ import { CreateCommand } from "../../../core/types/commands/create-command.js";
5
+ import { ExerciseByKeyCommand } from "../../../core/types/commands/exercise-by-key-command.js";
6
+ import { ExerciseCommand } from "../../../core/types/commands/exercise-command.js";
3
7
  import { SubmitCommandResponse } from "../../../core/types/responses/submit-command-response.js";
4
- export function mapGrpcSubmitCommandRequest(request, _signed) {
8
+ export function mapGrpcSubmitCommandRequest(request) {
5
9
  return {
6
10
  commands: {
7
11
  workflowId: "",
8
- userId: "",
12
+ userId: request.userId ?? "",
9
13
  commandId: randomUUID(),
10
- commands: [mapCreateCommand(request)],
14
+ commands: [mapGrpcLedgerCommand(request.command)],
11
15
  deduplicationPeriod: {
12
16
  oneofKind: undefined,
13
17
  },
@@ -29,18 +33,63 @@ export function mapGrpcSubmitCommand(payload) {
29
33
  : payload.updateId,
30
34
  });
31
35
  }
32
- function mapCreateCommand(request) {
36
+ export function mapGrpcLedgerCommand(command) {
37
+ if (command instanceof CreateCommand) {
38
+ return mapGrpcCreateCommand(command);
39
+ }
40
+ else if (command instanceof ExerciseCommand) {
41
+ return {
42
+ command: {
43
+ oneofKind: "exercise",
44
+ exercise: {
45
+ templateId: parseTemplateIdentifier(command.templateId),
46
+ contractId: command.contractId,
47
+ choice: command.choice,
48
+ choiceArgument: mapValue(command.argument),
49
+ },
50
+ },
51
+ };
52
+ }
53
+ else if (command instanceof ExerciseByKeyCommand) {
54
+ return {
55
+ command: {
56
+ oneofKind: "exerciseByKey",
57
+ exerciseByKey: {
58
+ templateId: parseTemplateIdentifier(command.templateId),
59
+ contractKey: mapValue(command.contractKey),
60
+ choice: command.choice,
61
+ choiceArgument: mapValue(command.argument),
62
+ },
63
+ },
64
+ };
65
+ }
66
+ else if (command instanceof CreateAndExerciseCommand) {
67
+ return {
68
+ command: {
69
+ oneofKind: "createAndExercise",
70
+ createAndExercise: {
71
+ templateId: parseTemplateIdentifier(command.templateId),
72
+ createArguments: mapRecord(command.payload),
73
+ choice: command.choice,
74
+ choiceArgument: mapValue(command.argument),
75
+ },
76
+ },
77
+ };
78
+ }
79
+ throw new ValidationError("unsupported submit command type");
80
+ }
81
+ export function mapGrpcCreateCommand(command) {
33
82
  return {
34
83
  command: {
35
84
  oneofKind: "create",
36
85
  create: {
37
- templateId: parseTemplateIdentifier(request.command.templateId),
38
- createArguments: mapRecord(request.command.payload),
86
+ templateId: parseTemplateIdentifier(command.templateId),
87
+ createArguments: mapRecord(command.payload),
39
88
  },
40
89
  },
41
90
  };
42
91
  }
43
- function mapRecord(payload) {
92
+ export function mapRecord(payload) {
44
93
  return {
45
94
  fields: Object.entries(payload).map(([label, value]) => ({
46
95
  label,
@@ -48,7 +97,7 @@ function mapRecord(payload) {
48
97
  })),
49
98
  };
50
99
  }
51
- function mapValue(value) {
100
+ export function mapValue(value) {
52
101
  if (value === null || value === undefined) {
53
102
  return {
54
103
  sum: {
@@ -105,7 +154,7 @@ function mapValue(value) {
105
154
  },
106
155
  };
107
156
  }
108
- function parseTemplateIdentifier(templateId) {
157
+ export function parseTemplateIdentifier(templateId) {
109
158
  const parts = templateId.split(":");
110
159
  if (parts.length === 2) {
111
160
  return {
@@ -0,0 +1,15 @@
1
+ import { SignCommandResult } from "../../../core/signing/sign-command-result.js";
2
+ import { SubmitCommandRequest } from "../../../core/types/requests/submit-command-request.js";
3
+ import { SubmitCommandResponse } from "../../../core/types/responses/submit-command-response.js";
4
+ import { Signature } from "../generated/canton/com/daml/ledger/api/v2/crypto.js";
5
+ import { ExecuteSubmissionAndWaitRequest, ExecuteSubmissionAndWaitResponse, HashingSchemeVersion, PrepareSubmissionRequest, PreparedTransaction } from "../generated/canton/com/daml/ledger/api/v2/interactive/interactive_submission_service.js";
6
+ export declare function mapGrpcPrepareSubmissionRequest(request: SubmitCommandRequest, commandId: string): PrepareSubmissionRequest;
7
+ export declare function mapGrpcExecuteSubmissionAndWaitRequest(init: {
8
+ request: SubmitCommandRequest;
9
+ preparedTransaction: PreparedTransaction;
10
+ hashingSchemeVersion: HashingSchemeVersion;
11
+ submissionId: string;
12
+ signerResult: SignCommandResult;
13
+ }): ExecuteSubmissionAndWaitRequest;
14
+ export declare function mapGrpcInteractiveSubmitCommand(payload: ExecuteSubmissionAndWaitResponse): SubmitCommandResponse;
15
+ export declare function mapGrpcSignature(result: SignCommandResult): Signature;
@@ -0,0 +1,54 @@
1
+ import { ValidationError } from "../../../core/errors/validation-error.js";
2
+ import { SubmitCommandResponse } from "../../../core/types/responses/submit-command-response.js";
3
+ import { SignatureFormat, SigningAlgorithmSpec, } from "../generated/canton/com/daml/ledger/api/v2/crypto.js";
4
+ import { mapGrpcLedgerCommand } from "./commands-mapper.js";
5
+ export function mapGrpcPrepareSubmissionRequest(request, commandId) {
6
+ return {
7
+ userId: request.userId ?? "",
8
+ commandId,
9
+ commands: [mapGrpcLedgerCommand(request.command)],
10
+ actAs: [...request.actAs],
11
+ readAs: [...request.readAs],
12
+ disclosedContracts: [],
13
+ synchronizerId: "",
14
+ packageIdSelectionPreference: [],
15
+ prefetchContractKeys: [],
16
+ verboseHashing: false,
17
+ };
18
+ }
19
+ export function mapGrpcExecuteSubmissionAndWaitRequest(init) {
20
+ return {
21
+ preparedTransaction: init.preparedTransaction,
22
+ partySignatures: {
23
+ signatures: [
24
+ {
25
+ party: init.request.actAs[0] ?? "",
26
+ signatures: [mapGrpcSignature(init.signerResult)],
27
+ },
28
+ ],
29
+ },
30
+ deduplicationPeriod: {
31
+ oneofKind: undefined,
32
+ },
33
+ submissionId: init.submissionId,
34
+ userId: init.request.userId ?? "",
35
+ hashingSchemeVersion: init.hashingSchemeVersion,
36
+ };
37
+ }
38
+ export function mapGrpcInteractiveSubmitCommand(payload) {
39
+ return new SubmitCommandResponse({
40
+ transactionId: payload.updateId,
41
+ });
42
+ }
43
+ export function mapGrpcSignature(result) {
44
+ const algorithm = result.algorithm.toLowerCase();
45
+ if (algorithm === "ed25519") {
46
+ return {
47
+ format: SignatureFormat.CONCAT,
48
+ signature: result.signature,
49
+ signedBy: result.signedBy,
50
+ signingAlgorithmSpec: SigningAlgorithmSpec.ED25519,
51
+ };
52
+ }
53
+ throw new ValidationError(`unsupported gRPC command signing algorithm '${result.algorithm}'`);
54
+ }
@@ -63,7 +63,6 @@ import { ParticipantListPackagesRequest } from "../../core/types/requests/partic
63
63
  import { SubmitCommandRequest } from "../../core/types/requests/submit-command-request.js";
64
64
  import { TrafficControlStateRequest } from "../../core/types/requests/traffic-control-state-request.js";
65
65
  import { UploadDarFileRequest } from "../../core/types/requests/upload-dar-file-request.js";
66
- import { SignCommandResult } from "../../core/signing/sign-command-result.js";
67
66
  import { AllocatePartyResponse } from "../../core/types/responses/allocate-party-response.js";
68
67
  import { AllocateExternalPartyResponse } from "../../core/types/responses/allocate-external-party-response.js";
69
68
  import { AddPartyAsyncResponse } from "../../core/types/responses/add-party-async-response.js";
@@ -127,6 +126,7 @@ import { SubmitCommandResponse } from "../../core/types/responses/submit-command
127
126
  import { TrafficControlStateResponse } from "../../core/types/responses/traffic-control-state-response.js";
128
127
  import { UploadDarFileResponse } from "../../core/types/responses/upload-dar-file-response.js";
129
128
  import { ITransport } from "../../core/transports/transport.interface.js";
129
+ import { ICommandSigner } from "../../core/signing/command-signer.interface.js";
130
130
  import { RequestOptions } from "../../core/types/request-options.js";
131
131
  import { IJsonHttpClient } from "./json-http-client.js";
132
132
  import { CompletionObserver } from "../../services/command-completion/completion-observer.interface.js";
@@ -233,6 +233,6 @@ export declare class JsonTransport implements ITransport {
233
233
  getUpdateByHashAsync(_request: GetUpdateByHashRequest, _options?: RequestOptions): Promise<GetUpdateByHashResponse>;
234
234
  getUpdatesPageAsync(_request: GetUpdatesPageRequest, _options?: RequestOptions): Promise<GetUpdatesPageResponse>;
235
235
  getCompletionsAsync(_request: GetCompletionsRequest, _observer: CompletionObserver, _options?: RequestOptions): Promise<void>;
236
- submitCommandAsync(request: SubmitCommandRequest, signed?: SignCommandResult, options?: RequestOptions): Promise<SubmitCommandResponse>;
236
+ submitCommandAsync(request: SubmitCommandRequest, signer?: ICommandSigner, options?: RequestOptions): Promise<SubmitCommandResponse>;
237
237
  private throwIfDisposed;
238
238
  }
@@ -5,7 +5,7 @@ import { ListKnownPartiesResponse } from "../../core/types/responses/list-known-
5
5
  import { UploadDarFileResponse } from "../../core/types/responses/upload-dar-file-response.js";
6
6
  import { NotSupportedError } from "../../core/errors/not-supported-error.js";
7
7
  import { ObjectDisposedError } from "../../core/errors/object-disposed-error.js";
8
- import { mapJsonSubmitCommand } from "./mappers/commands-mapper.js";
8
+ import { mapJsonSubmitCommand, mapJsonSubmitCommandRequest, } from "./mappers/commands-mapper.js";
9
9
  import { mapJsonUploadPackage } from "./mappers/packages-mapper.js";
10
10
  import { mapJsonAllocatePartyRequest, mapJsonCreateParty, mapJsonListParties, } from "./mappers/parties-mapper.js";
11
11
  import { mapJsonQueryContracts } from "./mappers/contracts-mapper.js";
@@ -453,18 +453,12 @@ export class JsonTransport {
453
453
  this.throwIfDisposed();
454
454
  throw new NotSupportedError("CommandCompletionService.GetCompletions is not supported by json transport");
455
455
  }
456
- async submitCommandAsync(request, signed, options) {
456
+ async submitCommandAsync(request, signer, options) {
457
457
  this.throwIfDisposed();
458
- if (signed) {
458
+ if (signer) {
459
459
  throw new NotSupportedError("command signing is not supported by json transport");
460
460
  }
461
- const payload = await this.httpClient.postAsync("/v1/create", {
462
- templateId: request.command.templateId,
463
- payload: request.command.payload,
464
- applicationId: request.applicationId,
465
- actAs: request.actAs,
466
- readAs: request.readAs,
467
- }, options);
461
+ const payload = await this.httpClient.postAsync("/v2/commands/submit-and-wait", mapJsonSubmitCommandRequest(request), options);
468
462
  return mapJsonSubmitCommand(payload);
469
463
  }
470
464
  throwIfDisposed() {
@@ -1,9 +1,20 @@
1
+ import { SubmitCommandRequest } from "../../../core/types/requests/submit-command-request.js";
1
2
  import { SubmitCommandResponse } from "../../../core/types/responses/submit-command-response.js";
3
+ export declare function mapJsonSubmitCommandRequest(request: SubmitCommandRequest): {
4
+ commandId: string;
5
+ actAs: readonly string[];
6
+ readAs: readonly string[];
7
+ commands: unknown[];
8
+ applicationId?: string;
9
+ };
2
10
  export declare function mapJsonSubmitCommand(payload: {
3
11
  result?: {
4
12
  commandId?: string;
5
13
  transactionId?: string;
14
+ updateId?: string;
6
15
  };
7
16
  commandId?: string;
8
17
  transactionId?: string;
18
+ updateId?: string;
19
+ completionOffset?: string;
9
20
  }): SubmitCommandResponse;
@@ -1,7 +1,66 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { ValidationError } from "../../../core/errors/validation-error.js";
3
+ import { CreateAndExerciseCommand } from "../../../core/types/commands/create-and-exercise-command.js";
4
+ import { CreateCommand } from "../../../core/types/commands/create-command.js";
5
+ import { ExerciseByKeyCommand } from "../../../core/types/commands/exercise-by-key-command.js";
6
+ import { ExerciseCommand } from "../../../core/types/commands/exercise-command.js";
1
7
  import { SubmitCommandResponse } from "../../../core/types/responses/submit-command-response.js";
8
+ export function mapJsonSubmitCommandRequest(request) {
9
+ return {
10
+ commandId: randomUUID(),
11
+ actAs: request.actAs,
12
+ readAs: request.readAs,
13
+ commands: [mapJsonCommand(request.command)],
14
+ applicationId: request.applicationId || undefined,
15
+ };
16
+ }
2
17
  export function mapJsonSubmitCommand(payload) {
3
18
  return new SubmitCommandResponse({
4
19
  commandId: payload.result?.commandId ?? payload.commandId,
5
- transactionId: payload.result?.transactionId ?? payload.transactionId,
20
+ transactionId: payload.result?.transactionId
21
+ ?? payload.result?.updateId
22
+ ?? payload.transactionId
23
+ ?? payload.updateId,
6
24
  });
7
25
  }
26
+ function mapJsonCommand(command) {
27
+ if (command instanceof CreateCommand) {
28
+ return {
29
+ CreateCommand: {
30
+ templateId: command.templateId,
31
+ createArguments: command.payload,
32
+ },
33
+ };
34
+ }
35
+ else if (command instanceof ExerciseCommand) {
36
+ return {
37
+ ExerciseCommand: {
38
+ templateId: command.templateId,
39
+ contractId: command.contractId,
40
+ choice: command.choice,
41
+ choiceArgument: command.argument,
42
+ },
43
+ };
44
+ }
45
+ else if (command instanceof ExerciseByKeyCommand) {
46
+ return {
47
+ ExerciseByKeyCommand: {
48
+ templateId: command.templateId,
49
+ contractKey: command.contractKey,
50
+ choice: command.choice,
51
+ choiceArgument: command.argument,
52
+ },
53
+ };
54
+ }
55
+ else if (command instanceof CreateAndExerciseCommand) {
56
+ return {
57
+ CreateAndExerciseCommand: {
58
+ templateId: command.templateId,
59
+ createArguments: command.payload,
60
+ choice: command.choice,
61
+ choiceArgument: command.argument,
62
+ },
63
+ };
64
+ }
65
+ throw new ValidationError("unsupported submit command type");
66
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@distrohelena/canton-typescript-sdk",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",