@hardkas/cli 0.2.2-alpha.1 → 0.3.0-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/accounts-keystore-runners-QYSNZMZV.js +155 -0
- package/dist/{artifact-lineage-runner-RJWQ3R3X.js → artifact-lineage-runner-TY4YTE6H.js} +6 -2
- package/dist/{chunk-AQWQW5ZG.js → chunk-K7XPWWIO.js} +45 -1
- package/dist/chunk-KA5CAWI2.js +163 -0
- package/dist/chunk-ZM2NBOAE.js +37 -0
- package/dist/{dag-runners-YQDHD7U6.js → dag-runners-NLBYR7I7.js} +2 -2
- package/dist/deployment-runners-GEICABEH.js +15 -0
- package/dist/index.js +1988 -544
- package/dist/replay-verify-runner-Y3RARVD7.js +50 -0
- package/dist/{rpc-doctor-runner-ERWXOXSE.js → rpc-doctor-runner-V7H7AAX4.js} +1 -1
- package/dist/{snapshot-restore-runner-QNAADGBX.js → snapshot-restore-runner-KIJNPLDV.js} +1 -1
- package/dist/{snapshot-verify-runner-BWRW3NUW.js → snapshot-verify-runner-PGMADWLN.js} +1 -1
- package/dist/{tx-verify-runner-Z5M2JDRI.js → tx-verify-runner-6EGY5ZN4.js} +11 -2
- package/dist/ui-SUYOHGGP.js +10 -0
- package/package.json +21 -15
- package/dist/accounts-keystore-runners-MCJIAGZ4.js +0 -112
- package/dist/replay-verify-runner-UMYALHNT.js +0 -37
- package/dist/ui-OVK5PX6H.js +0 -8
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UI
|
|
3
|
+
} from "./chunk-K7XPWWIO.js";
|
|
4
|
+
|
|
5
|
+
// src/runners/replay-verify-runner.ts
|
|
6
|
+
import { readTxPlanArtifact, readTxReceiptArtifact } from "@hardkas/artifacts";
|
|
7
|
+
import { loadOrCreateLocalnetState, verifyReplay } from "@hardkas/localnet";
|
|
8
|
+
import path from "path";
|
|
9
|
+
import pc from "picocolors";
|
|
10
|
+
async function runReplayVerify(options) {
|
|
11
|
+
const artifactDir = path.resolve(process.cwd(), options.path);
|
|
12
|
+
const planPath = path.join(artifactDir, "tx-plan.json");
|
|
13
|
+
const receiptPath = path.join(artifactDir, "tx-receipt.json");
|
|
14
|
+
UI.header(`Replay Verification: ${path.basename(artifactDir)}`);
|
|
15
|
+
try {
|
|
16
|
+
const plan = await readTxPlanArtifact(planPath);
|
|
17
|
+
const receipt = await readTxReceiptArtifact(receiptPath);
|
|
18
|
+
const state = await loadOrCreateLocalnetState();
|
|
19
|
+
const report = verifyReplay(state, plan, receipt);
|
|
20
|
+
console.log(` Workflow: ${report.checks.workflowDeterministic === "reproduced" ? pc.green("\u2713 REPRODUCED") : pc.red("\u2717 DIVERGED")}`);
|
|
21
|
+
console.log(` Consensus: ${pc.yellow("- UNIMPLEMENTED")} (HardKAS does not validate network consensus)`);
|
|
22
|
+
console.log(` L2 Logic: ${pc.yellow("- UNIMPLEMENTED")} (HardKAS does not validate bridge protocol)`);
|
|
23
|
+
console.log("");
|
|
24
|
+
if (report.invariantsOk) {
|
|
25
|
+
UI.success("Artifact workflow is deterministic.");
|
|
26
|
+
console.log(` Plan Hash: \u2713 MATCH`);
|
|
27
|
+
console.log(` Semantic Diff: \u2713 NO CHANGES`);
|
|
28
|
+
} else {
|
|
29
|
+
UI.error("Replay Verification Failed");
|
|
30
|
+
if (report.divergences.length > 0) {
|
|
31
|
+
console.log(pc.bold("\n Divergences found:"));
|
|
32
|
+
for (const div of report.divergences) {
|
|
33
|
+
console.log(` ${pc.cyan(div.path)}:`);
|
|
34
|
+
console.log(` Expected: ${pc.green(JSON.stringify(div.expected))}`);
|
|
35
|
+
console.log(` Actual: ${pc.red(JSON.stringify(div.actual))}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (report.errors.length > 0 && report.divergences.length === 0) {
|
|
39
|
+
report.errors.forEach((err) => console.log(` [!] ${err}`));
|
|
40
|
+
}
|
|
41
|
+
process.exitCode = 1;
|
|
42
|
+
}
|
|
43
|
+
} catch (e) {
|
|
44
|
+
UI.error(`Failed to perform replay verification: ${e.message}`);
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
runReplayVerify
|
|
50
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
UI
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-K7XPWWIO.js";
|
|
4
4
|
|
|
5
5
|
// src/runners/tx-verify-runner.ts
|
|
6
|
-
import { readTxPlanArtifact } from "@hardkas/artifacts";
|
|
6
|
+
import { readTxPlanArtifact, verifyArtifactIntegrity } from "@hardkas/artifacts";
|
|
7
7
|
import { verifyTxPlanSemantics } from "@hardkas/tx-builder";
|
|
8
8
|
import { formatSompi } from "@hardkas/core";
|
|
9
9
|
import path from "path";
|
|
@@ -12,6 +12,15 @@ async function runTxVerify(options) {
|
|
|
12
12
|
UI.header(`Transaction Verification: ${path.basename(options.path)}`);
|
|
13
13
|
try {
|
|
14
14
|
const artifact = await readTxPlanArtifact(absolutePath);
|
|
15
|
+
const integrityResult = await verifyArtifactIntegrity(absolutePath);
|
|
16
|
+
if (!integrityResult.ok) {
|
|
17
|
+
UI.error("INTEGRITY VERIFICATION FAILED");
|
|
18
|
+
integrityResult.issues.forEach((issue) => {
|
|
19
|
+
console.log(` [!] [${issue.code}] ${issue.message}`);
|
|
20
|
+
});
|
|
21
|
+
process.exitCode = 1;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
15
24
|
const result = verifyTxPlanSemantics(artifact);
|
|
16
25
|
if (options.json) {
|
|
17
26
|
console.log(JSON.stringify(result, (key, value) => typeof value === "bigint" ? value.toString() : value, 2));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardkas/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-alpha",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -13,22 +13,24 @@
|
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"commander": "^12.1.0",
|
|
15
15
|
"enquirer": "^2.4.1",
|
|
16
|
+
"execa": "^9.5.2",
|
|
16
17
|
"picocolors": "^1.1.1",
|
|
17
18
|
"zod": "^3.23.8",
|
|
18
|
-
"@hardkas/accounts": "0.
|
|
19
|
-
"@hardkas/artifacts": "0.
|
|
20
|
-
"@hardkas/config": "0.
|
|
21
|
-
"@hardkas/core": "0.
|
|
22
|
-
"@hardkas/
|
|
23
|
-
"@hardkas/l2": "0.
|
|
24
|
-
"@hardkas/
|
|
25
|
-
"@hardkas/
|
|
26
|
-
"@hardkas/
|
|
27
|
-
"@hardkas/node-
|
|
28
|
-
"@hardkas/query-store": "0.
|
|
29
|
-
"@hardkas/
|
|
30
|
-
"@hardkas/simulator": "0.
|
|
31
|
-
"@hardkas/
|
|
19
|
+
"@hardkas/accounts": "0.3.0-alpha",
|
|
20
|
+
"@hardkas/artifacts": "0.3.0-alpha",
|
|
21
|
+
"@hardkas/config": "0.3.0-alpha",
|
|
22
|
+
"@hardkas/core": "0.3.0-alpha",
|
|
23
|
+
"@hardkas/query": "0.3.0-alpha",
|
|
24
|
+
"@hardkas/l2": "0.3.0-alpha",
|
|
25
|
+
"@hardkas/kaspa-rpc": "0.3.0-alpha",
|
|
26
|
+
"@hardkas/node-orchestrator": "0.3.0-alpha",
|
|
27
|
+
"@hardkas/localnet": "0.3.0-alpha",
|
|
28
|
+
"@hardkas/node-runner": "0.3.0-alpha",
|
|
29
|
+
"@hardkas/query-store": "0.3.0-alpha",
|
|
30
|
+
"@hardkas/sdk": "0.3.0-alpha",
|
|
31
|
+
"@hardkas/simulator": "0.3.0-alpha",
|
|
32
|
+
"@hardkas/testing": "0.3.0-alpha",
|
|
33
|
+
"@hardkas/tx-builder": "0.3.0-alpha"
|
|
32
34
|
},
|
|
33
35
|
"devDependencies": {
|
|
34
36
|
"tsup": "^8.3.5",
|
|
@@ -52,7 +54,11 @@
|
|
|
52
54
|
"dev": "tsx src/index.ts",
|
|
53
55
|
"hardkas": "tsx src/index.ts",
|
|
54
56
|
"typecheck": "tsc --noEmit",
|
|
57
|
+
"docs:generate-cli": "tsx src/scripts/generate-cli-docs.ts",
|
|
58
|
+
"docs:check-cli": "tsx src/scripts/generate-cli-docs.ts --check",
|
|
55
59
|
"test": "vitest run",
|
|
60
|
+
"test:docs": "tsx test/docs-drift.node.ts",
|
|
61
|
+
"test:examples": "node --import tsx --test test/examples-acceptance.node.ts",
|
|
56
62
|
"lint": "eslint ."
|
|
57
63
|
}
|
|
58
64
|
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
UI
|
|
3
|
-
} from "./chunk-AQWQW5ZG.js";
|
|
4
|
-
|
|
5
|
-
// src/runners/accounts-keystore-runners.ts
|
|
6
|
-
import path from "path";
|
|
7
|
-
import enquirer from "enquirer";
|
|
8
|
-
import { KeystoreManager } from "@hardkas/accounts";
|
|
9
|
-
var { Password } = enquirer;
|
|
10
|
-
async function runAccountsKeystoreImport(options) {
|
|
11
|
-
const name = options.name || "default";
|
|
12
|
-
const address = options.address;
|
|
13
|
-
const privateKey = options.privateKey;
|
|
14
|
-
if (!options.encrypted) {
|
|
15
|
-
throw new Error("Plaintext import is handled by runAccountsRealImport. Use --encrypted for this runner.");
|
|
16
|
-
}
|
|
17
|
-
UI.warning("HardKAS encrypted keystore is for local developer workflows, not institutional custody.");
|
|
18
|
-
UI.info("Do not import mainnet keys unless you fully understand the risks.");
|
|
19
|
-
if (!address || !privateKey) {
|
|
20
|
-
throw new Error("Address and private key are required for import.");
|
|
21
|
-
}
|
|
22
|
-
const passwordPrompt = new Password({
|
|
23
|
-
name: "password",
|
|
24
|
-
message: "Enter keystore password:"
|
|
25
|
-
});
|
|
26
|
-
const password = await passwordPrompt.run();
|
|
27
|
-
if (!password) {
|
|
28
|
-
throw new Error("Password cannot be empty.");
|
|
29
|
-
}
|
|
30
|
-
const confirmPrompt = new Password({
|
|
31
|
-
name: "confirm",
|
|
32
|
-
message: "Confirm keystore password:"
|
|
33
|
-
});
|
|
34
|
-
const confirm = await confirmPrompt.run();
|
|
35
|
-
if (password !== confirm) {
|
|
36
|
-
throw new Error("Passwords do not match.");
|
|
37
|
-
}
|
|
38
|
-
const keystore = await KeystoreManager.createEncryptedKeystore(
|
|
39
|
-
{
|
|
40
|
-
address,
|
|
41
|
-
privateKey,
|
|
42
|
-
network: "devnet"
|
|
43
|
-
// Default for now
|
|
44
|
-
},
|
|
45
|
-
password,
|
|
46
|
-
{
|
|
47
|
-
label: name,
|
|
48
|
-
network: "devnet"
|
|
49
|
-
}
|
|
50
|
-
);
|
|
51
|
-
const keystoreDir = path.join(process.cwd(), ".hardkas", "keystore");
|
|
52
|
-
const filePath = path.join(keystoreDir, `${name}.json`);
|
|
53
|
-
await KeystoreManager.saveEncryptedKeystore(filePath, keystore);
|
|
54
|
-
return {
|
|
55
|
-
success: true,
|
|
56
|
-
name,
|
|
57
|
-
path: filePath,
|
|
58
|
-
formatted: `Successfully imported and encrypted account '${name}' to ${filePath}`
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
async function runAccountsKeystoreUnlock(options) {
|
|
62
|
-
const { name } = options;
|
|
63
|
-
const filePath = path.join(process.cwd(), ".hardkas", "keystore", `${name}.json`);
|
|
64
|
-
const keystore = await KeystoreManager.loadEncryptedKeystore(filePath);
|
|
65
|
-
const passwordPrompt = new Password({
|
|
66
|
-
name: "password",
|
|
67
|
-
message: `Enter password for account '${name}':`
|
|
68
|
-
});
|
|
69
|
-
const password = await passwordPrompt.run();
|
|
70
|
-
const result = await KeystoreManager.decryptEncryptedKeystore(keystore, password);
|
|
71
|
-
if (result.success) {
|
|
72
|
-
UI.success(`Password verified for account '${name}'.`);
|
|
73
|
-
UI.info("Unlock is session-only. Decrypted key is not persisted.");
|
|
74
|
-
} else {
|
|
75
|
-
throw new Error(result.error || "Failed to unlock keystore.");
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
async function runAccountsKeystoreChangePassword(options) {
|
|
79
|
-
const { name } = options;
|
|
80
|
-
const filePath = path.join(process.cwd(), ".hardkas", "keystore", `${name}.json`);
|
|
81
|
-
const keystore = await KeystoreManager.loadEncryptedKeystore(filePath);
|
|
82
|
-
const oldPasswordPrompt = new Password({
|
|
83
|
-
name: "old",
|
|
84
|
-
message: "Enter current password:"
|
|
85
|
-
});
|
|
86
|
-
const oldPassword = await oldPasswordPrompt.run();
|
|
87
|
-
const newPasswordPrompt = new Password({
|
|
88
|
-
name: "new",
|
|
89
|
-
message: "Enter new password:"
|
|
90
|
-
});
|
|
91
|
-
const newPassword = await newPasswordPrompt.run();
|
|
92
|
-
const confirmPrompt = new Password({
|
|
93
|
-
name: "confirm",
|
|
94
|
-
message: "Confirm new password:"
|
|
95
|
-
});
|
|
96
|
-
const confirm = await confirmPrompt.run();
|
|
97
|
-
if (newPassword !== confirm) {
|
|
98
|
-
throw new Error("New passwords do not match.");
|
|
99
|
-
}
|
|
100
|
-
const updatedKeystore = await KeystoreManager.changeKeystorePassword(
|
|
101
|
-
keystore,
|
|
102
|
-
oldPassword,
|
|
103
|
-
newPassword
|
|
104
|
-
);
|
|
105
|
-
await KeystoreManager.saveEncryptedKeystore(filePath, updatedKeystore);
|
|
106
|
-
UI.success(`Successfully changed password for account '${name}'.`);
|
|
107
|
-
}
|
|
108
|
-
export {
|
|
109
|
-
runAccountsKeystoreChangePassword,
|
|
110
|
-
runAccountsKeystoreImport,
|
|
111
|
-
runAccountsKeystoreUnlock
|
|
112
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
UI
|
|
3
|
-
} from "./chunk-AQWQW5ZG.js";
|
|
4
|
-
|
|
5
|
-
// src/runners/replay-verify-runner.ts
|
|
6
|
-
import { readTxPlanArtifact, readTxReceiptArtifact } from "@hardkas/artifacts";
|
|
7
|
-
import { loadOrCreateLocalnetState, verifyReplay } from "@hardkas/localnet";
|
|
8
|
-
import path from "path";
|
|
9
|
-
async function runReplayVerify(options) {
|
|
10
|
-
const artifactDir = path.resolve(process.cwd(), options.path);
|
|
11
|
-
const planPath = path.join(artifactDir, "tx-plan.json");
|
|
12
|
-
const receiptPath = path.join(artifactDir, "tx-receipt.json");
|
|
13
|
-
UI.header(`Replay Verification: ${path.basename(artifactDir)}`);
|
|
14
|
-
try {
|
|
15
|
-
const plan = await readTxPlanArtifact(planPath);
|
|
16
|
-
const receipt = await readTxReceiptArtifact(receiptPath);
|
|
17
|
-
const state = await loadOrCreateLocalnetState();
|
|
18
|
-
const report = verifyReplay(state, plan, receipt);
|
|
19
|
-
if (report.invariantsOk) {
|
|
20
|
-
UI.success("Replay Verified Successfully");
|
|
21
|
-
console.log(` Plan Hash: \u2713 MATCH`);
|
|
22
|
-
console.log(` State Hashes: \u2713 MATCH`);
|
|
23
|
-
console.log(` Mass/Fees: \u2713 MATCH`);
|
|
24
|
-
console.log(` Status: \u2713 MATCH`);
|
|
25
|
-
} else {
|
|
26
|
-
UI.error("Replay Verification Failed");
|
|
27
|
-
report.errors.forEach((err) => console.log(` [!] ${err}`));
|
|
28
|
-
process.exitCode = 1;
|
|
29
|
-
}
|
|
30
|
-
} catch (e) {
|
|
31
|
-
UI.error(`Failed to perform replay verification: ${e.message}`);
|
|
32
|
-
process.exitCode = 1;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
export {
|
|
36
|
-
runReplayVerify
|
|
37
|
-
};
|