@hardkas/sdk 0.7.7-alpha → 0.7.8-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.
Files changed (3) hide show
  1. package/dist/index.d.ts +58 -3
  2. package/dist/index.js +202 -35
  3. package/package.json +15 -14
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as _hardkas_config from '@hardkas/config';
2
2
  import { LoadedHardkasConfig } from '@hardkas/config';
3
3
  export { defineHardkasConfig } from '@hardkas/config';
4
4
  import { KaspaRpcClient } from '@hardkas/kaspa-rpc';
5
- import { NetworkId } from '@hardkas/core';
5
+ import { EventEnvelope, NetworkId } from '@hardkas/core';
6
6
  export { ArtifactId, HardkasError, KaspaAddress, LineageId, NetworkId, SOMPI_PER_KAS, TxId, formatSompi, parseKasToSompi } from '@hardkas/core';
7
7
  import { TxPlanArtifact, SignedTxArtifact, TxReceiptArtifact, HardkasArtifactBase, WorkflowArtifact } from '@hardkas/artifacts';
8
8
  export { ARTIFACT_SCHEMAS, HARDKAS_VERSION, SignedTxArtifact, TxPlanArtifact, TxReceiptArtifact, TxTraceArtifact, createTxPlanArtifact, writeArtifact } from '@hardkas/artifacts';
@@ -131,6 +131,21 @@ declare class HardkasQuery {
131
131
  * Internal lazy-loaded query engine.
132
132
  */
133
133
  private getEngine;
134
+ /**
135
+ * Synchronizes the query store with the filesystem artifacts.
136
+ */
137
+ sync(options?: {
138
+ force?: boolean;
139
+ }): Promise<any>;
140
+ /**
141
+ * Fetches events from the query store.
142
+ */
143
+ events(filter?: {
144
+ domain?: string;
145
+ kind?: string;
146
+ correlationId?: string;
147
+ artifactId?: string;
148
+ }): Promise<readonly EventEnvelope[]>;
134
149
  }
135
150
 
136
151
  /**
@@ -173,7 +188,28 @@ declare class HardkasReplay {
173
188
  * Verifies the deterministic artifact lineage of a transaction replay
174
189
  * against the mathematically reconstructed localnet state.
175
190
  */
176
- verify(options: ReplayVerifyOptions): Promise<ReplayVerifyResult>;
191
+ verify(targetOrOptions?: string | {
192
+ schema?: string;
193
+ artifactId?: string;
194
+ } | ReplayVerifyOptions, options?: ReplayVerifyOptions): Promise<ReplayVerifyResult>;
195
+ }
196
+
197
+ /**
198
+ * HardKAS Lineage Module
199
+ * @alpha
200
+ */
201
+ declare class HardkasLineage {
202
+ private sdk;
203
+ constructor(sdk: Hardkas);
204
+ /**
205
+ * Traces the lineage of an artifact, identifying ancestors and descendants.
206
+ */
207
+ trace(target: string | {
208
+ artifactId?: string;
209
+ contentHash?: string;
210
+ }, options?: {
211
+ direction?: "ancestors" | "descendants";
212
+ }): Promise<any>;
177
213
  }
178
214
 
179
215
  /**
@@ -251,6 +287,15 @@ declare class HardkasArtifactsManager {
251
287
  * Lists all artifacts in the workspace.
252
288
  */
253
289
  list(): Promise<any[]>;
290
+ /**
291
+ * Cryptographically verifies the determinism and integrity of an artifact.
292
+ * Throws an error with details if corruption or mismatch is found.
293
+ */
294
+ verify(target: string | {
295
+ schema?: string;
296
+ artifactId?: string;
297
+ contentHash?: string;
298
+ }): Promise<any>;
254
299
  }
255
300
 
