@hardkas/localnet 0.7.3-alpha → 0.7.5-alpha

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.
@@ -2,6 +2,9 @@
2
2
  import fs from "fs/promises";
3
3
  import path from "path";
4
4
  import { existsSync } from "fs";
5
+ import {
6
+ ARTIFACT_SCHEMAS
7
+ } from "@hardkas/artifacts";
5
8
  import { writeFileAtomic } from "@hardkas/core";
6
9
  import { deterministicCompare } from "@hardkas/core";
7
10
  function getDefaultReceiptsDir(cwd = process.cwd()) {
@@ -22,7 +25,9 @@ async function saveSimulatedReceipt(receipt, options) {
22
25
  await fs.mkdir(dir, { recursive: true });
23
26
  }
24
27
  const filePath = getReceiptPath(receipt.txId, options?.cwd);
25
- await writeFileAtomic(filePath, JSON.stringify(receipt, null, 2), { encoding: "utf-8" });
28
+ await writeFileAtomic(filePath, JSON.stringify(receipt, null, 2), {
29
+ encoding: "utf-8"
30
+ });
26
31
  return filePath;
27
32
  }
28
33
  async function loadSimulatedReceipt(txId, options) {
@@ -45,7 +50,9 @@ async function listSimulatedReceipts(options) {
45
50
  try {
46
51
  const txId = path.basename(file, ".json");
47
52
  const receipt = await loadSimulatedReceipt(txId, options);
48
- receipts.push(receipt);
53
+ if (receipt.schema === ARTIFACT_SCHEMAS.TX_RECEIPT) {
54
+ receipts.push(receipt);
55
+ }
49
56
  } catch (e) {
50
57
  }
51
58
  }
package/dist/index.d.ts CHANGED
@@ -372,7 +372,7 @@ declare function moveSink(dag: SimulatedDag, newSinkId: string, txProvider: (txI
372
372
  inputs: string[];
373
373
  } | undefined): SimulatedDag;
374
374
  /**
375
- * Deterministic Conflict Resolution (Approximation for 0.7.3-alpha)
375
+ * Deterministic Conflict Resolution (Approximation for 0.7.5-alpha)
376
376
  * Priority:
377
377
  * 1. sink ancestry priority (is part of selectedPathToSink?)
378
378
  * 2. deterministic block order (daaScore then block ID)
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  listSimulatedReceipts,
5
5
  loadSimulatedReceipt,
6
6
  saveSimulatedReceipt
7
- } from "./chunk-M5T6T465.js";
7
+ } from "./chunk-2YOFWE4E.js";
8
8
  import {
9
9
  getDefaultTracesDir,
10
10
  getTracePath,
@@ -101,7 +101,7 @@ var SimulatedKaspaChain = class {
101
101
  }
102
102
  /**
103
103
  * Creates a snapshot of the current chain state.
104
- * Snapshot IDs use Date.now() and are intended for session-based
104
+ * Snapshot IDs use Date.now() and are intended for session-based
105
105
  * debugging and restore points, not for canonical identity.
106
106
  */
107
107
  snapshot() {
@@ -135,7 +135,10 @@ async function startSimulatedDevnet(input) {
135
135
 
136
136
  // src/state.ts
137
137
  import { SOMPI_PER_KAS } from "@hardkas/core";
138
- import { HARDKAS_VERSION, ARTIFACT_SCHEMAS } from "@hardkas/artifacts";
138
+ import {
139
+ HARDKAS_VERSION,
140
+ ARTIFACT_SCHEMAS
141
+ } from "@hardkas/artifacts";
139
142
  function createInitialLocalnetState(options = {}) {
140
143
  const accountCount = options.accounts ?? 5;
141
144
  const initialBalanceSompi = options.initialBalanceSompi ?? 1000n * SOMPI_PER_KAS;
@@ -206,7 +209,9 @@ async function saveLocalnetState(state, filePath) {
206
209
  const targetPath = filePath ?? getDefaultLocalnetStatePath();
207
210
  const dir = path.dirname(targetPath);
208
211
  await fs.mkdir(dir, { recursive: true });
209
- await writeFileAtomic(targetPath, JSON.stringify(state, null, 2), { encoding: "utf-8" });
212
+ await writeFileAtomic(targetPath, JSON.stringify(state, null, 2), {
213
+ encoding: "utf-8"
214
+ });
210
215
  }
211
216
  async function loadLocalnetState(filePath) {
212
217
  const targetPath = filePath ?? getDefaultLocalnetStatePath();
@@ -284,7 +289,9 @@ function calculateUtxoSetHash(utxos) {
284
289
  return calculateContentHash(sorted);
285
290
  }
286
291
  function calculateAccountsHash(accounts) {
287
- const sorted = [...accounts || []].sort((a, b) => deterministicCompare(a.address, b.address));
292
+ const sorted = [...accounts || []].sort(
293
+ (a, b) => deterministicCompare(a.address, b.address)
294
+ );
288
295
  return calculateContentHash(sorted);
289
296
  }
290
297
  function calculateStateHash(state) {
@@ -329,20 +336,32 @@ function verifySnapshot(snapshot) {
329
336
  const errors = [];
330
337
  const currentContentHash = calculateContentHash(snapshot);
331
338
  const contentMatch = snapshot.contentHash === currentContentHash;
332
- if (!contentMatch) errors.push(`Content hash mismatch: expected ${snapshot.contentHash}, got ${currentContentHash}`);
339
+ if (!contentMatch)
340
+ errors.push(
341
+ `Content hash mismatch: expected ${snapshot.contentHash}, got ${currentContentHash}`
342
+ );
333
343
  const currentAccountsHash = calculateAccountsHash(snapshot.accounts);
334
344
  const accountsMatch = snapshot.accountsHash === currentAccountsHash;
335
- if (!accountsMatch) errors.push(`Accounts hash mismatch: expected ${snapshot.accountsHash}, got ${currentAccountsHash}`);
345
+ if (!accountsMatch)
346
+ errors.push(
347
+ `Accounts hash mismatch: expected ${snapshot.accountsHash}, got ${currentAccountsHash}`
348
+ );
336
349
  const currentUtxoSetHash = calculateUtxoSetHash(snapshot.utxos);
337
350
  const utxoSetMatch = snapshot.utxoSetHash === currentUtxoSetHash;
338
- if (!utxoSetMatch) errors.push(`UTXO set hash mismatch: expected ${snapshot.utxoSetHash}, got ${currentUtxoSetHash}`);
351
+ if (!utxoSetMatch)
352
+ errors.push(
353
+ `UTXO set hash mismatch: expected ${snapshot.utxoSetHash}, got ${currentUtxoSetHash}`
354
+ );
339
355
  const currentStateHash = calculateContentHash({
340
356
  daaScore: snapshot.daaScore,
341
357
  accountsHash: currentAccountsHash,
342
358
  utxoSetHash: currentUtxoSetHash
343
359
  });
344
360
  const stateMatch = snapshot.stateHash === currentStateHash;
345
- if (!stateMatch) errors.push(`State hash mismatch: expected ${snapshot.stateHash}, got ${currentStateHash}`);
361
+ if (!stateMatch)
362
+ errors.push(
363
+ `State hash mismatch: expected ${snapshot.stateHash}, got ${currentStateHash}`
364
+ );
346
365
  return {
347
366
  ok: errors.length === 0,
348
367
  hashes: {
@@ -430,7 +449,7 @@ function applySimulatedPayment(state, input, ctx) {
430
449
  }
431
450
  const unspent = getSpendableUtxos(state, fromAddress);
432
451
  if (unspent.length === 0) {
433
- throw new Error(`Insufficient funds: no unspent UTXOs for ${fromAddress}`);
452
+ throw new Error("insufficient simulated funds");
434
453
  }
435
454
  const availableUtxos = unspent.map((u) => {
436
455
  const parts = u.id.split(":");
@@ -449,15 +468,17 @@ function applySimulatedPayment(state, input, ctx) {
449
468
  availableUtxos,
450
469
  feeRateSompiPerMass
451
470
  });
452
- const spentUtxoIds = plan.inputs.map((i) => `${i.outpoint.transactionId}:${i.outpoint.index}`);
471
+ const spentUtxoIds = plan.inputs.map(
472
+ (i) => `${i.outpoint.transactionId}:${i.outpoint.index}`
473
+ );
453
474
  const uniqueSpentIds = new Set(spentUtxoIds);
454
475
  if (uniqueSpentIds.size !== spentUtxoIds.length) {
455
476
  throw new Error("Duplicate inputs detected in transaction plan");
456
477
  }
457
478
  for (const id of spentUtxoIds) {
458
479
  const utxo = state.utxos.find((u) => u.id === id);
459
- if (!utxo) throw new Error(`UTXO not found: ${id}`);
460
- if (utxo.spent) throw new Error(`UTXO already spent: ${id}`);
480
+ if (!utxo) throw new Error("missing simulated UTXO");
481
+ if (utxo.spent) throw new Error("invalid simulated input");
461
482
  }
462
483
  const planArtifact = createTxPlanArtifact({
463
484
  networkId: state.networkId || "simnet",
@@ -558,11 +579,13 @@ function applySimulatedPlan(state, planArtifact, ctx, options) {
558
579
  const errors = [];
559
580
  const preStateHash = calculateStateHash(state);
560
581
  try {
561
- const spentUtxoIds = planArtifact.inputs.map((i) => `${i.outpoint.transactionId}:${i.outpoint.index}`);
582
+ const spentUtxoIds = planArtifact.inputs.map(
583
+ (i) => `${i.outpoint.transactionId}:${i.outpoint.index}`
584
+ );
562
585
  for (const id of spentUtxoIds) {
563
586
  const utxo = state.utxos.find((u) => u.id === id);
564
- if (!utxo) throw new Error(`UTXO not found: ${id}`);
565
- if (utxo.spent) throw new Error(`UTXO already spent: ${id}`);
587
+ if (!utxo) throw new Error("missing simulated UTXO");
588
+ if (utxo.spent) throw new Error("invalid simulated input");
566
589
  }
567
590
  const nextDaaScore = (BigInt(state.daaScore) + 1n).toString();
568
591
  const txId = options?.txId || generateDeterministicTxId(planArtifact, preStateHash, nextDaaScore);
@@ -595,7 +618,11 @@ function applySimulatedPlan(state, planArtifact, ctx, options) {
595
618
  nextUtxos.push(changeUtxo);
596
619
  createdUtxoIds.push(changeUtxo.id);
597
620
  }
598
- const nextState = { ...state, daaScore: nextDaaScore, utxos: nextUtxos };
621
+ const nextState = {
622
+ ...state,
623
+ daaScore: nextDaaScore,
624
+ utxos: nextUtxos
625
+ };
599
626
  const postStateHash = calculateStateHash(nextState);
600
627
  const receipt = createSimulatedTxReceipt(planArtifact, txId, ctx, {
601
628
  spentUtxoIds,
@@ -648,7 +675,11 @@ function verifyReplay(state, originalPlan, originalReceipt, ctx) {
648
675
  planOk = false;
649
676
  const errorMsg = `TxPlan contentHash mismatch: expected ${originalPlan.contentHash}, got ${currentPlanHash}`;
650
677
  errors.push(errorMsg);
651
- reportDivergences.push({ path: "plan.contentHash", expected: originalPlan.contentHash, actual: currentPlanHash });
678
+ reportDivergences.push({
679
+ path: "plan.contentHash",
680
+ expected: originalPlan.contentHash,
681
+ actual: currentPlanHash
682
+ });
652
683
  }
653
684
  const originalPreState = originalReceipt.preStateHash;
654
685
  if (originalPreState) {
@@ -670,7 +701,9 @@ function verifyReplay(state, originalPlan, originalReceipt, ctx) {
670
701
  severity: "warning"
671
702
  });
672
703
  }
673
- const result = applySimulatedPlan(state, originalPlan, ctx, { txId: originalReceipt.txId });
704
+ const result = applySimulatedPlan(state, originalPlan, ctx, {
705
+ txId: originalReceipt.txId
706
+ });
674
707
  const replayReceipt = result.receipt;
675
708
  const diff = diffArtifacts(originalReceipt, replayReceipt);
676
709
  if (!diff.identical) {
@@ -680,7 +713,9 @@ function verifyReplay(state, originalPlan, originalReceipt, ctx) {
680
713
  expected: entry.left,
681
714
  actual: entry.right
682
715
  });
683
- errors.push(`Receipt divergence at ${entry.path}: expected ${JSON.stringify(entry.left)}, got ${JSON.stringify(entry.right)}`);
716
+ errors.push(
717
+ `Receipt divergence at ${entry.path}: expected ${JSON.stringify(entry.left)}, got ${JSON.stringify(entry.right)}`
718
+ );
684
719
  }
685
720
  }
686
721
  for (const div of reportDivergences) {
@@ -717,7 +752,7 @@ function verifyReplay(state, originalPlan, originalReceipt, ctx) {
717
752
  };
718
753
  }
719
754
  async function getSimulatedReplaySummary(txId, options = {}) {
720
- const { loadSimulatedReceipt: loadSimulatedReceipt2 } = await import("./receipts-7RMJMXXG.js");
755
+ const { loadSimulatedReceipt: loadSimulatedReceipt2 } = await import("./receipts-IEHNHM4Q.js");
721
756
  const { loadSimulatedTrace: loadSimulatedTrace2 } = await import("./traces-ZUBWSXYB.js");
722
757
  const receipt = await loadSimulatedReceipt2(txId, options);
723
758
  const trace = await loadSimulatedTrace2(txId, options);
@@ -1072,7 +1107,9 @@ async function forkFromNetwork(rpc, opts) {
1072
1107
  const networkId = info.networkId || opts.network;
1073
1108
  const targetDaaScore = opts.atDaaScore;
1074
1109
  if (!targetDaaScore) {
1075
- throw new Error(`[CRITICAL SEMANTIC ERROR] Implicit 'latest' resolution forbidden. You must explicitly provide atDaaScore.`);
1110
+ throw new Error(
1111
+ `[CRITICAL SEMANTIC ERROR] Implicit 'latest' resolution forbidden. You must explicitly provide atDaaScore.`
1112
+ );
1076
1113
  }
1077
1114
  const utxos = [];
1078
1115
  for (const address of opts.addresses) {
@@ -4,7 +4,7 @@ import {
4
4
  listSimulatedReceipts,
5
5
  loadSimulatedReceipt,
6
6
  saveSimulatedReceipt
7
- } from "./chunk-M5T6T465.js";
7
+ } from "./chunk-2YOFWE4E.js";
8
8
  export {
9
9
  getDefaultReceiptsDir,
10
10
  getReceiptPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/localnet",
3
- "version": "0.7.3-alpha",
3
+ "version": "0.7.5-alpha",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -8,12 +8,12 @@
8
8
  ".": "./dist/index.js"
9
9
  },
10
10
  "dependencies": {
11
- "@hardkas/artifacts": "0.7.3-alpha",
12
- "@hardkas/query": "0.7.3-alpha",
13
- "@hardkas/core": "0.7.3-alpha",
14
- "@hardkas/simulator": "0.7.3-alpha",
15
- "@hardkas/tx-builder": "0.7.3-alpha",
16
- "@hardkas/kaspa-rpc": "0.7.3-alpha"
11
+ "@hardkas/artifacts": "0.7.5-alpha",
12
+ "@hardkas/core": "0.7.5-alpha",
13
+ "@hardkas/simulator": "0.7.5-alpha",
14
+ "@hardkas/kaspa-rpc": "0.7.5-alpha",
15
+ "@hardkas/query": "0.7.5-alpha",
16
+ "@hardkas/tx-builder": "0.7.5-alpha"
17
17
  },
18
18
  "devDependencies": {
19
19
  "fast-check": "^4.8.0",