@distrohelena/canton-typescript-sdk 0.1.5 → 0.1.7

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 (246) hide show
  1. package/README.md +333 -1
  2. package/dist/client/canton-client-options.d.ts +3 -0
  3. package/dist/client/canton-client-options.js +2 -0
  4. package/dist/client/service-registry.js +3 -2
  5. package/dist/core/errors/grpc-transport-error.d.ts +14 -0
  6. package/dist/core/errors/grpc-transport-error.js +76 -0
  7. package/dist/core/signing/command-signer.interface.d.ts +2 -0
  8. package/dist/core/transports/transport.interface.d.ts +2 -2
  9. package/dist/core/types/canton-hash-purpose.d.ts +2 -1
  10. package/dist/core/types/canton-hash-purpose.js +1 -0
  11. package/dist/core/types/daml-numeric.d.ts +6 -0
  12. package/dist/core/types/daml-numeric.js +14 -0
  13. package/dist/core/types/daml-party.d.ts +6 -0
  14. package/dist/core/types/daml-party.js +14 -0
  15. package/dist/core/types/disclosed-contract.d.ts +13 -0
  16. package/dist/core/types/disclosed-contract.js +15 -0
  17. package/dist/core/types/requests/create-decentralized-party-request.d.ts +41 -0
  18. package/dist/core/types/requests/create-decentralized-party-request.js +82 -0
  19. package/dist/core/types/requests/create-external-party-request.d.ts +42 -0
  20. package/dist/core/types/requests/create-external-party-request.js +47 -0
  21. package/dist/core/types/requests/finalize-decentralized-party-request.d.ts +39 -0
  22. package/dist/core/types/requests/finalize-decentralized-party-request.js +42 -0
  23. package/dist/core/types/requests/get-active-contracts-page-request.d.ts +15 -2
  24. package/dist/core/types/requests/get-active-contracts-page-request.js +4 -0
  25. package/dist/core/types/requests/submit-command-request.d.ts +5 -0
  26. package/dist/core/types/requests/submit-command-request.js +4 -0
  27. package/dist/core/types/topology/topology-signature-format.d.ts +2 -1
  28. package/dist/core/types/topology/topology-signature-format.js +1 -0
  29. package/dist/daml-lf/container/dar-archive-entry.d.ts +8 -0
  30. package/dist/daml-lf/container/dar-archive-entry.js +8 -0
  31. package/dist/daml-lf/container/dar-archive-loader.js +14 -0
  32. package/dist/daml-lf/container/dar-archive.d.ts +6 -0
  33. package/dist/daml-lf/container/dar-archive.js +4 -0
  34. package/dist/daml-lf/container/dar-source-bundle-loader.d.ts +5 -0
  35. package/dist/daml-lf/container/dar-source-bundle-loader.js +33 -0
  36. package/dist/daml-lf/container/dar-source-bundle.d.ts +45 -0
  37. package/dist/daml-lf/container/dar-source-bundle.js +11 -0
  38. package/dist/daml-lf/container/dar-source-file-entry.d.ts +8 -0
  39. package/dist/daml-lf/container/dar-source-file-entry.js +8 -0
  40. package/dist/daml-lf/daml-lf-compilation.d.ts +12 -0
  41. package/dist/daml-lf/daml-lf-compilation.js +35 -0
  42. package/dist/daml-lf/index.d.ts +11 -0
  43. package/dist/daml-lf/index.js +10 -0
  44. package/dist/daml-lf/interpreter/daml-lf-builtin-dispatch.d.ts +43 -0
  45. package/dist/daml-lf/interpreter/daml-lf-builtin-dispatch.js +933 -0
  46. package/dist/daml-lf/interpreter/daml-lf-evaluator.d.ts +95 -0
  47. package/dist/daml-lf/interpreter/daml-lf-evaluator.js +1131 -0
  48. package/dist/daml-lf/interpreter/daml-lf-interpreter-scaffold.d.ts +3 -0
  49. package/dist/daml-lf/interpreter/daml-lf-interpreter-scaffold.js +6 -1
  50. package/dist/daml-lf/interpreter/daml-lf-lexical-scope.d.ts +13 -0
  51. package/dist/daml-lf/interpreter/daml-lf-lexical-scope.js +46 -0
  52. package/dist/daml-lf/interpreter/daml-lf-runtime-frame.d.ts +16 -0
  53. package/dist/daml-lf/interpreter/daml-lf-runtime-frame.js +15 -0
  54. package/dist/daml-lf/interpreter/daml-lf-runtime-value.d.ts +21 -0
  55. package/dist/daml-lf/interpreter/daml-lf-runtime-value.js +4 -1
  56. package/dist/daml-lf/interpreter/daml-lf-step-kind.d.ts +7 -0
  57. package/dist/daml-lf/interpreter/daml-lf-step-kind.js +8 -0
  58. package/dist/daml-lf/interpreter/daml-lf-trace-sink.interface.d.ts +30 -0
  59. package/dist/daml-lf/interpreter/daml-lf-trace-sink.interface.js +1 -0
  60. package/dist/daml-lf/model/daml-lf-builtin-type.d.ts +3 -0
  61. package/dist/daml-lf/model/daml-lf-builtin-type.js +3 -0
  62. package/dist/daml-lf/model/daml-lf-choice.d.ts +5 -0
  63. package/dist/daml-lf/model/daml-lf-choice.js +4 -0
  64. package/dist/daml-lf/model/daml-lf-expression-path.d.ts +2 -0
  65. package/dist/daml-lf/model/daml-lf-expression-path.js +81 -0
  66. package/dist/daml-lf/model/daml-lf-expression.d.ts +146 -0
  67. package/dist/daml-lf/model/daml-lf-expression.js +71 -0
  68. package/dist/daml-lf/model/daml-lf-template.d.ts +2 -0
  69. package/dist/daml-lf/model/daml-lf-template.js +2 -0
  70. package/dist/daml-lf/model/daml-lf-type.d.ts +2 -0
  71. package/dist/daml-lf/model/daml-lf-type.js +4 -0
  72. package/dist/daml-lf/model/lf-2-model-mapper.d.ts +5 -0
  73. package/dist/daml-lf/model/lf-2-model-mapper.js +445 -12
  74. package/dist/debugger/errors/replay-determinism.exception.d.ts +3 -0
  75. package/dist/debugger/errors/replay-determinism.exception.js +3 -0
  76. package/dist/debugger/errors/replay-missing-package.exception.d.ts +3 -0
  77. package/dist/debugger/errors/replay-missing-package.exception.js +3 -0
  78. package/dist/debugger/errors/replay-missing-source.exception.d.ts +3 -0
  79. package/dist/debugger/errors/replay-missing-source.exception.js +3 -0
  80. package/dist/debugger/errors/replay-source-map.exception.d.ts +3 -0
  81. package/dist/debugger/errors/replay-source-map.exception.js +3 -0
  82. package/dist/debugger/errors/replay-state-hydration.exception.d.ts +3 -0
  83. package/dist/debugger/errors/replay-state-hydration.exception.js +3 -0
  84. package/dist/debugger/errors/replay-unsupported-lf-construct.exception.d.ts +3 -0
  85. package/dist/debugger/errors/replay-unsupported-lf-construct.exception.js +3 -0
  86. package/dist/debugger/errors/replay-unsupported-update.exception.d.ts +3 -0
  87. package/dist/debugger/errors/replay-unsupported-update.exception.js +3 -0
  88. package/dist/debugger/index.d.ts +31 -0
  89. package/dist/debugger/index.js +31 -0
  90. package/dist/debugger/ledger-replay-debugger-client.d.ts +31 -0
  91. package/dist/debugger/ledger-replay-debugger-client.js +53 -0
  92. package/dist/debugger/replay/ledger-replay-environment-builder.d.ts +95 -0
  93. package/dist/debugger/replay/ledger-replay-environment-builder.js +249 -0
  94. package/dist/debugger/replay/ledger-replay-session-loader.d.ts +78 -0
  95. package/dist/debugger/replay/ledger-replay-session-loader.js +565 -0
  96. package/dist/debugger/replay/replay-artifact-resolver.d.ts +30 -0
  97. package/dist/debugger/replay/replay-artifact-resolver.js +210 -0
  98. package/dist/debugger/replay/replay-determinism-validator.d.ts +12 -0
  99. package/dist/debugger/replay/replay-determinism-validator.js +161 -0
  100. package/dist/debugger/replay/replay-entrypoint-definition-resolver.d.ts +40 -0
  101. package/dist/debugger/replay/replay-entrypoint-definition-resolver.js +337 -0
  102. package/dist/debugger/replay/replay-entrypoint.d.ts +22 -0
  103. package/dist/debugger/replay/replay-entrypoint.js +14 -0
  104. package/dist/debugger/replay/replay-ledger-value-normalizer.d.ts +7 -0
  105. package/dist/debugger/replay/replay-ledger-value-normalizer.js +194 -0
  106. package/dist/debugger/replay/replay-update-loader.d.ts +24 -0
  107. package/dist/debugger/replay/replay-update-loader.js +94 -0
  108. package/dist/debugger/replay/replay-update-visibility-validator.d.ts +19 -0
  109. package/dist/debugger/replay/replay-update-visibility-validator.js +19 -0
  110. package/dist/debugger/session/in-memory-replay-session-store.d.ts +27 -0
  111. package/dist/debugger/session/in-memory-replay-session-store.js +109 -0
  112. package/dist/debugger/session/replay-phase.d.ts +7 -0
  113. package/dist/debugger/session/replay-phase.js +8 -0
  114. package/dist/debugger/session/replay-scope.d.ts +10 -0
  115. package/dist/debugger/session/replay-scope.js +10 -0
  116. package/dist/debugger/session/replay-session-metadata.d.ts +10 -0
  117. package/dist/debugger/session/replay-session-metadata.js +10 -0
  118. package/dist/debugger/session/replay-session-request.d.ts +6 -0
  119. package/dist/debugger/session/replay-session-request.js +10 -0
  120. package/dist/debugger/session/replay-session.d.ts +12 -0
  121. package/dist/debugger/session/replay-session.js +10 -0
  122. package/dist/debugger/session/replay-source-location.d.ts +17 -0
  123. package/dist/debugger/session/replay-source-location.js +16 -0
  124. package/dist/debugger/session/replay-stack-frame.d.ts +8 -0
  125. package/dist/debugger/session/replay-stack-frame.js +8 -0
  126. package/dist/debugger/session/replay-state-delta.d.ts +29 -0
  127. package/dist/debugger/session/replay-state-delta.js +24 -0
  128. package/dist/debugger/session/replay-step-advance-result.d.ts +24 -0
  129. package/dist/debugger/session/replay-step-advance-result.js +16 -0
  130. package/dist/debugger/session/replay-step.d.ts +30 -0
  131. package/dist/debugger/session/replay-step.js +24 -0
  132. package/dist/debugger/session/replay-value-preview.d.ts +8 -0
  133. package/dist/debugger/session/replay-value-preview.js +15 -0
  134. package/dist/debugger/source/daml-source-mapper.d.ts +12 -0
  135. package/dist/debugger/source/daml-source-mapper.js +21 -0
  136. package/dist/debugger/source/dar-source-map-metadata.d.ts +26 -0
  137. package/dist/debugger/source/dar-source-map-metadata.js +10 -0
  138. package/dist/debugger/source/source-coverage-validator.d.ts +8 -0
  139. package/dist/debugger/source/source-coverage-validator.js +16 -0
  140. package/dist/debugger/source/source-indexed-compilation.d.ts +45 -0
  141. package/dist/debugger/source/source-indexed-compilation.js +110 -0
  142. package/dist/debugger/source/source-mapping-precision.d.ts +5 -0
  143. package/dist/debugger/source/source-mapping-precision.js +4 -0
  144. package/dist/index.d.ts +21 -0
  145. package/dist/index.js +13 -0
  146. package/dist/query/cache/memory-query-cache.d.ts +9 -0
  147. package/dist/query/cache/memory-query-cache.js +24 -0
  148. package/dist/query/cache/query-cache-store.d.ts +5 -0
  149. package/dist/query/cache/query-cache-store.js +1 -0
  150. package/dist/query/canton-manager-options.d.ts +17 -0
  151. package/dist/query/canton-manager-options.js +1 -0
  152. package/dist/query/canton-manager.d.ts +11 -0
  153. package/dist/query/canton-manager.js +42 -0
  154. package/dist/query/errors/pqs-query-error.d.ts +10 -0
  155. package/dist/query/errors/pqs-query-error.js +11 -0
  156. package/dist/query/errors/pqs-schema-profile-error.d.ts +3 -0
  157. package/dist/query/errors/pqs-schema-profile-error.js +3 -0
  158. package/dist/query/errors/query-capability-error.d.ts +7 -0
  159. package/dist/query/errors/query-capability-error.js +10 -0
  160. package/dist/query/grpc/grpc-contract-query-client.d.ts +32 -0
  161. package/dist/query/grpc/grpc-contract-query-client.js +126 -0
  162. package/dist/query/model-types.d.ts +258 -0
  163. package/dist/query/model-types.js +14 -0
  164. package/dist/query/pqs/pqs-pool.d.ts +13 -0
  165. package/dist/query/pqs/pqs-pool.js +18 -0
  166. package/dist/query/pqs/pqs-query-client.d.ts +49 -0
  167. package/dist/query/pqs/pqs-query-client.js +324 -0
  168. package/dist/query/pqs/pqs-schema-profile.d.ts +25 -0
  169. package/dist/query/pqs/pqs-schema-profile.js +120 -0
  170. package/dist/query/pqs/pqs-sql-compiler.d.ts +7 -0
  171. package/dist/query/pqs/pqs-sql-compiler.js +132 -0
  172. package/dist/query/pqs/read-only-sql.d.ts +1 -0
  173. package/dist/query/pqs/read-only-sql.js +35 -0
  174. package/dist/query/query-client.d.ts +61 -0
  175. package/dist/query/query-client.js +1 -0
  176. package/dist/query/query-source.d.ts +4 -0
  177. package/dist/query/query-source.js +5 -0
  178. package/dist/services/command/command-service-client.d.ts +2 -2
  179. package/dist/services/commands/command-submission-pipeline.d.ts +2 -2
  180. package/dist/services/party-management/decentralized-party-lifecycle.d.ts +6 -0
  181. package/dist/services/party-management/decentralized-party-lifecycle.js +82 -0
  182. package/dist/services/party-management/party-management-service-client.d.ts +16 -1
  183. package/dist/services/party-management/party-management-service-client.js +142 -1
  184. package/dist/services/topology-manager-write/topology-signed-transaction-assembler.js +4 -0
  185. package/dist/testing/campaign/campaign-artifact.d.ts +20 -0
  186. package/dist/testing/campaign/campaign-artifact.js +147 -0
  187. package/dist/testing/campaign/campaign-definition.d.ts +9 -0
  188. package/dist/testing/campaign/campaign-definition.js +78 -0
  189. package/dist/testing/campaign/campaign-metrics.d.ts +32 -0
  190. package/dist/testing/campaign/campaign-metrics.js +26 -0
  191. package/dist/testing/campaign/campaign-model.d.ts +11 -0
  192. package/dist/testing/campaign/campaign-model.js +21 -0
  193. package/dist/testing/campaign/campaign-runner.d.ts +99 -0
  194. package/dist/testing/campaign/campaign-runner.js +194 -0
  195. package/dist/testing/campaign/campaign-scheduler.d.ts +40 -0
  196. package/dist/testing/campaign/campaign-scheduler.js +75 -0
  197. package/dist/testing/campaign/campaign-types.d.ts +52 -0
  198. package/dist/testing/campaign/campaign-types.js +11 -0
  199. package/dist/testing/daml/daml-action-arbitrary.d.ts +13 -0
  200. package/dist/testing/daml/daml-action-arbitrary.js +24 -0
  201. package/dist/testing/daml/daml-choice-action-arbitrary.d.ts +18 -0
  202. package/dist/testing/daml/daml-choice-action-arbitrary.js +27 -0
  203. package/dist/testing/daml/daml-create-action-arbitrary.d.ts +19 -0
  204. package/dist/testing/daml/daml-create-action-arbitrary.js +34 -0
  205. package/dist/testing/daml/daml-testing-catalog.d.ts +38 -0
  206. package/dist/testing/daml/daml-testing-catalog.js +40 -0
  207. package/dist/testing/daml/daml-value-arbitrary.d.ts +8 -0
  208. package/dist/testing/daml/daml-value-arbitrary.js +43 -0
  209. package/dist/testing/daml/declarative-campaign-arbitrary.d.ts +15 -0
  210. package/dist/testing/daml/declarative-campaign-arbitrary.js +30 -0
  211. package/dist/testing/errors/invariant-campaign-failure.d.ts +24 -0
  212. package/dist/testing/errors/invariant-campaign-failure.js +37 -0
  213. package/dist/testing/errors/testing-configuration-error.d.ts +3 -0
  214. package/dist/testing/errors/testing-configuration-error.js +6 -0
  215. package/dist/testing/handlers/handler.d.ts +19 -0
  216. package/dist/testing/handlers/handler.js +31 -0
  217. package/dist/testing/index.d.ts +22 -0
  218. package/dist/testing/index.js +22 -0
  219. package/dist/testing/runtime/campaign-isolation.d.ts +14 -0
  220. package/dist/testing/runtime/campaign-isolation.js +23 -0
  221. package/dist/testing/runtime/canton-test-runtime.d.ts +58 -0
  222. package/dist/testing/runtime/canton-test-runtime.js +138 -0
  223. package/dist/testing/runtime/declarative-action-executor.d.ts +16 -0
  224. package/dist/testing/runtime/declarative-action-executor.js +41 -0
  225. package/dist/testing/targets/target.d.ts +49 -0
  226. package/dist/testing/targets/target.js +121 -0
  227. package/dist/transports/grpc/grpc-channel-factory.js +31 -1
  228. package/dist/transports/grpc/grpc-transport.d.ts +2 -2
  229. package/dist/transports/grpc/grpc-transport.js +11 -8
  230. package/dist/transports/grpc/mappers/commands-mapper.js +23 -2
  231. package/dist/transports/grpc/mappers/contracts-mapper.d.ts +3 -1
  232. package/dist/transports/grpc/mappers/contracts-mapper.js +16 -3
  233. package/dist/transports/grpc/mappers/interactive-command-mapper.d.ts +4 -1
  234. package/dist/transports/grpc/mappers/interactive-command-mapper.js +3 -8
  235. package/dist/transports/grpc/mappers/topology-manager-write-mapper.js +59 -1
  236. package/dist/transports/json/mappers/commands-mapper.js +20 -6
  237. package/node/.generated/start-local/additional-config.extra-participants.conf +37 -0
  238. package/node/.generated/start-local/additional-config.extra-validators.conf +35 -0
  239. package/node/.generated/start-local/compose-extra-participants.yaml +147 -0
  240. package/node/.generated/start-local/extra-participants.env +30 -0
  241. package/node/es256-jwt.mjs +177 -0
  242. package/node/start-local.sh +886 -0
  243. package/node/stop-local.sh +200 -0
  244. package/node/test-start-local.sh +354 -0
  245. package/node/test-stop-local.sh +112 -0
  246. package/package.json +21 -2
