@hardkas/cli 0.3.0-alpha → 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.
- package/dist/bridge-local-runner-E3LICYYX.js +174 -0
- package/dist/dev-doctor-runner-LTSENPQ3.js +145 -0
- package/dist/dev-server-runner-IM5DCDD3.js +45 -0
- package/dist/index.js +168 -27
- package/dist/kaspa-doctor-runner-F2ISPABM.js +81 -0
- package/dist/kaspa-wallet-runner-ORJ5YFKU.js +179 -0
- package/dist/local-wizard-runner-GCAWGZ6D.js +144 -0
- package/dist/metamask-runner-PRIOW4J3.js +132 -0
- package/dist/session-runner-LDSGDP47.js +118 -0
- package/package.json +21 -16
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import {
|
|
2
|
+
handleError
|
|
3
|
+
} from "./chunk-K7XPWWIO.js";
|
|
4
|
+
|
|
5
|
+
// src/runners/bridge-local-runner.ts
|
|
6
|
+
import pc from "picocolors";
|
|
7
|
+
import { loadHardkasConfig } from "@hardkas/config";
|
|
8
|
+
async function runBridgeLocalPlan(options) {
|
|
9
|
+
try {
|
|
10
|
+
const config = await loadHardkasConfig();
|
|
11
|
+
const { planBridgeEntry, resolveBridgeLocalContext } = await import("@hardkas/bridge-local");
|
|
12
|
+
const { MockKaspaRpcClient } = await import("@hardkas/kaspa-rpc");
|
|
13
|
+
const ctx = await resolveBridgeLocalContext({
|
|
14
|
+
config,
|
|
15
|
+
sessionName: options.session,
|
|
16
|
+
from: options.from,
|
|
17
|
+
toIgra: options.toIgra
|
|
18
|
+
});
|
|
19
|
+
const amountSompi = BigInt(Math.floor(parseFloat(options.amount) * 1e8));
|
|
20
|
+
const rpc = new MockKaspaRpcClient();
|
|
21
|
+
rpc.setUtxos(ctx.l1.address, [
|
|
22
|
+
{
|
|
23
|
+
outpoint: { transactionId: "mock-utxo", index: 0 },
|
|
24
|
+
address: ctx.l1.address,
|
|
25
|
+
amountSompi: 100000000000n,
|
|
26
|
+
// 1000 KAS
|
|
27
|
+
scriptPublicKey: "mock-script"
|
|
28
|
+
}
|
|
29
|
+
]);
|
|
30
|
+
const utxos = await rpc.getUtxosByAddress(ctx.l1.address);
|
|
31
|
+
const plan = planBridgeEntry({
|
|
32
|
+
fromAddress: ctx.l1.address,
|
|
33
|
+
targetEvmAddress: ctx.l2.address,
|
|
34
|
+
amountSompi,
|
|
35
|
+
networkId: config.config.networkId || config.config.defaultNetwork || "simnet",
|
|
36
|
+
availableUtxos: utxos.map((u) => ({ ...u, scriptPublicKey: "", blockDaaScore: u.blockDaaScore ? BigInt(u.blockDaaScore) : void 0 }))
|
|
37
|
+
});
|
|
38
|
+
if (options.json) {
|
|
39
|
+
console.log(JSON.stringify({
|
|
40
|
+
schema: "hardkas.bridgeLocalSessionPlan.v1",
|
|
41
|
+
session: {
|
|
42
|
+
source: ctx.source,
|
|
43
|
+
name: ctx.sessionName || null
|
|
44
|
+
},
|
|
45
|
+
l1: {
|
|
46
|
+
wallet: ctx.l1.walletName,
|
|
47
|
+
address: ctx.l1.address
|
|
48
|
+
},
|
|
49
|
+
l2: {
|
|
50
|
+
account: ctx.l2.accountName || null,
|
|
51
|
+
address: ctx.l2.address
|
|
52
|
+
},
|
|
53
|
+
bridge: {
|
|
54
|
+
mode: ctx.bridgeMode,
|
|
55
|
+
amount: options.amount,
|
|
56
|
+
payload: plan.serializedPayload
|
|
57
|
+
},
|
|
58
|
+
plan
|
|
59
|
+
}, (k, v) => typeof v === "bigint" ? v.toString() : v, 2));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
printBridgeContext(ctx, options.amount, plan.serializedPayload);
|
|
63
|
+
console.log(pc.bold("Local Bridge Entry Plan"));
|
|
64
|
+
console.log(pc.dim("----------------------------------------"));
|
|
65
|
+
console.log(`Fee (est): ${pc.yellow(Number(plan.estimatedFeeSompi) / 1e8)} KAS`);
|
|
66
|
+
console.log(`Mass: ${plan.estimatedMass}`);
|
|
67
|
+
console.log(pc.dim("----------------------------------------\n"));
|
|
68
|
+
} catch (e) {
|
|
69
|
+
handleError(e);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function runBridgeLocalSimulate(options) {
|
|
73
|
+
try {
|
|
74
|
+
const config = await loadHardkasConfig();
|
|
75
|
+
const { planBridgeEntry, simulatePrefixMining, resolveBridgeLocalContext } = await import("@hardkas/bridge-local");
|
|
76
|
+
const { MockKaspaRpcClient } = await import("@hardkas/kaspa-rpc");
|
|
77
|
+
const ctx = await resolveBridgeLocalContext({
|
|
78
|
+
config,
|
|
79
|
+
sessionName: options.session,
|
|
80
|
+
from: options.from,
|
|
81
|
+
toIgra: options.toIgra
|
|
82
|
+
});
|
|
83
|
+
const amountSompi = BigInt(Math.floor(parseFloat(options.amount) * 1e8));
|
|
84
|
+
const rpc = new MockKaspaRpcClient();
|
|
85
|
+
rpc.setUtxos(ctx.l1.address, [
|
|
86
|
+
{
|
|
87
|
+
outpoint: { transactionId: "mock-utxo", index: 0 },
|
|
88
|
+
address: ctx.l1.address,
|
|
89
|
+
amountSompi: 100000000000n,
|
|
90
|
+
// 1000 KAS
|
|
91
|
+
scriptPublicKey: "mock-script"
|
|
92
|
+
}
|
|
93
|
+
]);
|
|
94
|
+
const utxos = await rpc.getUtxosByAddress(ctx.l1.address);
|
|
95
|
+
const plan = planBridgeEntry({
|
|
96
|
+
fromAddress: ctx.l1.address,
|
|
97
|
+
targetEvmAddress: ctx.l2.address,
|
|
98
|
+
amountSompi,
|
|
99
|
+
networkId: config.config.networkId || config.config.defaultNetwork || "simnet",
|
|
100
|
+
availableUtxos: utxos.map((u) => ({ ...u, scriptPublicKey: "", blockDaaScore: u.blockDaaScore ? BigInt(u.blockDaaScore) : void 0 }))
|
|
101
|
+
});
|
|
102
|
+
if (!options.json) {
|
|
103
|
+
printBridgeContext(ctx, options.amount, plan.serializedPayload);
|
|
104
|
+
console.log(pc.bold("Bridge Entry Simulation"));
|
|
105
|
+
console.log(`${pc.cyan("Step 1:")} Planning entry transaction... OK`);
|
|
106
|
+
console.log(`${pc.cyan("Step 2:")} Simulating prefix mining for prefix "${pc.white(options.prefix)}"...`);
|
|
107
|
+
}
|
|
108
|
+
const miningResult = simulatePrefixMining(plan.bridgePayload, options.prefix);
|
|
109
|
+
if (options.json) {
|
|
110
|
+
console.log(JSON.stringify({
|
|
111
|
+
schema: "hardkas.bridgeLocalSessionSimulation.v1",
|
|
112
|
+
status: "success",
|
|
113
|
+
session: {
|
|
114
|
+
source: ctx.source,
|
|
115
|
+
name: ctx.sessionName || null
|
|
116
|
+
},
|
|
117
|
+
l1: {
|
|
118
|
+
wallet: ctx.l1.walletName,
|
|
119
|
+
address: ctx.l1.address
|
|
120
|
+
},
|
|
121
|
+
l2: {
|
|
122
|
+
account: ctx.l2.accountName || null,
|
|
123
|
+
address: ctx.l2.address
|
|
124
|
+
},
|
|
125
|
+
miningResult,
|
|
126
|
+
plan
|
|
127
|
+
}, (k, v) => typeof v === "bigint" ? v.toString() : v, 2));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
console.log(` ${pc.green("\u2713")} Target found at nonce: ${pc.white(miningResult.nonce)}`);
|
|
131
|
+
console.log(` ${pc.green("\u2713")} Attempts: ${miningResult.attempts}`);
|
|
132
|
+
console.log(` ${pc.green("\u2713")} Simulated Hash: ${pc.dim(miningResult.hash)}`);
|
|
133
|
+
console.log(`
|
|
134
|
+
${pc.bold(pc.green("SUCCESS"))}: Local bridge entry simulated.`);
|
|
135
|
+
console.log(pc.yellow(pc.bold("\n\u26A0\uFE0F SIMULATION DISCLAIMER:")));
|
|
136
|
+
console.log(` - ${pc.white("NO actual bridge settlement")} occurred on L1.`);
|
|
137
|
+
console.log(` - ${pc.white("NO L2 minting")} or state change occurred on Igra.`);
|
|
138
|
+
console.log(` - ${pc.white("NO real bridge validation")} or relayer action was involved.`);
|
|
139
|
+
console.log(` - This is a ${pc.bold("deterministic local proof")} for development workflows only.
|
|
140
|
+
`);
|
|
141
|
+
} catch (e) {
|
|
142
|
+
handleError(e);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async function runBridgeLocalInspect(txid, options) {
|
|
146
|
+
try {
|
|
147
|
+
console.log(pc.bold(`
|
|
148
|
+
Inspecting Local Bridge Transaction: ${txid}`));
|
|
149
|
+
console.log(pc.dim("Feature limited in alpha: no local tx store yet."));
|
|
150
|
+
} catch (e) {
|
|
151
|
+
handleError(e);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function printBridgeContext(ctx, amount, payload) {
|
|
155
|
+
console.log(pc.bold("\nSession"));
|
|
156
|
+
console.log(` Source: ${pc.white(ctx.source)}`);
|
|
157
|
+
console.log(` Name: ${pc.white(ctx.sessionName || "none")}`);
|
|
158
|
+
console.log(pc.bold("\nKaspa L1"));
|
|
159
|
+
console.log(` Wallet: ${pc.white(ctx.l1.walletName)}`);
|
|
160
|
+
console.log(` Address: ${pc.dim(ctx.l1.address)}`);
|
|
161
|
+
console.log(pc.bold("\nIgra L2"));
|
|
162
|
+
console.log(` Account: ${pc.white(ctx.l2.accountName || "explicit")}`);
|
|
163
|
+
console.log(` Address: ${pc.dim(ctx.l2.address)}`);
|
|
164
|
+
console.log(pc.bold("\nBridge"));
|
|
165
|
+
console.log(` Mode: ${pc.white(ctx.bridgeMode)}`);
|
|
166
|
+
console.log(` Amount: ${pc.green(amount)} KAS`);
|
|
167
|
+
console.log(` Payload: ${pc.dim(payload)}`);
|
|
168
|
+
console.log("");
|
|
169
|
+
}
|
|
170
|
+
export {
|
|
171
|
+
runBridgeLocalInspect,
|
|
172
|
+
runBridgeLocalPlan,
|
|
173
|
+
runBridgeLocalSimulate
|
|
174
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {
|
|
2
|
+
handleError
|
|
3
|
+
} from "./chunk-K7XPWWIO.js";
|
|
4
|
+
|
|
5
|
+
// src/runners/dev-doctor-runner.ts
|
|
6
|
+
import pc from "picocolors";
|
|
7
|
+
import { loadHardkasConfig } from "@hardkas/config";
|
|
8
|
+
async function runDevDoctor(options) {
|
|
9
|
+
const checks = [];
|
|
10
|
+
let finalStatus = "ready";
|
|
11
|
+
const timeoutMs = options.timeout ? parseInt(options.timeout, 10) : 3e3;
|
|
12
|
+
try {
|
|
13
|
+
const config = await loadHardkasConfig();
|
|
14
|
+
const networkId = config.config.networkId || config.config.defaultNetwork || "simnet";
|
|
15
|
+
const { getL2NetworkProfile, EvmJsonRpcClient, generateAddEthereumChainPayload } = await import("@hardkas/l2");
|
|
16
|
+
const { listHardkasAccounts } = await import("@hardkas/accounts");
|
|
17
|
+
let profile;
|
|
18
|
+
try {
|
|
19
|
+
profile = await getL2NetworkProfile({
|
|
20
|
+
name: options.profile,
|
|
21
|
+
userProfiles: config.config.l2?.networks,
|
|
22
|
+
cliOverrides: {
|
|
23
|
+
rpcUrl: options.rpcUrl || (networkId === "simnet" || networkId === "localnet" ? "http://127.0.0.1:8545" : void 0),
|
|
24
|
+
chainId: networkId === "simnet" || networkId === "localnet" ? 19416 : void 0
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
} catch (e) {
|
|
28
|
+
checks.push({ name: "L2 Profile", status: "error", message: e.message });
|
|
29
|
+
finalStatus = "failed";
|
|
30
|
+
}
|
|
31
|
+
if (profile) {
|
|
32
|
+
const rpcUrl = options.rpcUrl || profile.rpcUrl;
|
|
33
|
+
if (rpcUrl) {
|
|
34
|
+
const client = new EvmJsonRpcClient({ url: rpcUrl, timeoutMs });
|
|
35
|
+
try {
|
|
36
|
+
const block = await client.getBlockNumber();
|
|
37
|
+
checks.push({ name: "Igra RPC Connectivity", status: "success", message: `Reachable (Block #${block})` });
|
|
38
|
+
} catch (e) {
|
|
39
|
+
checks.push({ name: "Igra RPC Connectivity", status: "error", message: `Unreachable: ${e.message}` });
|
|
40
|
+
finalStatus = "failed";
|
|
41
|
+
}
|
|
42
|
+
if (profile.chainId !== void 0) {
|
|
43
|
+
try {
|
|
44
|
+
const chainId = await client.getChainId();
|
|
45
|
+
if (chainId === profile.chainId) {
|
|
46
|
+
checks.push({ name: "Chain ID Verification", status: "success", message: `Matches profile (${chainId})` });
|
|
47
|
+
} else {
|
|
48
|
+
checks.push({ name: "Chain ID Verification", status: "error", message: `Mismatch: profile expects ${profile.chainId}, node reports ${chainId}` });
|
|
49
|
+
finalStatus = "failed";
|
|
50
|
+
}
|
|
51
|
+
} catch (e) {
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const gasPrice = await client.getGasPriceWei();
|
|
56
|
+
checks.push({ name: "Gas Price Check", status: "success", message: `Responds (${gasPrice.toString()} wei)` });
|
|
57
|
+
} catch (e) {
|
|
58
|
+
}
|
|
59
|
+
const accounts = listHardkasAccounts(config.config);
|
|
60
|
+
const evmAccounts = accounts.filter((a) => a.kind === "evm-private-key");
|
|
61
|
+
let targetAccount = options.account ? evmAccounts.find((a) => a.name === options.account) : evmAccounts[0];
|
|
62
|
+
if (targetAccount) {
|
|
63
|
+
checks.push({ name: "Local EVM Account", status: "success", message: `Found "${targetAccount.name}" (${targetAccount.address})` });
|
|
64
|
+
if (targetAccount.address) {
|
|
65
|
+
try {
|
|
66
|
+
const balance = await client.getBalanceWei(targetAccount.address);
|
|
67
|
+
const kasBalance = Number(balance) / 1e18;
|
|
68
|
+
if (kasBalance > 0) {
|
|
69
|
+
checks.push({ name: "Account Balance", status: "success", message: `${kasBalance} iKAS` });
|
|
70
|
+
} else {
|
|
71
|
+
checks.push({ name: "Account Balance", status: "warning", message: "Zero balance (funding required)" });
|
|
72
|
+
if (finalStatus === "ready") finalStatus = "warning";
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
checks.push({ name: "Local EVM Account", status: "warning", message: "No EVM accounts found in config/store" });
|
|
79
|
+
if (finalStatus === "ready") finalStatus = "warning";
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
generateAddEthereumChainPayload(profile);
|
|
83
|
+
checks.push({ name: "MetaMask Readiness", status: "success", message: "Payload generation OK" });
|
|
84
|
+
} catch (e) {
|
|
85
|
+
checks.push({ name: "MetaMask Readiness", status: "error", message: e.message });
|
|
86
|
+
finalStatus = "failed";
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
checks.push({ name: "RPC Configuration", status: "error", message: "No RPC URL found in profile or options" });
|
|
90
|
+
finalStatus = "failed";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (finalStatus === "failed") {
|
|
94
|
+
process.exitCode = 1;
|
|
95
|
+
}
|
|
96
|
+
if (options.json) {
|
|
97
|
+
const result = {
|
|
98
|
+
schema: "hardkas.devDoctor.v1",
|
|
99
|
+
status: finalStatus,
|
|
100
|
+
checks
|
|
101
|
+
};
|
|
102
|
+
console.log(JSON.stringify(result, null, 2));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
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"));
|
|
106
|
+
console.log(pc.bold(`HardKAS \u2022 Dev Doctor`));
|
|
107
|
+
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"));
|
|
108
|
+
for (const check of checks) {
|
|
109
|
+
const icon = check.status === "success" ? pc.green("\u2713") : check.status === "warning" ? pc.yellow("\u26A0") : pc.red("\u2717");
|
|
110
|
+
console.log(`${icon} ${pc.bold(check.name)}: ${check.message}`);
|
|
111
|
+
}
|
|
112
|
+
console.log(pc.bold("\nStatus: ") + (finalStatus === "ready" ? pc.green("READY") : finalStatus === "warning" ? pc.yellow("WARNING") : pc.red("FAILED")));
|
|
113
|
+
if (finalStatus === "ready") {
|
|
114
|
+
const accName = options.account || "alice_evm";
|
|
115
|
+
console.log(`
|
|
116
|
+
${pc.cyan("Next steps:")}`);
|
|
117
|
+
console.log(` hardkas metamask account ${pc.white(accName)} --show-private-key
|
|
118
|
+
`);
|
|
119
|
+
} else if (finalStatus === "failed") {
|
|
120
|
+
console.log(`
|
|
121
|
+
${pc.red("Fix recommendations:")}`);
|
|
122
|
+
if (checks.some((c) => c.name === "Igra RPC Connectivity" && c.status === "error")) {
|
|
123
|
+
console.log(` - Ensure your local Igra/EVM node is running on ${pc.white("http://127.0.0.1:8545")}`);
|
|
124
|
+
console.log(` - Or use ${pc.cyan("--rpc-url <url>")} to specify a different node.`);
|
|
125
|
+
}
|
|
126
|
+
if (checks.some((c) => c.name === "Chain ID Verification" && c.status === "error")) {
|
|
127
|
+
console.log(` - Your profile expect ${pc.white(profile?.chainId)}, but the node is on another network.`);
|
|
128
|
+
}
|
|
129
|
+
console.log("");
|
|
130
|
+
} else if (finalStatus === "warning") {
|
|
131
|
+
console.log(`
|
|
132
|
+
${pc.yellow("Recommendations:")}`);
|
|
133
|
+
if (checks.some((c) => c.name === "Account Balance" && c.status === "warning")) {
|
|
134
|
+
console.log(` - Fund your account: ${pc.white("hardkas wallet fund <name> --l2")}`);
|
|
135
|
+
}
|
|
136
|
+
console.log("");
|
|
137
|
+
}
|
|
138
|
+
} catch (e) {
|
|
139
|
+
process.exitCode = 1;
|
|
140
|
+
handleError(e);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
export {
|
|
144
|
+
runDevDoctor
|
|
145
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
handleError
|
|
3
|
+
} from "./chunk-K7XPWWIO.js";
|
|
4
|
+
|
|
5
|
+
// src/runners/dev-server-runner.ts
|
|
6
|
+
import pc from "picocolors";
|
|
7
|
+
async function runDevServer(options) {
|
|
8
|
+
try {
|
|
9
|
+
const { createDevServer } = await import("@hardkas/dev-server");
|
|
10
|
+
const port = parseInt(options.port, 10);
|
|
11
|
+
let host = options.host;
|
|
12
|
+
if (options.unsafeExternal && options.host === "localhost") {
|
|
13
|
+
host = "0.0.0.0";
|
|
14
|
+
}
|
|
15
|
+
if (options.json) {
|
|
16
|
+
console.log(JSON.stringify({
|
|
17
|
+
schema: "hardkas.devServer.v1",
|
|
18
|
+
status: "running",
|
|
19
|
+
url: `http://${host}:${port}`,
|
|
20
|
+
config: { port, host, unsafeExternal: options.unsafeExternal }
|
|
21
|
+
}, null, 2));
|
|
22
|
+
}
|
|
23
|
+
const server = createDevServer({
|
|
24
|
+
port,
|
|
25
|
+
host,
|
|
26
|
+
unsafeExternal: options.unsafeExternal,
|
|
27
|
+
open: options.open
|
|
28
|
+
});
|
|
29
|
+
console.log(pc.bold("\nHardKas Dev Server"));
|
|
30
|
+
console.log(pc.dim("\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
|
+
server.start();
|
|
32
|
+
console.log(pc.dim("\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"));
|
|
33
|
+
console.log(pc.yellow("LOCAL DEV ONLY"));
|
|
34
|
+
console.log(pc.dim("Press Ctrl+C to stop.\n"));
|
|
35
|
+
process.on("SIGINT", () => {
|
|
36
|
+
console.log("\nStopping Dev Server...");
|
|
37
|
+
process.exit(0);
|
|
38
|
+
});
|
|
39
|
+
} catch (e) {
|
|
40
|
+
handleError(e);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
runDevServer
|
|
45
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -266,8 +266,8 @@ async function runTxPlan(input) {
|
|
|
266
266
|
const { target, name } = resolveNetworkTarget({ config, network: networkId });
|
|
267
267
|
resolvedNetwork = name;
|
|
268
268
|
if (target.kind === "simulated") {
|
|
269
|
-
const { loadOrCreateLocalnetState:
|
|
270
|
-
const localState = await
|
|
269
|
+
const { loadOrCreateLocalnetState: loadOrCreateLocalnetState3, getSpendableUtxos } = await import("@hardkas/localnet");
|
|
270
|
+
const localState = await loadOrCreateLocalnetState3();
|
|
271
271
|
const unspent = getSpendableUtxos(localState, fromAddress);
|
|
272
272
|
availableUtxos = unspent.map((u) => ({
|
|
273
273
|
outpoint: {
|
|
@@ -879,8 +879,8 @@ Signed artifact saved to: ${options.out}`);
|
|
|
879
879
|
await runTxVerify({ path: path15, ...options });
|
|
880
880
|
});
|
|
881
881
|
tx.command("trace <txId>").description(`Reconstruct the full operational trace of a transaction ${UI.maturity("research")}`).action(async (txId) => {
|
|
882
|
-
const { UI:
|
|
883
|
-
|
|
882
|
+
const { UI: UI3 } = await import("./ui-SUYOHGGP.js");
|
|
883
|
+
UI3.error("Tracing is temporarily disabled while the query API stabilizes.");
|
|
884
884
|
process.exitCode = 1;
|
|
885
885
|
});
|
|
886
886
|
}
|
|
@@ -3049,9 +3049,6 @@ function registerConfigCommands(program) {
|
|
|
3049
3049
|
});
|
|
3050
3050
|
}
|
|
3051
3051
|
|
|
3052
|
-
// src/commands/misc.ts
|
|
3053
|
-
import { loadOrCreateLocalnetState as loadOrCreateLocalnetState3 } from "@hardkas/localnet";
|
|
3054
|
-
|
|
3055
3052
|
// src/runners/example-list-runner.ts
|
|
3056
3053
|
import fs7 from "fs/promises";
|
|
3057
3054
|
import path9 from "path";
|
|
@@ -3155,16 +3152,6 @@ function registerMiscCommands(program) {
|
|
|
3155
3152
|
process.exitCode = 1;
|
|
3156
3153
|
}
|
|
3157
3154
|
});
|
|
3158
|
-
program.command("dev").description("Start development environment").option("--mode <mode>", "simulated or node", "simulated").action(async (options) => {
|
|
3159
|
-
if (options.mode === "simulated") {
|
|
3160
|
-
const state = await loadOrCreateLocalnetState3();
|
|
3161
|
-
UI.success("Local HardKAS devnet (simulated) is ready.");
|
|
3162
|
-
UI.info(`Network: ${state.networkId}`);
|
|
3163
|
-
UI.info(`Accounts: ${state.accounts.length}`);
|
|
3164
|
-
} else {
|
|
3165
|
-
UI.info("Node mode requires 'hardkas node start'.");
|
|
3166
|
-
}
|
|
3167
|
-
});
|
|
3168
3155
|
}
|
|
3169
3156
|
|
|
3170
3157
|
// src/commands/query.ts
|
|
@@ -5047,7 +5034,7 @@ function registerLocalnetCommands(program) {
|
|
|
5047
5034
|
function registerDeployCommands(program) {
|
|
5048
5035
|
const deployCmd = program.command("deploy").description("Track and manage deployments");
|
|
5049
5036
|
deployCmd.command("track <label>").description(`Create a deployment record for a transaction ${UI.maturity("stable")}`).requiredOption("--network <name>", "Network where deployed").option("--tx-id <txId>", "Transaction ID").option("--plan <artifactId>", "Reference to plan artifact").option("--receipt <artifactId>", "Reference to receipt artifact").option("--status <status>", "Deployment status", "sent").option("--notes <text>", "Notes about this deployment").option("--json", "Output as JSON", false).action(async (label, opts) => {
|
|
5050
|
-
const { UI:
|
|
5037
|
+
const { UI: UI3 } = await import("./ui-SUYOHGGP.js");
|
|
5051
5038
|
await trackDeployment({ label, ...opts });
|
|
5052
5039
|
});
|
|
5053
5040
|
deployCmd.command("list").description(`List all tracked deployments ${UI.maturity("stable")}`).option("--network <name>", "Filter by network").option("--status <status>", "Filter by status").option("--json", "Output as JSON", false).action(async (opts) => {
|
|
@@ -5064,13 +5051,160 @@ function registerDeployCommands(program) {
|
|
|
5064
5051
|
});
|
|
5065
5052
|
}
|
|
5066
5053
|
|
|
5054
|
+
// src/commands/metamask.ts
|
|
5055
|
+
function registerMetamaskCommands(program) {
|
|
5056
|
+
const metamaskCmd = program.command("metamask").description("MetaMask onboarding and account export (local-dev only)");
|
|
5057
|
+
metamaskCmd.command("network").description(`Show local Igra network parameters for MetaMask ${UI.maturity("stable")}`).option("--profile <name>", "L2 network profile name", "igra").option("--json", "Output as JSON", false).action(async (options) => {
|
|
5058
|
+
const { runMetamaskNetwork } = await import("./metamask-runner-PRIOW4J3.js");
|
|
5059
|
+
await runMetamaskNetwork(options);
|
|
5060
|
+
});
|
|
5061
|
+
metamaskCmd.command("snippet").description(`Generate JS snippet to add local network to MetaMask ${UI.maturity("stable")}`).option("--profile <name>", "L2 network profile name", "igra").action(async (options) => {
|
|
5062
|
+
const { runMetamaskSnippet } = await import("./metamask-runner-PRIOW4J3.js");
|
|
5063
|
+
await runMetamaskSnippet(options);
|
|
5064
|
+
});
|
|
5065
|
+
metamaskCmd.command("account <name>").description(`Export a local EVM account for MetaMask import ${UI.maturity("stable")}`).option("--show-private-key", "Reveal the private key (LOCAL DEV ONLY)", false).option("--json", "Output as JSON", false).option("--include-secret", "Include secret in JSON output (UNSAFE)", false).action(async (name, options) => {
|
|
5066
|
+
const { runMetamaskAccount } = await import("./metamask-runner-PRIOW4J3.js");
|
|
5067
|
+
await runMetamaskAccount(name, options);
|
|
5068
|
+
});
|
|
5069
|
+
}
|
|
5070
|
+
|
|
5071
|
+
// src/commands/dev.ts
|
|
5072
|
+
function registerDevCommands(program) {
|
|
5073
|
+
const devCmd = program.command("dev").description("Local development and Igra-native environment tools");
|
|
5074
|
+
devCmd.command("doctor").description(`Validate local dev environment readiness ${UI.maturity("stable")}`).option("--profile <name>", "L2 network profile name", "igra").option("--rpc-url <url>", "Explicit Igra RPC URL to check").option("--account <name>", "Local EVM account name to verify balance").option("--timeout <ms>", "RPC timeout in milliseconds", "3000").option("--json", "Output as JSON", false).action(async (options) => {
|
|
5075
|
+
const { runDevDoctor } = await import("./dev-doctor-runner-LTSENPQ3.js");
|
|
5076
|
+
await runDevDoctor(options);
|
|
5077
|
+
});
|
|
5078
|
+
devCmd.command("server").description(`Start the local HardKas Dev Server ${UI.maturity("stable")}`).option("--port <number>", "Port to bind to", "7420").option("--host <string>", "Host to bind to", "localhost").option("--open", "Open dashboard in browser automatically", false).option("--unsafe-external", "Allow external access (binds to 0.0.0.0 if host not specified)", false).option("--json", "Output status as JSON", false).action(async (options) => {
|
|
5079
|
+
const { runDevServer } = await import("./dev-server-runner-IM5DCDD3.js");
|
|
5080
|
+
await runDevServer(options);
|
|
5081
|
+
});
|
|
5082
|
+
}
|
|
5083
|
+
|
|
5084
|
+
// src/commands/local.ts
|
|
5085
|
+
function registerLocalCommands(program) {
|
|
5086
|
+
const localCmd = program.command("local").description("Local development and environment lifecycle tools");
|
|
5087
|
+
localCmd.command("wizard").description(`Guided setup for local development ${UI.maturity("stable")}`).option("--profile <name>", "L2 network profile name", "igra").option("--account <name>", "New or existing EVM account name", "dev_alice").option("--non-interactive", "Skip interactive prompts (will fail if input required)", false).option("--json", "Output as JSON", false).action(async (options) => {
|
|
5088
|
+
const { runLocalWizard } = await import("./local-wizard-runner-GCAWGZ6D.js");
|
|
5089
|
+
await runLocalWizard(options);
|
|
5090
|
+
});
|
|
5091
|
+
}
|
|
5092
|
+
|
|
5093
|
+
// src/commands/kaspa.ts
|
|
5094
|
+
function registerKaspaCommands(program) {
|
|
5095
|
+
const kaspaCmd = program.command("kaspa").description("Kaspa L1 native developer tools");
|
|
5096
|
+
const walletCmd = kaspaCmd.command("wallet").description("Manage local Kaspa L1 wallets");
|
|
5097
|
+
walletCmd.command("create <name>").description(`Create a new local Kaspa wallet ${UI.maturity("stable")}`).option("--network <id>", "Kaspa network ID", "simnet").action(async (name, options) => {
|
|
5098
|
+
const { runKaspaWalletCreate } = await import("./kaspa-wallet-runner-ORJ5YFKU.js");
|
|
5099
|
+
await runKaspaWalletCreate(name, options);
|
|
5100
|
+
});
|
|
5101
|
+
walletCmd.command("list").description(`List local Kaspa wallets ${UI.maturity("stable")}`).option("--json", "Output as JSON", false).action(async (options) => {
|
|
5102
|
+
const { runKaspaWalletList } = await import("./kaspa-wallet-runner-ORJ5YFKU.js");
|
|
5103
|
+
await runKaspaWalletList(options);
|
|
5104
|
+
});
|
|
5105
|
+
walletCmd.command("address <name>").description(`Show address of a local Kaspa wallet ${UI.maturity("stable")}`).action(async (name) => {
|
|
5106
|
+
const { runKaspaWalletAddress } = await import("./kaspa-wallet-runner-ORJ5YFKU.js");
|
|
5107
|
+
await runKaspaWalletAddress(name);
|
|
5108
|
+
});
|
|
5109
|
+
walletCmd.command("balance <name>").description(`Show balance of a local Kaspa wallet ${UI.maturity("stable")}`).option("--rpc-url <url>", "Kaspa RPC URL", "http://127.0.0.1:16110").option("--json", "Output as JSON", false).action(async (name, options) => {
|
|
5110
|
+
const { runKaspaWalletBalance } = await import("./kaspa-wallet-runner-ORJ5YFKU.js");
|
|
5111
|
+
await runKaspaWalletBalance(name, options);
|
|
5112
|
+
});
|
|
5113
|
+
walletCmd.command("send <from> <to>").description(`Send Kaspa between local wallets ${UI.maturity("stable")}`).option("--amount <kas>", "Amount in KAS to send").option("--dry-run", "Plan but do not sign or broadcast", false).option("--rpc-url <url>", "Kaspa RPC URL", "http://127.0.0.1:16110").action(async (from, to, options) => {
|
|
5114
|
+
const { runKaspaWalletSend } = await import("./kaspa-wallet-runner-ORJ5YFKU.js");
|
|
5115
|
+
await runKaspaWalletSend(from, to, options);
|
|
5116
|
+
});
|
|
5117
|
+
kaspaCmd.command("doctor").description(`Verify local Kaspa L1 environment readiness ${UI.maturity("stable")}`).option("--rpc-url <url>", "Kaspa RPC URL", "http://127.0.0.1:16110").option("--json", "Output as JSON", false).action(async (options) => {
|
|
5118
|
+
const { runKaspaDoctor } = await import("./kaspa-doctor-runner-F2ISPABM.js");
|
|
5119
|
+
await runKaspaDoctor(options);
|
|
5120
|
+
});
|
|
5121
|
+
}
|
|
5122
|
+
|
|
5123
|
+
// src/commands/bridge.ts
|
|
5124
|
+
function registerBridgeCommands(program) {
|
|
5125
|
+
const bridgeCmd = program.command("bridge").description("Kaspa -> Igra bridge developer tools");
|
|
5126
|
+
const localCmd = bridgeCmd.command("local").description("Local bridge entry simulation (deterministic)");
|
|
5127
|
+
localCmd.command("plan").description(`Plan a local bridge entry transaction ${UI.maturity("stable")}`).option("--session <name>", "Link to a specific developer session").option("--from <name>", "Source Kaspa wallet name (overrides session)").option("--to-igra <address>", "Target Igra EVM address (overrides session)").requiredOption("--amount <kas>", "Amount in KAS to bridge").option("--json", "Output as JSON", false).action(async (options) => {
|
|
5128
|
+
const { runBridgeLocalPlan } = await import("./bridge-local-runner-E3LICYYX.js");
|
|
5129
|
+
await runBridgeLocalPlan(options);
|
|
5130
|
+
});
|
|
5131
|
+
localCmd.command("simulate").description(`Simulate a bridge entry with prefix mining ${UI.maturity("stable")}`).option("--session <name>", "Link to a specific developer session").option("--from <name>", "Source Kaspa wallet name (overrides session)").option("--to-igra <address>", "Target Igra EVM address (overrides session)").requiredOption("--amount <kas>", "Amount in KAS to bridge").option("--prefix <hex>", "Prefix to mine for", "abc").option("--json", "Output as JSON", false).action(async (options) => {
|
|
5132
|
+
const { runBridgeLocalSimulate } = await import("./bridge-local-runner-E3LICYYX.js");
|
|
5133
|
+
await runBridgeLocalSimulate(options);
|
|
5134
|
+
});
|
|
5135
|
+
localCmd.command("inspect <txid>").description(`Inspect a local bridge transaction artifact ${UI.maturity("stable")}`).option("--json", "Output as JSON", false).action(async (txid, options) => {
|
|
5136
|
+
const { runBridgeLocalInspect } = await import("./bridge-local-runner-E3LICYYX.js");
|
|
5137
|
+
await runBridgeLocalInspect(txid, options);
|
|
5138
|
+
});
|
|
5139
|
+
}
|
|
5140
|
+
|
|
5141
|
+
// src/commands/session.ts
|
|
5142
|
+
function registerSessionCommands(program) {
|
|
5143
|
+
const sessionCmd = program.command("session").description("L1/L2 developer identity linkage and sessions");
|
|
5144
|
+
sessionCmd.command("create <name>").description(`Create a new L1/L2 session linkage ${UI.maturity("alpha")}`).requiredOption("--l1 <wallet>", "Name of the Kaspa L1 wallet").requiredOption("--l2 <account>", "Name of the Igra L2 account").action(async (name, options) => {
|
|
5145
|
+
const { runSessionCreate } = await import("./session-runner-LDSGDP47.js");
|
|
5146
|
+
await runSessionCreate(name, options);
|
|
5147
|
+
});
|
|
5148
|
+
sessionCmd.command("list").description(`List all configured sessions ${UI.maturity("alpha")}`).action(async () => {
|
|
5149
|
+
const { runSessionList } = await import("./session-runner-LDSGDP47.js");
|
|
5150
|
+
await runSessionList();
|
|
5151
|
+
});
|
|
5152
|
+
sessionCmd.command("status").description(`Show active session linkage ${UI.maturity("alpha")}`).action(async () => {
|
|
5153
|
+
const { runSessionStatus } = await import("./session-runner-LDSGDP47.js");
|
|
5154
|
+
await runSessionStatus();
|
|
5155
|
+
});
|
|
5156
|
+
sessionCmd.command("use <name>").description(`Set the active session ${UI.maturity("alpha")}`).action(async (name) => {
|
|
5157
|
+
const { runSessionUse } = await import("./session-runner-LDSGDP47.js");
|
|
5158
|
+
await runSessionUse(name);
|
|
5159
|
+
});
|
|
5160
|
+
}
|
|
5161
|
+
|
|
5162
|
+
// src/commands/dashboard.ts
|
|
5163
|
+
import pc5 from "picocolors";
|
|
5164
|
+
function registerDashboardCommand(program) {
|
|
5165
|
+
program.command("dashboard").description(`Open the HardKas Local Dashboard ${UI.maturity("stable")}`).option("--port <number>", "Port to bind to", "7420").option("--start-server", "Start the dev server if not running", false).action(async (options) => {
|
|
5166
|
+
try {
|
|
5167
|
+
const isRunning = await checkServerRunning(options.port);
|
|
5168
|
+
if (!isRunning) {
|
|
5169
|
+
if (options.startServer) {
|
|
5170
|
+
console.log(pc5.cyan("HardKas Dev Server not found. Starting it now..."));
|
|
5171
|
+
const { runDevServer } = await import("./dev-server-runner-IM5DCDD3.js");
|
|
5172
|
+
await runDevServer({ ...options, open: true, host: "localhost", unsafeExternal: false, json: false });
|
|
5173
|
+
} else {
|
|
5174
|
+
console.log(pc5.red("\nHardKas Dashboard requires the local dev server."));
|
|
5175
|
+
console.log(pc5.dim("\nRun:"));
|
|
5176
|
+
console.log(` ${pc5.bold("hardkas dev server")}`);
|
|
5177
|
+
console.log(pc5.dim("\nOr:"));
|
|
5178
|
+
console.log(` ${pc5.bold("hardkas dashboard --start-server")}
|
|
5179
|
+
`);
|
|
5180
|
+
process.exit(1);
|
|
5181
|
+
}
|
|
5182
|
+
} else {
|
|
5183
|
+
const open = (await import("open")).default;
|
|
5184
|
+
console.log(pc5.green(`Connecting to existing Dev Server on port ${options.port}...`));
|
|
5185
|
+
await open(`http://localhost:${options.port}`);
|
|
5186
|
+
}
|
|
5187
|
+
} catch (e) {
|
|
5188
|
+
console.error(pc5.red("Error starting dashboard:"), e);
|
|
5189
|
+
}
|
|
5190
|
+
});
|
|
5191
|
+
}
|
|
5192
|
+
async function checkServerRunning(port) {
|
|
5193
|
+
try {
|
|
5194
|
+
const res = await fetch(`http://localhost:${port}/`, { signal: AbortSignal.timeout(1e3) });
|
|
5195
|
+
return res.ok;
|
|
5196
|
+
} catch {
|
|
5197
|
+
return false;
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
5200
|
+
|
|
5067
5201
|
// src/program.ts
|
|
5068
5202
|
import { readFileSync } from "fs";
|
|
5069
5203
|
import { fileURLToPath } from "url";
|
|
5070
5204
|
import path14 from "path";
|
|
5071
5205
|
|
|
5072
5206
|
// src/commands/lock.ts
|
|
5073
|
-
import
|
|
5207
|
+
import pc6 from "picocolors";
|
|
5074
5208
|
import { listLocks, clearLock } from "@hardkas/core";
|
|
5075
5209
|
function registerLockCommands(program) {
|
|
5076
5210
|
const lockCmd = program.command("lock").description("Manage HardKAS workspace locks");
|
|
@@ -5087,10 +5221,10 @@ function registerLockCommands(program) {
|
|
|
5087
5221
|
return;
|
|
5088
5222
|
}
|
|
5089
5223
|
for (const lock of locks) {
|
|
5090
|
-
const status = lock.isAlive ?
|
|
5091
|
-
console.log(` ${
|
|
5092
|
-
console.log(` ${
|
|
5093
|
-
console.log(` ${
|
|
5224
|
+
const status = lock.isAlive ? pc6.green("live") : pc6.red("STALE");
|
|
5225
|
+
console.log(` ${pc6.bold(lock.name.padEnd(12))} ${pc6.dim("PID:")} ${lock.metadata.pid.toString().padEnd(6)} ${pc6.dim("State:")} ${status}`);
|
|
5226
|
+
console.log(` ${pc6.dim("Command:")} ${lock.metadata.command}`);
|
|
5227
|
+
console.log(` ${pc6.dim("Created:")} ${lock.metadata.createdAt}`);
|
|
5094
5228
|
console.log("");
|
|
5095
5229
|
}
|
|
5096
5230
|
} catch (e) {
|
|
@@ -5105,12 +5239,12 @@ function registerLockCommands(program) {
|
|
|
5105
5239
|
const lock = locks.find((l) => l.name === name);
|
|
5106
5240
|
if (!lock) {
|
|
5107
5241
|
console.log(`
|
|
5108
|
-
Lock '${name}' is ${
|
|
5242
|
+
Lock '${name}' is ${pc6.green("FREE")}.
|
|
5109
5243
|
`);
|
|
5110
5244
|
return;
|
|
5111
5245
|
}
|
|
5112
5246
|
UI.header(`Lock Status: ${name}`);
|
|
5113
|
-
console.log(` State: ${lock.isAlive ?
|
|
5247
|
+
console.log(` State: ${lock.isAlive ? pc6.green("HELD (live)") : pc6.red("HELD (STALE)")}`);
|
|
5114
5248
|
console.log(` PID: ${lock.metadata.pid}`);
|
|
5115
5249
|
console.log(` Host: ${lock.metadata.hostname}`);
|
|
5116
5250
|
console.log(` Command: ${lock.metadata.command}`);
|
|
@@ -5120,7 +5254,7 @@ function registerLockCommands(program) {
|
|
|
5120
5254
|
} else {
|
|
5121
5255
|
UI.header("Lock Summary");
|
|
5122
5256
|
for (const lock of locks) {
|
|
5123
|
-
console.log(` ${
|
|
5257
|
+
console.log(` ${pc6.bold(lock.name.padEnd(12))}: ${lock.isAlive ? pc6.green("HELD") : pc6.red("STALE")}`);
|
|
5124
5258
|
}
|
|
5125
5259
|
if (locks.length === 0) console.log(" All locks are FREE.");
|
|
5126
5260
|
console.log("");
|
|
@@ -5138,7 +5272,7 @@ function registerLockCommands(program) {
|
|
|
5138
5272
|
for (const lock of locks) {
|
|
5139
5273
|
if (!lock.isAlive) {
|
|
5140
5274
|
staleCount++;
|
|
5141
|
-
console.log(` ${
|
|
5275
|
+
console.log(` ${pc6.red("\u2717")} Stale lock found: ${pc6.bold(lock.name)} (PID: ${lock.metadata.pid})`);
|
|
5142
5276
|
console.log(` Suggestion: Run 'hardkas lock clear ${lock.name} --if-dead'`);
|
|
5143
5277
|
}
|
|
5144
5278
|
}
|
|
@@ -5212,6 +5346,13 @@ function buildHardkasProgram(options) {
|
|
|
5212
5346
|
registerNetworksCommand(program);
|
|
5213
5347
|
registerLocalnetCommands(program);
|
|
5214
5348
|
registerDeployCommands(program);
|
|
5349
|
+
registerMetamaskCommands(program);
|
|
5350
|
+
registerDevCommands(program);
|
|
5351
|
+
registerLocalCommands(program);
|
|
5352
|
+
registerKaspaCommands(program);
|
|
5353
|
+
registerBridgeCommands(program);
|
|
5354
|
+
registerSessionCommands(program);
|
|
5355
|
+
registerDashboardCommand(program);
|
|
5215
5356
|
if (options?.forDocs) {
|
|
5216
5357
|
}
|
|
5217
5358
|
return program;
|