@hardkas/sdk 0.7.8-alpha → 0.7.10-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 +7 -3
- package/dist/index.js +142 -60
- package/package.json +13 -13
package/dist/index.d.ts
CHANGED
|
@@ -79,10 +79,12 @@ declare class HardkasTx {
|
|
|
79
79
|
* Simulates a transaction on the local state without broadcasting to a real Kaspa node.
|
|
80
80
|
* Modifies the local deterministic state and outputs receipt/trace artifacts.
|
|
81
81
|
*/
|
|
82
|
-
simulate(
|
|
82
|
+
simulate(target: string | Partial<TxPlanArtifact> | SignedTxArtifact, options?: {
|
|
83
|
+
persist?: boolean;
|
|
84
|
+
}): Promise<{
|
|
83
85
|
receipt: TxReceiptArtifact;
|
|
84
|
-
receiptPath
|
|
85
|
-
tracePath
|
|
86
|
+
receiptPath?: string;
|
|
87
|
+
tracePath?: string;
|
|
86
88
|
}>;
|
|
87
89
|
/**
|
|
88
90
|
* Sends a signed transaction to the real RPC network.
|
|
@@ -295,6 +297,8 @@ declare class HardkasArtifactsManager {
|
|
|
295
297
|
schema?: string;
|
|
296
298
|
artifactId?: string;
|
|
297
299
|
contentHash?: string;
|
|
300
|
+
}, options?: {
|
|
301
|
+
throwOnInvalid?: boolean;
|
|
298
302
|
}): Promise<any>;
|
|
299
303
|
}
|
|
300
304
|
|
package/dist/index.js
CHANGED
|
@@ -405,7 +405,8 @@ var HardkasTx = class {
|
|
|
405
405
|
* Simulates a transaction on the local state without broadcasting to a real Kaspa node.
|
|
406
406
|
* Modifies the local deterministic state and outputs receipt/trace artifacts.
|
|
407
407
|
*/
|
|
408
|
-
async simulate(
|
|
408
|
+
async simulate(target, options = {}) {
|
|
409
|
+
const persist = options.persist ?? true;
|
|
409
410
|
const {
|
|
410
411
|
loadOrCreateLocalnetState,
|
|
411
412
|
saveLocalnetState,
|
|
@@ -420,12 +421,41 @@ var HardkasTx = class {
|
|
|
420
421
|
const events = [
|
|
421
422
|
{ type: "phase.started", phase: "send", timestamp: startTime }
|
|
422
423
|
];
|
|
423
|
-
|
|
424
|
+
let planArtifact;
|
|
425
|
+
let signedId = "unknown";
|
|
426
|
+
let sourcePlanId = "unknown";
|
|
427
|
+
let txId = `simulated-tx-${Date.now()}`;
|
|
428
|
+
let targetObj = target;
|
|
429
|
+
if (typeof target === "string") {
|
|
430
|
+
try {
|
|
431
|
+
targetObj = await this.sdk.artifacts.read(target);
|
|
432
|
+
} catch (e) {
|
|
433
|
+
throw new Error(`Artifact '${target}' not found. If you already have an in-memory artifact, pass the object directly to tx.simulate(artifact).`);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (targetObj.schema === ARTIFACT_SCHEMAS.SIGNED_TX) {
|
|
437
|
+
signedId = targetObj.signedId || targetObj.id || "unknown";
|
|
438
|
+
sourcePlanId = targetObj.sourcePlanId || "unknown";
|
|
439
|
+
txId = targetObj.txId || `simulated-${sourcePlanId}-tx`;
|
|
440
|
+
try {
|
|
441
|
+
planArtifact = await this.sdk.artifacts.read(sourcePlanId);
|
|
442
|
+
} catch (e) {
|
|
443
|
+
throw new Error(`Cannot simulate signed artifact: source plan '${sourcePlanId}' not found in workspace.`);
|
|
444
|
+
}
|
|
445
|
+
} else {
|
|
446
|
+
planArtifact = targetObj;
|
|
447
|
+
sourcePlanId = planArtifact.planId || planArtifact.id || "unknown";
|
|
448
|
+
txId = `simulated-${sourcePlanId}-tx`;
|
|
449
|
+
if (persist && !planArtifact.planId) {
|
|
450
|
+
const savedPlanResult = await this.sdk.artifacts.write(planArtifact);
|
|
451
|
+
sourcePlanId = planArtifact.planId || "unknown";
|
|
452
|
+
}
|
|
453
|
+
}
|
|
424
454
|
const simResult = applySimulatedPlan(
|
|
425
455
|
state,
|
|
426
456
|
planArtifact,
|
|
427
457
|
systemRuntimeContext,
|
|
428
|
-
{ txId
|
|
458
|
+
{ txId }
|
|
429
459
|
);
|
|
430
460
|
if (!simResult.ok) {
|
|
431
461
|
throw new Error(`Strict validation failed: ${simResult.errors?.join(", ")}`);
|
|
@@ -436,15 +466,18 @@ var HardkasTx = class {
|
|
|
436
466
|
endpoint: "simulated://local"
|
|
437
467
|
});
|
|
438
468
|
events.push({ type: "phase.completed", phase: "send", timestamp: Date.now() });
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
469
|
+
let receiptPath;
|
|
470
|
+
if (persist) {
|
|
471
|
+
await saveLocalnetState(
|
|
472
|
+
simResult.state,
|
|
473
|
+
getDefaultLocalnetStatePath(this.sdk.workspace.root)
|
|
474
|
+
);
|
|
475
|
+
receiptPath = await saveSimulatedReceipt(
|
|
476
|
+
simResult.receipt,
|
|
477
|
+
{ cwd: this.sdk.workspace.root }
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
const tracePath = receiptPath ? receiptPath.replace(".json", ".trace.json") : void 0;
|
|
448
481
|
const activeNetwork = this.sdk.config.config.defaultNetwork || "simnet";
|
|
449
482
|
const isSimulated = activeNetwork === "simulated" || this.sdk.config.config.networks?.[activeNetwork]?.kind === "simulated";
|
|
450
483
|
const receiptBase = {
|
|
@@ -458,10 +491,10 @@ var HardkasTx = class {
|
|
|
458
491
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
459
492
|
status: "confirmed",
|
|
460
493
|
txId: simResult.receipt.txId,
|
|
461
|
-
sourceSignedId:
|
|
462
|
-
from: { address:
|
|
463
|
-
to: { address:
|
|
464
|
-
amountSompi:
|
|
494
|
+
sourceSignedId: signedId,
|
|
495
|
+
from: { address: planArtifact.from?.address || "unknown" },
|
|
496
|
+
to: { address: planArtifact.to?.address || "unknown" },
|
|
497
|
+
amountSompi: planArtifact.amountSompi || "0",
|
|
465
498
|
feeSompi: simResult.receipt.feeSompi?.toString() || "0",
|
|
466
499
|
changeSompi: simResult.receipt.changeSompi?.toString() || "0",
|
|
467
500
|
spentUtxoIds: simResult.receipt.spentUtxoIds,
|
|
@@ -494,22 +527,26 @@ var HardkasTx = class {
|
|
|
494
527
|
steps: traceSteps
|
|
495
528
|
};
|
|
496
529
|
traceBase.contentHash = calculateContentHash(traceBase, CURRENT_HASH_VERSION);
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
530
|
+
if (persist) {
|
|
531
|
+
await saveSimulatedTrace(
|
|
532
|
+
{
|
|
533
|
+
...traceBase,
|
|
534
|
+
events,
|
|
535
|
+
receiptPath
|
|
536
|
+
},
|
|
537
|
+
{ cwd: this.sdk.workspace.root }
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
if (persist) {
|
|
541
|
+
coreEvents.normalizeAndEmit({
|
|
542
|
+
kind: "artifact.created",
|
|
543
|
+
schema: receipt.schema,
|
|
544
|
+
artifactId: receipt.txId,
|
|
545
|
+
network: receipt.networkId,
|
|
546
|
+
mode: receipt.mode,
|
|
547
|
+
path: receiptPath
|
|
548
|
+
});
|
|
549
|
+
}
|
|
513
550
|
coreEvents.normalizeAndEmit({
|
|
514
551
|
kind: "tx.confirmed",
|
|
515
552
|
txId: receipt.txId,
|
|
@@ -518,11 +555,10 @@ var HardkasTx = class {
|
|
|
518
555
|
amountSompi: receipt.amountSompi,
|
|
519
556
|
feeSompi: receipt.feeSompi
|
|
520
557
|
});
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
};
|
|
558
|
+
const result = { receipt };
|
|
559
|
+
if (receiptPath) result.receiptPath = receiptPath;
|
|
560
|
+
if (tracePath) result.tracePath = tracePath;
|
|
561
|
+
return result;
|
|
526
562
|
}
|
|
527
563
|
/**
|
|
528
564
|
* Sends a signed transaction to the real RPC network.
|
|
@@ -634,29 +670,48 @@ var HardkasQuery = class {
|
|
|
634
670
|
* Synchronizes the query store with the filesystem artifacts.
|
|
635
671
|
*/
|
|
636
672
|
async sync(options) {
|
|
637
|
-
const
|
|
638
|
-
const { withLock } = await import("@hardkas/core");
|
|
673
|
+
const fs4 = await import("fs");
|
|
639
674
|
const path4 = await import("path");
|
|
640
|
-
const
|
|
675
|
+
const hardkasDir = path4.join(this.sdk.workspace.root, ".hardkas");
|
|
676
|
+
if (!fs4.existsSync(hardkasDir)) {
|
|
677
|
+
throw new Error("Workspace not initialized. Run hardkas init or Hardkas.create({ autoBootstrap:true }).");
|
|
678
|
+
}
|
|
679
|
+
let HardkasStore, HardkasIndexer;
|
|
680
|
+
try {
|
|
681
|
+
const qs = await import("@hardkas/query-store");
|
|
682
|
+
HardkasStore = qs.HardkasStore;
|
|
683
|
+
HardkasIndexer = qs.HardkasIndexer;
|
|
684
|
+
} catch (e) {
|
|
685
|
+
throw new Error("Query store backend unavailable. Install @hardkas/query-store or run query.store.rebuild.");
|
|
686
|
+
}
|
|
687
|
+
const { withLock } = await import("@hardkas/core");
|
|
688
|
+
const dbPath = path4.join(hardkasDir, "store.db");
|
|
641
689
|
const store = new HardkasStore({ dbPath });
|
|
642
690
|
let stats;
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
691
|
+
try {
|
|
692
|
+
await withLock(
|
|
693
|
+
{
|
|
694
|
+
rootDir: this.sdk.workspace.root,
|
|
695
|
+
name: "query-store",
|
|
696
|
+
command: "query-sync",
|
|
697
|
+
wait: true
|
|
698
|
+
},
|
|
699
|
+
async () => {
|
|
700
|
+
store.connect({ autoMigrate: true });
|
|
701
|
+
const indexer = new HardkasIndexer(store.getDatabase());
|
|
702
|
+
if (options?.force) {
|
|
703
|
+
stats = await indexer.rebuild();
|
|
704
|
+
} else {
|
|
705
|
+
stats = await indexer.sync();
|
|
706
|
+
}
|
|
657
707
|
}
|
|
708
|
+
);
|
|
709
|
+
} catch (e) {
|
|
710
|
+
if (e.message?.includes("SQLITE") || e.message?.includes("Cannot read properties")) {
|
|
711
|
+
throw new Error("Query store database is not configured correctly or corrupted. Try running query.sync({ force: true }).");
|
|
658
712
|
}
|
|
659
|
-
|
|
713
|
+
throw e;
|
|
714
|
+
}
|
|
660
715
|
return stats;
|
|
661
716
|
}
|
|
662
717
|
/**
|
|
@@ -1224,14 +1279,36 @@ var HardkasArtifactsManager = class {
|
|
|
1224
1279
|
* Cryptographically verifies the determinism and integrity of an artifact.
|
|
1225
1280
|
* Throws an error with details if corruption or mismatch is found.
|
|
1226
1281
|
*/
|
|
1227
|
-
async verify(target) {
|
|
1282
|
+
async verify(target, options = {}) {
|
|
1283
|
+
const throwOnInvalid = options.throwOnInvalid ?? true;
|
|
1228
1284
|
const id = typeof target === "string" ? target : target.artifactId || target.contentHash || "";
|
|
1229
|
-
if (!id)
|
|
1230
|
-
|
|
1285
|
+
if (!id) {
|
|
1286
|
+
if (throwOnInvalid) throw new Error("No artifact target provided for verification.");
|
|
1287
|
+
return { valid: false, reason: "unknown", message: "No artifact target provided for verification." };
|
|
1288
|
+
}
|
|
1289
|
+
let artifact;
|
|
1290
|
+
try {
|
|
1291
|
+
artifact = await this.read(id);
|
|
1292
|
+
} catch (e) {
|
|
1293
|
+
if (throwOnInvalid) throw e;
|
|
1294
|
+
return { valid: false, reason: "missing_artifact", message: e.message, artifactId: id };
|
|
1295
|
+
}
|
|
1231
1296
|
const { verifyArtifactIntegrity: verifyArtifactIntegrity2 } = await import("@hardkas/artifacts");
|
|
1232
1297
|
const result = await verifyArtifactIntegrity2(artifact);
|
|
1233
1298
|
if (!result.ok) {
|
|
1234
|
-
|
|
1299
|
+
if (throwOnInvalid) {
|
|
1300
|
+
throw new Error(`Artifact ${id} corrupted or invalid: ` + JSON.stringify(result.issues, null, 2));
|
|
1301
|
+
}
|
|
1302
|
+
return {
|
|
1303
|
+
valid: false,
|
|
1304
|
+
reason: result.issues[0]?.code === "HASH_MISMATCH" ? "hash_mismatch" : result.issues[0]?.code === "MISSING_SIGNATURE" ? "missing_signature" : "schema_invalid",
|
|
1305
|
+
message: result.issues.map((i) => i.message).join(", "),
|
|
1306
|
+
artifactId: id,
|
|
1307
|
+
details: result.issues
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
if (!throwOnInvalid) {
|
|
1311
|
+
return { valid: true, artifactId: id, details: result };
|
|
1235
1312
|
}
|
|
1236
1313
|
return result;
|
|
1237
1314
|
}
|
|
@@ -1613,7 +1690,12 @@ var Hardkas = class _Hardkas {
|
|
|
1613
1690
|
if (options.network) {
|
|
1614
1691
|
loaded.config.defaultNetwork = options.network;
|
|
1615
1692
|
}
|
|
1616
|
-
|
|
1693
|
+
let provider;
|
|
1694
|
+
if (isSimulated) {
|
|
1695
|
+
const { LocalnetSimulatedProvider } = await import("@hardkas/localnet");
|
|
1696
|
+
provider = new LocalnetSimulatedProvider(cwd);
|
|
1697
|
+
}
|
|
1698
|
+
return new _Hardkas(loaded, options, provider);
|
|
1617
1699
|
}
|
|
1618
1700
|
/**
|
|
1619
1701
|
* Alias for open(). Used in most examples.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardkas/sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.10-alpha",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@hardkas/
|
|
27
|
-
"@hardkas/
|
|
28
|
-
"@hardkas/
|
|
29
|
-
"@hardkas/
|
|
30
|
-
"@hardkas/
|
|
31
|
-
"@hardkas/
|
|
32
|
-
"@hardkas/
|
|
33
|
-
"@hardkas/
|
|
34
|
-
"@hardkas/
|
|
35
|
-
"@hardkas/
|
|
36
|
-
"@hardkas/query-store": "0.7.
|
|
37
|
-
"@hardkas/wallet-adapter": "0.7.
|
|
26
|
+
"@hardkas/config": "0.7.10-alpha",
|
|
27
|
+
"@hardkas/accounts": "0.7.10-alpha",
|
|
28
|
+
"@hardkas/artifacts": "0.7.10-alpha",
|
|
29
|
+
"@hardkas/l2": "0.7.10-alpha",
|
|
30
|
+
"@hardkas/simulator": "0.7.10-alpha",
|
|
31
|
+
"@hardkas/core": "0.7.10-alpha",
|
|
32
|
+
"@hardkas/localnet": "0.7.10-alpha",
|
|
33
|
+
"@hardkas/kaspa-rpc": "0.7.10-alpha",
|
|
34
|
+
"@hardkas/query": "0.7.10-alpha",
|
|
35
|
+
"@hardkas/tx-builder": "0.7.10-alpha",
|
|
36
|
+
"@hardkas/query-store": "0.7.10-alpha",
|
|
37
|
+
"@hardkas/wallet-adapter": "0.7.10-alpha"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"tsup": "^8.3.5",
|