@hardkas/sdk 0.8.1-alpha → 0.8.3-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.
package/dist/index.d.ts CHANGED
@@ -63,9 +63,12 @@ declare class HardkasTx {
63
63
  plan(options: {
64
64
  from: string | HardkasAccount;
65
65
  to: string | HardkasAccount;
66
- amount: string | bigint;
66
+ amount: string | number | bigint;
67
67
  feeRate?: bigint;
68
68
  workflowId?: string;
69
+ policy?: string;
70
+ networkProfile?: string;
71
+ assumption?: string;
69
72
  }): Promise<TxPlanArtifact>;
70
73
  /**
71
74
  * Signs a transaction plan.
@@ -304,11 +307,7 @@ declare class HardkasArtifactsManager {
304
307
  * Cryptographically verifies the determinism and integrity of an artifact.
305
308
  * Throws an error with details if corruption or mismatch is found.
306
309
  */
307
- verify(target: string | {
308
- schema?: string;
309
- artifactId?: string;
310
- contentHash?: string;
311
- }, options?: {
310
+ verify(target: any, options?: {
312
311
  throwOnInvalid?: boolean;
313
312
  }): Promise<any>;
314
313
  }
package/dist/index.js CHANGED
@@ -153,7 +153,7 @@ var HardkasTx = class {
153
153
  throw new Error(`From account ${fromAccount.name} has no address.`);
154
154
  if (!toAccount.address)
155
155
  throw new Error(`To account ${toAccount.name} has no address.`);
156
- const amountSompi = typeof options.amount === "string" ? parseKasToSompi(options.amount) : typeof options.amount === "number" ? BigInt(options.amount) : options.amount;
156
+ const amountSompi = typeof options.amount === "string" ? parseKasToSompi(options.amount) : typeof options.amount === "number" ? parseKasToSompi(options.amount.toString()) : options.amount;
157
157
  if (amountSompi === 0n) {
158
158
  throw new Error("Kaspa value-transfer outputs require amount > 0.\nFor metadata/notary/DID marker transactions use --amount 1.\nFuture: hardkas tx anchor.");
159
159
  }
@@ -200,7 +200,7 @@ var HardkasTx = class {
200
200
  feeRateSompiPerMass: options.feeRate ?? 1n
201
201
  });
202
202
  const isSimulated = activeNetwork === "simulated" || this.sdk.config.config.networks?.[activeNetwork]?.kind === "simulated";
203
- return createTxPlanArtifact({
203
+ const basePlan = createTxPlanArtifact({
204
204
  networkId: activeNetwork,
205
205
  mode: isSimulated ? "simulated" : "real",
206
206
  from: {
@@ -216,11 +216,52 @@ var HardkasTx = class {
216
216
  plan: builderPlan,
217
217
  ctx: options.workflowId ? { ...systemRuntimeContext, workflowId: options.workflowId } : systemRuntimeContext
218
218
  });
219
+ if (options.policy) {
220
+ try {
221
+ const pol = await this.sdk.artifacts.read(options.policy);
222
+ basePlan.policyRef = pol.contentHash || pol.artifactId || options.policy;
223
+ } catch (e) {
224
+ basePlan.policyRef = options.policy;
225
+ }
226
+ }
227
+ if (options.networkProfile) {
228
+ try {
229
+ const net = await this.sdk.artifacts.read(options.networkProfile);
230
+ basePlan.networkProfileRef = net.contentHash || net.artifactId || options.networkProfile;
231
+ } catch (e) {
232
+ basePlan.networkProfileRef = options.networkProfile;
233
+ }
234
+ }
235
+ if (options.assumption) {
236
+ try {
237
+ const asm = await this.sdk.artifacts.read(options.assumption);
238
+ basePlan.assumptionRef = asm.contentHash || asm.artifactId || options.assumption;
239
+ } catch (e) {
240
+ basePlan.assumptionRef = options.assumption;
241
+ }
242
+ }
243
+ const { CURRENT_HASH_VERSION: CURRENT_HASH_VERSION2, calculateContentHash: calculateContentHash2 } = await import("@hardkas/artifacts");
244
+ const newHash = calculateContentHash2(basePlan, CURRENT_HASH_VERSION2);
245
+ basePlan.contentHash = newHash;
246
+ if (basePlan.lineage) {
247
+ basePlan.lineage.artifactId = newHash;
248
+ basePlan.lineage.parentArtifactId = newHash;
249
+ basePlan.lineage.rootArtifactId = newHash;
250
+ const finalHash = calculateContentHash2(basePlan, CURRENT_HASH_VERSION2);
251
+ basePlan.contentHash = finalHash;
252
+ basePlan.lineage.artifactId = finalHash;
253
+ basePlan.lineage.parentArtifactId = finalHash;
254
+ basePlan.lineage.rootArtifactId = finalHash;
255
+ }
256
+ return basePlan;
219
257
  }
220
258
  /**
221
259
  * Signs a transaction plan.
222
260
  */
223
261
  async sign(plan, account, options) {
262
+ if (typeof plan === "object" && plan !== null && plan.contentHash) {
263
+ await this.sdk.artifacts.verify(plan, { throwOnInvalid: true });
264
+ }
224
265
  let resolvedAccount;
225
266
  if (typeof account === "string") {
226
267
  resolvedAccount = await this.sdk.accounts.resolve(account);
@@ -298,7 +339,7 @@ var HardkasTx = class {
298
339
  lineage: {
299
340
  artifactId: "",
300
341
  // To be computed from contentHash
301
- lineageId: partialTx.lineage?.lineageId || `lineage-${Math.random().toString(36).slice(2, 10)}`,
342
+ lineageId: partialTx.lineage?.lineageId || partialTx.contentHash || "0".repeat(64),
302
343
  parentArtifactId: partialTx.contentHash || partialTx.signedId,
303
344
  rootArtifactId: partialTx.lineage?.rootArtifactId || partialTx.sourcePlanId
304
345
  }
@@ -382,7 +423,7 @@ var HardkasTx = class {
382
423
  lineage: {
383
424
  artifactId: "",
384
425
  // To be computed
385
- lineageId: plan.lineage?.lineageId || `lineage-${Math.random().toString(36).slice(2, 10)}`,
426
+ lineageId: plan.lineage?.lineageId || plan.contentHash || "0".repeat(64),
386
427
  parentArtifactId: plan.contentHash || plan.planId,
387
428
  rootArtifactId: plan.contentHash || plan.planId
388
429
  },
@@ -401,6 +442,9 @@ var HardkasTx = class {
401
442
  if (draft.lineage) draft.lineage.artifactId = draft.signedId;
402
443
  signedArtifact = draft;
403
444
  } else {
445
+ if (resolvedAccount.address !== plan.from.address) {
446
+ throw new Error(`Signer account '${resolvedAccount.address}' is not authorized to sign for '${plan.from.address}'.`);
447
+ }
404
448
  signedArtifact = await signTxPlanArtifact({
405
449
  planArtifact: plan,
406
450
  account: resolvedAccount,
@@ -437,6 +481,9 @@ var HardkasTx = class {
437
481
  * Modifies the local deterministic state and outputs receipt/trace artifacts.
438
482
  */
439
483
  async simulate(target, options = {}) {
484
+ if (typeof target === "object" && target !== null && target.contentHash) {
485
+ await this.sdk.artifacts.verify(target, { throwOnInvalid: true });
486
+ }
440
487
  const persist = options.persist ?? true;
441
488
  const {
442
489
  loadOrCreateLocalnetState,
@@ -537,9 +584,22 @@ var HardkasTx = class {
537
584
  submittedAt: simResult.receipt.createdAt,
538
585
  confirmedAt: simResult.receipt.createdAt,
539
586
  rpcUrl: "simulated://local",
540
- tracePath
587
+ tracePath,
588
+ lineage: {
589
+ artifactId: "",
590
+ // To be computed
591
+ lineageId: targetObj.lineage?.lineageId || targetObj.contentHash || "0".repeat(64),
592
+ parentArtifactId: targetObj.contentHash || "0".repeat(64),
593
+ rootArtifactId: targetObj.lineage?.rootArtifactId || "0".repeat(64),
594
+ sequence: (targetObj.lineage?.sequence || 1) + 1
595
+ }
541
596
  };
542
597
  receiptBase.contentHash = calculateContentHash(receiptBase, CURRENT_HASH_VERSION);
598
+ if (receiptBase.lineage) {
599
+ receiptBase.lineage.artifactId = receiptBase.contentHash;
600
+ receiptBase.contentHash = calculateContentHash(receiptBase, CURRENT_HASH_VERSION);
601
+ receiptBase.lineage.artifactId = receiptBase.contentHash;
602
+ }
543
603
  const receipt = Object.freeze(receiptBase);
544
604
  const traceSteps = events.map((ev) => ({
545
605
  phase: ev.phase || ev.message || "unknown",
@@ -596,6 +656,9 @@ var HardkasTx = class {
596
656
  * Sends a signed transaction to the real RPC network.
597
657
  */
598
658
  async send(signedArtifact, urlOrOptions) {
659
+ if (typeof signedArtifact === "object" && signedArtifact !== null && signedArtifact.contentHash) {
660
+ await this.sdk.artifacts.verify(signedArtifact, { throwOnInvalid: true });
661
+ }
599
662
  const verification = verifySignedTxSemantics(signedArtifact);
600
663
  if (!verification.ok) {
601
664
  throw new Error(
@@ -675,12 +738,26 @@ var HardkasTx = class {
675
738
  feeSompi: signedArtifact.metadata?.estimatedFeeSompi || "0",
676
739
  submittedAt: (/* @__PURE__ */ new Date()).toISOString(),
677
740
  ...url ? { rpcUrl: url } : {},
678
- ...signedArtifact.workflowId ? { workflowId: signedArtifact.workflowId } : {}
741
+ ...signedArtifact.workflowId ? { workflowId: signedArtifact.workflowId } : {},
742
+ tracePath: void 0,
743
+ lineage: {
744
+ artifactId: "",
745
+ // To be computed
746
+ lineageId: signedArtifact.lineage?.lineageId || signedArtifact.contentHash || "0".repeat(64),
747
+ parentArtifactId: signedArtifact.contentHash || "0".repeat(64),
748
+ rootArtifactId: signedArtifact.lineage?.rootArtifactId || "0".repeat(64),
749
+ sequence: (signedArtifact.lineage?.sequence || 1) + 1
750
+ }
679
751
  };
680
752
  realReceiptBase.contentHash = calculateContentHash(
681
753
  realReceiptBase,
682
754
  CURRENT_HASH_VERSION
683
755
  );
756
+ if (realReceiptBase.lineage) {
757
+ realReceiptBase.lineage.artifactId = realReceiptBase.contentHash;
758
+ realReceiptBase.contentHash = calculateContentHash(realReceiptBase, CURRENT_HASH_VERSION);
759
+ realReceiptBase.lineage.artifactId = realReceiptBase.contentHash;
760
+ }
684
761
  const receipt = realReceiptBase;
685
762
  const receiptPath = getDefaultReceiptPath(receipt.txId, this.sdk.config.cwd);
686
763
  await writeArtifact(receiptPath, receipt);
@@ -985,6 +1062,21 @@ var HardkasReplay = class {
985
1062
  * against the mathematically reconstructed localnet state.
986
1063
  */
987
1064
  async verify(targetOrOptions, options) {
1065
+ const throwOnInvalid = options?.throwOnInvalid !== false;
1066
+ if (typeof targetOrOptions === "object" && targetOrOptions !== null && targetOrOptions.contentHash) {
1067
+ const verifyRes = await this.sdk.artifacts.verify(targetOrOptions, { throwOnInvalid });
1068
+ if (!verifyRes.valid && !throwOnInvalid) {
1069
+ return {
1070
+ passed: false,
1071
+ artifactsScanned: 1,
1072
+ lineage: "invalid",
1073
+ determinism: "failed",
1074
+ contamination: "clean",
1075
+ report: null,
1076
+ error: `Artifact verification failed: ${verifyRes.reason}`
1077
+ };
1078
+ }
1079
+ }
988
1080
  let opts = options || {};
989
1081
  if (typeof targetOrOptions === "string") {
990
1082
  opts.path = targetOrOptions;
@@ -1368,29 +1460,38 @@ var HardkasArtifactsManager = class {
1368
1460
  */
1369
1461
  async verify(target, options = {}) {
1370
1462
  const throwOnInvalid = options.throwOnInvalid ?? true;
1371
- const id = typeof target === "string" ? target : target.artifactId || target.contentHash || "";
1372
- if (!id) {
1373
- if (throwOnInvalid) throw new Error("No artifact target provided for verification.");
1374
- return { valid: false, reason: "unknown", message: "No artifact target provided for verification." };
1375
- }
1376
1463
  let artifact;
1377
- try {
1378
- artifact = await this.read(id);
1379
- } catch (e) {
1380
- if (throwOnInvalid) throw e;
1381
- return { valid: false, reason: "missing_artifact", message: e.message, artifactId: id };
1464
+ let id;
1465
+ if (typeof target === "string") {
1466
+ id = target;
1467
+ if (!id) {
1468
+ if (throwOnInvalid) throw new Error("No artifact target provided for verification.");
1469
+ return { valid: false, reason: "unknown", message: "No artifact target provided for verification." };
1470
+ }
1471
+ try {
1472
+ artifact = await this.read(id);
1473
+ } catch (e) {
1474
+ if (throwOnInvalid) throw e;
1475
+ return { valid: false, reason: "missing_artifact", message: e.message, artifactId: id };
1476
+ }
1477
+ } else {
1478
+ artifact = target;
1479
+ id = artifact.artifactId || artifact.contentHash || "";
1382
1480
  }
1383
1481
  const { verifyArtifactIntegrity: verifyArtifactIntegrity2 } = await import("@hardkas/artifacts");
1384
1482
  const result = await verifyArtifactIntegrity2(artifact);
1385
1483
  if (!result.ok) {
1484
+ const mappedReason = result.issues[0]?.code === "HASH_MISMATCH" ? "content_hash_mismatch" : result.issues[0]?.code === "MISSING_CONTENT_HASH" ? "missing_content_hash" : result.issues[0]?.code === "MISSING_SIGNATURE" ? "missing_signature" : "schema_invalid";
1386
1485
  if (throwOnInvalid) {
1387
1486
  throw new Error(`Artifact ${id} corrupted or invalid: ` + JSON.stringify(result.issues, null, 2));
1388
1487
  }
1389
1488
  return {
1390
1489
  valid: false,
1391
- reason: result.issues[0]?.code === "HASH_MISMATCH" ? "hash_mismatch" : result.issues[0]?.code === "MISSING_SIGNATURE" ? "missing_signature" : "schema_invalid",
1490
+ reason: mappedReason,
1392
1491
  message: result.issues.map((i) => i.message).join(", "),
1393
1492
  artifactId: id,
1493
+ expected: result.expectedHash,
1494
+ actual: result.actualHash,
1394
1495
  details: result.issues
1395
1496
  };
1396
1497
  }
@@ -1733,8 +1834,8 @@ var Hardkas = class _Hardkas {
1733
1834
  resolveRpcUrl() {
1734
1835
  const networkId = this.config.config.defaultNetwork || "simnet";
1735
1836
  const target = this.config.config.networks?.[networkId];
1736
- if (target && (target.kind === "kaspa-rpc" || target.kind === "igra" || target.kind === "kaspa-node")) {
1737
- return target.rpcUrl || "ws://127.0.0.1:18210";
1837
+ if (target && "rpcUrl" in target && typeof target.rpcUrl === "string") {
1838
+ return target.rpcUrl;
1738
1839
  }
1739
1840
  return "ws://127.0.0.1:18210";
1740
1841
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/sdk",
3
- "version": "0.8.1-alpha",
3
+ "version": "0.8.3-alpha",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -23,18 +23,18 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@hardkas/artifacts": "0.8.1-alpha",
27
- "@hardkas/accounts": "0.8.1-alpha",
28
- "@hardkas/core": "0.8.1-alpha",
29
- "@hardkas/config": "0.8.1-alpha",
30
- "@hardkas/kaspa-rpc": "0.8.1-alpha",
31
- "@hardkas/l2": "0.8.1-alpha",
32
- "@hardkas/query": "0.8.1-alpha",
33
- "@hardkas/localnet": "0.8.1-alpha",
34
- "@hardkas/simulator": "0.8.1-alpha",
35
- "@hardkas/wallet-adapter": "0.8.1-alpha",
36
- "@hardkas/query-store": "0.8.1-alpha",
37
- "@hardkas/tx-builder": "0.8.1-alpha"
26
+ "@hardkas/artifacts": "0.8.3-alpha",
27
+ "@hardkas/accounts": "0.8.3-alpha",
28
+ "@hardkas/kaspa-rpc": "0.8.3-alpha",
29
+ "@hardkas/config": "0.8.3-alpha",
30
+ "@hardkas/core": "0.8.3-alpha",
31
+ "@hardkas/l2": "0.8.3-alpha",
32
+ "@hardkas/localnet": "0.8.3-alpha",
33
+ "@hardkas/simulator": "0.8.3-alpha",
34
+ "@hardkas/wallet-adapter": "0.8.3-alpha",
35
+ "@hardkas/query": "0.8.3-alpha",
36
+ "@hardkas/tx-builder": "0.8.3-alpha",
37
+ "@hardkas/query-store": "0.8.3-alpha"
38
38
  },
39
39
  "devDependencies": {
40
40
  "tsup": "^8.3.5",