@hardkas/testing 0.12.0-rc.21 → 0.12.0-rc.23

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
@@ -1,65 +1,65 @@
1
- # @hardkas/testing
2
-
3
- The `@hardkas/testing` package provides the `scenario` engine to write fully deterministic, artifact-driven tests and scenarios for HardKAS projects using [Vitest](https://vitest.dev/).
4
-
5
- ## Your first scenario
6
-
7
- Writing a scenario is just like writing a normal Vitest test, but using the `scenario` bridge. The engine automatically provisions a fully configured `HardkasEnvironment` (`hk`) for your test, complete with funded simulated accounts and artifact tracing.
8
-
9
- ```typescript
10
- import { scenario, expect } from "@hardkas/testing/scenarios";
11
-
12
- scenario("my first payment", async ({ hk }) => {
13
- // 1. Resolve accounts
14
- const alice = await hk.accounts.resolve("alice");
15
- const bob = await hk.accounts.resolve("bob");
16
-
17
- const beforeBob = await hk.accounts.balance(bob.address);
18
-
19
- // 2. Transact
20
- const plan = await hk.tx.plan({
21
- from: alice.address,
22
- to: bob.address,
23
- amount: "10" // 10 KAS
24
- });
25
-
26
- const signed = await hk.tx.sign(plan);
27
- const result = await hk.tx.send(signed);
28
-
29
- // 3. Verify
30
- const afterBob = await hk.accounts.balance(bob.address);
31
- expect(afterBob.sompi - beforeBob.sompi).toBe(10n * 100000000n);
32
- });
33
- ```
34
-
35
- ## Scenario Result Artifacts
36
-
37
- Whenever a scenario finishes running, it produces a `ScenarioResultV1` artifact, saving the outcome inside your project's `.hardkas/artifacts/` folder:
38
-
39
- ```json
40
- {
41
- "schema": "hardkas.scenarioResult.v1",
42
- "scenarioName": "my first payment",
43
- "status": "passed",
44
- "artifactsGenerated": [
45
- "simulated-plan-4d7c...",
46
- "signedTx-89799cd..."
47
- ]
48
- }
49
- ```
50
-
51
- If your test fails, the engine safely extracts the assertion error and logs a `failed` scenario result, capturing the state of the failure natively without dumping raw stack traces into the JSON.
52
-
53
- ## Parallel Execution
54
- Localnet state currently defaults to a shared state across scenarios. To avoid state corruption, make sure you configure your `vitest.config.ts` to execute sequentially:
55
-
56
- ```typescript
57
- import { defineConfig } from "vitest/config";
58
-
59
- export default defineConfig({
60
- test: {
61
- fileParallelism: false,
62
- pool: "forks"
63
- }
64
- });
65
- ```
1
+ # @hardkas/testing
2
+
3
+ The `@hardkas/testing` package provides the `scenario` engine to write fully deterministic, artifact-driven tests and scenarios for HardKAS projects using [Vitest](https://vitest.dev/).
4
+
5
+ ## Your first scenario
6
+
7
+ Writing a scenario is just like writing a normal Vitest test, but using the `scenario` bridge. The engine automatically provisions a fully configured `HardkasEnvironment` (`hk`) for your test, complete with funded simulated accounts and artifact tracing.
8
+
9
+ ```typescript
10
+ import { scenario, expect } from "@hardkas/testing/scenarios";
11
+
12
+ scenario("my first payment", async ({ hk }) => {
13
+ // 1. Resolve accounts
14
+ const alice = await hk.accounts.resolve("alice");
15
+ const bob = await hk.accounts.resolve("bob");
16
+
17
+ const beforeBob = await hk.accounts.balance(bob.address);
18
+
19
+ // 2. Transact
20
+ const plan = await hk.tx.plan({
21
+ from: alice.address,
22
+ to: bob.address,
23
+ amount: "10" // 10 KAS
24
+ });
25
+
26
+ const signed = await hk.tx.sign(plan);
27
+ const result = await hk.tx.send(signed);
28
+
29
+ // 3. Verify
30
+ const afterBob = await hk.accounts.balance(bob.address);
31
+ expect(afterBob.sompi - beforeBob.sompi).toBe(10n * 100000000n);
32
+ });
33
+ ```
34
+
35
+ ## Scenario Result Artifacts
36
+
37
+ Whenever a scenario finishes running, it produces a `ScenarioResultV1` artifact, saving the outcome inside your project's `.hardkas/artifacts/` folder:
38
+
39
+ ```json
40
+ {
41
+ "schema": "hardkas.scenarioResult.v1",
42
+ "scenarioName": "my first payment",
43
+ "status": "passed",
44
+ "artifactsGenerated": [
45
+ "simulated-plan-4d7c...",
46
+ "signedTx-89799cd..."
47
+ ]
48
+ }
49
+ ```
50
+
51
+ If your test fails, the engine safely extracts the assertion error and logs a `failed` scenario result, capturing the state of the failure natively without dumping raw stack traces into the JSON.
52
+
53
+ ## Parallel Execution
54
+ Localnet state currently defaults to a shared state across scenarios. To avoid state corruption, make sure you configure your `vitest.config.ts` to execute sequentially:
55
+
56
+ ```typescript
57
+ import { defineConfig } from "vitest/config";
58
+
59
+ export default defineConfig({
60
+ test: {
61
+ fileParallelism: false,
62
+ pool: "forks"
63
+ }
64
+ });
65
+ ```
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AdversarialFixtures
3
- } from "./chunk-FTTKPLMQ.js";
3
+ } from "./chunk-LALAYTVL.js";
4
4
  import "./chunk-3RG5ZIWI.js";
