@hardkas/cli 0.2.2-alpha.1 → 0.4.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.
Files changed (26) hide show
  1. package/dist/accounts-keystore-runners-QYSNZMZV.js +155 -0
  2. package/dist/{artifact-lineage-runner-RJWQ3R3X.js → artifact-lineage-runner-TY4YTE6H.js} +6 -2
  3. package/dist/bridge-local-runner-E3LICYYX.js +174 -0
  4. package/dist/{chunk-AQWQW5ZG.js → chunk-K7XPWWIO.js} +45 -1
  5. package/dist/chunk-KA5CAWI2.js +163 -0
  6. package/dist/chunk-ZM2NBOAE.js +37 -0
  7. package/dist/{dag-runners-YQDHD7U6.js → dag-runners-NLBYR7I7.js} +2 -2
  8. package/dist/deployment-runners-GEICABEH.js +15 -0
  9. package/dist/dev-doctor-runner-LTSENPQ3.js +145 -0
  10. package/dist/dev-server-runner-IM5DCDD3.js +45 -0
  11. package/dist/index.js +2145 -560
  12. package/dist/kaspa-doctor-runner-F2ISPABM.js +81 -0
  13. package/dist/kaspa-wallet-runner-ORJ5YFKU.js +179 -0
  14. package/dist/local-wizard-runner-GCAWGZ6D.js +144 -0
  15. package/dist/metamask-runner-PRIOW4J3.js +132 -0
  16. package/dist/replay-verify-runner-Y3RARVD7.js +50 -0
  17. package/dist/{rpc-doctor-runner-ERWXOXSE.js → rpc-doctor-runner-V7H7AAX4.js} +1 -1
  18. package/dist/session-runner-LDSGDP47.js +118 -0
  19. package/dist/{snapshot-restore-runner-QNAADGBX.js → snapshot-restore-runner-KIJNPLDV.js} +1 -1
  20. package/dist/{snapshot-verify-runner-BWRW3NUW.js → snapshot-verify-runner-PGMADWLN.js} +1 -1
  21. package/dist/{tx-verify-runner-Z5M2JDRI.js → tx-verify-runner-6EGY5ZN4.js} +11 -2
  22. package/dist/ui-SUYOHGGP.js +10 -0
  23. package/package.json +26 -15
  24. package/dist/accounts-keystore-runners-MCJIAGZ4.js +0 -112
  25. package/dist/replay-verify-runner-UMYALHNT.js +0 -37
  26. package/dist/ui-OVK5PX6H.js +0 -8