256
301
  interface WorkflowRunOptions {
@@ -290,6 +335,15 @@ interface HardkasOptions {
290
335
  cwd?: string;
291
336
  configPath?: string;
292
337
  mode?: "developer" | "agent";
338
+ network?: string;
339
+ autoBootstrap?: boolean;
340
+ logger?: {
341
+ info: (msg: string) => void;
342
+ warn: (msg: string) => void;
343
+ error: (msg: string) => void;
344
+ debug: (msg: string) => void;
345
+ [key: string]: any;
346
+ };
293
347
  policy?: {
294
348
  allowNetwork?: boolean;
295
349
  allowMainnet?: boolean;
@@ -313,6 +367,7 @@ declare class Hardkas {
313
367
  readonly query: HardkasQuery;
314
368
  readonly localnet: HardkasLocalnet;
315
369
  readonly replay: HardkasReplay;
370
+ readonly lineage: HardkasLineage;
316
371
  readonly workflow: HardkasWorkflow;
317
372
  readonly mode: "developer" | "agent";
318
373
  readonly policy: Required<NonNullable<HardkasOptions["policy"]>>;
@@ -340,4 +395,4 @@ declare class Hardkas {
340
395
  enforcePolicy(action: "network" | "mainnet" | "external-wallet" | "mutation", context?: string): void;
341
396
  }
342
397
 
343
- export { Hardkas, HardkasAccounts, HardkasArtifactsManager, HardkasL2, HardkasLocalnet, type HardkasOptions, HardkasQuery, HardkasReplay, HardkasTx, HardkasWorkspace, type TaskArgs, type TaskContext, defineTask };
398
+ export { Hardkas, HardkasAccounts, HardkasArtifactsManager, HardkasL2, HardkasLineage, HardkasLocalnet, type HardkasOptions, HardkasQuery, HardkasReplay, HardkasTx, HardkasWorkspace, type TaskArgs, type TaskContext, defineTask };
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  loadHardkasConfig as loadConfig
8
8
  } from "@hardkas/config";
9
9
  import { JsonWrpcKaspaClient } from "@hardkas/kaspa-rpc";
10
- import { HardkasError as HardkasError2 } from "@hardkas/core";
10
+ import { HardkasError as HardkasError3 } from "@hardkas/core";
11
11
 
12
12
  // src/accounts.ts
13
13
  import { resolveHardkasAccount } from "@hardkas/accounts";
@@ -56,8 +56,23 @@ var HardkasAccounts = class {
56
56
  * Funds an account from another account (defaults to 'default' account).
57
57
  */
58
58
  async fund(accountNameOrAddress, options) {
59
- const from = options?.from || "default";
59
+ let from = options?.from;
60
60
  const amount = options?.amount || "1000000000";
61
+ if (!from) {
62
+ const accounts = await this.list();
63
+ if (accounts.includes("faucet")) {
64
+ from = "faucet";
65
+ } else if (accounts.includes("simulated_faucet")) {
66
+ from = "simulated_faucet";
67
+ } else if (this.sdk.network === "simulated" && accounts.includes("alice")) {
68
+ from = "alice";
69
+ } else {
70
+ throw new Error("No funding account available.\nFor simulated mode, run Hardkas.create({ network: 'simulated', autoBootstrap: true })\nor call accounts.fund(target, { from: 'alice' }).");
71
+ }
72
+ }
73
+ if (from === accountNameOrAddress) {
74
+ throw new Error(`Cannot fund account '${accountNameOrAddress}' from itself.`);
75
+ }
61
76
  const plan = await this.sdk.tx.plan({
62
77
  from,
63
78
  to: accountNameOrAddress,
@@ -73,7 +88,7 @@ var HardkasAccounts = class {
73
88
  };
74
89
 
75
90
  // src/tx.ts
76
- import { systemRuntimeContext } from "@hardkas/core";
91
+ import { systemRuntimeContext, deterministicCompare } from "@hardkas/core";
77
92
  import {
78
93
  buildPaymentPlan,
79
94
  verifySignedTxSemantics
@@ -112,7 +127,8 @@ var HardkasTx = class {
112
127
  throw new Error("Kaspa value-transfer outputs require amount > 0.\nFor metadata/notary/DID marker transactions use --amount 1.\nFuture: hardkas tx anchor.");
113
128
  }
114
129
  let builderUtxos = [];
115
- if (this.sdk.network === "simulated") {
130
+ const activeNetwork = this.sdk.config.config.defaultNetwork || "simnet";
131
+ if (activeNetwork === "simulated" || this.sdk.config.config.networks?.[activeNetwork]?.kind === "simulated") {
116
132
  const { loadOrCreateLocalnetState, getSpendableUtxos } = await import("@hardkas/localnet");
117
133
  const localState = await loadOrCreateLocalnetState({
118
134
  cwd: this.sdk.workspace.root
@@ -152,9 +168,10 @@ var HardkasTx = class {
152
168
  ],
153
169
  feeRateSompiPerMass: options.feeRate ?? 1n
154
170
  });
171
+ const isSimulated = activeNetwork === "simulated" || this.sdk.config.config.networks?.[activeNetwork]?.kind === "simulated";
155
172
  return createTxPlanArtifact({
156
- networkId: this.sdk.network,
157
- mode: "simulated",
173
+ networkId: activeNetwork,
174
+ mode: isSimulated ? "simulated" : "real",
158
175
  from: {
159
176
  input: fromAccount.name || fromAccount.address,
160
177
  address: fromAccount.address,
@@ -228,7 +245,7 @@ var HardkasTx = class {
228
245
  signature: `simulated-signature-of-${signerAddress}`
229
246
  };
230
247
  const newSignatures = [...sigs, signatureEntry].sort(
231
- (a, b) => a.signer.localeCompare(b.signer)
248
+ (a, b) => deterministicCompare(a.signer, b.signer)
232
249
  );
233
250
  const newMeta = [
234
251
  ...partialTx.signatureMetadata || [],
@@ -299,7 +316,7 @@ var HardkasTx = class {
299
316
  signature: `simulated-signature-of-${signerAddress}`
300
317
  };
301
318
  const signatures = [signatureEntry].sort(
302
- (a, b) => a.signer.localeCompare(b.signer)
319
+ (a, b) => deterministicCompare(a.signer, b.signer)
303
320
  );
304
321
  const signatureMetadata = [
305
322
  {
@@ -428,14 +445,16 @@ var HardkasTx = class {
428
445
  { cwd: this.sdk.workspace.root }
429
446
  );
430
447
  const tracePath = receiptPath.replace(".json", ".trace.json");
448
+ const activeNetwork = this.sdk.config.config.defaultNetwork || "simnet";
449
+ const isSimulated = activeNetwork === "simulated" || this.sdk.config.config.networks?.[activeNetwork]?.kind === "simulated";
431
450
  const receiptBase = {
432
451
  schema: ARTIFACT_SCHEMAS.TX_RECEIPT,
433
452
  schemaVersion: "hardkas.receipt.v1",
434
453
  hardkasVersion: HARDKAS_VERSION,
435
454
  version: ARTIFACT_VERSION,
436
455
  hashVersion: CURRENT_HASH_VERSION,
437
- networkId: this.sdk.network,
438
- mode: "simulated",
456
+ networkId: activeNetwork,
457
+ mode: isSimulated ? "simulated" : "real",
439
458
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
440
459
  status: "confirmed",
441
460
  txId: simResult.receipt.txId,
@@ -470,8 +489,8 @@ var HardkasTx = class {
470
489
  hashVersion: CURRENT_HASH_VERSION,
471
490
  createdAt: receipt.createdAt,
472
491
  txId: receipt.txId,
473
- mode: "simulated",
474
- networkId: this.sdk.network,
492
+ mode: isSimulated ? "simulated" : "real",
493
+ networkId: activeNetwork,
475
494
  steps: traceSteps
476
495
  };
477
496
  traceBase.contentHash = calculateContentHash(traceBase, CURRENT_HASH_VERSION);
@@ -604,11 +623,62 @@ var HardkasQuery = class {
604
623
  async getEngine() {
605
624
  if (this._engine) return this._engine;
606
625
  const { QueryEngine } = await import("@hardkas/query");
607
- this._engine = new QueryEngine({
608
- artifactDir: this.sdk.config.cwd
626
+ this._engine = await QueryEngine.create({
627
+ artifactDir: this.sdk.workspace.root,
628
+ autoSync: false
629
+ // We don't auto-sync on every getter
609
630
  });
610
631
  return this._engine;
611
632
  }
633
+ /**
634
+ * Synchronizes the query store with the filesystem artifacts.
635
+ */
636
+ async sync(options) {
637
+ const { HardkasStore, HardkasIndexer } = await import("@hardkas/query-store");
638
+ const { withLock } = await import("@hardkas/core");
639
+ const path4 = await import("path");
640
+ const dbPath = path4.join(this.sdk.workspace.root, ".hardkas", "store.db");
641
+ const store = new HardkasStore({ dbPath });
642
+ let stats;
643
+ await withLock(
644
+ {
645
+ rootDir: this.sdk.workspace.root,
646
+ name: "query-store",
647
+ command: "query-sync",
648
+ wait: true
649
+ },
650
+ async () => {
651
+ store.connect({ autoMigrate: true });
652
+ const indexer = new HardkasIndexer(store.getDatabase());
653
+ if (options?.force) {
654
+ stats = await indexer.rebuild();
655
+ } else {
656
+ stats = await indexer.sync();
657
+ }
658
+ }
659
+ );
660
+ return stats;
661
+ }
662
+ /**
663
+ * Fetches events from the query store.
664
+ */
665
+ async events(filter) {
666
+ const engine = await this.getEngine();
667
+ const { createQueryRequest } = await import("@hardkas/query");
668
+ const filters = [];
669
+ if (filter) {
670
+ for (const [k, v] of Object.entries(filter)) {
671
+ if (v) filters.push({ field: k, op: "eq", value: v });
672
+ }
673
+ }
674
+ const request = createQueryRequest({
675
+ domain: "events",
676
+ op: "list",
677
+ filters
678
+ });
679
+ const result = await engine.execute(request);
680
+ return result.items;
681
+ }
612
682
  };
613
683
 
614
684
  // src/localnet.ts
@@ -652,6 +722,7 @@ import {
652
722
  verifyArtifactIntegrity,
653
723
  writeArtifact as writeArtifact2
654
724
  } from "@hardkas/artifacts";
725
+ import { deterministicCompare as deterministicCompare2 } from "@hardkas/core";
655
726
  function resolveReplayTargets(cwd, options) {
656
727
  if (options.path) {
657
728
  const fullPath = path.resolve(cwd, options.path);
@@ -728,7 +799,7 @@ function resolveFromDirectory(dir, source) {
728
799
  Hint: Run a transaction first: hardkas tx send --from alice --to bob --amount 10 --network simulated --yes`
729
800
  );
730
801
  }
731
- plans.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
802
+ plans.sort((a, b) => deterministicCompare2(b.createdAt, a.createdAt));
732
803
  for (const plan of plans) {
733
804
  const matchingReceipt = receipts.find(
734
805
  (r) => (
@@ -779,16 +850,24 @@ var HardkasReplay = class {
779
850
  * Verifies the deterministic artifact lineage of a transaction replay
780
851
  * against the mathematically reconstructed localnet state.
781
852
  */
782
- async verify(options) {
783
- const targets = resolveReplayTargets(this.sdk.config.cwd, options);
853
+ async verify(targetOrOptions, options) {
854
+ let opts = options || {};
855
+ if (typeof targetOrOptions === "string") {
856
+ opts.path = targetOrOptions;
857
+ } else if (targetOrOptions && "artifactId" in targetOrOptions) {
858
+ opts.path = targetOrOptions.artifactId;
859
+ } else if (targetOrOptions) {
860
+ opts = { ...opts, ...targetOrOptions };
861
+ }
862
+ const targets = resolveReplayTargets(this.sdk.config.cwd, opts);
784
863
  let { planPath, receiptPath, artifactDir } = targets;
785
864
  if (!fs.existsSync(path.join(this.sdk.config.cwd, "hardkas.config.ts"))) {
786
865
  throw new Error(`Workspace not found at ${this.sdk.config.cwd}`);
787
866
  }
788
867
  const canonicalDirs = [
789
- path.join(artifactDir, ".hardkas", "receipts"),
790
- path.join(artifactDir, ".hardkas", "traces"),
791
- path.join(artifactDir, ".hardkas", "deployments")
868
+ path.join(this.sdk.workspace.hardkasDir, "receipts"),
869
+ path.join(this.sdk.workspace.hardkasDir, "traces"),
870
+ path.join(this.sdk.workspace.hardkasDir, "deployments")
792
871
  ];
793
872
  const files = [];
794
873
  for (const dir of canonicalDirs) {
@@ -851,9 +930,9 @@ var HardkasReplay = class {
851
930
  let receipt;
852
931
  let verifyErrorMsg;
853
932
  let report = null;
854
- if (options.workflowId) {
933
+ if (opts.workflowId) {
855
934
  try {
856
- const wfArtifactPath = fs.readdirSync(this.sdk.workspace.artifactsDir).find((f) => f.includes(options.workflowId) && f.endsWith(".json"));
935
+ const wfArtifactPath = fs.readdirSync(this.sdk.workspace.artifactsDir).find((f) => f.includes(opts.workflowId) && f.endsWith(".json"));
857
936
  if (!wfArtifactPath) throw new Error("Workflow artifact not found");
858
937
  const wfArtifactStr = fs.readFileSync(
859
938
  path.join(this.sdk.workspace.artifactsDir, wfArtifactPath),
@@ -861,7 +940,7 @@ var HardkasReplay = class {
861
940
  );
862
941
  const wfArtifact = JSON.parse(wfArtifactStr);
863
942
  if (wfArtifact.schema !== "hardkas.workflow.v1") {
864
- throw new Error(`Artifact ${options.workflowId} is not a workflow artifact`);
943
+ throw new Error(`Artifact ${opts.workflowId} is not a workflow artifact`);
865
944
  }
866
945
  const childArtifacts = wfArtifact.producedArtifacts || [];
867
946
  for (const childId of childArtifacts) {
@@ -940,6 +1019,33 @@ var HardkasReplay = class {
940
1019
  }
941
1020
  };
942
1021
 
1022
+ // src/lineage.ts
1023
+ var HardkasLineage = class {
1024
+ constructor(sdk) {
1025
+ this.sdk = sdk;
1026
+ }
1027
+ sdk;
1028
+ /**
1029
+ * Traces the lineage of an artifact, identifying ancestors and descendants.
1030
+ */
1031
+ async trace(target, options) {
1032
+ const anchor = typeof target === "string" ? target : target.artifactId || target.contentHash || "";
1033
+ if (!anchor) throw new Error("No anchor target provided for lineage trace.");
1034
+ const { createQueryRequest, QueryEngine } = await import("@hardkas/query");
1035
+ const engine = await QueryEngine.create({
1036
+ artifactDir: this.sdk.workspace.root,
1037
+ autoSync: false
1038
+ });
1039
+ const request = createQueryRequest({
1040
+ domain: "lineage",
1041
+ op: "chain",
1042
+ params: { anchor, direction: options?.direction || "ancestors" }
1043
+ });
1044
+ const result = await engine.execute(request);
1045
+ return result.items[0];
1046
+ }
1047
+ };
1048
+
943
1049
  // src/workspace.ts
944
1050
  import path2 from "path";
945
1051
  import fs2 from "fs";
@@ -955,7 +1061,7 @@ var HardkasWorkspace = class {
955
1061
  return path2.join(this.hardkasDir, "artifacts");
956
1062
  }
957
1063
  get localnetStatePath() {
958
- return path2.join(this.hardkasDir, "localnet-state.json");
1064
+ return path2.join(this.hardkasDir, "localnet.json");
959
1065
  }
960
1066
  get keystoreDir() {
961
1067
  return path2.join(this.hardkasDir, "keystore");
@@ -985,6 +1091,7 @@ var HardkasWorkspace = class {
985
1091
  // src/artifacts-manager.ts
986
1092
  import path3 from "path";
987
1093
  import fs3 from "fs";
1094
+ import { HardkasError } from "@hardkas/core";
988
1095
  var HardkasArtifactsManager = class {
989
1096
  constructor(workspace) {
990
1097
  this.workspace = workspace;
@@ -1059,6 +1166,15 @@ var HardkasArtifactsManager = class {
1059
1166
  }
1060
1167
  const { readArtifact } = await import("@hardkas/artifacts");
1061
1168
  let filePath = id;
1169
+ let resolvedPath = path3.resolve(this.workspace.root, filePath);
1170
+ if (fs3.existsSync(resolvedPath)) {
1171
+ resolvedPath = fs3.realpathSync(resolvedPath);
1172
+ }
1173
+ const rootRel = path3.relative(this.workspace.root, resolvedPath);
1174
+ const artifactsRel = path3.relative(this.workspace.artifactsDir, resolvedPath);
1175
+ if ((rootRel.startsWith("..") || path3.isAbsolute(rootRel)) && (artifactsRel.startsWith("..") || path3.isAbsolute(artifactsRel))) {
1176
+ throw new HardkasError("PATH_TRAVERSAL", "Artifact path escapes workspace boundary");
1177
+ }
1062
1178
  if (!fs3.existsSync(filePath)) {
1063
1179
  filePath = path3.join(this.workspace.artifactsDir, `${id}.json`);
1064
1180
  if (!fs3.existsSync(filePath)) {
@@ -1104,11 +1220,26 @@ var HardkasArtifactsManager = class {
1104
1220
  }
1105
1221
  return artifacts;
1106
1222
  }
1223
+ /**
1224
+ * Cryptographically verifies the determinism and integrity of an artifact.
1225
+ * Throws an error with details if corruption or mismatch is found.
1226
+ */
1227
+ async verify(target) {
1228
+ const id = typeof target === "string" ? target : target.artifactId || target.contentHash || "";
1229
+ if (!id) throw new Error("No artifact target provided for verification.");
1230
+ const artifact = await this.read(id);
1231
+ const { verifyArtifactIntegrity: verifyArtifactIntegrity2 } = await import("@hardkas/artifacts");
1232
+ const result = await verifyArtifactIntegrity2(artifact);
1233
+ if (!result.ok) {
1234
+ throw new Error(`Artifact ${id} corrupted or invalid: ` + JSON.stringify(result.issues, null, 2));
1235
+ }
1236
+ return result;
1237
+ }
1107
1238
  };
1108
1239
 
1109
1240
  // src/workflow.ts
1110
1241
  import { HARDKAS_VERSION as HARDKAS_VERSION2 } from "@hardkas/artifacts";
1111
- import { HardkasError, deterministicCompare } from "@hardkas/core";
1242
+ import { HardkasError as HardkasError2, deterministicCompare as deterministicCompare3 } from "@hardkas/core";
1112
1243
  var HardkasWorkflow = class {
1113
1244
  constructor(sdk) {
1114
1245
  this.sdk = sdk;
@@ -1155,12 +1286,12 @@ var HardkasWorkflow = class {
1155
1286
  try {
1156
1287
  if (step.type === "simulate-failure") {
1157
1288
  if (this.sdk.mode === "agent") {
1158
- throw new HardkasError(
1289
+ throw new HardkasError2(
1159
1290
  "POLICY_DENIED",
1160
1291
  "simulate-failure is strictly prohibited in agent mode"
1161
1292
  );
1162
1293
  }
1163
- throw new HardkasError("MOCKED_FAIL", "Simulated failure for contract tests");
1294
+ throw new HardkasError2("MOCKED_FAIL", "Simulated failure for contract tests");
1164
1295
  }
1165
1296
  let producedArtifactId = void 0;
1166
1297
  let result = void 0;
@@ -1321,9 +1452,9 @@ var HardkasWorkflow = class {
1321
1452
  artifactId: workflowId,
1322
1453
  status,
1323
1454
  steps: artifactSteps,
1324
- parentArtifacts: parentArtifacts.sort(deterministicCompare),
1455
+ parentArtifacts: parentArtifacts.sort(deterministicCompare3),
1325
1456
  producedArtifacts: Array.from(new Set(producedArtifacts)).sort(
1326
- deterministicCompare
1457
+ deterministicCompare3
1327
1458
  ),
1328
1459
  generationRange: {
1329
1460
  start: generationStart,
@@ -1393,7 +1524,7 @@ import {
1393
1524
  } from "@hardkas/artifacts";
1394
1525
  import {
1395
1526
  SOMPI_PER_KAS,
1396
- HardkasError as HardkasError3,
1527
+ HardkasError as HardkasError4,
1397
1528
  parseKasToSompi as parseKasToSompi2,
1398
1529
  formatSompi as formatSompi2
1399
1530
  } from "@hardkas/core";
@@ -1418,6 +1549,7 @@ var Hardkas = class _Hardkas {
1418
1549
  this.query = new HardkasQuery(this);
1419
1550
  this.localnet = new HardkasLocalnet(this);
1420
1551
  this.replay = new HardkasReplay(this);
1552
+ this.lineage = new HardkasLineage(this);
1421
1553
  this.workflow = new HardkasWorkflow(this);
1422
1554
  }
1423
1555
  config;
@@ -1429,6 +1561,7 @@ var Hardkas = class _Hardkas {
1429
1561
  query;
1430
1562
  localnet;
1431
1563
  replay;
1564
+ lineage;
1432
1565
  workflow;
1433
1566
  mode;
1434
1567
  policy;
@@ -1447,6 +1580,39 @@ var Hardkas = class _Hardkas {
1447
1580
  static async open(dirOrOptions = ".") {
1448
1581
  const options = typeof dirOrOptions === "string" ? { cwd: dirOrOptions } : dirOrOptions;
1449
1582
  const loaded = await loadConfig(options);
1583
+ const activeNetwork = options.network || loaded.config.defaultNetwork || "simnet";
1584
+ const isSimulated = activeNetwork === "simulated" || loaded.config.networks?.[activeNetwork]?.kind === "simulated";
1585
+ const autoBootstrap = options.autoBootstrap ?? (isSimulated ? true : false);
1586
+ const fs4 = await import("fs");
1587
+ const path4 = await import("path");
1588
+ const cwd = options.cwd || process.cwd();
1589
+ const hardkasDir = path4.join(cwd, ".hardkas");
1590
+ if (autoBootstrap) {
1591
+ if (!isSimulated) {
1592
+ if (options.logger) {
1593
+ options.logger.warn("[HardKAS] autoBootstrap ignored for non-simulated network");
1594
+ }
1595
+ } else {
1596
+ if (!fs4.existsSync(hardkasDir)) {
1597
+ if (options.logger) {
1598
+ options.logger.info("[HardKAS] Auto-bootstrapping simulated workspace");
1599
+ }
1600
+ fs4.mkdirSync(hardkasDir, { recursive: true });
1601
+ }
1602
+ try {
1603
+ const { loadOrCreateLocalnetState } = await import("@hardkas/localnet");
1604
+ await loadOrCreateLocalnetState({ cwd });
1605
+ } catch {
1606
+ }
1607
+ }
1608
+ } else {
1609
+ if (!fs4.existsSync(hardkasDir)) {
1610
+ throw new HardkasError3("NOT_INITIALIZED", "Workspace not initialized. Run npx hardkas init . or pass autoBootstrap: true.");
1611
+ }
1612
+ }
1613
+ if (options.network) {
1614
+ loaded.config.defaultNetwork = options.network;
1615
+ }
1450
1616
  return new _Hardkas(loaded, options);
1451
1617
  }
1452
1618
  /**
@@ -1477,19 +1643,19 @@ var Hardkas = class _Hardkas {
1477
1643
  switch (action) {
1478
1644
  case "network":
1479
1645
  if (!this.policy.allowNetwork)
1480
- throw new HardkasError2("POLICY_VIOLATION", msg("allowNetwork"));
1646
+ throw new HardkasError3("POLICY_VIOLATION", msg("allowNetwork"));
1481
1647
  break;
1482
1648
  case "mainnet":
1483
1649
  if (!this.policy.allowMainnet)
1484
- throw new HardkasError2("POLICY_VIOLATION", msg("allowMainnet"));
1650
+ throw new HardkasError3("POLICY_VIOLATION", msg("allowMainnet"));
1485
1651
  break;
1486
1652
  case "external-wallet":
1487
1653
  if (!this.policy.allowExternalWallet)
1488
- throw new HardkasError2("POLICY_VIOLATION", msg("allowExternalWallet"));
1654
+ throw new HardkasError3("POLICY_VIOLATION", msg("allowExternalWallet"));
1489
1655
  break;
1490
1656
  case "mutation":
1491
1657
  if (this.policy.requireDryRun)
1492
- throw new HardkasError2("POLICY_VIOLATION", msg("requireDryRun"));
1658
+ throw new HardkasError3("POLICY_VIOLATION", msg("requireDryRun"));
1493
1659
  break;
1494
1660
  }
1495
1661
  }
@@ -1500,8 +1666,9 @@ export {
1500
1666
  Hardkas,
1501
1667
  HardkasAccounts,
1502
1668
  HardkasArtifactsManager,
1503
- HardkasError3 as HardkasError,
1669
+ HardkasError4 as HardkasError,
1504
1670
  HardkasL2,
1671
+ HardkasLineage,
1505
1672
  HardkasLocalnet,
1506
1673
  HardkasQuery,
1507
1674
  HardkasReplay,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/sdk",
3
- "version": "0.7.7-alpha",
3
+ "version": "0.7.8-alpha",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -23,23 +23,24 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@hardkas/artifacts": "0.7.7-alpha",
27
- "@hardkas/accounts": "0.7.7-alpha",
28
- "@hardkas/core": "0.7.7-alpha",
29
- "@hardkas/kaspa-rpc": "0.7.7-alpha",
30
- "@hardkas/localnet": "0.7.7-alpha",
31
- "@hardkas/query": "0.7.7-alpha",
32
- "@hardkas/config": "0.7.7-alpha",
33
- "@hardkas/simulator": "0.7.7-alpha",
34
- "@hardkas/tx-builder": "0.7.7-alpha",
35
- "@hardkas/l2": "0.7.7-alpha",
36
- "@hardkas/wallet-adapter": "0.7.7-alpha"
26
+ "@hardkas/artifacts": "0.7.8-alpha",
27
+ "@hardkas/core": "0.7.8-alpha",
28
+ "@hardkas/config": "0.7.8-alpha",
29
+ "@hardkas/kaspa-rpc": "0.7.8-alpha",
30
+ "@hardkas/l2": "0.7.8-alpha",
31
+ "@hardkas/localnet": "0.7.8-alpha",
32
+ "@hardkas/accounts": "0.7.8-alpha",
33
+ "@hardkas/query": "0.7.8-alpha",
34
+ "@hardkas/tx-builder": "0.7.8-alpha",
35
+ "@hardkas/simulator": "0.7.8-alpha",
36
+ "@hardkas/query-store": "0.7.8-alpha",
37
+ "@hardkas/wallet-adapter": "0.7.8-alpha"
37
38
  },
38
39
  "devDependencies": {
39
40
  "tsup": "^8.3.5",
41
+ "@types/node": "^20.12.7",
40
42
  "typescript": "^5.7.2",
41
- "vitest": "^2.1.8",
42
- "@hardkas/query-store": "0.7.7-alpha"
43
+ "vitest": "^2.1.8"
43
44
  },
44
45
  "license": "MIT",
45
46
  "author": "Javier Rodriguez",