5
5
  export {
6
6
  AdversarialFixtures
@@ -9,23 +9,19 @@ var AdversarialFixtures = {
9
9
  * Circular lineage: A -> B -> A
10
10
  */
11
11
  circularLineage() {
12
+ const bodyA = { schema: "hardkas.txPlan", version: ARTIFACT_VERSION, hashVersion: 3, networkId: "simnet", mode: "simulator", nonce: "A" };
13
+ const bodyB = { schema: "hardkas.txPlan", version: ARTIFACT_VERSION, hashVersion: 3, networkId: "simnet", mode: "simulator", nonce: "B" };
14
+ const hashA = calculateContentHash(bodyA, 3);
15
+ const hashB = calculateContentHash(bodyB, 3);
12
16
  const artifactA = {
13
- schema: "hardkas.txPlan",
14
- version: ARTIFACT_VERSION,
15
- artifactId: "art-a",
16
- contentHash: "hash-a",
17
- networkId: "simnet",
18
- mode: "simulator",
19
- lineage: { parentArtifactId: "art-b" }
17
+ ...bodyA,
18
+ contentHash: hashA,
19
+ lineage: { artifactId: hashA, lineageId: hashB, parentArtifactId: hashB, rootArtifactId: hashB, sequence: 2 }
20
20
  };
21
21
  const artifactB = {
22
- schema: "hardkas.txPlan",
23
- version: ARTIFACT_VERSION,
24
- artifactId: "art-b",
25
- contentHash: "hash-b",
26
- networkId: "simnet",
27
- mode: "simulator",
28
- lineage: { parentArtifactId: "art-a" }
22
+ ...bodyB,
23
+ contentHash: hashB,
24
+ lineage: { artifactId: hashB, lineageId: hashA, parentArtifactId: hashA, rootArtifactId: hashA, sequence: 2 }
29
25
  };
30
26
  return { artifactA, artifactB };
31
27
  },
@@ -60,25 +56,29 @@ var AdversarialFixtures = {
60
56
  const parent = {
61
57
  schema: "hardkas.txPlan",
62
58
  version: ARTIFACT_VERSION,
63
- artifactId: "parent-mainnet",
64
- contentHash: "hash-mainnet",
59
+ hashVersion: CURRENT_HASH_VERSION,
65
60
  networkId: "mainnet",
66
- mode: "l1-rpc"
61
+ mode: "l1-rpc",
62
+ lineage: { artifactId: "", sequence: 1 }
67
63
  };
64
+ parent.contentHash = calculateContentHash(parent, CURRENT_HASH_VERSION);
65
+ parent.lineage.artifactId = parent.contentHash;
68
66
  const child = {
69
67
  schema: "hardkas.signedTx",
70
68
  version: ARTIFACT_VERSION,
71
- artifactId: "child-simnet",
72
- contentHash: "hash-simnet",
69
+ hashVersion: CURRENT_HASH_VERSION,
73
70
  networkId: "simnet",
74
71
  mode: "simulator",
75
72
  lineage: {
76
- artifactId: "hash-simnet",
77
- parentArtifactId: "parent-mainnet",
78
- lineageId: "b".repeat(64),
79
- rootArtifactId: "c".repeat(64)
73
+ artifactId: "",
74
+ parentArtifactId: parent.contentHash,
75
+ lineageId: parent.contentHash,
76
+ rootArtifactId: parent.contentHash,
77
+ sequence: 2
80
78
  }
81
79
  };
80
+ child.contentHash = calculateContentHash(child, CURRENT_HASH_VERSION);
81
+ child.lineage.artifactId = child.contentHash;
82
82
  return { parent, child };
83
83
  },
84
84
  /**
@@ -16,10 +16,10 @@ var hardKasMatchers = {
16
16
  },
17
17
  toHaveValidTxId(received) {
18
18
  const txId = received?.txId || (typeof received === "string" ? received : "");
19
- const pass = typeof txId === "string" && (txId.startsWith("simtx_") || /^[0-9a-fA-F]{64}$/.test(txId));
19
+ const pass = typeof txId === "string" && (/^synthetic-[0-9a-f]{64}$/.test(txId) || /^[0-9a-fA-F]{64}$/.test(txId));
20
20
  return {
21
21
  pass,
22
- message: () => pass ? `Expected "${txId}" NOT to be a valid txId` : `Expected "${txId}" to be a valid txId (starts with "simtx_" or is 64-char hex)`
22
+ message: () => pass ? `Expected "${txId}" NOT to be a valid txId` : `Expected "${txId}" to be a valid txId (synthetic-<64 hex> or 64-char hex)`
23
23
  };
24
24
  },
25
25
  toHaveValidContentHash(received) {
@@ -3,8 +3,9 @@ import {
3
3
  } from "./chunk-AHS4TIKV.js";
4
4
 
5
5
  // src/reproducibility.ts
6
- import { calculateContentHash, HARDKAS_VERSION } from "@hardkas/artifacts";
6
+ import { calculateContentHash, CURRENT_HASH_VERSION, HARDKAS_VERSION } from "@hardkas/artifacts";
7
7
  import { runLinearChain, runWideDag, profileMass } from "@hardkas/simulator";
8
+ var digestCurrent = (value) => calculateContentHash(value, CURRENT_HASH_VERSION);
8
9
  function generateReproducibilityReport() {
9
10
  const l1Plan = {
10
11
  schema: "hardkas.txPlan",
@@ -85,30 +86,30 @@ function generateReproducibilityReport() {
85
86
  proofVersion: "repro-v0",
86
87
  hardkasVersion: HARDKAS_VERSION,
87
88
  artifacts: {
88
- l1Plan: calculateContentHash(l1Plan),
89
- l1Signed: calculateContentHash(l1Signed),
90
- igraPlan: calculateContentHash(igraPlan),
91
- dagLinearScenario: calculateContentHash({
89
+ l1Plan: digestCurrent(l1Plan),
90
+ l1Signed: digestCurrent(l1Signed),
91
+ igraPlan: digestCurrent(igraPlan),
92
+ dagLinearScenario: digestCurrent({
92
93
  totalBlocks: linearResult.metrics.totalBlocks,
93
94
  blueBlocks: linearResult.metrics.blueBlocks,
94
95
  redBlocks: linearResult.metrics.redBlocks,
95
96
  redRatioPpm: linearRedPpm,
96
97
  selectedChainLength: linearResult.metrics.selectedChainLength
97
98
  }),
98
- dagWideScenario: calculateContentHash({
99
+ dagWideScenario: digestCurrent({
99
100
  totalBlocks: wideResult.metrics.totalBlocks,
100
101
  blueBlocks: wideResult.metrics.blueBlocks,
101
102
  redBlocks: wideResult.metrics.redBlocks,
102
103
  redRatioPpm: wideRedPpm
103
104
  }),
104
- massProfile: calculateContentHash({
105
+ massProfile: digestCurrent({
105
106
  totalMass: massResult.totalMass.toString(),
106
107
  inputMass: massResult.inputMass.toString(),
107
108
  outputMass: massResult.outputMass.toString(),
108
109
  estimatedFeeSompi: massResult.estimatedFeeSompi.toString()
109
110
  }),
110
- canonicalNested: calculateContentHash(nestedObj),
111
- simulatedTxReceipt: txResult.ok ? calculateContentHash({
111
+ canonicalNested: digestCurrent(nestedObj),
112
+ simulatedTxReceipt: txResult.ok ? digestCurrent({
112
113
  status: txResult.receipt.status,
113
114
  txId: txResult.receipt.txId
114
115
  }) : "TX_FAILED"
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ interface HardKasMatchers<R = void> {
27
27
  toBeAccepted(): R;
28
28
  /** Assert a receipt has status "failed". */
29
29
  toBeFailed(): R;
30
- /** Assert a receipt contains a valid txId (starts with "simtx_" or is 64-char hex). */
30
+ /** Assert a receipt contains a valid txId (`synthetic-<64 hex>` or 64-char hex). */
31
31
  toHaveValidTxId(): R;
32
32
  /** Assert an artifact has a valid contentHash (64-char hex). */
33
33
  toHaveValidContentHash(): R;
@@ -100,21 +100,58 @@ declare const hardKasMatchers: {
100
100
  };
101
101
 
102
102
  /**
103
- * Deterministic fixture signer for Docker testing on simnet.
103
+ * Domain tag under which the registry keys below are computed. Publicly known
104
+ * dev-only marker: any key computed under it is by construction NOT a production
105
+ * key and MUST NOT hold real funds. Bumping this string is a breaking change to
106
+ * every fixture address and requires updating the registry values in lockstep.
107
+ */
108
+ declare const HARDKAS_FIXTURE_DERIVATION_DOMAIN = "hardkas-dev-fixture:v1";
109
+ /**
110
+ * The exhaustive, auditable set of HardKAS development fixture names.
111
+ * Extending this set is a repo-visible change (add a name + its derived hex).
112
+ * Anything not in this set fails closed at signer construction — HardKAS does
113
+ * NOT expose a general "name → private key" derivation API to external callers.
114
+ */
115
+ declare const HARDKAS_FIXTURE_NAMES: readonly ["default", "alice", "bob", "carol", "dave", "erin"];
116
+ type HardkasFixtureName = (typeof HARDKAS_FIXTURE_NAMES)[number];
117
+ /**
118
+ * Read-only registry of fixture name → 32-byte private-key hex. Values are
119
+ * derived once from the domain above and frozen. Consumers can audit each
120
+ * entry by recomputing `sha256("hardkas-dev-fixture:v1\0<name>")`.
121
+ */
122
+ declare const HARDKAS_FIXTURE_REGISTRY: Readonly<Record<HardkasFixtureName, string>>;
123
+ /**
124
+ * Return the private-key hex for a registered fixture name.
125
+ * Throws HARDKAS_UNKNOWN_FIXTURE when the name is not in the registry.
126
+ */
127
+ declare function getHardkasFixtureKey(fixtureName: HardkasFixtureName | string): string;
128
+ /**
129
+ * Deterministic fixture signer for HardKAS development on simnet/testnet.
104
130
  * Never to be used with real funds or mainnet.
131
+ *
132
+ * Historical note (rc.22 audit DEF-14 + Wave 0):
133
+ * - Pre-Wave 0: a single RFC 6979 test-vector key was hard-coded; every
134
+ * fixture-named account collapsed to one identity.
135
+ * - Wave 0 first pass: switched to arbitrary-name sha256 derivation.
136
+ * - Wave 0 design review: rejected the arbitrary-name API — HardKAS does not
137
+ * introduce a general "human name → private key" scheme merely to solve test
138
+ * fixtures. The registry above is the entire fixture identity surface.
105
139
  */
106
140
  declare class HardkasFixtureSigner implements ExternalHardkasSigner {
107
- private networkId;
108
- private readonly FIXTURE_PK;
109
- constructor(networkId?: string);
141
+ readonly networkId: string;
142
+ readonly fixtureName: HardkasFixtureName;
143
+ private cachedPrivateKeyHex;
144
+ constructor(networkId?: string, fixtureName?: HardkasFixtureName | string);
145
+ private privateKeyHex;
110
146
  private loadKaspa;
111
147
  getAddress(): Promise<string>;
112
148
  signTransaction(plan: TxPlanArtifact): Promise<SignedTxArtifact>;
113
149
  }
114
150
 
115
151
  /**
116
- * Simulated signer for simnet development.
117
- * Produces deterministic signatures without real private keys.
152
+ * Synthetic authorizer for simnet development (Wave 1.4 · IC-6′.4).
153
+ * Produces no signature: it authorizes the plan by its identity, deterministically,
154
+ * without private keys. The txId is the single synthetic scheme `synthetic-<planArtifactId>`.
118
155
  */
119
156
  declare class SimulatedTxPlanSigner implements HardkasTxPlanSigner {
120
157
  kind: HardkasSignerKind;
@@ -194,4 +231,4 @@ declare class TortureInvariantError extends Error {
194
231
  constructor(message: string, code: string, severity?: "info" | "warning" | "critical" | "catastrophic");
195
232
  }
196
233
 
197
- export { type FixtureDefinition, type HardKasMatchers, HardkasFixtureSigner, LcgPrng, SimulatedTxPlanSigner, TestHarness, type TortureBucket, type TortureBucketContext, type TortureCaseResult, TortureInvariantError, createFixture, getAllTortureBuckets, getTortureBucket, hardKasMatchers };
234
+ export { type FixtureDefinition, HARDKAS_FIXTURE_DERIVATION_DOMAIN, HARDKAS_FIXTURE_NAMES, HARDKAS_FIXTURE_REGISTRY, type HardKasMatchers, type HardkasFixtureName, HardkasFixtureSigner, LcgPrng, SimulatedTxPlanSigner, TestHarness, type TortureBucket, type TortureBucketContext, type TortureCaseResult, TortureInvariantError, createFixture, getAllTortureBuckets, getHardkasFixtureKey, getTortureBucket, hardKasMatchers };
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  AdversarialFixtures
3
- } from "./chunk-FTTKPLMQ.js";
3
+ } from "./chunk-LALAYTVL.js";
4
4
  import {
5
5
  generateReproducibilityReport
6
- } from "./chunk-67IMLFOT.js";
6
+ } from "./chunk-Q4NLRRZC.js";
7
7
  import {
8
8
  clearMassRecords,
9
9
  createTestHarness,
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-AHS4TIKV.js";
14
14
  import {
15
15
  hardKasMatchers
16
- } from "./chunk-J7YJZ3SC.js";
16
+ } from "./chunk-LAUXD45S.js";
17
17
  import {
18
18
  __require
19
19
  } from "./chunk-3RG5ZIWI.js";