@@ -0,0 +1,81 @@
1
+ import {
2
+ handleError
3
+ } from "./chunk-K7XPWWIO.js";
4
+
5
+ // src/runners/kaspa-doctor-runner.ts
6
+ import pc from "picocolors";
7
+ async function runKaspaDoctor(options) {
8
+ const checks = [];
9
+ let finalStatus = "ready";
10
+ try {
11
+ const { JsonWrpcKaspaClient } = await import("@hardkas/kaspa-rpc");
12
+ const client = new JsonWrpcKaspaClient({ rpcUrl: options.rpcUrl, timeoutMs: 3e3 });
13
+ try {
14
+ const info = await client.getInfo();
15
+ checks.push({ name: "RPC Reachability", status: "success", message: `Connected to kaspad ${info.serverVersion || ""}` });
16
+ if (info.isSynced) {
17
+ checks.push({ name: "Sync Status", status: "success", message: "Node is synced" });
18
+ } else {
19
+ checks.push({ name: "Sync Status", status: "warning", message: "Node is still syncing" });
20
+ if (finalStatus === "ready") finalStatus = "warning";
21
+ }
22
+ if (info.isUtxoIndexed) {
23
+ checks.push({ name: "UTXO Index", status: "success", message: "Indexed and searchable" });
24
+ } else {
25
+ checks.push({ name: "UTXO Index", status: "error", message: "UTXO index disabled (required for wallet balance/send)" });
26
+ finalStatus = "failed";
27
+ }
28
+ try {
29
+ const dag = await client.getBlockDagInfo();
30
+ checks.push({ name: "DAG Status", status: "success", message: `Network: ${dag.networkId}, DAA Score: ${dag.virtualDaaScore}` });
31
+ } catch (e) {
32
+ checks.push({ name: "DAG Status", status: "error", message: `Failed to fetch DAG info: ${e.message}` });
33
+ finalStatus = "failed";
34
+ }
35
+ try {
36
+ const mempoolSize = info.mempoolSize ?? 0;
37
+ checks.push({ name: "Mempool", status: "success", message: `${mempoolSize} transactions pending` });
38
+ } catch (e) {
39
+ }
40
+ } catch (e) {
41
+ checks.push({ name: "RPC Reachability", status: "error", message: `Failed to connect: ${e.message}` });
42
+ finalStatus = "failed";
43
+ }
44
+ if (options.json) {
45
+ const result = {
46
+ schema: "hardkas.kaspaDoctor.v1",
47
+ status: finalStatus,
48
+ checks
49
+ };
50
+ console.log(JSON.stringify(result, null, 2));
51
+ if (finalStatus === "failed") process.exitCode = 1;
52
+ return;
53
+ }
54
+ console.log(pc.bold("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
55
+ console.log(pc.bold(`HardKAS \u2022 Kaspa Doctor (L1)`));
56
+ console.log(pc.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
57
+ for (const check of checks) {
58
+ const icon = check.status === "success" ? pc.green("\u2713") : check.status === "warning" ? pc.yellow("\u26A0") : pc.red("\u2717");
59
+ console.log(`${icon} ${pc.bold(check.name)}: ${check.message}`);
60
+ }
61
+ console.log(pc.bold("\nStatus: ") + (finalStatus === "ready" ? pc.green("READY") : finalStatus === "warning" ? pc.yellow("WARNING") : pc.red("FAILED")));
62
+ if (finalStatus === "failed") {
63
+ console.log(`
64
+ ${pc.red("Fix recommendations:")}`);
65
+ if (checks.some((c) => c.name === "RPC Reachability" && c.status === "error")) {
66
+ console.log(` - Ensure kaspad is running with ${pc.white("--rpclisten-json")}.`);
67
+ console.log(` - Check if the port ${pc.white("16110")} is open.`);
68
+ }
69
+ if (checks.some((c) => c.name === "UTXO Index" && c.status === "error")) {
70
+ console.log(` - Start kaspad with ${pc.white("--utxoindex")}.`);
71
+ }
72
+ process.exitCode = 1;
73
+ }
74
+ } catch (e) {
75
+ process.exitCode = 1;
76
+ handleError(e);
77
+ }
78
+ }
79
+ export {
80
+ runKaspaDoctor
81
+ };
@@ -0,0 +1,179 @@
1
+ import {
2
+ UI,
3
+ handleError
4
+ } from "./chunk-K7XPWWIO.js";
5
+
6
+ // src/runners/kaspa-wallet-runner.ts
7
+ import pc from "picocolors";
8
+ import { loadHardkasConfig } from "@hardkas/config";
9
+ async function runKaspaWalletCreate(name, options) {
10
+ try {
11
+ const { createLocalKaspaWallet } = await import("@hardkas/accounts");
12
+ console.log(pc.bold("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
13
+ console.log(pc.bold(`HardKAS \u2022 Kaspa Wallet Creation`));
14
+ console.log(pc.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
15
+ const wallet = await createLocalKaspaWallet({ networkId: options.network });
16
+ console.log(` ${pc.green("\u2713")} New Kaspa L1 wallet generated:`);
17
+ console.log(` Name: ${pc.white(name)}`);
18
+ console.log(` Address: ${pc.white(wallet.address)}`);
19
+ console.log(` Network: ${pc.white(options.network)}`);
20
+ console.log(`
21
+ ${pc.yellow("Action Required:")} Add this to your ${pc.white("hardkas.config.ts")}:`);
22
+ console.log(pc.gray(" ----------------------------------------"));
23
+ console.log(pc.white(` accounts: {`));
24
+ console.log(pc.white(` ${name}: {`));
25
+ console.log(pc.white(` kind: "kaspa-private-key",`));
26
+ console.log(pc.white(` address: "${wallet.address}",`));
27
+ console.log(pc.white(` privateKeyEnv: "${name.toUpperCase()}_PRIVATE_KEY"`));
28
+ console.log(pc.white(` }`));
29
+ console.log(pc.white(` }`));
30
+ console.log(pc.gray(" ----------------------------------------"));
31
+ console.log(`
32
+ ${pc.dim("Set your private key in .env:")}`);
33
+ console.log(` ${name.toUpperCase()}_PRIVATE_KEY=${wallet.privateKey}
34
+ `);
35
+ console.log(`${pc.dim("HardKAS never auto-writes secrets for your protection.")}`);
36
+ } catch (e) {
37
+ handleError(e);
38
+ }
39
+ }
40
+ async function runKaspaWalletList(options) {
41
+ try {
42
+ const config = await loadHardkasConfig();
43
+ const { listHardkasAccounts } = await import("@hardkas/accounts");
44
+ const accounts = listHardkasAccounts(config.config).filter((a) => a.kind === "kaspa-private-key" || a.kind === "simulated");
45
+ if (options.json) {
46
+ console.log(JSON.stringify(accounts, null, 2));
47
+ return;
48
+ }
49
+ console.log(pc.bold("\nLocal Kaspa Wallets"));
50
+ console.log(pc.dim("----------------------------------------"));
51
+ for (const acc of accounts) {
52
+ console.log(`${pc.white(acc.name.padEnd(12))} ${pc.cyan(acc.address?.padEnd(40))} ${pc.dim(`(${acc.kind})`)}`);
53
+ }
54
+ console.log("");
55
+ } catch (e) {
56
+ handleError(e);
57
+ }
58
+ }
59
+ async function runKaspaWalletAddress(name) {
60
+ try {
61
+ const config = await loadHardkasConfig();
62
+ const { resolveHardkasAccountAddress } = await import("@hardkas/accounts");
63
+ const address = resolveHardkasAccountAddress(name, config.config);
64
+ console.log(address);
65
+ } catch (e) {
66
+ handleError(e);
67
+ process.exitCode = 1;
68
+ }
69
+ }
70
+ async function runKaspaWalletBalance(name, options) {
71
+ try {
72
+ const config = await loadHardkasConfig();
73
+ const { resolveHardkasAccountAddress } = await import("@hardkas/accounts");
74
+ const { JsonWrpcKaspaClient } = await import("@hardkas/kaspa-rpc");
75
+ const address = resolveHardkasAccountAddress(name, config.config);
76
+ const client = new JsonWrpcKaspaClient({ rpcUrl: options.rpcUrl });
77
+ const balance = await client.getBalanceByAddress(address);
78
+ if (options.json) {
79
+ console.log(JSON.stringify(balance, (k, v) => typeof v === "bigint" ? v.toString() : v, 2));
80
+ return;
81
+ }
82
+ console.log(`
83
+ Wallet: ${pc.white(name)}`);
84
+ console.log(`Address: ${pc.dim(address)}`);
85
+ console.log(`Balance: ${pc.green(Number(balance.balanceSompi) / 1e8)} KAS
86
+ `);
87
+ } catch (e) {
88
+ handleError(e);
89
+ process.exitCode = 1;
90
+ }
91
+ }
92
+ async function runKaspaWalletSend(from, to, options) {
93
+ try {
94
+ const config = await loadHardkasConfig();
95
+ const { resolveHardkasAccount, resolveHardkasAccountAddress } = await import("@hardkas/accounts");
96
+ const { JsonWrpcKaspaClient } = await import("@hardkas/kaspa-rpc");
97
+ const { buildPaymentPlan } = await import("@hardkas/tx-builder");
98
+ const { signTxPlanArtifact } = await import("@hardkas/accounts");
99
+ const { HARDKAS_VERSION } = await import("@hardkas/artifacts");
100
+ const sender = resolveHardkasAccount({ nameOrAddress: from, config: config.config });
101
+ const targetAddress = resolveHardkasAccountAddress(to, config.config);
102
+ const amountSompi = BigInt(Math.floor(parseFloat(options.amount) * 1e8));
103
+ const client = new JsonWrpcKaspaClient({ rpcUrl: options.rpcUrl });
104
+ const utxos = await client.getUtxosByAddress(sender.address);
105
+ const plan = buildPaymentPlan({
106
+ fromAddress: sender.address,
107
+ outputs: [{ address: targetAddress, amountSompi }],
108
+ availableUtxos: utxos.map((u) => ({
109
+ outpoint: u.outpoint,
110
+ address: u.address,
111
+ amountSompi: u.amountSompi,
112
+ scriptPublicKey: u.scriptPublicKey || ""
113
+ })),
114
+ feeRateSompiPerMass: 1n,
115
+ // Default 1 sompi/mass
116
+ changeAddress: sender.address
117
+ });
118
+ console.log(pc.bold("\nTransaction Plan"));
119
+ console.log(pc.dim("----------------------------------------"));
120
+ console.log(`From: ${pc.white(from)} (${sender.address})`);
121
+ console.log(`To: ${pc.white(to)} (${targetAddress})`);
122
+ console.log(`Amount: ${pc.green(Number(amountSompi) / 1e8)} KAS`);
123
+ console.log(`Fee: ${pc.yellow(Number(plan.estimatedFeeSompi) / 1e8)} KAS`);
124
+ console.log(`Mass: ${plan.estimatedMass}`);
125
+ console.log(`Inputs: ${plan.inputs.length} UTXOs`);
126
+ console.log(pc.dim("----------------------------------------\n"));
127
+ if (options.dryRun) {
128
+ console.log(pc.blue("Dry-run mode: Transaction NOT signed or broadcast.\n"));
129
+ return;
130
+ }
131
+ const confirm = await UI.confirm(`Proceed with signing and broadcasting this transaction?`);
132
+ if (!confirm) {
133
+ console.log(pc.red("Cancelled.\n"));
134
+ return;
135
+ }
136
+ const planArtifact = {
137
+ schema: "hardkas.txPlan",
138
+ planId: `plan-${Date.now()}`,
139
+ hardkasVersion: HARDKAS_VERSION,
140
+ version: "1.0.0-alpha",
141
+ networkId: config.config.networkId || config.config.defaultNetwork || "simnet",
142
+ mode: sender.kind === "simulated" ? "simulated" : "real",
143
+ from: { address: sender.address },
144
+ to: { address: targetAddress },
145
+ amountSompi,
146
+ inputs: plan.inputs,
147
+ outputs: plan.outputs,
148
+ change: plan.change,
149
+ estimatedFeeSompi: plan.estimatedFeeSompi
150
+ };
151
+ const signedArtifact = await signTxPlanArtifact({
152
+ planArtifact,
153
+ account: sender,
154
+ config: config.config
155
+ });
156
+ console.log(` ${pc.green("\u2713")} Transaction signed.`);
157
+ const submitResult = await client.submitTransaction(signedArtifact.signedTransaction.payload);
158
+ if (submitResult.accepted) {
159
+ console.log(` ${pc.green("\u2713")} Transaction accepted by node.`);
160
+ console.log(` TXID: ${pc.bold(pc.white(submitResult.transactionId))}
161
+ `);
162
+ } else {
163
+ console.log(` ${pc.red("\u2717")} Transaction rejected by node.`);
164
+ console.log(` Details: ${JSON.stringify(submitResult.raw)}
165
+ `);
166
+ process.exitCode = 1;
167
+ }
168
+ } catch (e) {
169
+ handleError(e);
170
+ process.exitCode = 1;
171
+ }
172
+ }
173
+ export {
174
+ runKaspaWalletAddress,
175
+ runKaspaWalletBalance,
176
+ runKaspaWalletCreate,
177
+ runKaspaWalletList,
178
+ runKaspaWalletSend
179
+ };
@@ -0,0 +1,144 @@
1
+ import {
2
+ UI,
3
+ handleError
4
+ } from "./chunk-K7XPWWIO.js";
5
+
6
+ // src/runners/local-wizard-runner.ts
7
+ import pc from "picocolors";
8
+ import { loadHardkasConfig } from "@hardkas/config";
9
+ async function runLocalWizard(options) {
10
+ try {
11
+ const config = await loadHardkasConfig();
12
+ const networkId = config.config.networkId || config.config.defaultNetwork || "simnet";
13
+ const { getL2NetworkProfile, EvmJsonRpcClient } = await import("@hardkas/l2");
14
+ const { listHardkasAccounts } = await import("@hardkas/accounts");
15
+ if (!options.json) {
16
+ console.log(pc.bold("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
17
+ console.log(pc.bold(`HardKAS \u2022 Local Dev Wizard`));
18
+ console.log(pc.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
19
+ }
20
+ const result = {
21
+ schema: "hardkas.localWizard.v1",
22
+ step: "preflight",
23
+ status: "pending"
24
+ };
25
+ if (!options.json) console.log(`${pc.cyan(pc.bold("1. Checking Environment"))}`);
26
+ let profile;
27
+ try {
28
+ profile = await getL2NetworkProfile({
29
+ name: options.profile,
30
+ userProfiles: config.config.l2?.networks,
31
+ cliOverrides: {
32
+ rpcUrl: options.rpcUrl || (networkId === "simnet" || networkId === "localnet" ? "http://127.0.0.1:8545" : void 0),
33
+ chainId: networkId === "simnet" || networkId === "localnet" ? 19416 : void 0
34
+ }
35
+ });
36
+ const client2 = new EvmJsonRpcClient({ url: profile.rpcUrl, timeoutMs: 2e3 });
37
+ await client2.getBlockNumber();
38
+ if (!options.json) console.log(` ${pc.green("\u2713")} Igra RPC is reachable (${profile.rpcUrl})`);
39
+ } catch (e) {
40
+ if (!options.json) {
41
+ console.log(` ${pc.red("\u2717")} Igra RPC is unreachable.`);
42
+ console.log(` ${pc.dim("Please start your local node first.")}`);
43
+ }
44
+ result.status = "failed";
45
+ result.suggestion = "Start local Igra node";
46
+ if (options.json) console.log(JSON.stringify(result, null, 2));
47
+ return;
48
+ }
49
+ result.step = "accounts";
50
+ if (!options.json) console.log(`
51
+ ${pc.cyan(pc.bold("2. Checking Accounts"))}`);
52
+ const accounts = listHardkasAccounts(config.config);
53
+ let targetAccount = accounts.find((a) => a.name === options.account && a.kind === "evm-private-key");
54
+ if (!targetAccount) {
55
+ if (options.nonInteractive) {
56
+ result.status = "failed";
57
+ result.suggestion = `Account "${options.account}" missing. Run in interactive mode to generate.`;
58
+ if (options.json) console.log(JSON.stringify(result, null, 2));
59
+ else console.log(` ${pc.red("\u2717")} Account missing (non-interactive mode).`);
60
+ return;
61
+ }
62
+ if (!options.json) console.log(` ${pc.yellow("\u26A0")} No EVM account named "${options.account}" found.`);
63
+ const confirm = await UI.confirm(`Would you like to generate a new local EVM account for "${options.account}"?`);
64
+ if (confirm) {
65
+ const { generatePrivateKey, privateKeyToAccount } = await import("viem/accounts");
66
+ const privKey = generatePrivateKey();
67
+ const account = privateKeyToAccount(privKey);
68
+ if (!options.json) {
69
+ console.log(`
70
+ ${pc.bgYellow(pc.black(pc.bold(" SECURITY ACTION: PRIVATE KEY GENERATED ")))}`);
71
+ console.log(` ${pc.yellow("This key is for LOCAL DEVELOPMENT ONLY. Never use it for real assets.")}
72
+ `);
73
+ console.log(` ${pc.green("\u2713")} New account generated:`);
74
+ console.log(` Name: ${pc.white(options.account)}`);
75
+ console.log(` Address: ${pc.white(account.address)}`);
76
+ console.log(`
77
+ ${pc.yellow("Action Required:")} Add this to your ${pc.white("hardkas.config.ts")}:`);
78
+ console.log(pc.gray(" ----------------------------------------"));
79
+ console.log(pc.white(` accounts: {`));
80
+ console.log(pc.white(` ${options.account}: {`));
81
+ console.log(pc.white(` kind: "evm-private-key",`));
82
+ console.log(pc.white(` address: "${account.address}",`));
83
+ console.log(pc.white(` privateKey: "${privKey}"`));
84
+ console.log(pc.white(` }`));
85
+ console.log(pc.white(` }`));
86
+ console.log(pc.gray(" ----------------------------------------"));
87
+ console.log(`
88
+ ${pc.dim("HardKAS does not automatically write secrets to your config for safety.")}`);
89
+ console.log(` ${pc.dim("Please update your config and run the wizard again to finish setup.")}`);
90
+ }
91
+ result.status = "pending";
92
+ result.accountCreated = true;
93
+ result.suggestion = "Update hardkas.config.ts with generated key";
94
+ if (options.json) console.log(JSON.stringify(result, null, 2));
95
+ return;
96
+ } else {
97
+ if (!options.json) console.log(` ${pc.red("\u2717")} Setup cancelled.`);
98
+ result.status = "failed";
99
+ if (options.json) console.log(JSON.stringify(result, null, 2));
100
+ return;
101
+ }
102
+ } else {
103
+ if (!options.json) console.log(` ${pc.green("\u2713")} Account "${targetAccount.name}" found (${targetAccount.address})`);
104
+ }
105
+ result.step = "balance";
106
+ if (!options.json) console.log(`
107
+ ${pc.cyan(pc.bold("3. Checking Balance"))}`);
108
+ const client = new EvmJsonRpcClient({ url: profile.rpcUrl });
109
+ const balance = await client.getBalanceWei(targetAccount.address);
110
+ const kasBalance = Number(balance) / 1e18;
111
+ if (kasBalance === 0) {
112
+ if (!options.json) {
113
+ console.log(` ${pc.yellow("\u26A0")} Account has 0 iKAS.`);
114
+ console.log(` ${pc.dim("Please fund your account manually or via local faucet.")}`);
115
+ }
116
+ result.status = "failed";
117
+ result.suggestion = "Fund local account";
118
+ } else {
119
+ if (!options.json) console.log(` ${pc.green("\u2713")} Balance: ${kasBalance} iKAS`);
120
+ }
121
+ result.status = kasBalance > 0 ? "success" : "failed";
122
+ if (options.json) {
123
+ console.log(JSON.stringify(result, null, 2));
124
+ return;
125
+ }
126
+ if (result.status === "success") {
127
+ console.log(`
128
+ ${pc.cyan(pc.bold("4. MetaMask Onboarding"))}`);
129
+ console.log(` ${pc.dim("To add this network to MetaMask, run:")}`);
130
+ console.log(` ${pc.white("hardkas metamask snippet")}`);
131
+ console.log(`
132
+ ${pc.bold(pc.green("READY!"))} Local environment is set up.`);
133
+ console.log(`
134
+ ${pc.cyan("Final step:")} Import your account into MetaMask:`);
135
+ console.log(` hardkas metamask account ${pc.white(options.account)} --show-private-key
136
+ `);
137
+ }
138
+ } catch (e) {
139
+ handleError(e);
140
+ }
141
+ }
142
+ export {
143
+ runLocalWizard
144
+ };
@@ -0,0 +1,132 @@
1
+ import {
2
+ handleError
3
+ } from "./chunk-K7XPWWIO.js";
4
+
5
+ // src/runners/metamask-runner.ts
6
+ import pc from "picocolors";
7
+ import { loadHardkasConfig } from "@hardkas/config";
8
+ async function runMetamaskNetwork(options) {
9
+ try {
10
+ const config = await loadHardkasConfig();
11
+ const networkId = config.config.networkId || config.config.defaultNetwork || "simnet";
12
+ if (networkId === "mainnet" || networkId.startsWith("testnet")) {
13
+ throw new Error(`MetaMask onboarding is only allowed on local development networks (simnet, localnet). Current network: ${networkId}`);
14
+ }
15
+ const { getL2NetworkProfile } = await import("@hardkas/l2");
16
+ const { generateAddEthereumChainPayload } = await import("@hardkas/l2");
17
+ const profile = await getL2NetworkProfile({
18
+ name: options.profile,
19
+ userProfiles: config.config.l2?.networks,
20
+ cliOverrides: {
21
+ rpcUrl: networkId === "simnet" || networkId === "localnet" ? "http://127.0.0.1:8545" : void 0,
22
+ chainId: networkId === "simnet" || networkId === "localnet" ? 19416 : void 0
23
+ }
24
+ });
25
+ const payload = generateAddEthereumChainPayload(profile);
26
+ if (options.json) {
27
+ console.log(JSON.stringify(payload, null, 2));
28
+ return;
29
+ }
30
+ console.log(pc.bold("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
31
+ console.log(pc.bold(`HardKAS \u2022 MetaMask Network`));
32
+ console.log(pc.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
33
+ console.log(`${pc.cyan(pc.bold("Network Details"))}`);
34
+ console.log(` Name: ${pc.white(payload.chainName)}`);
35
+ console.log(` RPC URL: ${pc.white(payload.rpcUrls[0])}`);
36
+ console.log(` Chain ID: ${pc.white(parseInt(payload.chainId, 16))} (${payload.chainId})`);
37
+ console.log(` Currency: ${pc.white(payload.nativeCurrency.symbol)} (${payload.nativeCurrency.name})`);
38
+ if (payload.blockExplorerUrls) {
39
+ console.log(` Explorer: ${pc.white(payload.blockExplorerUrls[0])}`);
40
+ }
41
+ console.log(`
42
+ ${pc.yellow("To add this network to MetaMask:")}`);
43
+ console.log(` 1. Open MetaMask settings`);
44
+ console.log(` 2. Go to Networks -> Add a network -> Add a network manually`);
45
+ console.log(` 3. Fill in the details above.
46
+ `);
47
+ console.log(`${pc.dim("Alternatively, run: ")} ${pc.cyan("hardkas metamask snippet")}
48
+ `);
49
+ } catch (e) {
50
+ handleError(e);
51
+ }
52
+ }
53
+ async function runMetamaskSnippet(options) {
54
+ try {
55
+ const config = await loadHardkasConfig();
56
+ const networkId = config.config.networkId || config.config.defaultNetwork || "simnet";
57
+ if (networkId === "mainnet" || networkId.startsWith("testnet")) {
58
+ throw new Error(`MetaMask onboarding is only allowed on local development networks (simnet, localnet).`);
59
+ }
60
+ const { getL2NetworkProfile } = await import("@hardkas/l2");
61
+ const { generateMetaMaskSnippet } = await import("@hardkas/l2");
62
+ const profile = await getL2NetworkProfile({
63
+ name: options.profile,
64
+ userProfiles: config.config.l2?.networks,
65
+ cliOverrides: {
66
+ rpcUrl: networkId === "simnet" || networkId === "localnet" ? "http://127.0.0.1:8545" : void 0,
67
+ chainId: networkId === "simnet" || networkId === "localnet" ? 19416 : void 0
68
+ }
69
+ });
70
+ const snippet = generateMetaMaskSnippet(profile);
71
+ console.log(pc.bold("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
72
+ console.log(pc.bold(`HardKAS \u2022 MetaMask Snippet`));
73
+ console.log(pc.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
74
+ console.log(`${pc.yellow("Copy and paste this snippet into your browser console while MetaMask is open:")}
75
+ `);
76
+ console.log(pc.gray("```javascript"));
77
+ console.log(pc.white(snippet));
78
+ console.log(pc.gray("```\n"));
79
+ } catch (e) {
80
+ handleError(e);
81
+ }
82
+ }
83
+ async function runMetamaskAccount(name, options) {
84
+ try {
85
+ const config = await loadHardkasConfig();
86
+ const { resolveHardkasAccount, prepareEvmAccountExport } = await import("@hardkas/accounts");
87
+ const account = resolveHardkasAccount({ nameOrAddress: name, config: config.config });
88
+ const networkId = config.config.networkId || config.config.defaultNetwork || "simnet";
89
+ const includeSecretRequested = options.json ? options.includeSecret && options.showPrivateKey : options.showPrivateKey;
90
+ const exportData = await prepareEvmAccountExport(account, networkId, {
91
+ includeSecret: includeSecretRequested
92
+ });
93
+ if (options.json) {
94
+ if (!options.includeSecret) {
95
+ delete exportData.privateKey;
96
+ }
97
+ console.log(JSON.stringify(exportData, null, 2));
98
+ return;
99
+ }
100
+ console.log(pc.bold("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
101
+ console.log(pc.bold(`HardKAS \u2022 MetaMask Export`));
102
+ console.log(pc.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
103
+ console.log(`${pc.cyan(pc.bold("Account"))}`);
104
+ console.log(` Name: ${pc.white(name)}`);
105
+ console.log(` Address: ${pc.white(exportData.address)}`);
106
+ if (options.showPrivateKey && exportData.privateKey) {
107
+ console.log(`
108
+ ${pc.bgRed(pc.white(pc.bold(" SECURITY WARNING ")))}`);
109
+ console.log(` ${pc.red("This is a LOCAL DEV ONLY account. Never share private keys.")}
110
+ `);
111
+ console.log(` Private Key: ${pc.white(exportData.privateKey)}`);
112
+ } else {
113
+ console.log(`
114
+ Private Key: ${pc.dim("[HIDDEN]")}`);
115
+ console.log(` ${pc.dim("Run with ")} ${pc.cyan("--show-private-key")} ${pc.dim("to reveal.")}`);
116
+ }
117
+ console.log(`
118
+ ${pc.yellow("To import this account into MetaMask:")}`);
119
+ console.log(` 1. Open MetaMask`);
120
+ console.log(` 2. Click the Account menu (top right)`);
121
+ console.log(` 3. Click "Import Account"`);
122
+ console.log(` 4. Paste the private key above.
123
+ `);
124
+ } catch (e) {
125
+ handleError(e);
126
+ }
127
+ }
128
+ export {
129
+ runMetamaskAccount,
130
+ runMetamaskNetwork,
131
+ runMetamaskSnippet
132
+ };
@@ -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,6 +1,6 @@
1
1
  import {
2
2
  UI
3
- } from "./chunk-AQWQW5ZG.js";
3
+ } from "./chunk-K7XPWWIO.js";
4
4
 
5
5
  // src/runners/rpc-doctor-runner.ts
6
6
  import { KaspaJsonRpcClient } from "@hardkas/kaspa-rpc";