@distrohelena/canton-typescript-sdk 0.1.30 → 0.1.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -81,6 +81,11 @@ not an exact Numeric value.
81
81
 
82
82
  The repository also supports a live SDK validation suite against an already-running CN quickstart localnet.
83
83
 
84
+ The current party-creation flows were developed and live-tested against Canton
85
+ Participant 3.5.7. In particular, external-party allocation signs the generated
86
+ combined topology hash (`multi_hash`) rather than each topology transaction
87
+ individually.
88
+
84
89
  ## Localnet launchers
85
90
 
86
91
  The published package includes launchers for an existing CN Quickstart checkout.
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PartyManagementServiceClient = void 0;
4
- const external_party_onboarding_transaction_js_1 = require("../../core/types/external-party/external-party-onboarding-transaction.js");
5
4
  const external_party_signature_js_1 = require("../../core/types/external-party/external-party-signature.js");
6
5
  const validation_error_js_1 = require("../../core/errors/validation-error.js");
7
6
  const decentralized_party_lifecycle_js_1 = require("./decentralized-party-lifecycle.js");
@@ -132,21 +131,12 @@ class PartyManagementServiceClient {
132
131
  confirmationThreshold: request.confirmationThreshold,
133
132
  observingParticipantUids: [...request.observingParticipantUids],
134
133
  }), options);
135
- const onboardingTransactions = [];
136
- for (const transaction of generated.topologyTransactions) {
137
- onboardingTransactions.push(new external_party_onboarding_transaction_js_1.ExternalPartyOnboardingTransaction({
138
- transaction,
139
- signatures: [
140
- await this.signExternalPartyPayloadAsync(request, transaction, "topology-transaction", generated.partyId, generated.publicKeyFingerprint),
141
- ],
142
- }));
143
- }
144
134
  const multiHashSignature = await this.signExternalPartyPayloadAsync(request, generated.multiHash, "multi-hash", generated.partyId, generated.publicKeyFingerprint);