@@ -0,0 +1,78 @@
1
+ import { TestingConfigurationError } from "../errors/testing-configuration-error.js";
2
+ export function defineInvariantCampaign(init) {
3
+ const config = resolveConfig(init.config);
4
+ const targetKeys = new Set();
5
+ const targets = init.targets.map((target) => {
6
+ validateTarget(target, init.runtime);
7
+ if (targetKeys.has(target.key)) {
8
+ throw new TestingConfigurationError(`Invariant campaign target '${target.key}' is duplicated.`);
9
+ }
10
+ targetKeys.add(target.key);
11
+ return Object.freeze({
12
+ key: target.key,
13
+ ...(target.actors === undefined
14
+ ? {}
15
+ : { actors: Object.freeze([...target.actors]) }),
16
+ });
17
+ });
18
+ if (targets.length === 0) {
19
+ throw new TestingConfigurationError("Invariant campaigns require at least one target.");
20
+ }
21
+ const handlers = Object.freeze([...(init.handlers ?? [])]);
22
+ validateHandlers(handlers, init.runtime);
23
+ return Object.freeze({
24
+ runtime: init.runtime,
25
+ config,
26
+ targets: Object.freeze(targets),
27
+ handlers,
28
+ invariants: Object.freeze([...init.invariants]),
29
+ });
30
+ }
31
+ function validateHandlers(handlers, runtime) {
32
+ const names = new Set();
33
+ for (const handler of handlers) {
34
+ if (names.has(handler.name)) {
35
+ throw new TestingConfigurationError(`Invariant campaign handler '${handler.name}' is duplicated.`);
36
+ }
37
+ names.add(handler.name);
38
+ if (runtime.isolation.kind === "cleanup" && handler.cleanup === "none") {
39
+ throw new TestingConfigurationError(`Invariant campaign handler '${handler.name}' requires discovery cleanup under cleanup isolation.`);
40
+ }
41
+ }
42
+ }
43
+ function resolveConfig(config) {
44
+ if (!Number.isSafeInteger(config.runs) || config.runs < 1) {
45
+ throw new TestingConfigurationError("Invariant campaign runs must be a positive safe integer.");
46
+ }
47
+ else if (!Number.isSafeInteger(config.depth) || config.depth < 1) {
48
+ throw new TestingConfigurationError("Invariant campaign depth must be a positive safe integer.");
49
+ }
50
+ else if (config.seed !== undefined && !Number.isSafeInteger(config.seed)) {
51
+ throw new TestingConfigurationError("Invariant campaign seed must be a safe integer.");
52
+ }
53
+ else if (config.timeoutMs !== undefined
54
+ && (!Number.isSafeInteger(config.timeoutMs) || config.timeoutMs < 1)) {
55
+ throw new TestingConfigurationError("Invariant campaign timeout must be a positive safe integer.");
56
+ }
57
+ return Object.freeze({
58
+ runs: config.runs,
59
+ depth: config.depth,
60
+ failOnRevert: config.failOnRevert ?? false,
61
+ ...(config.path === undefined ? {} : { path: config.path }),
62
+ ...(config.seed === undefined ? {} : { seed: config.seed }),
63
+ ...(config.timeoutMs === undefined ? {} : { timeoutMs: config.timeoutMs }),
64
+ });
65
+ }
66
+ function validateTarget(target, runtime) {
67
+ if (target.key.length === 0) {
68
+ throw new TestingConfigurationError("Invariant campaign target keys must not be empty.");
69
+ }
70
+ else if (target.actors !== undefined && target.actors.length === 0) {
71
+ throw new TestingConfigurationError(`Invariant campaign target '${target.key}' requires at least one actor.`);
72
+ }
73
+ for (const actor of target.actors ?? []) {
74
+ if (runtime.actors[actor] === undefined) {
75
+ throw new TestingConfigurationError(`Invariant campaign target '${target.key}' references unknown actor '${actor}'.`);
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,32 @@
1
+ export type CampaignMetricOutcome = {
2
+ readonly kind: "accepted";
3
+ readonly updateId: string;
4
+ } | {
5
+ readonly kind: "discarded";
6
+ readonly reason: string;
7
+ } | {
8
+ readonly kind: "malformed-response";
9
+ readonly reason: string;
10
+ } | {
11
+ readonly kind: "protocol-revert";
12
+ readonly reason: string;
13
+ } | {
14
+ readonly kind: "timeout";
15
+ readonly reason: string;
16
+ } | {
17
+ readonly kind: "transport-error";
18
+ readonly reason: string;
19
+ } | {
20
+ readonly kind: "unknown-commit-outcome";
21
+ readonly reason: string;
22
+ };
23
+ export interface CampaignMetrics {
24
+ readonly byActor: Readonly<Record<string, Readonly<Record<string, number>>>>;
25
+ readonly byTarget: Readonly<Record<string, Readonly<Record<string, number>>>>;
26
+ }
27
+ export declare function createCampaignMetrics(): CampaignMetrics;
28
+ export declare function recordCampaignAction(metrics: CampaignMetrics, action: {
29
+ readonly actor: string;
30
+ readonly outcome: CampaignMetricOutcome;
31
+ readonly targetKey: string;
32
+ }): void;
@@ -0,0 +1,26 @@
1
+ export function createCampaignMetrics() {
2
+ return {
3
+ byActor: {},
4
+ byTarget: {},
5
+ };
6
+ }
7
+ export function recordCampaignAction(metrics, action) {
8
+ const mutableMetrics = metrics;
9
+ mutableMetrics.byActor = incrementMetric(mutableMetrics.byActor, action.actor, action.outcome.kind);
10
+ mutableMetrics.byTarget = incrementMetric(mutableMetrics.byTarget, action.targetKey, action.outcome.kind);
11
+ }
12
+ function incrementMetric(metric, key, outcome) {
13
+ const next = {
14
+ ...metric,
15
+ [key]: {
16
+ ...metric[key],
17
+ [outcome]: (metric[key]?.[outcome] ?? 0) + 1,
18
+ },
19
+ };
20
+ return Object.fromEntries(Object.entries(next)
21
+ .sort(([left], [right]) => left.localeCompare(right))
22
+ .map(([metricKey, outcomes]) => [
23
+ metricKey,
24
+ Object.fromEntries(Object.entries(outcomes).sort(([left], [right]) => left.localeCompare(right))),
25
+ ]));
26
+ }
@@ -0,0 +1,11 @@
1
+ import { CampaignMetricOutcome } from "./campaign-metrics.js";
2
+ export interface CampaignModel<Ledger, Ghost> {
3
+ readonly ghost: Ghost;
4
+ readonly ledger: Ledger;
5
+ }
6
+ export declare function createCampaignModel<Ledger, Ghost>(init: {
7
+ readonly ghost: Ghost;
8
+ readonly ledger: Ledger;
9
+ }): CampaignModel<Ledger, Ghost>;
10
+ export declare function reconcileCampaignModel<Ledger, Ghost>(model: CampaignModel<Ledger, Ghost>, ledger: Ledger): CampaignModel<Ledger, Ghost>;
11
+ export declare function applyAcceptedGhostTransition<Ledger, Ghost>(model: CampaignModel<Ledger, Ghost>, outcome: CampaignMetricOutcome, transition: (ghost: Ghost) => Ghost): CampaignModel<Ledger, Ghost>;
@@ -0,0 +1,21 @@
1
+ export function createCampaignModel(init) {
2
+ return Object.freeze({
3
+ ledger: init.ledger,
4
+ ghost: init.ghost,
5
+ });
6
+ }
7
+ export function reconcileCampaignModel(model, ledger) {
8
+ return Object.freeze({
9
+ ledger,
10
+ ghost: model.ghost,
11
+ });
12
+ }
13
+ export function applyAcceptedGhostTransition(model, outcome, transition) {
14
+ if (outcome.kind !== "accepted") {
15
+ return model;
16
+ }
17
+ return Object.freeze({
18
+ ledger: model.ledger,
19
+ ghost: transition(model.ghost),
20
+ });
21
+ }
@@ -0,0 +1,99 @@
1
+ import * as fc from "fast-check";
2
+ import { CampaignMetricOutcome, CampaignMetrics } from "./campaign-metrics.js";
3
+ import { InvariantCampaign } from "./campaign-types.js";
4
+ export interface CampaignInvariantFailure {
5
+ readonly code: string;
6
+ readonly invariant: string;
7
+ readonly message: string;
8
+ }
9
+ export declare function evaluateCampaignInvariantsAsync(init: readonly {
10
+ readonly check: () => Promise<{
11
+ readonly code: string;
12
+ readonly message: string;
13
+ } | undefined>;
14
+ readonly name: string;
15
+ }[]): Promise<readonly CampaignInvariantFailure[]>;
16
+ export declare function runCampaignCheckAsync<Input, Trace>(init: {
17
+ readonly arbitrary: fc.Arbitrary<Input>;
18
+ readonly executeAsync: (input: Input) => Promise<{
19
+ readonly passed: boolean;
20
+ readonly trace: Trace;
21
+ }>;
22
+ readonly key: (input: Input) => string;
23
+ readonly numRuns: number;
24
+ readonly path?: string;
25
+ readonly seed?: number;
26
+ readonly timeoutMs?: number;
27
+ }): Promise<{
28
+ readonly counterexampleTrace?: Trace;
29
+ readonly details: fc.RunDetails<[Input]>;
30
+ }>;
31
+ export interface CampaignExecutableAction {
32
+ readonly actor: string;
33
+ readonly targetKey: string;
34
+ }
35
+ export type CampaignLifecyclePhase<Action> = {
36
+ readonly kind: "before-run";
37
+ } | {
38
+ readonly action: Action;
39
+ readonly kind: "after-action";
40
+ } | {
41
+ readonly kind: "after-run";
42
+ } | {
43
+ readonly kind: "post-cleanup";
44
+ };
45
+ export interface CampaignLifecycleTrace<Action> {
46
+ readonly actions: readonly {
47
+ readonly action: Action;
48
+ readonly outcome: CampaignMetricOutcome;
49
+ }[];
50
+ readonly failures: readonly CampaignInvariantFailure[];
51
+ readonly metrics: CampaignMetrics;
52
+ readonly failureKind?: "execution-error" | "invalid-depth";
53
+ }
54
+ /**
55
+ * Runs generated fixed-depth action sequences with Foundry-style revert
56
+ * handling. Runtime-specific setup, reconciliation, and cleanup stay in
57
+ * caller-provided hooks so this remains usable with any ledger adapter.
58
+ */
59
+ export declare function runCampaignLifecycleCheckAsync<Context, Action extends CampaignExecutableAction>(init: {
60
+ readonly arbitrary: fc.Arbitrary<readonly Action[]>;
61
+ readonly checkInvariantsAsync?: (context: Context, phase: CampaignLifecyclePhase<Action>) => Promise<readonly CampaignInvariantFailure[]>;
62
+ readonly cleanupAsync?: (context: Context) => Promise<void>;
63
+ readonly depth: number;
64
+ readonly executeAsync: (context: Context, action: Action) => Promise<CampaignMetricOutcome>;
65
+ readonly failOnRevert: boolean;
66
+ readonly key: (actions: readonly Action[]) => string;
67
+ readonly numRuns: number;
68
+ readonly path?: string;
69
+ readonly reconcileAsync?: (context: Context, phase: CampaignLifecyclePhase<Action>) => Promise<void>;
70
+ readonly seed?: number;
71
+ /** Receives the candidate so setup can derive deterministic run state. */
72
+ readonly setupAsync: (actions: readonly Action[]) => Promise<Context>;
73
+ readonly timeoutMs?: number;
74
+ }): Promise<{
75
+ readonly counterexampleTrace?: CampaignLifecycleTrace<Action>;
76
+ readonly details: fc.RunDetails<[readonly Action[]]>;
77
+ }>;
78
+ /**
79
+ * Runs a declared invariant campaign and evaluates its invariant functions at
80
+ * every lifecycle checkpoint. The caller supplies the ledger-specific action
81
+ * executor and model hydration hooks; the campaign supplies runs, depth,
82
+ * seed, revert policy, and declared invariants.
83
+ */
84
+ export declare function runInvariantCampaignCheckAsync<Model, Ghost, Action extends CampaignExecutableAction, Context extends {
85
+ readonly ghost: Ghost;
86
+ readonly model: Model;
87
+ }>(init: {
88
+ readonly arbitrary: fc.Arbitrary<readonly Action[]>;
89
+ readonly campaign: InvariantCampaign<Model, Ghost>;
90
+ readonly checkInvariantsAsync?: (context: Context, phase: CampaignLifecyclePhase<Action>) => Promise<readonly CampaignInvariantFailure[]>;
91
+ readonly cleanupAsync?: (context: Context) => Promise<void>;
92
+ readonly executeAsync: (context: Context, action: Action) => Promise<CampaignMetricOutcome>;
93
+ readonly key: (actions: readonly Action[]) => string;
94
+ readonly reconcileAsync?: (context: Context, phase: CampaignLifecyclePhase<Action>) => Promise<void>;
95
+ readonly setupAsync: (actions: readonly Action[]) => Promise<Context>;
96
+ }): Promise<{
97
+ readonly counterexampleTrace?: CampaignLifecycleTrace<Action>;
98
+ readonly details: fc.RunDetails<[readonly Action[]]>;
99
+ }>;
@@ -0,0 +1,194 @@
1
+ import * as fc from "fast-check";
2
+ import { createCampaignMetrics, recordCampaignAction, } from "./campaign-metrics.js";
3
+ export async function evaluateCampaignInvariantsAsync(init) {
4
+ const failures = [];
5
+ for (const invariant of init) {
6
+ try {
7
+ const failure = await invariant.check();
8
+ if (failure !== undefined) {
9
+ failures.push({ invariant: invariant.name, ...failure });
10
+ }
11
+ }
12
+ catch (error) {
13
+ failures.push({
14
+ invariant: invariant.name,
15
+ code: "thrown",
16
+ message: error instanceof Error ? error.message : String(error),
17
+ });
18
+ }
19
+ }
20
+ return failures;
21
+ }
22
+ export async function runCampaignCheckAsync(init) {
23
+ const traces = new Map();
24
+ const details = await fc.check(fc.asyncProperty(init.arbitrary, async (input) => {
25
+ const result = await init.executeAsync(input);
26
+ traces.set(init.key(input), result.trace);
27
+ return result.passed;
28
+ }), {
29
+ numRuns: init.numRuns,
30
+ ...(init.seed === undefined ? {} : { seed: init.seed }),
31
+ ...(init.path === undefined ? {} : { path: init.path }),
32
+ ...(init.timeoutMs === undefined
33
+ ? {}
34
+ : { interruptAfterTimeLimit: init.timeoutMs }),
35
+ });
36
+ const counterexample = details.counterexample?.[0];
37
+ return {
38
+ details,
39
+ ...(counterexample === undefined
40
+ ? {}
41
+ : { counterexampleTrace: traces.get(init.key(counterexample)) }),
42
+ };
43
+ }
44
+ /**
45
+ * Runs generated fixed-depth action sequences with Foundry-style revert
46
+ * handling. Runtime-specific setup, reconciliation, and cleanup stay in
47
+ * caller-provided hooks so this remains usable with any ledger adapter.
48
+ */
49
+ export async function runCampaignLifecycleCheckAsync(init) {
50
+ return runCampaignCheckAsync({
51
+ arbitrary: init.arbitrary,
52
+ key: init.key,
53
+ numRuns: init.numRuns,
54
+ path: init.path,
55
+ seed: init.seed,
56
+ timeoutMs: init.timeoutMs,
57
+ executeAsync: async (actions) => runCampaignCandidateAsync(init, actions),
58
+ });
59
+ }
60
+ /**
61
+ * Runs a declared invariant campaign and evaluates its invariant functions at
62
+ * every lifecycle checkpoint. The caller supplies the ledger-specific action
63
+ * executor and model hydration hooks; the campaign supplies runs, depth,
64
+ * seed, revert policy, and declared invariants.
65
+ */
66
+ export async function runInvariantCampaignCheckAsync(init) {
67
+ return runCampaignLifecycleCheckAsync({
68
+ arbitrary: init.arbitrary,
69
+ depth: init.campaign.config.depth,
70
+ failOnRevert: init.campaign.config.failOnRevert,
71
+ key: init.key,
72
+ numRuns: init.campaign.config.runs,
73
+ path: init.campaign.config.path,
74
+ seed: init.campaign.config.seed,
75
+ timeoutMs: init.campaign.config.timeoutMs,
76
+ setupAsync: init.setupAsync,
77
+ executeAsync: init.executeAsync,
78
+ cleanupAsync: init.cleanupAsync,
79
+ reconcileAsync: init.reconcileAsync,
80
+ checkInvariantsAsync: async (context, phase) => {
81
+ const declaredFailures = await evaluateCampaignInvariantsAsync(init.campaign.invariants.map((invariant, index) => ({
82
+ name: invariant.label ?? (invariant.name || `invariant-${index + 1}`),
83
+ check: async () => {
84
+ await invariant({
85
+ model: context.model,
86
+ ghost: context.ghost,
87
+ });
88
+ return undefined;
89
+ },
90
+ })));
91
+ const additionalFailures = await init.checkInvariantsAsync?.(context, phase) ?? [];
92
+ return [...declaredFailures, ...additionalFailures];
93
+ },
94
+ });
95
+ }
96
+ async function runCampaignCandidateAsync(init, actions) {
97
+ const metrics = createCampaignMetrics();
98
+ const executed = [];
99
+ const failures = [];
100
+ let context;
101
+ let failureKind;
102
+ let passed = true;
103
+ if (actions.length !== init.depth) {
104
+ return {
105
+ passed: false,
106
+ trace: {
107
+ actions: [],
108
+ failures: [],
109
+ metrics,
110
+ failureKind: "invalid-depth",
111
+ },
112
+ };
113
+ }
114
+ const checkInvariantsAsync = async (phase) => {
115
+ if (context === undefined || init.checkInvariantsAsync === undefined) {
116
+ return;
117
+ }
118
+ const phaseFailures = await init.checkInvariantsAsync(context, phase);
119
+ failures.push(...phaseFailures);
120
+ if (phaseFailures.length > 0) {
121
+ passed = false;
122
+ }
123
+ };
124
+ try {
125
+ context = await init.setupAsync(actions);
126
+ const beforeRun = { kind: "before-run" };
127
+ await init.reconcileAsync?.(context, beforeRun);
128
+ await checkInvariantsAsync(beforeRun);
129
+ for (const action of actions) {
130
+ if (!passed) {
131
+ break;
132
+ }
133
+ let outcome;
134
+ try {
135
+ outcome = await init.executeAsync(context, action);
136
+ }
137
+ catch {
138
+ outcome = {
139
+ kind: "transport-error",
140
+ reason: "Campaign action execution threw an error.",
141
+ };
142
+ }
143
+ executed.push({ action, outcome });
144
+ recordCampaignAction(metrics, {
145
+ actor: action.actor,
146
+ targetKey: action.targetKey,
147
+ outcome,
148
+ });
149
+ const afterAction = { kind: "after-action", action };
150
+ if (outcome.kind === "accepted") {
151
+ await init.reconcileAsync?.(context, afterAction);
152
+ }
153
+ await checkInvariantsAsync(afterAction);
154
+ if (outcome.kind !== "accepted"
155
+ && (outcome.kind !== "protocol-revert" || init.failOnRevert)) {
156
+ passed = false;
157
+ }
158
+ }
159
+ if (passed) {
160
+ await checkInvariantsAsync({ kind: "after-run" });
161
+ }
162
+ }
163
+ catch {
164
+ passed = false;
165
+ failureKind = "execution-error";
166
+ }
167
+ finally {
168
+ if (context !== undefined) {
169
+ try {
170
+ await init.cleanupAsync?.(context);
171
+ }
172
+ catch {
173
+ passed = false;
174
+ failureKind ??= "execution-error";
175
+ }
176
+ try {
177
+ await checkInvariantsAsync({ kind: "post-cleanup" });
178
+ }
179
+ catch {
180
+ passed = false;
181
+ failureKind ??= "execution-error";
182
+ }
183
+ }
184
+ }
185
+ return {
186
+ passed,
187
+ trace: {
188
+ actions: Object.freeze(executed.map((entry) => Object.freeze(entry))),
189
+ failures: Object.freeze(failures.map((failure) => Object.freeze({ ...failure }))),
190
+ metrics,
191
+ ...(failureKind === undefined ? {} : { failureKind }),
192
+ },
193
+ };
194
+ }
@@ -0,0 +1,40 @@
1
+ import * as fc from "fast-check";
2
+ import { InvariantCampaign } from "./campaign-types.js";
3
+ export interface CampaignSchedulingTarget {
4
+ readonly actors: readonly string[];
5
+ readonly key: string;
6
+ readonly requiresActiveContract?: boolean;
7
+ readonly weight: number;
8
+ }
9
+ export type ScheduledCampaignSlot = {
10
+ readonly kind: "probe";
11
+ } | {
12
+ readonly actor: string;
13
+ readonly kind: "target";
14
+ readonly targetKey: string;
15
+ };
16
+ /**
17
+ * Generates exact-depth scheduling inputs with fast-check's seed and shrink
18
+ * support while delegating all eligibility decisions to the pure scheduler.
19
+ */
20
+ export declare function createCampaignScheduleArbitrary(init: {
21
+ readonly depth: number;
22
+ readonly hasActiveContract: boolean;
23
+ readonly targets: readonly CampaignSchedulingTarget[];
24
+ }): fc.Arbitrary<readonly ScheduledCampaignSlot[]>;
25
+ /**
26
+ * Projects a public invariant campaign definition onto generated scheduling
27
+ * slots. Targets without explicit actors use every configured actor in stable
28
+ * name order, allowing lightweight read/probe targets to share the campaign
29
+ * actor matrix.
30
+ */
31
+ export declare function createInvariantCampaignScheduleArbitrary(campaign: InvariantCampaign, options?: {
32
+ readonly hasActiveContract?: boolean;
33
+ }): fc.Arbitrary<readonly ScheduledCampaignSlot[]>;
34
+ export declare function scheduleCampaignSlots(init: {
35
+ readonly actorRolls: readonly number[];
36
+ readonly depth: number;
37
+ readonly hasActiveContract: boolean;
38
+ readonly targetRolls: readonly number[];
39
+ readonly targets: readonly CampaignSchedulingTarget[];
40
+ }): readonly ScheduledCampaignSlot[];
@@ -0,0 +1,75 @@
1
+ import * as fc from "fast-check";
2
+ /**
3
+ * Generates exact-depth scheduling inputs with fast-check's seed and shrink
4
+ * support while delegating all eligibility decisions to the pure scheduler.
5
+ */
6
+ export function createCampaignScheduleArbitrary(init) {
7
+ if (!Number.isSafeInteger(init.depth) || init.depth < 1) {
8
+ throw new Error("Campaign schedule depth must be a positive safe integer.");
9
+ }
10
+ const roll = fc.integer({ min: 0, max: Number.MAX_SAFE_INTEGER });
11
+ return fc.tuple(fc.array(roll, { minLength: init.depth, maxLength: init.depth }), fc.array(roll, { minLength: init.depth, maxLength: init.depth })).map(([targetRolls, actorRolls]) => scheduleCampaignSlots({
12
+ ...init,
13
+ targetRolls,
14
+ actorRolls,
15
+ }));
16
+ }
17
+ /**
18
+ * Projects a public invariant campaign definition onto generated scheduling
19
+ * slots. Targets without explicit actors use every configured actor in stable
20
+ * name order, allowing lightweight read/probe targets to share the campaign
21
+ * actor matrix.
22
+ */
23
+ export function createInvariantCampaignScheduleArbitrary(campaign, options = {}) {
24
+ const defaultActors = Object.keys(campaign.runtime.actors).sort();
25
+ return createCampaignScheduleArbitrary({
26
+ depth: campaign.config.depth,
27
+ hasActiveContract: options.hasActiveContract ?? true,
28
+ targets: campaign.targets.map((target) => ({
29
+ key: target.key,
30
+ weight: 1,
31
+ actors: target.actors ?? defaultActors,
32
+ })),
33
+ });
34
+ }
35
+ export function scheduleCampaignSlots(init) {
36
+ if (!Number.isSafeInteger(init.depth) || init.depth < 1) {
37
+ throw new Error("Campaign schedule depth must be a positive safe integer.");
38
+ }
39
+ const eligibleTargets = init.targets.filter((target) => target.weight > 0
40
+ && target.actors.length > 0
41
+ && (init.hasActiveContract || target.requiresActiveContract !== true));
42
+ const totalWeight = eligibleTargets.reduce((sum, target) => sum + target.weight, 0);
43
+ if (!Number.isSafeInteger(totalWeight)) {
44
+ throw new Error("Campaign target weights must sum to a safe integer.");
45
+ }
46
+ return Array.from({ length: init.depth }, (_, index) => {
47
+ if (totalWeight === 0) {
48
+ return { kind: "probe" };
49
+ }
50
+ const target = selectByWeight(eligibleTargets, rollAt(init.targetRolls, index), totalWeight);
51
+ const actor = target.actors[rollAt(init.actorRolls, index) % target.actors.length];
52
+ return {
53
+ kind: "target",
54
+ targetKey: target.key,
55
+ actor,
56
+ };
57
+ });
58
+ }
59
+ function rollAt(rolls, index) {
60
+ if (rolls.length === 0) {
61
+ return 0;
62
+ }
63
+ const roll = rolls[index % rolls.length];
64
+ return Number.isSafeInteger(roll) && roll >= 0 ? roll : 0;
65
+ }
66
+ function selectByWeight(targets, roll, totalWeight) {
67
+ let remaining = roll % totalWeight;
68
+ for (const target of targets) {
69
+ if (remaining < target.weight) {
70
+ return target;
71
+ }
72
+ remaining -= target.weight;
73
+ }
74
+ throw new Error("Campaign scheduler could not select an eligible target.");
75
+ }
@@ -0,0 +1,52 @@
1
+ export interface CantonTestActor {
2
+ readonly party: string;
3
+ readonly participant: string;
4
+ readonly actAs?: readonly string[];
5
+ readonly readAs?: readonly string[];
6
+ }
7
+ export type CampaignIsolation = {
8
+ readonly kind: "cleanup";
9
+ } | {
10
+ readonly kind: "external";
11
+ } | {
12
+ readonly kind: "snapshot";
13
+ };
14
+ export interface CampaignRuntime {
15
+ readonly actors: Readonly<Record<string, CantonTestActor>>;
16
+ readonly isolation: CampaignIsolation;
17
+ }
18
+ export interface InvariantCampaignConfig {
19
+ readonly runs: number;
20
+ readonly depth: number;
21
+ readonly failOnRevert?: boolean;
22
+ readonly path?: string;
23
+ readonly seed?: number;
24
+ readonly timeoutMs?: number;
25
+ }
26
+ export interface ResolvedInvariantCampaignConfig {
27
+ readonly runs: number;
28
+ readonly depth: number;
29
+ readonly failOnRevert: boolean;
30
+ readonly path?: string;
31
+ readonly seed?: number;
32
+ readonly timeoutMs?: number;
33
+ }
34
+ export interface CampaignTarget {
35
+ readonly key: string;
36
+ readonly actors?: readonly string[];
37
+ }
38
+ export type CampaignInvariant<Model = unknown, Ghost = unknown> = ((context: {
39
+ readonly model: Model;
40
+ readonly ghost: Ghost;
41
+ }) => void | Promise<void>) & {
42
+ readonly label?: string;
43
+ };
44
+ export declare function invariant<Model = unknown, Ghost = unknown>(label: string, check: CampaignInvariant<Model, Ghost>): CampaignInvariant<Model, Ghost>;
45
+ export interface InvariantCampaign<Model = unknown, Ghost = unknown> {
46
+ readonly runtime: CampaignRuntime;
47
+ readonly config: ResolvedInvariantCampaignConfig;
48
+ readonly targets: readonly CampaignTarget[];
49
+ readonly handlers: readonly CampaignHandler[];
50
+ readonly invariants: readonly CampaignInvariant<Model, Ghost>[];
51
+ }
52
+ import { CampaignHandler } from "../handlers/handler.js";
@@ -0,0 +1,11 @@
1
+ export function invariant(label, check) {
2
+ if (label.length === 0) {
3
+ throw new Error("Invariant campaign invariant names must not be empty.");
4
+ }
5
+ const named = (context) => check(context);
6
+ Object.defineProperty(named, "label", {
7
+ value: label,
8
+ enumerable: true,
9
+ });
10
+ return Object.freeze(named);
11
+ }
@@ -0,0 +1,13 @@
1
+ import * as fc from "fast-check";
2
+ import { DeclarativeChoiceAction } from "./daml-choice-action-arbitrary.js";
3
+ import { DeclarativeCreateAction, DeclarativeCreateActionGenerationOptions } from "./daml-create-action-arbitrary.js";
4
+ import { DamlTestingCatalog } from "./daml-testing-catalog.js";
5
+ import { ResolvedDeclarativeTarget } from "../targets/target.js";
6
+ export type DeclarativeAction = DeclarativeChoiceAction | DeclarativeCreateAction;
7
+ export type DeclarativeActionGenerationOptions = DeclarativeCreateActionGenerationOptions;
8
+ /**
9
+ * Combines resolved template-create and template-choice targets into one
10
+ * shrinkable campaign action arbitrary. Runtime adapters can discriminate the
11
+ * result by `payload` (create) or `argument` (choice) before submission.
12
+ */
13
+ export declare function createDeclarativeActionArbitrary(catalog: DamlTestingCatalog, targets: readonly ResolvedDeclarativeTarget[], options?: DeclarativeActionGenerationOptions): fc.Arbitrary<DeclarativeAction>;