@@ -39,6 +39,7 @@ function createFixture(def) {
39
39
  }
40
40
 
41
41
  // src/fixture-signer.ts
42
+ import { createHash } from "crypto";
42
43
  import {
43
44
  calculateContentHash,
44
45
  HARDKAS_VERSION,
@@ -52,22 +53,74 @@ import {
52
53
  planOutputsWithChange,
53
54
  toWasmScriptPublicKey
54
55
  } from "@hardkas/accounts";
56
+ var HARDKAS_FIXTURE_DERIVATION_DOMAIN = "hardkas-dev-fixture:v1";
57
+ var HARDKAS_FIXTURE_NAMES = [
58
+ "default",
59
+ "alice",
60
+ "bob",
61
+ "carol",
62
+ "dave",
63
+ "erin"
64
+ ];
65
+ function internalDeriveFixtureKeyHex(name) {
66
+ const material = `${HARDKAS_FIXTURE_DERIVATION_DOMAIN}\0${name}`;
67
+ const hex = createHash("sha256").update(material, "utf8").digest("hex");
68
+ if (/^0+$/.test(hex)) {
69
+ throw new Error("FIXTURE_DERIVATION_DEGENERATE: derived key is zero (astronomically improbable).");
70
+ }
71
+ return hex;
72
+ }
73
+ var HARDKAS_FIXTURE_REGISTRY = Object.freeze(
74
+ HARDKAS_FIXTURE_NAMES.reduce(
75
+ (acc, name) => {
76
+ acc[name] = internalDeriveFixtureKeyHex(name);
77
+ return acc;
78
+ },
79
+ {}
80
+ )
81
+ );
82
+ function getHardkasFixtureKey(fixtureName) {
83
+ if (!(fixtureName in HARDKAS_FIXTURE_REGISTRY)) {
84
+ const known = HARDKAS_FIXTURE_NAMES.join(", ");
85
+ const err = new Error(
86
+ `HARDKAS_UNKNOWN_FIXTURE: '${fixtureName}' is not a registered dev fixture. Known fixtures: ${known}. HardKAS does not derive keys from arbitrary names; use 'hardkas accounts real generate' to create a fresh keypair with any name.`
87
+ );
88
+ err.code = "HARDKAS_UNKNOWN_FIXTURE";
89
+ throw err;
90
+ }
91
+ return HARDKAS_FIXTURE_REGISTRY[fixtureName];
92
+ }
55
93
  var HardkasFixtureSigner = class {
56
94
  networkId;
57
- // A deterministic, known private key exclusively for Docker tests.
58
- FIXTURE_PK = "b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfef";
59
- constructor(networkId = "simnet") {
95
+ fixtureName;
96
+ cachedPrivateKeyHex;
97
+ constructor(networkId = "simnet", fixtureName = "default") {
60
98
  this.networkId = networkId;
61
99
  if (networkId === "mainnet") {
62
100
  throw new Error("FixtureSigner cannot be used on mainnet.");
63
101
  }
102
+ if (!(fixtureName in HARDKAS_FIXTURE_REGISTRY)) {
103
+ const known = HARDKAS_FIXTURE_NAMES.join(", ");
104
+ const err = new Error(
105
+ `HARDKAS_UNKNOWN_FIXTURE: '${fixtureName}' is not a registered dev fixture. Known fixtures: ${known}. HardKAS does not derive keys from arbitrary names; use 'hardkas accounts real generate' to create a fresh keypair with any name.`
106
+ );
107
+ err.code = "HARDKAS_UNKNOWN_FIXTURE";
108
+ throw err;
109
+ }
110
+ this.fixtureName = fixtureName;
111
+ }
112
+ privateKeyHex() {
113
+ if (!this.cachedPrivateKeyHex) {
114
+ this.cachedPrivateKeyHex = HARDKAS_FIXTURE_REGISTRY[this.fixtureName];
115
+ }
116
+ return this.cachedPrivateKeyHex;
64
117
  }
65
118
  async loadKaspa() {
66
119
  return loadKaspaWasm();
67
120
  }
68
121
  async getAddress() {
69
122
  const kaspa = await this.loadKaspa();
70
- const privKey = new kaspa.PrivateKey(this.FIXTURE_PK);
123
+ const privKey = new kaspa.PrivateKey(this.privateKeyHex());
71
124
  return privKey.toKeypair().toAddress(this.networkId).toString();
72
125
  }
73
126
  async signTransaction(plan) {
@@ -75,7 +128,7 @@ var HardkasFixtureSigner = class {
75
128
  throw new Error("FixtureSigner refuses to sign mainnet transactions.");
76
129
  }
77
130
  const kaspa = await this.loadKaspa();
78
- const privateKey = new kaspa.PrivateKey(this.FIXTURE_PK);
131
+ const privateKey = new kaspa.PrivateKey(this.privateKeyHex());
79
132
  const utxos = plan.inputs.map((u) => {
80
133
  if (!u.outpoint.transactionId || u.outpoint.index === void 0) {
81
134
  throw new Error(`UTXO is missing transactionId or index. Re-run tx plan.`);
@@ -154,17 +207,20 @@ var HardkasFixtureSigner = class {
154
207
  };
155
208
 
156
209
  // src/simulated-tx-plan-signer.ts
210
+ import { SYNTHETIC_AUTHORIZATION_FORMAT, syntheticTxIdFor } from "@hardkas/artifacts";
157
211
  var SimulatedTxPlanSigner = class {
158
212
  kind = "synthetic";
159
213
  async signTxPlan(input) {
160
214
  const { planArtifact } = input;
161
215
  const plan = planArtifact;
216
+ const planArtifactId = typeof plan.contentHash === "string" ? plan.contentHash : "";
162
217
  return {
163
218
  signatureKind: "synthetic",
164
219
  signerAddress: plan.from.address,
220
+ .../^[0-9a-f]{64}$/.test(planArtifactId) ? { txId: syntheticTxIdFor(planArtifactId) } : {},
165
221
  signedTransaction: {
166
- format: "simulated",
167
- payload: `simulated-signed-tx:${plan.planId}`
222
+ format: SYNTHETIC_AUTHORIZATION_FORMAT,
223
+ payload: planArtifactId
168
224
  }
169
225
  };
170
226
  }
@@ -267,7 +323,7 @@ registerTortureBucket({
267
323
  for (let i = 0; i < artifactCount; i++) {
268
324
  const payload = {
269
325
  schema: "hardkas.txPlan",
270
- hardkasVersion: "0.12.0-rc.21",
326
+ hardkasVersion: "0.12.0-rc.23",
271
327
  version: ARTIFACT_VERSION2,
272
328
  networkId: "simnet",
273
329
  mode: "simulator",
@@ -361,7 +417,7 @@ registerTortureBucket({
361
417
  try {
362
418
  const payload = {
363
419
  schema: "hardkas.txPlan",
364
- hardkasVersion: "0.12.0-rc.21",
420
+ hardkasVersion: "0.12.0-rc.23",
365
421
  version: ARTIFACT_VERSION2,
366
422
  networkId: "simnet",
367
423
  mode: "simulator",
@@ -441,7 +497,7 @@ registerTortureBucket({
441
497
  const orderA = prngA.shuffle(["alice", "bob", "carol", "dave"]);
442
498
  const payloadA = {
443
499
  schema: "hardkas.txPlan",
444
- version: "0.12.0-rc.21",
500
+ version: "0.12.0-rc.23",
445
501
  networkId: "simnet",
446
502
  mode: "simulator",
447
503
  amountSompi: amountSompiA,
@@ -455,7 +511,7 @@ registerTortureBucket({
455
511
  const orderB = prngB.shuffle(["alice", "bob", "carol", "dave"]);
456
512
  const payloadB = {
457
513
  schema: "hardkas.txPlan",
458
- version: "0.12.0-rc.21",
514
+ version: "0.12.0-rc.23",
459
515
  networkId: "simnet",
460
516
  mode: "simulator",
461
517
  amountSompi: amountSompiB,
@@ -487,7 +543,7 @@ registerTortureBucket({
487
543
  try {
488
544
  const payloadV1 = {
489
545
  schema: "hardkas.txPlan",
490
- hardkasVersion: "0.12.0-rc.21",
546
+ hardkasVersion: "0.12.0-rc.23",
491
547
  version: ARTIFACT_VERSION2,
492
548
  networkId: "simnet",
493
549
  mode: "simulator",
@@ -588,7 +644,7 @@ registerTortureBucket({
588
644
  }
589
645
  const planArtifact = {
590
646
  schema: "hardkas.txPlan",
591
- hardkasVersion: "0.12.0-rc.21",
647
+ hardkasVersion: "0.12.0-rc.23",
592
648
  version: ARTIFACT_VERSION2,
593
649
  networkId: "simnet",
594
650
  mode: "simulator",
@@ -645,7 +701,7 @@ registerTortureBucket({
645
701
  }
646
702
  const receiptArtifact = {
647
703
  schema: "hardkas.txReceipt",
648
- hardkasVersion: "0.12.0-rc.21",
704
+ hardkasVersion: "0.12.0-rc.23",
649
705
  version: ARTIFACT_VERSION2,
650
706
  networkId: "simnet",
651
707
  mode: "simulator",
@@ -712,7 +768,7 @@ registerTortureBucket({
712
768
  const planId = `plan-mock-${ctx.caseId}-${ctx.caseSeed}`;
713
769
  const payload = {
714
770
  schema: "hardkas.txPlan",
715
- hardkasVersion: "0.12.0-rc.21",
771
+ hardkasVersion: "0.12.0-rc.23",
716
772
  version: ARTIFACT_VERSION2,
717
773
  networkId: "simnet",
718
774
  mode: "simulator",
@@ -801,7 +857,7 @@ registerTortureBucket({
801
857
  case 8: {
802
858
  const orphanReceipt = {
803
859
  schema: "hardkas.txReceipt",
804
- hardkasVersion: "0.12.0-rc.21",
860
+ hardkasVersion: "0.12.0-rc.23",
805
861
  version: ARTIFACT_VERSION2,
806
862
  networkId: "simnet",
807
863
  mode: "simulator",
@@ -925,7 +981,7 @@ registerTortureBucket({
925
981
  const pId = `plan-race-${i}-${ctx.caseSeed}`;
926
982
  const payload = {
927
983
  schema: "hardkas.txPlan",
928
- hardkasVersion: "0.12.0-rc.21",
984
+ hardkasVersion: "0.12.0-rc.23",
929
985
  version: ARTIFACT_VERSION2,
930
986
  networkId: "simnet",
931
987
  mode: "simulator",
@@ -1010,7 +1066,7 @@ registerTortureBucket({
1010
1066
  const planId = `plan-stale-${ctx.caseSeed}`;
1011
1067
  const payload = {
1012
1068
  schema: "hardkas.txPlan",
1013
- hardkasVersion: "0.12.0-rc.21",
1069
+ hardkasVersion: "0.12.0-rc.23",
1014
1070
  version: ARTIFACT_VERSION2,
1015
1071
  networkId: "simnet",
1016
1072
  mode: "simulator",
@@ -1165,7 +1221,7 @@ registerTortureBucket({
1165
1221
  for (let i = 0; i < 10; i++) {
1166
1222
  const payload = {
1167
1223
  schema: "hardkas.txPlan",
1168
- hardkasVersion: "0.12.0-rc.21",
1224
+ hardkasVersion: "0.12.0-rc.23",
1169
1225
  version: ARTIFACT_VERSION2,
1170
1226
  networkId: "simnet",
1171
1227
  mode: "simulator",
@@ -1252,7 +1308,7 @@ registerTortureBucket({
1252
1308
  const traverseArtId = "../../traversal-escape";
1253
1309
  const payload = {
1254
1310
  schema: "hardkas.txPlan",
1255
- hardkasVersion: "0.12.0-rc.21",
1311
+ hardkasVersion: "0.12.0-rc.23",
1256
1312
  version: ARTIFACT_VERSION2,
1257
1313
  networkId: "simnet",
1258
1314
  mode: "simulator",
@@ -1620,7 +1676,7 @@ registerTortureBucket({
1620
1676
  const idx = generatedIds.length;
1621
1677
  const payload = {
1622
1678
  schema: "hardkas.txPlan",
1623
- hardkasVersion: "0.12.0-rc.21",
1679
+ hardkasVersion: "0.12.0-rc.23",
1624
1680
  version: ARTIFACT_VERSION2,
1625
1681
  networkId: "simnet",
1626
1682
  mode: "simulator",
@@ -1771,7 +1827,7 @@ registerTortureBucket({
1771
1827
  for (let i = 0; i < artifactsPerWorker; i++) {
1772
1828
  const payload = {
1773
1829
  schema: "hardkas.txPlan",
1774
- hardkasVersion: "0.12.0-rc.21",
1830
+ hardkasVersion: "0.12.0-rc.23",
1775
1831
  version: ARTIFACT_VERSION2,
1776
1832
  networkId: "simnet",
1777
1833
  mode: "simulator",
@@ -2061,7 +2117,7 @@ registerTortureBucket({
2061
2117
  const backend = new SqliteQueryBackend(store);
2062
2118
  const payload = {
2063
2119
  schema: "hardkas.txPlan",
2064
- hardkasVersion: "0.12.0-rc.21",
2120
+ hardkasVersion: "0.12.0-rc.23",
2065
2121
  version: ARTIFACT_VERSION2,
2066
2122
  networkId: "simnet",
2067
2123
  mode: "simulator",
@@ -2124,7 +2180,7 @@ registerTortureBucket({
2124
2180
  case 1: {
2125
2181
  const payload1 = {
2126
2182
  schema: "hardkas.txPlan",
2127
- hardkasVersion: "0.12.0-rc.21",
2183
+ hardkasVersion: "0.12.0-rc.23",
2128
2184
  version: ARTIFACT_VERSION2,
2129
2185
  networkId: "simnet",
2130
2186
  mode: "simulator",
@@ -2207,7 +2263,7 @@ registerTortureBucket({
2207
2263
  }
2208
2264
  const safePayload = {
2209
2265
  schema: "hardkas.txPlan",
2210
- hardkasVersion: "0.12.0-rc.21",
2266
+ hardkasVersion: "0.12.0-rc.23",
2211
2267
  version: ARTIFACT_VERSION2,
2212
2268
  networkId: "simnet",
2213
2269
  mode: "simulator",
@@ -2255,7 +2311,7 @@ registerTortureBucket({
2255
2311
  case 3: {
2256
2312
  const payload = {
2257
2313
  schema: "hardkas.txPlan",
2258
- hardkasVersion: "0.12.0-rc.21",
2314
+ hardkasVersion: "0.12.0-rc.23",
2259
2315
  version: ARTIFACT_VERSION2,
2260
2316
  networkId: "simnet",
2261
2317
  mode: "simulator",
@@ -2320,7 +2376,7 @@ registerTortureBucket({
2320
2376
  }
2321
2377
  const payload = {
2322
2378
  schema: "hardkas.txPlan",
2323
- hardkasVersion: "0.12.0-rc.21",
2379
+ hardkasVersion: "0.12.0-rc.23",
2324
2380
  version: ARTIFACT_VERSION2,
2325
2381
  networkId: "simnet",
2326
2382
  mode: "simulator",
@@ -2384,7 +2440,7 @@ registerTortureBucket({
2384
2440
  case 5: {
2385
2441
  const payloadWithCRLF = {
2386
2442
  schema: "hardkas.txPlan",
2387
- hardkasVersion: "0.12.0-rc.21",
2443
+ hardkasVersion: "0.12.0-rc.23",
2388
2444
  version: ARTIFACT_VERSION2,
2389
2445
  networkId: "simnet",
2390
2446
  mode: "simulator",
@@ -2435,7 +2491,7 @@ registerTortureBucket({
2435
2491
  case 6: {
2436
2492
  const payload = {
2437
2493
  schema: "hardkas.txPlan",
2438
- hardkasVersion: "0.12.0-rc.21",
2494
+ hardkasVersion: "0.12.0-rc.23",
2439
2495
  version: ARTIFACT_VERSION2,
2440
2496
  networkId: "simnet",
2441
2497
  mode: "simulator",
@@ -2519,7 +2575,7 @@ registerTortureBucket({
2519
2575
  const nfdString = "e\u0301";
2520
2576
  const payload1 = {
2521
2577
  schema: "hardkas.txPlan",
2522
- hardkasVersion: "0.12.0-rc.21",
2578
+ hardkasVersion: "0.12.0-rc.23",
2523
2579
  version: ARTIFACT_VERSION2,
2524
2580
  networkId: "simnet",
2525
2581
  mode: "simulator",
@@ -2571,7 +2627,7 @@ registerTortureBucket({
2571
2627
  const emoji = ctx.prng.pick(emojiStrings);
2572
2628
  const payload = {
2573
2629
  schema: "hardkas.txPlan",
2574
- hardkasVersion: "0.12.0-rc.21",
2630
+ hardkasVersion: "0.12.0-rc.23",
2575
2631
  version: ARTIFACT_VERSION2,
2576
2632
  networkId: "simnet",
2577
2633
  mode: "simulator",
@@ -2638,7 +2694,7 @@ registerTortureBucket({
2638
2694
  const invisible = ctx.prng.pick(invisibleChars);
2639
2695
  const payload = {
2640
2696
  schema: "hardkas.txPlan",
2641
- hardkasVersion: "0.12.0-rc.21",
2697
+ hardkasVersion: "0.12.0-rc.23",
2642
2698
  version: ARTIFACT_VERSION2,
2643
2699
  networkId: "simnet",
2644
2700
  mode: "simulator",
@@ -2692,7 +2748,7 @@ registerTortureBucket({
2692
2748
  const cyrillicAddr = "kaspa:sim_address_with_\u0430";
2693
2749
  const payloadLatin = {
2694
2750
  schema: "hardkas.txPlan",
2695
- hardkasVersion: "0.12.0-rc.21",
2751
+ hardkasVersion: "0.12.0-rc.23",
2696
2752
  version: ARTIFACT_VERSION2,
2697
2753
  networkId: "simnet",
2698
2754
  mode: "simulator",
@@ -2764,7 +2820,7 @@ registerTortureBucket({
2764
2820
  const mixedString = "caf\xE9 re\u0301sume\u0301";
2765
2821
  const payload = {
2766
2822
  schema: "hardkas.txPlan",
2767
- hardkasVersion: "0.12.0-rc.21",
2823
+ hardkasVersion: "0.12.0-rc.23",
2768
2824
  version: ARTIFACT_VERSION2,
2769
2825
  networkId: "simnet",
2770
2826
  mode: "simulator",
@@ -2833,7 +2889,7 @@ registerTortureBucket({
2833
2889
  let writeArtifact2 = function(suffix, amount) {
2834
2890
  const payload = {
2835
2891
  schema: "hardkas.txPlan",
2836
- hardkasVersion: "0.12.0-rc.21",
2892
+ hardkasVersion: "0.12.0-rc.23",
2837
2893
  version: ARTIFACT_VERSION2,
2838
2894
  networkId: "simnet",
2839
2895
  mode: "simulator",
@@ -2957,7 +3013,7 @@ registerTortureBucket({
2957
3013
  fs.utimesSync(filePath, oldTime, oldTime);
2958
3014
  const newPayload = {
2959
3015
  schema: "hardkas.txPlan",
2960
- hardkasVersion: "0.12.0-rc.21",
3016
+ hardkasVersion: "0.12.0-rc.23",
2961
3017
  version: ARTIFACT_VERSION2,
2962
3018
  networkId: "simnet",
2963
3019
  mode: "simulator",
@@ -3032,7 +3088,7 @@ registerTortureBucket({
3032
3088
  for (let i = 0; i < artifactCount; i++) {
3033
3089
  const payload = {
3034
3090
  schema: "hardkas.txPlan",
3035
- hardkasVersion: "0.12.0-rc.21",
3091
+ hardkasVersion: "0.12.0-rc.23",
3036
3092
  version: ARTIFACT_VERSION2,
3037
3093
  networkId: "simnet",
3038
3094
  mode: "simulator",
@@ -3131,7 +3187,7 @@ registerTortureBucket({
3131
3187
  for (let i = 0; i < extraCount; i++) {
3132
3188
  const payload = {
3133
3189
  schema: "hardkas.txPlan",
3134
- hardkasVersion: "0.12.0-rc.21",
3190
+ hardkasVersion: "0.12.0-rc.23",
3135
3191
  version: ARTIFACT_VERSION2,
3136
3192
  networkId: "simnet",
3137
3193
  mode: "simulator",
@@ -3201,7 +3257,7 @@ registerTortureBucket({
3201
3257
  for (let i = 0; i < 5; i++) {
3202
3258
  const payload = {
3203
3259
  schema: "hardkas.txPlan",
3204
- hardkasVersion: "0.12.0-rc.21",
3260
+ hardkasVersion: "0.12.0-rc.23",
3205
3261
  version: ARTIFACT_VERSION2,
3206
3262
  networkId: "simnet",
3207
3263
  mode: "simulator",
@@ -3311,7 +3367,7 @@ registerTortureBucket({
3311
3367
  case 5: {
3312
3368
  const phantomPayload = {
3313
3369
  schema: "hardkas.txPlan",
3314
- hardkasVersion: "0.12.0-rc.21",
3370
+ hardkasVersion: "0.12.0-rc.23",
3315
3371
  version: ARTIFACT_VERSION2,
3316
3372
  networkId: "simnet",
3317
3373
  mode: "simulator",
@@ -3380,7 +3436,7 @@ registerTortureBucket({
3380
3436
  let writePlan2 = function(id, amount) {
3381
3437
  const payload = {
3382
3438
  schema: "hardkas.txPlan",
3383
- hardkasVersion: "0.12.0-rc.21",
3439
+ hardkasVersion: "0.12.0-rc.23",
3384
3440
  version: ARTIFACT_VERSION2,
3385
3441
  networkId: "simnet",
3386
3442
  mode: "simulator",
@@ -3559,7 +3615,7 @@ registerTortureBucket({
3559
3615
  const outsideFile = path.join(outsideDir, "outside-artifact.json");
3560
3616
  const outsidePayload = {
3561
3617
  schema: "hardkas.txPlan",
3562
- hardkasVersion: "0.12.0-rc.21",
3618
+ hardkasVersion: "0.12.0-rc.23",
3563
3619
  version: ARTIFACT_VERSION2,
3564
3620
  networkId: "simnet",
3565
3621
  mode: "simulator",
@@ -3598,7 +3654,7 @@ registerTortureBucket({
3598
3654
  let writePlan2 = function(id, amount) {
3599
3655
  const payload = {
3600
3656
  schema: "hardkas.txPlan",
3601
- hardkasVersion: "0.12.0-rc.21",
3657
+ hardkasVersion: "0.12.0-rc.23",
3602
3658
  version: ARTIFACT_VERSION2,
3603
3659
  networkId: "simnet",
3604
3660
  mode: "simulator",
@@ -3707,7 +3763,7 @@ registerTortureBucket({
3707
3763
  }
3708
3764
  const payload = {
3709
3765
  schema: "hardkas.txPlan",
3710
- hardkasVersion: "0.12.0-rc.21",
3766
+ hardkasVersion: "0.12.0-rc.23",
3711
3767
  version: ARTIFACT_VERSION2,
3712
3768
  networkId: "simnet",
3713
3769
  mode: "simulator",
@@ -3824,7 +3880,7 @@ registerTortureBucket({
3824
3880
  let writePlan2 = function(id, amount) {
3825
3881
  const payload = {
3826
3882
  schema: "hardkas.txPlan",
3827
- hardkasVersion: "0.12.0-rc.21",
3883
+ hardkasVersion: "0.12.0-rc.23",
3828
3884
  version: ARTIFACT_VERSION2,
3829
3885
  networkId: "simnet",
3830
3886
  mode: "simulator",
@@ -3956,7 +4012,7 @@ registerTortureBucket({
3956
4012
  let writePlan2 = function(id, amount) {
3957
4013
  const payload = {
3958
4014
  schema: "hardkas.txPlan",
3959
- hardkasVersion: "0.12.0-rc.21",
4015
+ hardkasVersion: "0.12.0-rc.23",
3960
4016
  version: ARTIFACT_VERSION2,
3961
4017
  networkId: "simnet",
3962
4018
  mode: "simulator",
@@ -4115,7 +4171,7 @@ registerTortureBucket({
4115
4171
  let writePlan2 = function(id, amount) {
4116
4172
  const payload = {
4117
4173
  schema: "hardkas.txPlan",
4118
- hardkasVersion: "0.12.0-rc.21",
4174
+ hardkasVersion: "0.12.0-rc.23",
4119
4175
  version: ARTIFACT_VERSION2,
4120
4176
  networkId: "simnet",
4121
4177
  mode: "simulator",
@@ -4160,7 +4216,7 @@ registerTortureBucket({
4160
4216
  await new Promise((resolve) => setTimeout(resolve, 20));
4161
4217
  const payload = {
4162
4218
  schema: "hardkas.txPlan",
4163
- hardkasVersion: "0.12.0-rc.21",
4219
+ hardkasVersion: "0.12.0-rc.23",
4164
4220
  version: ARTIFACT_VERSION2,
4165
4221
  networkId: "simnet",
4166
4222
  mode: "simulator",
@@ -4478,6 +4534,9 @@ registerTortureBucket({
4478
4534
  });
4479
4535
  export {
4480
4536
  AdversarialFixtures,
4537
+ HARDKAS_FIXTURE_DERIVATION_DOMAIN,
4538
+ HARDKAS_FIXTURE_NAMES,
4539
+ HARDKAS_FIXTURE_REGISTRY,
4481
4540
  HardkasFixtureSigner,
4482
4541
  LcgPrng,
4483
4542
  SimulatedTxPlanSigner,
@@ -4489,6 +4548,7 @@ export {
4489
4548
  enableMassTracking,
4490
4549
  generateReproducibilityReport,
4491
4550
  getAllTortureBuckets,
4551
+ getHardkasFixtureKey,
4492
4552
  getMassRecords,
4493
4553
  getTortureBucket,
4494
4554
  hardKasMatchers
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  generateReproducibilityReport
3
- } from "./chunk-67IMLFOT.js";
3
+ } from "./chunk-Q4NLRRZC.js";
4
4
  import "./chunk-AHS4TIKV.js";
5
5
  import "./chunk-3RG5ZIWI.js";
6
6
  export {
package/dist/scenarios.js CHANGED
@@ -94,7 +94,7 @@ var scenario = isVitest ? vitestTest.extend({
94
94
  const safeScenarioName2 = task.name.replace(/[^a-z0-9]/gi, "_").toLowerCase();
95
95
  const scenarioResult = {
96
96
  schema: HardkasSchemas.ScenarioResultV1 || "hardkas.scenarioResult.v1",
97
- hardkasVersion: "0.12.0-rc.21",
97
+ hardkasVersion: "0.12.0-rc.23",
98
98
  version: "1.0.0-alpha",
99
99
  networkId: hardkas.network || "simnet",
100
100
  mode: "agent",
package/dist/setup.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  hardKasMatchers
3
- } from "./chunk-J7YJZ3SC.js";
3
+ } from "./chunk-LAUXD45S.js";
4
4
  import "./chunk-3RG5ZIWI.js";
5
5
 
6
6
  // src/setup.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/testing",
3
- "version": "0.12.0-rc.21",
3
+ "version": "0.12.0-rc.23",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -37,16 +37,16 @@
37
37
  }
38
38
  },
39
39
  "dependencies": {
40
- "@hardkas/accounts": "0.12.0-rc.21",
41
- "@hardkas/artifacts": "0.12.0-rc.21",
42
- "@hardkas/node-runner": "0.12.0-rc.21",
43
- "@hardkas/kaspa-rpc": "0.12.0-rc.21",
44
- "@hardkas/localnet": "0.12.0-rc.21",
45
- "@hardkas/core": "0.12.0-rc.21",
46
- "@hardkas/query-store": "0.12.0-rc.21",
47
- "@hardkas/simulator": "0.12.0-rc.21",
48
- "@hardkas/sdk": "0.12.0-rc.21",
49
- "@hardkas/tx-builder": "0.12.0-rc.21"
40
+ "@hardkas/accounts": "0.12.0-rc.23",
41
+ "@hardkas/kaspa-rpc": "0.12.0-rc.23",
42
+ "@hardkas/artifacts": "0.12.0-rc.23",
43
+ "@hardkas/node-runner": "0.12.0-rc.23",
44
+ "@hardkas/localnet": "0.12.0-rc.23",
45
+ "@hardkas/query-store": "0.12.0-rc.23",
46
+ "@hardkas/core": "0.12.0-rc.23",
47
+ "@hardkas/sdk": "0.12.0-rc.23",
48
+ "@hardkas/simulator": "0.12.0-rc.23",
49
+ "@hardkas/tx-builder": "0.12.0-rc.23"
50
50
  },
51
51
  "devDependencies": {
52
52
  "execa": "^9.5.2",