145
135
  return this.allocateExternalPartyAsync(party_management_service_js_1.AllocateExternalPartyRequest.create({
146
136
  synchronizer: request.synchronizer,
147
- onboardingTransactions: onboardingTransactions.map((transaction) => ({
148
- transaction: transaction.transaction,
149
- signatures: transaction.signatures.map(toGeneratedSignature),
137
+ onboardingTransactions: generated.topologyTransactions.map((transaction) => ({
138
+ transaction,
139
+ signatures: [],
150
140
  })),
151
141
  multiHashSignatures: [toGeneratedSignature(multiHashSignature)],
152
142
  identityProviderId: request.identityProviderId,
@@ -1,4 +1,3 @@
1
- import { ExternalPartyOnboardingTransaction } from "../../core/types/external-party/external-party-onboarding-transaction.js";
2
1
  import { ExternalPartySignature } from "../../core/types/external-party/external-party-signature.js";
3
2
  import { ValidationError } from "../../core/errors/validation-error.js";
4
3
  import { prepareDecentralizedPartyAsync } from "./decentralized-party-lifecycle.js";
@@ -129,21 +128,12 @@ export class PartyManagementServiceClient {
129
128
  confirmationThreshold: request.confirmationThreshold,
130
129
  observingParticipantUids: [...request.observingParticipantUids],
131
130
  }), options);
132
- const onboardingTransactions = [];
133
- for (const transaction of generated.topologyTransactions) {
134
- onboardingTransactions.push(new ExternalPartyOnboardingTransaction({
135
- transaction,
136
- signatures: [
137
- await this.signExternalPartyPayloadAsync(request, transaction, "topology-transaction", generated.partyId, generated.publicKeyFingerprint),
138
- ],
139
- }));
140
- }
141
131
  const multiHashSignature = await this.signExternalPartyPayloadAsync(request, generated.multiHash, "multi-hash", generated.partyId, generated.publicKeyFingerprint);
142
132
  return this.allocateExternalPartyAsync(AllocateExternalPartyRequest.create({
143
133
  synchronizer: request.synchronizer,
144
- onboardingTransactions: onboardingTransactions.map((transaction) => ({
145
- transaction: transaction.transaction,
146
- signatures: transaction.signatures.map(toGeneratedSignature),
134
+ onboardingTransactions: generated.topologyTransactions.map((transaction) => ({
135
+ transaction,
136
+ signatures: [],
147
137
  })),
148
138
  multiHashSignatures: [toGeneratedSignature(multiHashSignature)],
149
139
  identityProviderId: request.identityProviderId,
@@ -70,75 +70,3 @@ canton.participants.extra-3 = $${_participant} {
70
70
  }
71
71
  }
72
72
 
73
- canton.participants.extra-1.ledger-api.auth-services = [
74
- {
75
- type = unsafe-jwt-hmac-256
76
- target-audience = "https://canton.network.global"
77
- secret = "unsafe"
78
- },
79
- {
80
- type = jwt-es-256-crt
81
- certificate = "/app/es256-certificate.pem"
82
- target-audience = "https://canton.network.global/es256"
83
- }
84
- ]
85
-
86
- canton.participants.extra-2.ledger-api.auth-services = [
87
- {
88
- type = unsafe-jwt-hmac-256
89
- target-audience = "https://canton.network.global"
90
- secret = "unsafe"
91
- },
92
- {
93
- type = jwt-es-256-crt
94
- certificate = "/app/es256-certificate.pem"
95
- target-audience = "https://canton.network.global/es256"
96
- }
97
- ]
98
-
99
- canton.participants.extra-3.ledger-api.auth-services = [
100
- {
101
- type = unsafe-jwt-hmac-256
102
- target-audience = "https://canton.network.global"
103
- secret = "unsafe"
104
- },
105
- {
106
- type = jwt-es-256-crt
107
- certificate = "/app/es256-certificate.pem"
108
- target-audience = "https://canton.network.global/es256"
109
- }
110
- ]
111
-
112
- canton.participants.extra-1.ledger-api.tls {
113
- cert-chain-file = "/app/localnet-tls/server.crt"
114
- private-key-file = "/app/localnet-tls/server.key"
115
- trust-collection-file = "/app/localnet-tls/ca.crt"
116
- }
117
- canton.participants.extra-1.admin-api.tls {
118
- cert-chain-file = "/app/localnet-tls/server.crt"
119
- private-key-file = "/app/localnet-tls/server.key"
120
- trust-collection-file = "/app/localnet-tls/ca.crt"
121
- }
122
-
123
- canton.participants.extra-2.ledger-api.tls {
124
- cert-chain-file = "/app/localnet-tls/server.crt"
125
- private-key-file = "/app/localnet-tls/server.key"
126
- trust-collection-file = "/app/localnet-tls/ca.crt"
127
- }
128
- canton.participants.extra-2.admin-api.tls {
129
- cert-chain-file = "/app/localnet-tls/server.crt"
130
- private-key-file = "/app/localnet-tls/server.key"
131
- trust-collection-file = "/app/localnet-tls/ca.crt"
132
- }
133
-
134
- canton.participants.extra-3.ledger-api.tls {
135
- cert-chain-file = "/app/localnet-tls/server.crt"
136
- private-key-file = "/app/localnet-tls/server.key"
137
- trust-collection-file = "/app/localnet-tls/ca.crt"
138
- }
139
- canton.participants.extra-3.admin-api.tls {
140
- cert-chain-file = "/app/localnet-tls/server.crt"
141
- private-key-file = "/app/localnet-tls/server.key"
142
- trust-collection-file = "/app/localnet-tls/ca.crt"
143
- }
144
-
@@ -103,18 +103,3 @@ canton.validator-apps.extra-3-validator_backend = $${_validator_backend} {
103
103
 
104
104
  canton.sv-apps.sv.expected-validator-onboardings += { secret = "${EXTRA_VALIDATOR_3_ONBOARDING_SECRET}" }
105
105
 
106
- canton.validator-apps.extra-1-validator_backend.participant-client {
107
- admin-api.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
108
- ledger-api.client-config.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
109
- }
110
-
111
- canton.validator-apps.extra-2-validator_backend.participant-client {
112
- admin-api.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
113
- ledger-api.client-config.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
114
- }
115
-
116
- canton.validator-apps.extra-3-validator_backend.participant-client {
117
- admin-api.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
118
- ledger-api.client-config.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
119
- }
120
-
@@ -84,78 +84,6 @@ services:
84
84
  }
85
85
  }
86
86
 
87
- canton.participants.extra-1.ledger-api.auth-services = [
88
- {
89
- type = unsafe-jwt-hmac-256
90
- target-audience = "https://canton.network.global"
91
- secret = "unsafe"
92
- },
93
- {
94
- type = jwt-es-256-crt
95
- certificate = "/app/es256-certificate.pem"
96
- target-audience = "https://canton.network.global/es256"
97
- }
98
- ]
99
-
100
- canton.participants.extra-2.ledger-api.auth-services = [
101
- {
102
- type = unsafe-jwt-hmac-256
103
- target-audience = "https://canton.network.global"
104
- secret = "unsafe"
105
- },
106
- {
107
- type = jwt-es-256-crt
108
- certificate = "/app/es256-certificate.pem"
109
- target-audience = "https://canton.network.global/es256"
110
- }
111
- ]
112
-
113
- canton.participants.extra-3.ledger-api.auth-services = [
114
- {
115
- type = unsafe-jwt-hmac-256
116
- target-audience = "https://canton.network.global"
117
- secret = "unsafe"
118
- },
119
- {
120
- type = jwt-es-256-crt
121
- certificate = "/app/es256-certificate.pem"
122
- target-audience = "https://canton.network.global/es256"
123
- }
124
- ]
125
-
126
- canton.participants.extra-1.ledger-api.tls {
127
- cert-chain-file = "/app/localnet-tls/server.crt"
128
- private-key-file = "/app/localnet-tls/server.key"
129
- trust-collection-file = "/app/localnet-tls/ca.crt"
130
- }
131
- canton.participants.extra-1.admin-api.tls {
132
- cert-chain-file = "/app/localnet-tls/server.crt"
133
- private-key-file = "/app/localnet-tls/server.key"
134
- trust-collection-file = "/app/localnet-tls/ca.crt"
135
- }
136
-
137
- canton.participants.extra-2.ledger-api.tls {
138
- cert-chain-file = "/app/localnet-tls/server.crt"
139
- private-key-file = "/app/localnet-tls/server.key"
140
- trust-collection-file = "/app/localnet-tls/ca.crt"
141
- }
142
- canton.participants.extra-2.admin-api.tls {
143
- cert-chain-file = "/app/localnet-tls/server.crt"
144
- private-key-file = "/app/localnet-tls/server.key"
145
- trust-collection-file = "/app/localnet-tls/ca.crt"
146
- }
147
-
148
- canton.participants.extra-3.ledger-api.tls {
149
- cert-chain-file = "/app/localnet-tls/server.crt"
150
- private-key-file = "/app/localnet-tls/server.key"
151
- trust-collection-file = "/app/localnet-tls/ca.crt"
152
- }
153
- canton.participants.extra-3.admin-api.tls {
154
- cert-chain-file = "/app/localnet-tls/server.crt"
155
- private-key-file = "/app/localnet-tls/server.key"
156
- trust-collection-file = "/app/localnet-tls/ca.crt"
157
- }
158
-
159
87
  ports:
160
88
  - "${EXTRA_PARTICIPANT_1_LEDGER_API_PUBLISHED_PORT}:${EXTRA_PARTICIPANT_1_LEDGER_API_PORT}"
161
89
  - "${EXTRA_PARTICIPANT_1_ADMIN_API_PUBLISHED_PORT}:${EXTRA_PARTICIPANT_1_ADMIN_API_PORT}"
@@ -276,21 +204,6 @@ services:
276
204
 
277
205
  canton.sv-apps.sv.expected-validator-onboardings += { secret = "${EXTRA_VALIDATOR_3_ONBOARDING_SECRET}" }
278
206
 
279
- canton.validator-apps.extra-1-validator_backend.participant-client {
280
- admin-api.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
281
- ledger-api.client-config.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
282
- }
283
-
284
- canton.validator-apps.extra-2-validator_backend.participant-client {
285
- admin-api.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
286
- ledger-api.client-config.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
287
- }
288
-
289
- canton.validator-apps.extra-3-validator_backend.participant-client {
290
- admin-api.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
291
- ledger-api.client-config.tls.trust-collection-file = "/app/localnet-tls/ca.crt"
292
- }
293
-
294
207
  ports:
295
208
  - "${EXTRA_VALIDATOR_1_ADMIN_API_PUBLISHED_PORT}:${EXTRA_VALIDATOR_1_ADMIN_API_PORT}"
296
209
  - "${EXTRA_VALIDATOR_2_ADMIN_API_PUBLISHED_PORT}:${EXTRA_VALIDATOR_2_ADMIN_API_PORT}"
@@ -333,10 +246,8 @@ services:
333
246
  SCRIBE_TARGET_POSTGRES_USERNAME: ${DB_USER}
334
247
  SCRIBE_TARGET_POSTGRES_PASSWORD: ${DB_PASSWORD}
335
248
  SCRIBE_CONFIG: /onboarding/extra-1-pqs.conf
336
- SCRIBE_SOURCE_LEDGER_TLS_CAFILE: /app/localnet-tls/ca.crt
337
249
  volumes:
338
250
  - onboarding:/onboarding
339
- - "/home/helena/env/daml/typescript-sdk/.generated/localnet-tls/ca.crt:/app/localnet-tls/ca.crt:ro"
340
251
  command:
341
252
  - pipeline
342
253
  - ledger
@@ -387,10 +298,8 @@ services:
387
298
  SCRIBE_TARGET_POSTGRES_USERNAME: ${DB_USER}
388
299
  SCRIBE_TARGET_POSTGRES_PASSWORD: ${DB_PASSWORD}
389
300
  SCRIBE_CONFIG: /onboarding/extra-2-pqs.conf
390
- SCRIBE_SOURCE_LEDGER_TLS_CAFILE: /app/localnet-tls/ca.crt
391
301
  volumes:
392
302
  - onboarding:/onboarding
393
- - "/home/helena/env/daml/typescript-sdk/.generated/localnet-tls/ca.crt:/app/localnet-tls/ca.crt:ro"
394
303
  command:
395
304
  - pipeline
396
305
  - ledger
@@ -441,10 +350,8 @@ services:
441
350
  SCRIBE_TARGET_POSTGRES_USERNAME: ${DB_USER}
442
351
  SCRIBE_TARGET_POSTGRES_PASSWORD: ${DB_PASSWORD}
443
352
  SCRIBE_CONFIG: /onboarding/extra-3-pqs.conf
444
- SCRIBE_SOURCE_LEDGER_TLS_CAFILE: /app/localnet-tls/ca.crt
445
353
  volumes:
446
354
  - onboarding:/onboarding
447
- - "/home/helena/env/daml/typescript-sdk/.generated/localnet-tls/ca.crt:/app/localnet-tls/ca.crt:ro"
448
355
  command:
449
356
  - pipeline
450
357
  - ledger
@@ -911,7 +911,7 @@ extra_participants_healthy() {
911
911
  local prefix=$((index + 4))
912
912
  local health_port
913
913
  health_port="$(participant_port "$prefix" "$CANTON_HTTP_HEALTHCHECK_PORT_SUFFIX")"
914
- checks+=("curl -sf --max-time 2 http://localhost:${health_port}/health > /dev/null")
914
+ checks+=("wget -q --timeout=2 --tries=1 -O /dev/null http://localhost:${health_port}/health")
915
915
  done
916
916
 
917
917
  local joined_checks
@@ -958,40 +958,88 @@ extra_pqs_services() {
958
958
  done
959
959
  }
960
960
 
961
- wait_for_container_health() {
961
+ container_readiness_state() {
962
962
  local container="$1"
963
- local attempts="${2:-30}"
964
- local delay_seconds="${3:-2}"
965
- local status
963
+ docker inspect --format '{{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$container" \
964
+ 2>/dev/null | tail -n 1 || true
965
+ }
966
966
 
967
- for ((i = 1; i <= attempts; i++)); do
968
- status="$(docker inspect --format '{{.State.Health.Status}}' "$container" 2>/dev/null | tail -n 1 || true)"
969
- if [[ "$status" == "healthy" ]]; then
970
- return 0
971
- fi
972
- sleep "$delay_seconds"
973
- done
967
+ container_health_is_ready() {
968
+ local _container="$1"
969
+ local _lifecycle_state="$2"
970
+ local health_status="$3"
971
+ [[ "$lifecycle_state" == "running" && "$health_status" == "healthy" ]]
972
+ }
974
973
 
975
- echo "$container did not become healthy after $((attempts * delay_seconds)) seconds." >&2
976
- return 1
974
+ canton_and_extras_are_ready() {
975
+ local _container="$1"
976
+ local _lifecycle_state="$2"
977
+ local health_status="$3"
978
+ local extra_participants="$4"
979
+ [[ "$lifecycle_state" == "running" && "$health_status" == "healthy" ]] \
980
+ && extra_participants_healthy "$extra_participants"
977
981
  }
978
982
 
979
- wait_for_canton_health() {
980
- local extra_participants="${1:-0}"
981
- local attempts=30
982
- local delay_seconds=2
983
- local status
983
+ print_container_logs() {
984
+ local container="$1"
985
+ echo "Recent logs for $container:" >&2
986
+ docker logs --tail 40 "$container" >&2 || true
987
+ }
988
+
989
+ readiness_elapsed_seconds() {
990
+ if [[ -n "${START_LOCAL_TEST_READINESS_CLOCK_FILE:-}" ]]; then
991
+ cat "$START_LOCAL_TEST_READINESS_CLOCK_FILE"
992
+ return 0
993
+ fi
994
+ printf '%s\n' "$SECONDS"
995
+ }
984
996
 
985
- for ((i = 1; i <= attempts; i++)); do
986
- status="$(docker inspect --format '{{.State.Health.Status}}' canton 2>/dev/null | tail -n 1 || true)"
987
- if [[ "$status" == "healthy" ]] && extra_participants_healthy "$extra_participants"; then
997
+ wait_for_container_readiness() {
998
+ local container="$1"
999
+ local readiness_predicate="$2"
1000
+ shift 2
1001
+
1002
+ local last_readiness_state=""
1003
+ local last_diagnostic_at
1004
+ last_diagnostic_at="$(readiness_elapsed_seconds)"
1005
+
1006
+ while true; do
1007
+ local lifecycle_state health_status readiness_state
1008
+ read -r lifecycle_state health_status <<< "$(container_readiness_state "$container")"
1009
+ lifecycle_state="${lifecycle_state:-missing}"
1010
+ health_status="${health_status:-unknown}"
1011
+
1012
+ if [[ "$lifecycle_state" != "running" && "$lifecycle_state" != "restarting" ]]; then
1013
+ echo "$container is not running (state: $lifecycle_state)." >&2
1014
+ print_container_logs "$container"
1015
+ return 1
1016
+ fi
1017
+
1018
+ readiness_state="$lifecycle_state/$health_status"
1019
+ if [[ "$readiness_state" != "$last_readiness_state" ]]; then
1020
+ echo "$container readiness: $readiness_state"
1021
+ last_readiness_state="$readiness_state"
1022
+ fi
1023
+
1024
+ if "$readiness_predicate" "$container" "$lifecycle_state" "$health_status" "$@"; then
988
1025
  return 0
989
1026
  fi
990
- sleep "$delay_seconds"
1027
+
1028
+ local now
1029
+ now="$(readiness_elapsed_seconds)"
1030
+ if (( now - last_diagnostic_at >= 30 )); then
1031
+ echo "$container is still not ready (state: $lifecycle_state, health: $health_status)." >&2
1032
+ print_container_logs "$container"
1033
+ last_diagnostic_at="$now"
1034
+ fi
1035
+
1036
+ sleep 2
991
1037
  done
1038
+ }
992
1039
 
993
- echo "canton did not become healthy after $((attempts * delay_seconds)) seconds." >&2
994
- return 1
1040
+ wait_for_canton_health() {
1041
+ local extra_participants="${1:-0}"
1042
+ wait_for_container_readiness canton canton_and_extras_are_ready "$extra_participants"
995
1043
  }
996
1044
 
997
1045
  provision_extra_pqs() {
@@ -1190,8 +1238,8 @@ start_ledger_stack() {
1190
1238
  docker_compose "${compose_args[@]}" up -d --no-recreate "${followup_services[@]}"
1191
1239
 
1192
1240
  if (( extra_participants > 0 )); then
1193
- wait_for_container_health splice 60 2
1194
- wait_for_container_health splice-onboarding 60 2
1241
+ wait_for_container_readiness splice container_health_is_ready
1242
+ wait_for_container_readiness splice-onboarding container_health_is_ready
1195
1243
  if [[ "$auth_mode" == "shared-secret" ]]; then
1196
1244
  grant_localnet_validator_read_rights "$extra_participants"
1197
1245
  fi
@@ -42,8 +42,9 @@ run_case() {
42
42
  local quickstart_root_dir="$tmpdir/cn-quickstart"
43
43
  local stubbin="$tmpdir/bin"
44
44
  local generated_dir="$tmpdir/generated"
45
+ local docker_state_dir="$tmpdir/docker-state"
45
46
 
46
- rm -rf "$quickstart_dir" "$quickstart_root_dir" "$stubbin" "$generated_dir" "$tmpdir/tls"
47
+ rm -rf "$quickstart_dir" "$quickstart_root_dir" "$stubbin" "$generated_dir" "$docker_state_dir" "$tmpdir/tls"
47
48
  mkdir -p \
48
49
  "$quickstart_root_dir" \
49
50
  "$quickstart_dir/docker/modules/localnet/env" \
@@ -51,7 +52,9 @@ run_case() {
51
52
  "$quickstart_dir/docker/modules/splice-onboarding" \
52
53
  "$quickstart_dir/docker/modules/keycloak" \
53
54
  "$stubbin" \
54
- "$generated_dir"
55
+ "$generated_dir" \
56
+ "$docker_state_dir"
57
+ printf '0\n' > "$docker_state_dir/readiness-seconds"
55
58
  ln -s "$quickstart_dir" "$quickstart_root_dir/quickstart"
56
59
  printf '%s\n' "$makefile_targets" > "$quickstart_dir/Makefile"
57
60
  printf '%s\n' \
@@ -132,11 +135,68 @@ printf 'stub env SV_PROFILE=%s\n' "${SV_PROFILE:-}"
132
135
  printf 'stub env PQS_SV_PROFILE=%s\n' "${PQS_SV_PROFILE:-}"
133
136
  printf 'stub env AUTH_MODE=%s\n' "${AUTH_MODE:-}"
134
137
  if [[ "${1:-}" == "inspect" ]]; then
135
- printf 'healthy\n'
138
+ container="${!#}"
139
+ state_file="${START_LOCAL_TEST_DOCKER_STATE_DIR}/${docker_mode}-${container}.count"
140
+ count=0
141
+ if [[ -f "$state_file" ]]; then
142
+ count="$(<"$state_file")"
143
+ fi
144
+ count=$((count + 1))
145
+ printf '%s\n' "$count" > "$state_file"
146
+
147
+ lifecycle=running
148
+ health=healthy
149
+ case "$docker_mode:$container" in
150
+ slow-canton:canton)
151
+ if (( count <= 31 )); then health=starting; fi
152
+ ;;
153
+ slow-splice:splice)
154
+ if (( count <= 61 )); then health=starting; fi
155
+ ;;
156
+ restarting-canton:canton)
157
+ if (( count == 1 )); then
158
+ lifecycle=restarting
159
+ health=unhealthy
160
+ fi
161
+ ;;
162
+ restarting-healthy-canton:canton)
163
+ if (( count == 1 )); then
164
+ lifecycle=restarting
165
+ health=healthy
166
+ fi
167
+ ;;
168
+ exited-canton:canton)
169
+ lifecycle=exited
170
+ health=unhealthy
171
+ ;;
172
+ esac
173
+
174
+ if [[ "$*" == *'.State.Status'* ]]; then
175
+ printf '%s %s\n' "$lifecycle" "$health"
176
+ else
177
+ printf '%s\n' "$health"
178
+ fi
179
+ exit 0
180
+ fi
181
+ if [[ "${1:-}" == "logs" ]]; then
182
+ printf 'stub log tail for %s\n' "${!#}"
136
183
  exit 0
137
184
  fi
138
- if [[ "${1:-}" == "exec" ]]; then
139
- extra_pqs_config_file=""
185
+ if [[ "${1:-}" == "exec" ]]; then
186
+ if [[ "$*" == *"http://localhost:"* ]]; then
187
+ printf '%s\n' "$*" > "${START_LOCAL_TEST_DOCKER_STATE_DIR}/extra-healthcheck-command"
188
+ healthcheck_state_file="${START_LOCAL_TEST_DOCKER_STATE_DIR}/${docker_mode}-extra-healthcheck.count"
189
+ healthcheck_count=0
190
+ if [[ -f "$healthcheck_state_file" ]]; then
191
+ healthcheck_count="$(<"$healthcheck_state_file")"
192
+ fi
193
+ healthcheck_count=$((healthcheck_count + 1))
194
+ printf '%s\n' "$healthcheck_count" > "$healthcheck_state_file"
195
+ if [[ "$docker_mode" == "slow-extra-health" && "$healthcheck_count" == "1" ]]; then
196
+ exit 1
197
+ fi
198
+ fi
199
+ extra_pqs_config_file=""
140
200
  while (( "$#" )); do
141
201
  if [[ "${1:-}" == "-e" && "${2:-}" == EXTRA_PQS_CONFIG_FILE=* ]]; then
142
202
  extra_pqs_config_file="${2#EXTRA_PQS_CONFIG_FILE=}"
@@ -160,6 +220,9 @@ if [[ "${1:-}" == "compose" && "${2:-}" == "version" ]]; then
160
220
  exit 0
161
221
  fi
162
222
  printf 'stub docker %s\n' "$*"
223
+ if [[ "$*" == *" up -d --no-recreate pqs-extra-1"* ]]; then
224
+ printf 'stub extra pqs startup\n'
225
+ fi
163
226
  if [[ "$docker_mode" == "staged-start" ]]; then
164
227
  if [[ "${1:-}" == "compose" && "$*" == *" down -v --remove-orphans"* ]]; then
165
228
  exit 0
@@ -189,6 +252,16 @@ EOF
189
252
  sed -i "s|__DOCKER_MODE__|$docker_mode|" "$stubbin/docker"
190
253
  chmod +x "$stubbin/docker"
191
254
 
255
+ cat > "$stubbin/sleep" <<'EOF'
256
+ #!/usr/bin/env bash
257
+ set -euo pipefail
258
+ if [[ -n "${START_LOCAL_TEST_READINESS_CLOCK_FILE:-}" ]]; then
259
+ current="$(<"$START_LOCAL_TEST_READINESS_CLOCK_FILE")"
260
+ printf '%s\n' "$((current + ${1:-0}))" > "$START_LOCAL_TEST_READINESS_CLOCK_FILE"
261
+ fi
262
+ EOF
263
+ chmod +x "$stubbin/sleep"
264
+
192
265
  cat > "$stubbin/docker-compose" <<'EOF'
193
266
  #!/usr/bin/env bash
194
267
  set -euo pipefail
@@ -226,6 +299,8 @@ EOF
226
299
  LOCALNET_TLS_CERT_CHAIN_PATH="$tls_cert_chain_path" \
227
300
  LOCALNET_TLS_PRIVATE_KEY_PATH="$tls_private_key_path" \
228
301
  LOCALNET_TLS_CA_CERT_PATH="$tls_ca_cert_path" \
302
+ START_LOCAL_TEST_DOCKER_STATE_DIR="$docker_state_dir" \
303
+ START_LOCAL_TEST_READINESS_CLOCK_FILE="$docker_state_dir/readiness-seconds" \
229
304
  EXTRA_PARTICIPANTS="$extra_participants" \
230
305
  PATH="$stubbin:$PATH" \
231
306
  bash ./start-local.sh 2>&1
@@ -240,6 +315,8 @@ EOF
240
315
  LOCALNET_TLS_CERT_CHAIN_PATH="$tls_cert_chain_path" \
241
316
  LOCALNET_TLS_PRIVATE_KEY_PATH="$tls_private_key_path" \
242
317
  LOCALNET_TLS_CA_CERT_PATH="$tls_ca_cert_path" \
318
+ START_LOCAL_TEST_DOCKER_STATE_DIR="$docker_state_dir" \
319
+ START_LOCAL_TEST_READINESS_CLOCK_FILE="$docker_state_dir/readiness-seconds" \
243
320
  EXTRA_PARTICIPANTS="$extra_participants" \
244
321
  PATH="$stubbin:$PATH" \
245
322
  bash ./start-local.sh 2>&1
@@ -353,7 +430,11 @@ printf 'stub env SV_PROFILE=%s\n' "${SV_PROFILE:-}"
353
430
  printf 'stub env PQS_SV_PROFILE=%s\n' "${PQS_SV_PROFILE:-}"
354
431
  printf 'stub env AUTH_MODE=%s\n' "${AUTH_MODE:-}"
355
432
  if [[ "${1:-}" == "inspect" ]]; then
356
- printf 'healthy\n'
433
+ if [[ "$*" == *'.State.Status'* ]]; then
434
+ printf 'running healthy\n'
435
+ else
436
+ printf 'healthy\n'
437
+ fi
357
438
  exit 0
358
439
  fi
359
440
  if [[ "${1:-}" == "exec" ]]; then
@@ -390,6 +471,15 @@ run_case $'.PHONY: start\nstart:\n' 'stub env APP_USER_PROFILE=off'
390
471
  run_case $'.PHONY: start\nstart:\n' 'stub env SV_PROFILE=on'
391
472
  run_case $'.PHONY: start\nstart:\n' 'stub env PQS_SV_PROFILE=on'
392
473
  run_case $'.PHONY: start\nstart:\n' 'stub env AUTH_MODE=oauth2' oauth2
474
+ run_case $'.PHONY: start\nstart:\n' 'canton readiness: running/starting' shared-secret slow-canton
475
+ run_case $'.PHONY: start\nstart:\n' 'canton is still not ready (state: running, health: starting).' shared-secret slow-canton
476
+ run_case $'.PHONY: start\nstart:\n' 'stub log tail for canton' shared-secret slow-canton
477
+ run_case $'.PHONY: start\nstart:\n' 'canton readiness: restarting/unhealthy' shared-secret restarting-canton
478
+ run_case $'.PHONY: start\nstart:\n' 'canton readiness: running/healthy' shared-secret restarting-healthy-canton
479
+ run_case $'.PHONY: start\nstart:\n' 'canton is not running (state: exited).' shared-secret exited-canton '' '' '' 0 0 '' '' '' 1
480
+ run_case $'.PHONY: start\nstart:\n' 'stub log tail for canton' shared-secret exited-canton '' '' '' 0 0 '' '' '' 1
481
+ run_case $'.PHONY: start\nstart:\n' 'splice readiness: running/starting' shared-secret slow-splice 1
482
+ run_case $'.PHONY: start\nstart:\n' 'stub extra pqs startup' shared-secret slow-splice 1
393
483
  run_case $'.PHONY: start\nstart:\n' 'stub docker compose -f compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/localnet/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/splice-onboarding/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/pqs/compose.yaml --env-file .env --env-file .env.local --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/compose.env --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/env/common.env --env-file '"$tmpdir"'/quickstart/docker/modules/pqs/compose.env --profile app-provider --profile pqs-app-provider --profile pqs-sv down -v --remove-orphans'
394
484
  run_case $'.PHONY: start\nstart:\n' 'stub docker compose -f compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/localnet/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/splice-onboarding/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/pqs/compose.yaml --env-file .env --env-file .env.local --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/compose.env --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/env/common.env --env-file '"$tmpdir"'/quickstart/docker/modules/pqs/compose.env --profile app-provider --profile pqs-app-provider --profile pqs-sv up -d --no-recreate postgres canton'
395
485
  run_case $'.PHONY: start\nstart:\n' 'stub docker compose -f compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/localnet/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/splice-onboarding/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/pqs/compose.yaml --env-file .env --env-file .env.local --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/compose.env --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/env/common.env --env-file '"$tmpdir"'/quickstart/docker/modules/pqs/compose.env --profile app-provider --profile pqs-app-provider --profile pqs-sv -f '"$tmpdir"'/quickstart/docker/modules/keycloak/compose.yaml --env-file '"$tmpdir"'/quickstart/docker/modules/keycloak/compose.env --profile keycloak down -v --remove-orphans' oauth2
@@ -398,6 +488,9 @@ run_case $'.PHONY: start\nstart:\n' 'stub docker-compose -f compose.yaml -f '"$t
398
488
  run_case $'.PHONY: start\nstart:\n' 'stub docker compose -f compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/localnet/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/splice-onboarding/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/pqs/compose.yaml --env-file .env --env-file .env.local --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/compose.env --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/env/common.env --env-file '"$tmpdir"'/quickstart/docker/modules/pqs/compose.env --profile app-provider --profile pqs-app-provider --profile pqs-sv -f '"$tmpdir"'/generated/compose-extra-participants.yaml --env-file '"$tmpdir"'/generated/extra-participants.env down -v --remove-orphans' shared-secret default 3
399
489
  run_case $'.PHONY: start\nstart:\n' 'stub docker compose -f compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/localnet/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/splice-onboarding/compose.yaml -f '"$tmpdir"'/quickstart/docker/modules/pqs/compose.yaml --env-file .env --env-file .env.local --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/compose.env --env-file '"$tmpdir"'/quickstart/docker/modules/localnet/env/common.env --env-file '"$tmpdir"'/quickstart/docker/modules/pqs/compose.env --profile app-provider --profile pqs-app-provider --profile pqs-sv -f '"$tmpdir"'/generated/compose-extra-participants.yaml --env-file '"$tmpdir"'/generated/extra-participants.env up -d --no-recreate pqs-extra-1 pqs-extra-2 pqs-extra-3' shared-secret default 3
400
490
  run_case $'.PHONY: start\nstart:\n' 'ES256 bearer token written to '"$tmpdir"'/es256/ledger-api-user.token' shared-secret default 3 '' '' 1
491
+ assert_file_contains_text "$tmpdir/docker-state/extra-healthcheck-command" 'wget -q --timeout=2 --tries=1 -O /dev/null http://localhost:5900/health'
492
+ assert_file_contains_text "$tmpdir/docker-state/extra-healthcheck-command" 'wget -q --timeout=2 --tries=1 -O /dev/null http://localhost:6900/health'
493
+ assert_file_contains_text "$tmpdir/docker-state/extra-healthcheck-command" 'wget -q --timeout=2 --tries=1 -O /dev/null http://localhost:7900/health'
401
494
  assert_file_contains "$tmpdir/es256/canton-es256.conf" 'canton.participants.app-provider.ledger-api.auth-services = ['
402
495
  assert_file_contains "$tmpdir/es256/canton-es256.conf" ' type = jwt-es-256-crt'
403
496
  assert_file_contains "$tmpdir/es256/canton-es256.conf" ' certificate = "/app/es256-certificate.pem"'
@@ -418,6 +511,8 @@ assert_file_contains "$tmpdir/generated/extra-participants.env" 'EXTRA_VALIDATOR
418
511
  assert_file_contains "$tmpdir/generated/extra-participants.env" 'EXTRA_VALIDATOR_1_WALLET_ADMIN_USER_NAME=extra-1'
419
512
  assert_file_contains "$tmpdir/generated/extra-participants.env" 'EXTRA_VALIDATOR_1_AUTH_AUDIENCE=https://canton.network.global'
420
513
  assert_file_contains "$tmpdir/generated/extra-participants.env" 'CREATE_DATABASE_EXTRA_PQS_1=pqs-extra-1'
514
+ run_case $'.PHONY: start\nstart:\n' 'stub extra pqs startup' shared-secret slow-extra-health 3
515
+ assert_file_contains "$tmpdir/docker-state/slow-extra-health-extra-healthcheck.count" '2'
421
516
  assert_file_contains "$tmpdir/generated/extra-participants.env" 'EXTRA_PQS_1_POSTGRES_PUBLISHED_PORT=5541'
422
517
  assert_file_contains "$tmpdir/generated/extra-participants.env" 'EXTRA_PQS_3_POSTGRES_PUBLISHED_PORT=5543'
423
518
  assert_file_contains "$tmpdir/generated/compose-extra-participants.yaml" ' ADDITIONAL_CONFIG_EXTRA_PARTICIPANTS: |'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@distrohelena/canton-typescript-sdk",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -79,6 +79,13 @@
79
79
  "build": "node ./scripts/clean-dist.mjs && tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && node ./scripts/write-cjs-package.mjs",
80
80
  "generate:daml-interface": "node ./dist/daml-interface/cli/daml-interface-cli-main.js",
81
81
  "generate:grpc": "node ./scripts/generate-grpc-bindings.mjs",
82
+ "examples:check": "npm run build && tsc -p tsconfig.examples.json --noEmit",
83
+ "example:init": "npm run build && node --loader ts-node/esm examples/01-client-initialization.ts",
84
+ "example:tls": "npm run build && node --loader ts-node/esm examples/02-tls-connection.ts",
85
+ "example:jwt": "npm run build && node --loader ts-node/esm examples/03-jwt-authentication.ts",
86
+ "example:party:hosted": "npm run build && node --loader ts-node/esm examples/10-hosted-party.ts",
87
+ "example:party:external": "npm run build && node --loader ts-node/esm examples/20-external-party-ed25519.ts",
88
+ "example:party:decentralized": "npm run build && node --loader ts-node/esm examples/30-decentralized-party-ed25519.ts",
82
89
  "lint": "eslint . --max-warnings=0",
83
90
  "lint:fix": "eslint . --fix --max-warnings=0",
84
91
  "start:local-ledger": "bash node/start-local.sh",