arc402-cli 1.0.0-rc.1 → 1.0.0
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/README.md +41 -2
- package/dist/abis.d.ts +1 -0
- package/dist/abis.d.ts.map +1 -1
- package/dist/abis.js +29 -1
- package/dist/abis.js.map +1 -1
- package/dist/commands/backup.d.ts +3 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +106 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/compute.d.ts +14 -0
- package/dist/commands/compute.d.ts.map +1 -0
- package/dist/commands/compute.js +466 -0
- package/dist/commands/compute.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +11 -1
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +67 -0
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/discover.d.ts.map +1 -1
- package/dist/commands/discover.js +60 -15
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +205 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/wallet.d.ts.map +1 -1
- package/dist/commands/wallet.js +299 -65
- package/dist/commands/wallet.js.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +146 -9
- package/dist/commands/watch.js.map +1 -1
- package/dist/commands/workroom.d.ts.map +1 -1
- package/dist/commands/workroom.js +112 -6
- package/dist/commands/workroom.js.map +1 -1
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +41 -4
- package/dist/config.js.map +1 -1
- package/dist/daemon/compute-metering.d.ts +61 -0
- package/dist/daemon/compute-metering.d.ts.map +1 -0
- package/dist/daemon/compute-metering.js +299 -0
- package/dist/daemon/compute-metering.js.map +1 -0
- package/dist/daemon/compute-session.d.ts +100 -0
- package/dist/daemon/compute-session.d.ts.map +1 -0
- package/dist/daemon/compute-session.js +231 -0
- package/dist/daemon/compute-session.js.map +1 -0
- package/dist/daemon/config.d.ts +33 -1
- package/dist/daemon/config.d.ts.map +1 -1
- package/dist/daemon/config.js +69 -0
- package/dist/daemon/config.js.map +1 -1
- package/dist/daemon/credentials.d.ts +24 -0
- package/dist/daemon/credentials.d.ts.map +1 -0
- package/dist/daemon/credentials.js +80 -0
- package/dist/daemon/credentials.js.map +1 -0
- package/dist/daemon/delivery-client.d.ts +35 -0
- package/dist/daemon/delivery-client.d.ts.map +1 -0
- package/dist/daemon/delivery-client.js +231 -0
- package/dist/daemon/delivery-client.js.map +1 -0
- package/dist/daemon/file-delivery.d.ts +98 -0
- package/dist/daemon/file-delivery.d.ts.map +1 -0
- package/dist/daemon/file-delivery.js +461 -0
- package/dist/daemon/file-delivery.js.map +1 -0
- package/dist/daemon/index.d.ts +1 -0
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +793 -227
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/notify.d.ts +35 -6
- package/dist/daemon/notify.d.ts.map +1 -1
- package/dist/daemon/notify.js +176 -48
- package/dist/daemon/notify.js.map +1 -1
- package/dist/daemon/worker-executor.d.ts +71 -0
- package/dist/daemon/worker-executor.d.ts.map +1 -0
- package/dist/daemon/worker-executor.js +382 -0
- package/dist/daemon/worker-executor.js.map +1 -0
- package/dist/drain-v4.js +2 -2
- package/dist/drain-v4.js.map +1 -1
- package/dist/endpoint-notify.d.ts +9 -1
- package/dist/endpoint-notify.d.ts.map +1 -1
- package/dist/endpoint-notify.js +116 -3
- package/dist/endpoint-notify.js.map +1 -1
- package/dist/index.js +81 -1
- package/dist/index.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +6 -0
- package/dist/program.js.map +1 -1
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +69 -486
- package/dist/repl.js.map +1 -1
- package/dist/tui/App.d.ts +12 -0
- package/dist/tui/App.d.ts.map +1 -0
- package/dist/tui/App.js +154 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/Footer.d.ts +11 -0
- package/dist/tui/Footer.d.ts.map +1 -0
- package/dist/tui/Footer.js +13 -0
- package/dist/tui/Footer.js.map +1 -0
- package/dist/tui/Header.d.ts +14 -0
- package/dist/tui/Header.d.ts.map +1 -0
- package/dist/tui/Header.js +19 -0
- package/dist/tui/Header.js.map +1 -0
- package/dist/tui/InputLine.d.ts +11 -0
- package/dist/tui/InputLine.d.ts.map +1 -0
- package/dist/tui/InputLine.js +145 -0
- package/dist/tui/InputLine.js.map +1 -0
- package/dist/tui/Viewport.d.ts +14 -0
- package/dist/tui/Viewport.d.ts.map +1 -0
- package/dist/tui/Viewport.js +48 -0
- package/dist/tui/Viewport.js.map +1 -0
- package/dist/tui/WalletConnectPairing.d.ts +23 -0
- package/dist/tui/WalletConnectPairing.d.ts.map +1 -0
- package/dist/tui/WalletConnectPairing.js +61 -0
- package/dist/tui/WalletConnectPairing.js.map +1 -0
- package/dist/tui/components/Button.d.ts +7 -0
- package/dist/tui/components/Button.d.ts.map +1 -0
- package/dist/tui/components/Button.js +21 -0
- package/dist/tui/components/Button.js.map +1 -0
- package/dist/tui/components/CeremonyView.d.ts +13 -0
- package/dist/tui/components/CeremonyView.d.ts.map +1 -0
- package/dist/tui/components/CeremonyView.js +10 -0
- package/dist/tui/components/CeremonyView.js.map +1 -0
- package/dist/tui/components/CompletionDropdown.d.ts +7 -0
- package/dist/tui/components/CompletionDropdown.d.ts.map +1 -0
- package/dist/tui/components/CompletionDropdown.js +23 -0
- package/dist/tui/components/CompletionDropdown.js.map +1 -0
- package/dist/tui/components/ConfirmPrompt.d.ts +9 -0
- package/dist/tui/components/ConfirmPrompt.d.ts.map +1 -0
- package/dist/tui/components/ConfirmPrompt.js +10 -0
- package/dist/tui/components/ConfirmPrompt.js.map +1 -0
- package/dist/tui/components/CustomTextInput.d.ts +15 -0
- package/dist/tui/components/CustomTextInput.d.ts.map +1 -0
- package/dist/tui/components/CustomTextInput.js +99 -0
- package/dist/tui/components/CustomTextInput.js.map +1 -0
- package/dist/tui/components/InteractiveTable.d.ts +14 -0
- package/dist/tui/components/InteractiveTable.d.ts.map +1 -0
- package/dist/tui/components/InteractiveTable.js +61 -0
- package/dist/tui/components/InteractiveTable.js.map +1 -0
- package/dist/tui/components/StepSpinner.d.ts +11 -0
- package/dist/tui/components/StepSpinner.d.ts.map +1 -0
- package/dist/tui/components/StepSpinner.js +32 -0
- package/dist/tui/components/StepSpinner.js.map +1 -0
- package/dist/tui/components/Toast.d.ts +18 -0
- package/dist/tui/components/Toast.d.ts.map +1 -0
- package/dist/tui/components/Toast.js +29 -0
- package/dist/tui/components/Toast.js.map +1 -0
- package/dist/tui/index.d.ts +2 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +55 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/useChat.d.ts +11 -0
- package/dist/tui/useChat.d.ts.map +1 -0
- package/dist/tui/useChat.js +91 -0
- package/dist/tui/useChat.js.map +1 -0
- package/dist/tui/useCommand.d.ts +12 -0
- package/dist/tui/useCommand.d.ts.map +1 -0
- package/dist/tui/useCommand.js +137 -0
- package/dist/tui/useCommand.js.map +1 -0
- package/dist/tui/useNotifications.d.ts +9 -0
- package/dist/tui/useNotifications.d.ts.map +1 -0
- package/dist/tui/useNotifications.js +17 -0
- package/dist/tui/useNotifications.js.map +1 -0
- package/dist/tui/useScroll.d.ts +17 -0
- package/dist/tui/useScroll.d.ts.map +1 -0
- package/dist/tui/useScroll.js +46 -0
- package/dist/tui/useScroll.js.map +1 -0
- package/dist/ui/format.d.ts.map +1 -1
- package/dist/ui/format.js +2 -0
- package/dist/ui/format.js.map +1 -1
- package/dist/ui/qr-render.d.ts +25 -0
- package/dist/ui/qr-render.d.ts.map +1 -0
- package/dist/ui/qr-render.js +90 -0
- package/dist/ui/qr-render.js.map +1 -0
- package/dist/ui/rpc-fallback.d.ts +11 -0
- package/dist/ui/rpc-fallback.d.ts.map +1 -0
- package/dist/ui/rpc-fallback.js +58 -0
- package/dist/ui/rpc-fallback.js.map +1 -0
- package/dist/walletconnect.d.ts +4 -0
- package/dist/walletconnect.d.ts.map +1 -1
- package/dist/walletconnect.js.map +1 -1
- package/package.json +10 -2
- package/scripts/authorize-machine-key.ts +0 -43
- package/scripts/drain-wallet.ts +0 -149
- package/scripts/execute-spend-only.ts +0 -81
- package/scripts/register-agent-userop.ts +0 -186
- package/src/abis.ts +0 -187
- package/src/bundler.ts +0 -235
- package/src/client.ts +0 -36
- package/src/coinbase-smart-wallet.ts +0 -51
- package/src/commands/accept.ts +0 -64
- package/src/commands/agent-handshake.ts +0 -72
- package/src/commands/agent.ts +0 -691
- package/src/commands/agreements.ts +0 -350
- package/src/commands/arbitrator.ts +0 -180
- package/src/commands/arena-handshake.ts +0 -257
- package/src/commands/arena.ts +0 -122
- package/src/commands/cancel.ts +0 -35
- package/src/commands/channel.ts +0 -218
- package/src/commands/coldstart.ts +0 -165
- package/src/commands/config.ts +0 -58
- package/src/commands/contract-interaction.ts +0 -166
- package/src/commands/daemon.ts +0 -978
- package/src/commands/deliver.ts +0 -148
- package/src/commands/discover.ts +0 -297
- package/src/commands/dispute.ts +0 -375
- package/src/commands/endpoint.ts +0 -620
- package/src/commands/feed.ts +0 -229
- package/src/commands/hire.ts +0 -245
- package/src/commands/migrate.ts +0 -177
- package/src/commands/negotiate.ts +0 -271
- package/src/commands/openshell.ts +0 -1055
- package/src/commands/owner.ts +0 -35
- package/src/commands/policy.ts +0 -263
- package/src/commands/relay.ts +0 -273
- package/src/commands/remediate.ts +0 -24
- package/src/commands/reputation.ts +0 -79
- package/src/commands/setup.ts +0 -343
- package/src/commands/trust.ts +0 -27
- package/src/commands/verify.ts +0 -91
- package/src/commands/wallet.ts +0 -3280
- package/src/commands/watch.ts +0 -23
- package/src/commands/watchtower.ts +0 -248
- package/src/commands/workroom.ts +0 -959
- package/src/config.ts +0 -174
- package/src/daemon/config.ts +0 -308
- package/src/daemon/hire-listener.ts +0 -226
- package/src/daemon/index.ts +0 -955
- package/src/daemon/job-lifecycle.ts +0 -215
- package/src/daemon/notify.ts +0 -157
- package/src/daemon/token-metering.ts +0 -183
- package/src/daemon/userops.ts +0 -119
- package/src/daemon/wallet-monitor.ts +0 -90
- package/src/drain-v4.ts +0 -159
- package/src/endpoint-config.ts +0 -83
- package/src/endpoint-notify.ts +0 -46
- package/src/index.ts +0 -26
- package/src/openshell-runtime.ts +0 -277
- package/src/program.ts +0 -83
- package/src/repl.ts +0 -680
- package/src/signing.ts +0 -28
- package/src/telegram-notify.ts +0 -88
- package/src/ui/banner.ts +0 -51
- package/src/ui/colors.ts +0 -30
- package/src/ui/format.ts +0 -77
- package/src/ui/spinner.ts +0 -56
- package/src/ui/tree.ts +0 -16
- package/src/utils/format.ts +0 -48
- package/src/utils/hash.ts +0 -5
- package/src/utils/time.ts +0 -15
- package/src/wallet-router.ts +0 -178
- package/src/walletconnect-session.ts +0 -27
- package/src/walletconnect.ts +0 -294
- package/test/time.test.js +0 -11
- package/tsconfig.json +0 -19
package/dist/commands/wallet.js
CHANGED
|
@@ -26,6 +26,26 @@ const tree_1 = require("../ui/tree");
|
|
|
26
26
|
const spinner_1 = require("../ui/spinner");
|
|
27
27
|
const colors_1 = require("../ui/colors");
|
|
28
28
|
const POLICY_ENGINE_DEFAULT = "0x44102e70c2A366632d98Fe40d892a2501fC7fFF2";
|
|
29
|
+
const GUARDIAN_KEY_PATH = path_1.default.join(os_1.default.homedir(), ".arc402", "guardian.key");
|
|
30
|
+
/** Save guardian private key to a restricted standalone file (never to config.json). */
|
|
31
|
+
function saveGuardianKey(privateKey) {
|
|
32
|
+
fs_1.default.mkdirSync(path_1.default.dirname(GUARDIAN_KEY_PATH), { recursive: true, mode: 0o700 });
|
|
33
|
+
fs_1.default.writeFileSync(GUARDIAN_KEY_PATH, privateKey + "\n", { mode: 0o400 });
|
|
34
|
+
}
|
|
35
|
+
/** Load guardian private key from file, falling back to config for backwards compat. */
|
|
36
|
+
function loadGuardianKey(config) {
|
|
37
|
+
try {
|
|
38
|
+
return fs_1.default.readFileSync(GUARDIAN_KEY_PATH, "utf-8").trim();
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// Migration: if key still in config, migrate it to the file now
|
|
42
|
+
if (config.guardianPrivateKey) {
|
|
43
|
+
saveGuardianKey(config.guardianPrivateKey);
|
|
44
|
+
return config.guardianPrivateKey;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
29
49
|
function parseAmount(raw) {
|
|
30
50
|
const lower = raw.toLowerCase();
|
|
31
51
|
if (lower.endsWith("eth")) {
|
|
@@ -161,6 +181,9 @@ async function runCompleteOnboardingCeremony(walletAddress, ownerAddress, config
|
|
|
161
181
|
await sendTx({ to: walletAddress, data: mkIface.encodeFunctionData("authorizeMachineKey", [machineKeyAddress]), value: "0x0" }, "authorizeMachineKey");
|
|
162
182
|
console.log(" " + colors_1.c.success + " Machine key authorized");
|
|
163
183
|
}
|
|
184
|
+
// Save progress after machine key step
|
|
185
|
+
config.onboardingProgress = { walletAddress, step: 2, completedSteps: ["machineKey"] };
|
|
186
|
+
(0, config_1.saveConfig)(config);
|
|
164
187
|
// ── Step 3: Passkey ───────────────────────────────────────────────────────
|
|
165
188
|
console.log("\n" + colors_1.c.dim("── Step 3: Passkey (Face ID / WebAuthn) ──────────────────────"));
|
|
166
189
|
let passkeyActive = false;
|
|
@@ -192,6 +215,9 @@ async function runCompleteOnboardingCeremony(walletAddress, ownerAddress, config
|
|
|
192
215
|
console.log(" " + colors_1.c.success + " Passkey set (via browser)");
|
|
193
216
|
}
|
|
194
217
|
}
|
|
218
|
+
// Save progress after passkey step
|
|
219
|
+
config.onboardingProgress = { walletAddress, step: 3, completedSteps: ["machineKey", "passkey"] };
|
|
220
|
+
(0, config_1.saveConfig)(config);
|
|
195
221
|
// ── Step 4: Policy ────────────────────────────────────────────────────────
|
|
196
222
|
console.log("\n" + colors_1.c.dim("── Step 4: Policy ─────────────────────────────────────────────"));
|
|
197
223
|
// 4a) setVelocityLimit
|
|
@@ -240,12 +266,15 @@ async function runCompleteOnboardingCeremony(walletAddress, ownerAddress, config
|
|
|
240
266
|
const guardianInput = guardianAns.guardian?.trim() ?? "";
|
|
241
267
|
if (guardianInput.toLowerCase() === "g") {
|
|
242
268
|
const generatedGuardian = ethers_1.ethers.Wallet.createRandom();
|
|
243
|
-
|
|
269
|
+
// Save guardian private key to a separate restricted file, NOT config.json
|
|
270
|
+
const guardianKeyPath = path_1.default.join(os_1.default.homedir(), ".arc402", "guardian.key");
|
|
271
|
+
fs_1.default.mkdirSync(path_1.default.dirname(guardianKeyPath), { recursive: true, mode: 0o700 });
|
|
272
|
+
fs_1.default.writeFileSync(guardianKeyPath, generatedGuardian.privateKey + "\n", { mode: 0o400 });
|
|
273
|
+
// Only save address (not private key) to config
|
|
244
274
|
config.guardianAddress = generatedGuardian.address;
|
|
245
275
|
(0, config_1.saveConfig)(config);
|
|
246
276
|
guardianAddress = generatedGuardian.address;
|
|
247
|
-
console.log("\n " + colors_1.c.warning + "
|
|
248
|
-
console.log(" " + colors_1.c.dim(generatedGuardian.privateKey));
|
|
277
|
+
console.log("\n " + colors_1.c.warning + " Guardian key saved to ~/.arc402/guardian.key — move offline for security");
|
|
249
278
|
console.log(" " + colors_1.c.dim("Address: ") + colors_1.c.white(generatedGuardian.address) + "\n");
|
|
250
279
|
const guardianIface = new ethers_1.ethers.Interface(["function setGuardian(address _guardian) external"]);
|
|
251
280
|
await sendTx({ to: walletAddress, data: guardianIface.encodeFunctionData("setGuardian", [guardianAddress]), value: "0x0" }, "setGuardian");
|
|
@@ -297,6 +326,9 @@ async function runCompleteOnboardingCeremony(walletAddress, ownerAddress, config
|
|
|
297
326
|
await sendTx({ to: policyAddress, data: contractInteractionIface.encodeFunctionData("enableContractInteraction", [walletAddress, handshakeAddress]), value: "0x0" }, "enableContractInteraction: Handshake");
|
|
298
327
|
(0, config_1.saveConfig)(config);
|
|
299
328
|
console.log(" " + colors_1.c.success + " Policy configured");
|
|
329
|
+
// Save progress after policy step
|
|
330
|
+
config.onboardingProgress = { walletAddress, step: 4, completedSteps: ["machineKey", "passkey", "policy"] };
|
|
331
|
+
(0, config_1.saveConfig)(config);
|
|
300
332
|
// ── Step 5: Agent Registration ─────────────────────────────────────────────
|
|
301
333
|
console.log("\n" + colors_1.c.dim("── Step 5: Agent Registration ─────────────────────────────────"));
|
|
302
334
|
let agentAlreadyRegistered = false;
|
|
@@ -374,6 +406,90 @@ async function runCompleteOnboardingCeremony(walletAddress, ownerAddress, config
|
|
|
374
406
|
else {
|
|
375
407
|
console.log(" " + colors_1.c.warning + " AgentRegistry address not configured — skipping");
|
|
376
408
|
}
|
|
409
|
+
// Save progress after agent step, then clear on ceremony complete
|
|
410
|
+
config.onboardingProgress = { walletAddress, step: 5, completedSteps: ["machineKey", "passkey", "policy", "agent"] };
|
|
411
|
+
(0, config_1.saveConfig)(config);
|
|
412
|
+
// ── Step 7: Workroom Init ─────────────────────────────────────────────────
|
|
413
|
+
console.log("\n" + colors_1.c.dim("── Step 7: Workroom ────────────────────────────────────────────"));
|
|
414
|
+
let workroomInitialized = false;
|
|
415
|
+
let dockerFound = false;
|
|
416
|
+
try {
|
|
417
|
+
const dockerCheck = (0, child_process_1.spawnSync)("docker", ["--version"], { encoding: "utf-8", timeout: 5000 });
|
|
418
|
+
dockerFound = dockerCheck.status === 0;
|
|
419
|
+
}
|
|
420
|
+
catch {
|
|
421
|
+
dockerFound = false;
|
|
422
|
+
}
|
|
423
|
+
if (dockerFound) {
|
|
424
|
+
console.log(" " + colors_1.c.dim("Docker found — initializing workroom..."));
|
|
425
|
+
try {
|
|
426
|
+
const initResult = (0, child_process_1.spawnSync)(process.execPath, [process.argv[1], "workroom", "init"], {
|
|
427
|
+
encoding: "utf-8",
|
|
428
|
+
timeout: 120000,
|
|
429
|
+
env: { ...process.env },
|
|
430
|
+
});
|
|
431
|
+
workroomInitialized = initResult.status === 0;
|
|
432
|
+
if (workroomInitialized) {
|
|
433
|
+
console.log(" " + colors_1.c.success + " Workroom initialized");
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
console.log(" " + colors_1.c.warning + " Workroom init incomplete — run: arc402 workroom init");
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
catch {
|
|
440
|
+
console.log(" " + colors_1.c.warning + " Workroom init failed — run: arc402 workroom init");
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
console.log(" " + colors_1.c.warning + " Docker not found");
|
|
445
|
+
console.log(" Install Docker: https://docs.docker.com/get-docker/");
|
|
446
|
+
console.log(" Or run daemon in host mode: " + colors_1.c.white("arc402 daemon start --host"));
|
|
447
|
+
}
|
|
448
|
+
// ── Step 8: Daemon Start ──────────────────────────────────────────────────
|
|
449
|
+
console.log("\n" + colors_1.c.dim("── Step 8: Daemon ──────────────────────────────────────────────"));
|
|
450
|
+
let daemonRunning = false;
|
|
451
|
+
const relayPort = 4402;
|
|
452
|
+
if (workroomInitialized) {
|
|
453
|
+
try {
|
|
454
|
+
const startResult = (0, child_process_1.spawnSync)(process.execPath, [process.argv[1], "workroom", "start"], {
|
|
455
|
+
encoding: "utf-8",
|
|
456
|
+
timeout: 30000,
|
|
457
|
+
env: { ...process.env },
|
|
458
|
+
});
|
|
459
|
+
daemonRunning = startResult.status === 0;
|
|
460
|
+
if (daemonRunning) {
|
|
461
|
+
console.log(" " + colors_1.c.success + " Daemon online (port " + relayPort + ")");
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
console.log(" " + colors_1.c.warning + " Daemon start failed — run: arc402 workroom start");
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
console.log(" " + colors_1.c.warning + " Daemon start failed — run: arc402 workroom start");
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
else if (!dockerFound) {
|
|
472
|
+
try {
|
|
473
|
+
const startResult = (0, child_process_1.spawnSync)(process.execPath, [process.argv[1], "daemon", "start", "--host"], {
|
|
474
|
+
encoding: "utf-8",
|
|
475
|
+
timeout: 30000,
|
|
476
|
+
env: { ...process.env },
|
|
477
|
+
});
|
|
478
|
+
daemonRunning = startResult.status === 0;
|
|
479
|
+
if (daemonRunning) {
|
|
480
|
+
console.log(" " + colors_1.c.success + " Daemon online — host mode (port " + relayPort + ")");
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
console.log(" " + colors_1.c.warning + " Daemon not started — run: arc402 daemon start --host");
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
catch {
|
|
487
|
+
console.log(" " + colors_1.c.warning + " Daemon not started — run: arc402 daemon start --host");
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
console.log(" " + colors_1.c.warning + " Daemon not started — run: arc402 workroom init first");
|
|
492
|
+
}
|
|
377
493
|
// ── Step 6: Summary ───────────────────────────────────────────────────────
|
|
378
494
|
const trustScore = await (async () => {
|
|
379
495
|
try {
|
|
@@ -385,6 +501,18 @@ async function runCompleteOnboardingCeremony(walletAddress, ownerAddress, config
|
|
|
385
501
|
return "100";
|
|
386
502
|
}
|
|
387
503
|
})();
|
|
504
|
+
const workroomLabel = dockerFound
|
|
505
|
+
? (workroomInitialized ? (daemonRunning ? colors_1.c.green("✓ Running") : colors_1.c.yellow("✓ Initialized")) : colors_1.c.yellow("⚠ Init needed"))
|
|
506
|
+
: colors_1.c.yellow("⚠ No Docker");
|
|
507
|
+
const daemonLabel = daemonRunning
|
|
508
|
+
? colors_1.c.green("✓ Online (port " + relayPort + ")")
|
|
509
|
+
: colors_1.c.dim("not started");
|
|
510
|
+
const endpointLabel = agentEndpoint
|
|
511
|
+
? colors_1.c.white(agentEndpoint) + colors_1.c.dim(` → localhost:${relayPort}`)
|
|
512
|
+
: colors_1.c.dim("—");
|
|
513
|
+
// Clear onboarding progress — ceremony complete
|
|
514
|
+
delete config.onboardingProgress;
|
|
515
|
+
(0, config_1.saveConfig)(config);
|
|
388
516
|
console.log("\n " + colors_1.c.success + colors_1.c.white(" Onboarding complete"));
|
|
389
517
|
(0, tree_1.renderTree)([
|
|
390
518
|
{ label: "Wallet", value: colors_1.c.white(walletAddress) },
|
|
@@ -396,11 +524,12 @@ async function runCompleteOnboardingCeremony(walletAddress, ownerAddress, config
|
|
|
396
524
|
{ label: "Hire limit", value: colors_1.c.white(hireLimit + " ETH") },
|
|
397
525
|
{ label: "Agent", value: agentName ? colors_1.c.white(agentName) : colors_1.c.dim("not registered") },
|
|
398
526
|
{ label: "Service", value: agentServiceType ? colors_1.c.white(agentServiceType) : colors_1.c.dim("—") },
|
|
399
|
-
{ label: "
|
|
527
|
+
{ label: "Workroom", value: workroomLabel },
|
|
528
|
+
{ label: "Daemon", value: daemonLabel },
|
|
529
|
+
{ label: "Endpoint", value: endpointLabel },
|
|
400
530
|
{ label: "Trust", value: colors_1.c.white(`${trustScore}`), last: true },
|
|
401
531
|
]);
|
|
402
532
|
console.log("\n " + colors_1.c.dim("Next: fund your wallet with 0.002 ETH on Base"));
|
|
403
|
-
console.log(" " + colors_1.c.dim(" arc402 daemon start"));
|
|
404
533
|
}
|
|
405
534
|
function printOpenShellHint() {
|
|
406
535
|
const r = (0, child_process_1.spawnSync)("which", ["openshell"], { encoding: "utf-8" });
|
|
@@ -422,11 +551,20 @@ function registerWalletCommands(program) {
|
|
|
422
551
|
const usdcAddress = (0, config_1.getUsdcAddress)(config);
|
|
423
552
|
const usdc = new ethers_1.ethers.Contract(usdcAddress, ["function balanceOf(address owner) external view returns (uint256)"], provider);
|
|
424
553
|
const trust = new sdk_1.TrustClient(config.trustRegistryAddress, provider);
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
554
|
+
const statusSpinner = opts.json ? null : (0, spinner_1.startSpinner)("Loading wallet status…");
|
|
555
|
+
let ethBalance, usdcBalance, score;
|
|
556
|
+
try {
|
|
557
|
+
[ethBalance, usdcBalance, score] = await Promise.all([
|
|
558
|
+
provider.getBalance(address),
|
|
559
|
+
usdc.balanceOf(address),
|
|
560
|
+
trust.getScore(address),
|
|
561
|
+
]);
|
|
562
|
+
statusSpinner?.succeed("Wallet status loaded");
|
|
563
|
+
}
|
|
564
|
+
catch (err) {
|
|
565
|
+
statusSpinner?.fail("Failed to load wallet status");
|
|
566
|
+
throw err;
|
|
567
|
+
}
|
|
430
568
|
// Query contract wallet for frozen/guardian state if deployed
|
|
431
569
|
let contractFrozen = null;
|
|
432
570
|
let contractGuardian = null;
|
|
@@ -546,16 +684,40 @@ function registerWalletCommands(program) {
|
|
|
546
684
|
console.log(colors_1.c.dim("Next: fund your wallet with ETH, then run: arc402 wallet deploy"));
|
|
547
685
|
});
|
|
548
686
|
// ─── import ────────────────────────────────────────────────────────────────
|
|
549
|
-
wallet.command("import
|
|
550
|
-
.description("Import an existing private key")
|
|
687
|
+
wallet.command("import")
|
|
688
|
+
.description("Import an existing private key (use --key-file or stdin prompt)")
|
|
551
689
|
.option("--network <network>", "Network (base-mainnet or base-sepolia)", "base-sepolia")
|
|
552
|
-
.
|
|
690
|
+
.option("--key-file <path>", "Read private key from file instead of prompting")
|
|
691
|
+
.action(async (opts) => {
|
|
553
692
|
const network = opts.network;
|
|
554
693
|
const defaults = config_1.NETWORK_DEFAULTS[network];
|
|
555
694
|
if (!defaults) {
|
|
556
695
|
console.error(`Unknown network: ${network}. Use base-mainnet or base-sepolia.`);
|
|
557
696
|
process.exit(1);
|
|
558
697
|
}
|
|
698
|
+
let privateKey;
|
|
699
|
+
if (opts.keyFile) {
|
|
700
|
+
try {
|
|
701
|
+
privateKey = fs_1.default.readFileSync(opts.keyFile, "utf-8").trim();
|
|
702
|
+
}
|
|
703
|
+
catch (e) {
|
|
704
|
+
console.error(`Cannot read key file: ${e instanceof Error ? e.message : String(e)}`);
|
|
705
|
+
process.exit(1);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
// Interactive prompt — hidden input avoids shell history
|
|
710
|
+
const answer = await (0, prompts_1.default)({
|
|
711
|
+
type: "password",
|
|
712
|
+
name: "key",
|
|
713
|
+
message: "Paste private key (hidden):",
|
|
714
|
+
});
|
|
715
|
+
privateKey = (answer.key ?? "").trim();
|
|
716
|
+
if (!privateKey) {
|
|
717
|
+
console.error("No private key entered.");
|
|
718
|
+
process.exit(1);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
559
721
|
let imported;
|
|
560
722
|
try {
|
|
561
723
|
imported = new ethers_1.ethers.Wallet(privateKey);
|
|
@@ -703,8 +865,31 @@ function registerWalletCommands(program) {
|
|
|
703
865
|
.option("--smart-wallet", "Connect via Base Smart Wallet (Coinbase Wallet SDK) instead of WalletConnect")
|
|
704
866
|
.option("--hardware", "Hardware wallet mode: show raw wc: URI only (for Ledger Live, Trezor Suite, etc.)")
|
|
705
867
|
.option("--sponsored", "Use CDP paymaster for gas sponsorship (requires paymasterUrl + cdpKeyName + CDP_PRIVATE_KEY env)")
|
|
868
|
+
.option("--dry-run", "Simulate the deployment ceremony without sending transactions")
|
|
706
869
|
.action(async (opts) => {
|
|
707
870
|
const config = (0, config_1.loadConfig)();
|
|
871
|
+
if (opts.dryRun) {
|
|
872
|
+
const factoryAddr = config.walletFactoryAddress ?? config_1.NETWORK_DEFAULTS[config.network]?.walletFactoryAddress ?? "(not configured)";
|
|
873
|
+
const chainId = config.network === "base-mainnet" ? 8453 : 84532;
|
|
874
|
+
console.log();
|
|
875
|
+
console.log(" " + colors_1.c.dim("── Dry run: wallet deploy ──────────────────────────────────────"));
|
|
876
|
+
console.log(" " + colors_1.c.dim("Network: ") + colors_1.c.white(config.network));
|
|
877
|
+
console.log(" " + colors_1.c.dim("Chain ID: ") + colors_1.c.white(String(chainId)));
|
|
878
|
+
console.log(" " + colors_1.c.dim("RPC: ") + colors_1.c.white(config.rpcUrl));
|
|
879
|
+
console.log(" " + colors_1.c.dim("WalletFactory: ") + colors_1.c.white(factoryAddr));
|
|
880
|
+
console.log(" " + colors_1.c.dim("Signing method: ") + colors_1.c.white(opts.smartWallet ? "Base Smart Wallet" : opts.hardware ? "Hardware (WC URI)" : "WalletConnect"));
|
|
881
|
+
console.log(" " + colors_1.c.dim("Sponsored: ") + colors_1.c.white(opts.sponsored ? "yes" : "no"));
|
|
882
|
+
console.log();
|
|
883
|
+
console.log(" " + colors_1.c.dim("Steps that would run:"));
|
|
884
|
+
console.log(" 1. Connect " + (opts.smartWallet ? "Coinbase Smart Wallet" : "WalletConnect") + " session");
|
|
885
|
+
console.log(" 2. Call WalletFactory.createWallet() → deploy ARC402Wallet");
|
|
886
|
+
console.log(" 3. Save walletContractAddress to config");
|
|
887
|
+
console.log(" 4. Run onboarding ceremony (PolicyEngine, machine key, agent registration)");
|
|
888
|
+
console.log();
|
|
889
|
+
console.log(" " + colors_1.c.dim("No transactions sent (--dry-run mode)."));
|
|
890
|
+
console.log();
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
708
893
|
const factoryAddress = config.walletFactoryAddress ?? config_1.NETWORK_DEFAULTS[config.network]?.walletFactoryAddress;
|
|
709
894
|
if (!factoryAddress) {
|
|
710
895
|
console.error("walletFactoryAddress not found in config or NETWORK_DEFAULTS. Add walletFactoryAddress to your config.");
|
|
@@ -845,12 +1030,44 @@ function registerWalletCommands(program) {
|
|
|
845
1030
|
const telegramOpts = config.telegramBotToken && config.telegramChatId
|
|
846
1031
|
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
847
1032
|
: undefined;
|
|
1033
|
+
// ── Resume check ──────────────────────────────────────────────────────
|
|
1034
|
+
const resumeProgress = config.onboardingProgress;
|
|
1035
|
+
const isResuming = !!(resumeProgress?.walletAddress &&
|
|
1036
|
+
resumeProgress.walletAddress === config.walletContractAddress &&
|
|
1037
|
+
config.ownerAddress);
|
|
1038
|
+
if (isResuming) {
|
|
1039
|
+
const stepNames = {
|
|
1040
|
+
2: "machine key", 3: "passkey", 4: "policy setup", 5: "agent registration",
|
|
1041
|
+
};
|
|
1042
|
+
const nextStep = (resumeProgress.step ?? 1) + 1;
|
|
1043
|
+
console.log(" " + colors_1.c.dim(`◈ Resuming onboarding from step ${nextStep} (${stepNames[nextStep] ?? "ceremony"})...`));
|
|
1044
|
+
}
|
|
1045
|
+
// ── Gas estimation ─────────────────────────────────────────────────────
|
|
1046
|
+
if (!isResuming) {
|
|
1047
|
+
let gasMsg = "~0.003 ETH (6 transactions on Base)";
|
|
1048
|
+
try {
|
|
1049
|
+
const feeData = await provider.getFeeData();
|
|
1050
|
+
const gasPrice = feeData.maxFeePerGas ?? feeData.gasPrice ?? BigInt(1500000000);
|
|
1051
|
+
const deployGas = await provider.estimateGas({
|
|
1052
|
+
to: factoryAddress,
|
|
1053
|
+
data: factoryInterface.encodeFunctionData("createWallet", ["0x0000000071727De22E5E9d8BAf0edAc6f37da032"]),
|
|
1054
|
+
}).catch(() => BigInt(280000));
|
|
1055
|
+
const ceremonyGas = BigInt(700000); // ~5 ceremony txs × ~140k each
|
|
1056
|
+
const totalGasEth = parseFloat(ethers_1.ethers.formatEther((deployGas + ceremonyGas) * gasPrice));
|
|
1057
|
+
gasMsg = `~${totalGasEth.toFixed(4)} ETH (6 transactions on Base)`;
|
|
1058
|
+
}
|
|
1059
|
+
catch { /* use default */ }
|
|
1060
|
+
console.log(" " + colors_1.c.dim(`◈ Estimated gas: ${gasMsg}`));
|
|
1061
|
+
}
|
|
848
1062
|
// ── Step 1: Connect ────────────────────────────────────────────────────
|
|
849
|
-
const
|
|
1063
|
+
const connectPrompt = isResuming
|
|
1064
|
+
? "Connect wallet to resume onboarding"
|
|
1065
|
+
: "Approve ARC402Wallet deployment — you will be set as owner";
|
|
1066
|
+
const { client, session, account } = await (0, walletconnect_1.connectPhoneWallet)(config.walletConnectProjectId, chainId, config, { telegramOpts, prompt: connectPrompt, hardware: !!opts.hardware });
|
|
850
1067
|
const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
|
|
851
1068
|
const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
|
|
852
1069
|
console.log("\n" + colors_1.c.success + colors_1.c.white(` Connected: ${shortAddr} on ${networkName}`));
|
|
853
|
-
if (telegramOpts) {
|
|
1070
|
+
if (telegramOpts && !isResuming) {
|
|
854
1071
|
// Send "connected" message with a deploy confirmation button.
|
|
855
1072
|
// TODO: wire up full callback_data round-trip when a persistent bot process is available.
|
|
856
1073
|
await (0, telegram_notify_1.sendTelegramMessage)({
|
|
@@ -861,50 +1078,59 @@ function registerWalletCommands(program) {
|
|
|
861
1078
|
buttons: [[{ text: "🚀 Deploy ARC-402 Wallet", callback_data: "arc402_deploy_confirm" }]],
|
|
862
1079
|
});
|
|
863
1080
|
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
data: factoryInterface.encodeFunctionData("createWallet", ["0x0000000071727De22E5E9d8BAf0edAc6f37da032"]),
|
|
870
|
-
value: "0x0",
|
|
871
|
-
});
|
|
872
|
-
console.log(`\nTransaction submitted: ${txHash}`);
|
|
873
|
-
console.log("Waiting for confirmation...");
|
|
874
|
-
const receipt = await provider.waitForTransaction(txHash);
|
|
875
|
-
if (!receipt) {
|
|
876
|
-
console.error("Transaction not confirmed. Check on-chain.");
|
|
877
|
-
process.exit(1);
|
|
1081
|
+
let walletAddress;
|
|
1082
|
+
if (isResuming) {
|
|
1083
|
+
// Resume: skip deploy, use existing wallet
|
|
1084
|
+
walletAddress = config.walletContractAddress;
|
|
1085
|
+
console.log(" " + colors_1.c.dim(`◈ Using existing wallet: ${walletAddress}`));
|
|
878
1086
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
1087
|
+
else {
|
|
1088
|
+
// ── Step 2: Confirm & Deploy ─────────────────────────────────────────
|
|
1089
|
+
// WalletConnect approval already confirmed intent — sending automatically
|
|
1090
|
+
console.log("Deploying...");
|
|
1091
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, {
|
|
1092
|
+
to: factoryAddress,
|
|
1093
|
+
data: factoryInterface.encodeFunctionData("createWallet", ["0x0000000071727De22E5E9d8BAf0edAc6f37da032"]),
|
|
1094
|
+
value: "0x0",
|
|
1095
|
+
});
|
|
1096
|
+
console.log(`\nTransaction submitted: ${txHash}`);
|
|
1097
|
+
console.log("Waiting for confirmation...");
|
|
1098
|
+
const receipt = await provider.waitForTransaction(txHash);
|
|
1099
|
+
if (!receipt) {
|
|
1100
|
+
console.error("Transaction not confirmed. Check on-chain.");
|
|
1101
|
+
process.exit(1);
|
|
1102
|
+
}
|
|
1103
|
+
let deployedWallet = null;
|
|
1104
|
+
const factoryContract = new ethers_1.ethers.Contract(factoryAddress, abis_1.WALLET_FACTORY_ABI, provider);
|
|
1105
|
+
for (const log of receipt.logs) {
|
|
1106
|
+
try {
|
|
1107
|
+
const parsed = factoryContract.interface.parseLog(log);
|
|
1108
|
+
if (parsed?.name === "WalletCreated") {
|
|
1109
|
+
deployedWallet = parsed.args.walletAddress;
|
|
1110
|
+
break;
|
|
1111
|
+
}
|
|
887
1112
|
}
|
|
1113
|
+
catch { /* skip unparseable logs */ }
|
|
888
1114
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1115
|
+
if (!deployedWallet) {
|
|
1116
|
+
console.error("Could not find WalletCreated event in receipt. Check the transaction on-chain.");
|
|
1117
|
+
process.exit(1);
|
|
1118
|
+
}
|
|
1119
|
+
walletAddress = deployedWallet;
|
|
1120
|
+
// ── Step 1 complete: save wallet + owner immediately ─────────────────
|
|
1121
|
+
config.walletContractAddress = walletAddress;
|
|
1122
|
+
config.ownerAddress = account;
|
|
1123
|
+
(0, config_1.saveConfig)(config);
|
|
1124
|
+
try {
|
|
1125
|
+
fs_1.default.chmodSync((0, config_1.getConfigPath)(), 0o600);
|
|
1126
|
+
}
|
|
1127
|
+
catch { /* best-effort */ }
|
|
1128
|
+
console.log("\n " + colors_1.c.success + colors_1.c.white(" Wallet deployed"));
|
|
1129
|
+
(0, tree_1.renderTree)([
|
|
1130
|
+
{ label: "Wallet", value: walletAddress },
|
|
1131
|
+
{ label: "Owner", value: account, last: true },
|
|
1132
|
+
]);
|
|
901
1133
|
}
|
|
902
|
-
catch { /* best-effort */ }
|
|
903
|
-
console.log("\n " + colors_1.c.success + colors_1.c.white(" Wallet deployed"));
|
|
904
|
-
(0, tree_1.renderTree)([
|
|
905
|
-
{ label: "Wallet", value: walletAddress },
|
|
906
|
-
{ label: "Owner", value: account, last: true },
|
|
907
|
-
]);
|
|
908
1134
|
// ── Steps 2–6: Complete onboarding ceremony (same WalletConnect session)
|
|
909
1135
|
const sendTxCeremony = async (call, description) => {
|
|
910
1136
|
console.log(" " + colors_1.c.dim(`◈ ${description}`));
|
|
@@ -945,8 +1171,11 @@ function registerWalletCommands(program) {
|
|
|
945
1171
|
const guardianWallet = ethers_1.ethers.Wallet.createRandom();
|
|
946
1172
|
config.walletContractAddress = walletAddress;
|
|
947
1173
|
config.ownerAddress = address;
|
|
948
|
-
config.guardianPrivateKey = guardianWallet.privateKey;
|
|
949
1174
|
config.guardianAddress = guardianWallet.address;
|
|
1175
|
+
// Save key to restricted file — never store in config.json
|
|
1176
|
+
saveGuardianKey(guardianWallet.privateKey);
|
|
1177
|
+
if (config.guardianPrivateKey)
|
|
1178
|
+
delete config.guardianPrivateKey;
|
|
950
1179
|
(0, config_1.saveConfig)(config);
|
|
951
1180
|
// Call setGuardian on the deployed wallet
|
|
952
1181
|
const walletContract = new ethers_1.ethers.Contract(walletAddress, abis_1.ARC402_WALLET_GUARDIAN_ABI, signer);
|
|
@@ -967,7 +1196,7 @@ function registerWalletCommands(program) {
|
|
|
967
1196
|
{ label: "Wallet", value: walletAddress },
|
|
968
1197
|
{ label: "Guardian", value: guardianWallet.address, last: true },
|
|
969
1198
|
]);
|
|
970
|
-
console.log(`Guardian private key saved to
|
|
1199
|
+
console.log(`Guardian private key saved to ~/.arc402/guardian.key (chmod 400 — keep it safe, used for emergency freeze only)`);
|
|
971
1200
|
console.log(`Your wallet contract is ready for policy enforcement`);
|
|
972
1201
|
printOpenShellHint();
|
|
973
1202
|
}
|
|
@@ -1164,12 +1393,13 @@ function registerWalletCommands(program) {
|
|
|
1164
1393
|
console.error("walletContractAddress not set in config. Run `arc402 wallet deploy` first.");
|
|
1165
1394
|
process.exit(1);
|
|
1166
1395
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1396
|
+
const guardianKey = loadGuardianKey(config);
|
|
1397
|
+
if (!guardianKey) {
|
|
1398
|
+
console.error(`Guardian key not found. Expected at ~/.arc402/guardian.key (or guardianPrivateKey in config for legacy setups).`);
|
|
1169
1399
|
process.exit(1);
|
|
1170
1400
|
}
|
|
1171
1401
|
const provider = new ethers_1.ethers.JsonRpcProvider(config.rpcUrl);
|
|
1172
|
-
const guardianSigner = new ethers_1.ethers.Wallet(
|
|
1402
|
+
const guardianSigner = new ethers_1.ethers.Wallet(guardianKey, provider);
|
|
1173
1403
|
const walletContract = new ethers_1.ethers.Contract(config.walletContractAddress, abis_1.ARC402_WALLET_GUARDIAN_ABI, guardianSigner);
|
|
1174
1404
|
let tx;
|
|
1175
1405
|
if (opts.drain) {
|
|
@@ -1289,12 +1519,14 @@ function registerWalletCommands(program) {
|
|
|
1289
1519
|
value: "0x0",
|
|
1290
1520
|
});
|
|
1291
1521
|
await provider.waitForTransaction(txHash);
|
|
1292
|
-
|
|
1522
|
+
saveGuardianKey(guardianWallet.privateKey);
|
|
1523
|
+
if (config.guardianPrivateKey)
|
|
1524
|
+
delete config.guardianPrivateKey;
|
|
1293
1525
|
config.guardianAddress = guardianWallet.address;
|
|
1294
1526
|
(0, config_1.saveConfig)(config);
|
|
1295
1527
|
console.log("\n" + colors_1.c.success + colors_1.c.white(` Guardian set to: ${guardianWallet.address}`));
|
|
1296
1528
|
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(txHash));
|
|
1297
|
-
console.log(" " + colors_1.c.dim("Guardian private key saved to
|
|
1529
|
+
console.log(" " + colors_1.c.dim("Guardian private key saved to ~/.arc402/guardian.key (chmod 400)."));
|
|
1298
1530
|
console.log(" " + colors_1.c.warning + " " + colors_1.c.yellow("The guardian key can freeze your wallet. Store it separately from your hot key."));
|
|
1299
1531
|
});
|
|
1300
1532
|
// ─── policy-engine freeze / unfreeze (legacy — for PolicyEngine-level freeze) ──
|
|
@@ -2005,9 +2237,11 @@ function registerWalletCommands(program) {
|
|
|
2005
2237
|
txHashes.push(txHash);
|
|
2006
2238
|
}
|
|
2007
2239
|
}
|
|
2008
|
-
// Persist guardian key if generated
|
|
2240
|
+
// Persist guardian key if generated — save to restricted file, not config.json
|
|
2009
2241
|
if (guardianWallet) {
|
|
2010
|
-
|
|
2242
|
+
saveGuardianKey(guardianWallet.privateKey);
|
|
2243
|
+
if (config.guardianPrivateKey)
|
|
2244
|
+
delete config.guardianPrivateKey;
|
|
2011
2245
|
config.guardianAddress = guardianWallet.address;
|
|
2012
2246
|
(0, config_1.saveConfig)(config);
|
|
2013
2247
|
}
|
|
@@ -2019,7 +2253,7 @@ function registerWalletCommands(program) {
|
|
|
2019
2253
|
txHashes.forEach((h, i) => console.log(" " + colors_1.c.dim(`Tx ${i + 1}:`) + " " + colors_1.c.white(h)));
|
|
2020
2254
|
}
|
|
2021
2255
|
if (guardianWallet) {
|
|
2022
|
-
console.log(" " + colors_1.c.success + colors_1.c.dim(` Guardian key saved to
|
|
2256
|
+
console.log(" " + colors_1.c.success + colors_1.c.dim(` Guardian key saved to ~/.arc402/guardian.key — address: ${guardianWallet.address}`));
|
|
2023
2257
|
console.log(" " + colors_1.c.warning + " " + colors_1.c.yellow("Store the guardian private key separately from your hot key."));
|
|
2024
2258
|
}
|
|
2025
2259
|
console.log(colors_1.c.dim("\nVerify with: arc402 wallet status && arc402 wallet policy show"));
|