arc402-cli 0.3.4 → 0.4.1

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 (145) hide show
  1. package/dist/commands/accept.d.ts.map +1 -1
  2. package/dist/commands/accept.js +17 -7
  3. package/dist/commands/accept.js.map +1 -1
  4. package/dist/commands/agent-handshake.d.ts.map +1 -1
  5. package/dist/commands/agent-handshake.js +9 -4
  6. package/dist/commands/agent-handshake.js.map +1 -1
  7. package/dist/commands/agent.d.ts.map +1 -1
  8. package/dist/commands/agent.js +14 -8
  9. package/dist/commands/agent.js.map +1 -1
  10. package/dist/commands/agreements.d.ts.map +1 -1
  11. package/dist/commands/agreements.js +51 -26
  12. package/dist/commands/agreements.js.map +1 -1
  13. package/dist/commands/arbitrator.d.ts.map +1 -1
  14. package/dist/commands/arbitrator.js +77 -20
  15. package/dist/commands/arbitrator.js.map +1 -1
  16. package/dist/commands/arena-handshake.d.ts.map +1 -1
  17. package/dist/commands/arena-handshake.js +14 -11
  18. package/dist/commands/arena-handshake.js.map +1 -1
  19. package/dist/commands/arena.d.ts.map +1 -1
  20. package/dist/commands/arena.js +4 -3
  21. package/dist/commands/arena.js.map +1 -1
  22. package/dist/commands/cancel.d.ts.map +1 -1
  23. package/dist/commands/cancel.js +20 -10
  24. package/dist/commands/cancel.js.map +1 -1
  25. package/dist/commands/channel.d.ts.map +1 -1
  26. package/dist/commands/channel.js +27 -17
  27. package/dist/commands/channel.js.map +1 -1
  28. package/dist/commands/coldstart.d.ts.map +1 -1
  29. package/dist/commands/coldstart.js +33 -22
  30. package/dist/commands/coldstart.js.map +1 -1
  31. package/dist/commands/config.d.ts.map +1 -1
  32. package/dist/commands/config.js +34 -17
  33. package/dist/commands/config.js.map +1 -1
  34. package/dist/commands/daemon.d.ts.map +1 -1
  35. package/dist/commands/daemon.js +44 -37
  36. package/dist/commands/daemon.js.map +1 -1
  37. package/dist/commands/deliver.d.ts.map +1 -1
  38. package/dist/commands/deliver.js +16 -3
  39. package/dist/commands/deliver.js.map +1 -1
  40. package/dist/commands/discover.d.ts.map +1 -1
  41. package/dist/commands/discover.js +2 -0
  42. package/dist/commands/discover.js.map +1 -1
  43. package/dist/commands/dispute.d.ts.map +1 -1
  44. package/dist/commands/dispute.js +11 -10
  45. package/dist/commands/dispute.js.map +1 -1
  46. package/dist/commands/endpoint.d.ts.map +1 -1
  47. package/dist/commands/endpoint.js +4 -3
  48. package/dist/commands/endpoint.js.map +1 -1
  49. package/dist/commands/feed.d.ts.map +1 -1
  50. package/dist/commands/feed.js.map +1 -1
  51. package/dist/commands/hire.d.ts.map +1 -1
  52. package/dist/commands/hire.js +15 -2
  53. package/dist/commands/hire.js.map +1 -1
  54. package/dist/commands/migrate.d.ts.map +1 -1
  55. package/dist/commands/migrate.js +29 -29
  56. package/dist/commands/migrate.js.map +1 -1
  57. package/dist/commands/negotiate.d.ts.map +1 -1
  58. package/dist/commands/negotiate.js +8 -7
  59. package/dist/commands/negotiate.js.map +1 -1
  60. package/dist/commands/openshell.d.ts.map +1 -1
  61. package/dist/commands/openshell.js +6 -5
  62. package/dist/commands/openshell.js.map +1 -1
  63. package/dist/commands/owner.d.ts.map +1 -1
  64. package/dist/commands/owner.js +7 -2
  65. package/dist/commands/owner.js.map +1 -1
  66. package/dist/commands/policy.d.ts.map +1 -1
  67. package/dist/commands/policy.js +22 -10
  68. package/dist/commands/policy.js.map +1 -1
  69. package/dist/commands/relay.d.ts.map +1 -1
  70. package/dist/commands/relay.js +6 -5
  71. package/dist/commands/relay.js.map +1 -1
  72. package/dist/commands/remediate.d.ts.map +1 -1
  73. package/dist/commands/remediate.js +3 -2
  74. package/dist/commands/remediate.js.map +1 -1
  75. package/dist/commands/reputation.d.ts.map +1 -1
  76. package/dist/commands/reputation.js +12 -5
  77. package/dist/commands/reputation.js.map +1 -1
  78. package/dist/commands/trust.d.ts.map +1 -1
  79. package/dist/commands/trust.js +16 -1
  80. package/dist/commands/trust.js.map +1 -1
  81. package/dist/commands/verify.d.ts.map +1 -1
  82. package/dist/commands/verify.js +6 -4
  83. package/dist/commands/verify.js.map +1 -1
  84. package/dist/commands/wallet.d.ts.map +1 -1
  85. package/dist/commands/wallet.js +217 -170
  86. package/dist/commands/wallet.js.map +1 -1
  87. package/dist/commands/watch.d.ts +3 -0
  88. package/dist/commands/watch.d.ts.map +1 -0
  89. package/dist/commands/watch.js +23 -0
  90. package/dist/commands/watch.js.map +1 -0
  91. package/dist/commands/watchtower.d.ts.map +1 -1
  92. package/dist/commands/watchtower.js +30 -13
  93. package/dist/commands/watchtower.js.map +1 -1
  94. package/dist/commands/workroom.d.ts.map +1 -1
  95. package/dist/commands/workroom.js +123 -95
  96. package/dist/commands/workroom.js.map +1 -1
  97. package/dist/config.d.ts.map +1 -1
  98. package/dist/config.js +16 -2
  99. package/dist/config.js.map +1 -1
  100. package/dist/index.js +73 -38
  101. package/dist/index.js.map +1 -1
  102. package/dist/ui/banner.d.ts.map +1 -1
  103. package/dist/ui/banner.js +4 -2
  104. package/dist/ui/banner.js.map +1 -1
  105. package/dist/ui/tree.d.ts +7 -0
  106. package/dist/ui/tree.d.ts.map +1 -0
  107. package/dist/ui/tree.js +13 -0
  108. package/dist/ui/tree.js.map +1 -0
  109. package/package.json +1 -1
  110. package/src/commands/accept.ts +19 -10
  111. package/src/commands/agent-handshake.ts +9 -4
  112. package/src/commands/agent.ts +15 -6
  113. package/src/commands/agreements.ts +51 -25
  114. package/src/commands/arbitrator.ts +71 -20
  115. package/src/commands/arena-handshake.ts +15 -8
  116. package/src/commands/arena.ts +4 -3
  117. package/src/commands/cancel.ts +19 -10
  118. package/src/commands/channel.ts +27 -17
  119. package/src/commands/coldstart.ts +29 -20
  120. package/src/commands/config.ts +34 -17
  121. package/src/commands/daemon.ts +45 -38
  122. package/src/commands/deliver.ts +16 -3
  123. package/src/commands/discover.ts +2 -0
  124. package/src/commands/dispute.ts +12 -10
  125. package/src/commands/endpoint.ts +4 -3
  126. package/src/commands/feed.ts +1 -0
  127. package/src/commands/hire.ts +17 -2
  128. package/src/commands/migrate.ts +28 -26
  129. package/src/commands/negotiate.ts +8 -7
  130. package/src/commands/openshell.ts +7 -5
  131. package/src/commands/owner.ts +7 -2
  132. package/src/commands/policy.ts +21 -10
  133. package/src/commands/relay.ts +6 -5
  134. package/src/commands/remediate.ts +4 -2
  135. package/src/commands/reputation.ts +13 -5
  136. package/src/commands/trust.ts +13 -1
  137. package/src/commands/verify.ts +7 -4
  138. package/src/commands/wallet.ts +218 -170
  139. package/src/commands/watch.ts +23 -0
  140. package/src/commands/watchtower.ts +29 -13
  141. package/src/commands/workroom.ts +121 -95
  142. package/src/config.ts +16 -2
  143. package/src/index.ts +43 -3
  144. package/src/ui/banner.ts +5 -2
  145. package/src/ui/tree.ts +16 -0
@@ -17,6 +17,10 @@ import { clearWCSession } from "../walletconnect-session";
17
17
  import { handleWalletError } from "../wallet-router";
18
18
  import { requestCoinbaseSmartWalletSignature } from "../coinbase-smart-wallet";
19
19
  import { sendTelegramMessage } from "../telegram-notify";
20
+ import { renderTree } from "../ui/tree";
21
+ import { startSpinner } from "../ui/spinner";
22
+ import { c } from "../ui/colors";
23
+ import { formatAddress } from "../ui/format";
20
24
 
21
25
  const POLICY_ENGINE_DEFAULT = "0x44102e70c2A366632d98Fe40d892a2501fC7fFF2";
22
26
 
@@ -66,9 +70,9 @@ async function runWalletOnboardingCeremony(
66
70
  alreadyDefiEnabled = await policyGov.defiAccessEnabled(walletAddress);
67
71
  } catch { /* assume not enabled */ }
68
72
 
69
- console.log("\n── Onboarding ceremony ────────────────────────────────────────");
70
- console.log(` PolicyEngine: ${policyAddress}`);
71
- console.log(` Wallet: ${walletAddress}`);
73
+ console.log("\n" + c.dim("── Onboarding ceremony ────────────────────────────────────────"));
74
+ console.log(" " + c.dim("PolicyEngine:") + " " + c.white(policyAddress));
75
+ console.log(" " + c.dim("Wallet: ") + " " + c.white(walletAddress));
72
76
 
73
77
  // Step 1: registerWallet (if not already done)
74
78
  if (!alreadyRegistered) {
@@ -86,7 +90,7 @@ async function runWalletOnboardingCeremony(
86
90
  value: "0x0",
87
91
  }, "registerWallet on PolicyEngine");
88
92
  } else {
89
- console.log(" registerWallet — already done by constructor");
93
+ console.log(" " + c.success + c.dim(" registerWallet — already done by constructor"));
90
94
  }
91
95
 
92
96
  // Step 2: enableDefiAccess (if not already done)
@@ -97,7 +101,7 @@ async function runWalletOnboardingCeremony(
97
101
  value: "0x0",
98
102
  }, "enableDefiAccess on PolicyEngine");
99
103
  } else {
100
- console.log(" enableDefiAccess — already done by constructor");
104
+ console.log(" " + c.success + c.dim(" enableDefiAccess — already done by constructor"));
101
105
  }
102
106
 
103
107
  // Steps 3–6: category limits (always set — idempotent)
@@ -113,10 +117,10 @@ async function runWalletOnboardingCeremony(
113
117
  }, `setCategoryLimitFor: ${name} → ${amountEth} ETH`);
114
118
  }
115
119
 
116
- console.log("── Onboarding complete ─────────────────────────────────────────");
117
- console.log("💡 Tip: For production security, also configure:");
118
- console.log(" arc402 wallet set-velocity-limit <eth> — wallet-level hourly ETH cap");
119
- console.log(" arc402 wallet policy set-daily-limit --category general --amount <eth> — daily per-category cap");
120
+ console.log(c.dim("── Onboarding complete ─────────────────────────────────────────"));
121
+ console.log(c.dim("Tip: For production security, also configure:"));
122
+ console.log(" " + c.dim("arc402 wallet set-velocity-limit <eth> — wallet-level hourly ETH cap"));
123
+ console.log(" " + c.dim("arc402 wallet policy set-daily-limit --category general --amount <eth> — daily per-category cap"));
120
124
  }
121
125
 
122
126
  function printOpenShellHint(): void {
@@ -174,10 +178,18 @@ export function registerWalletCommands(program: Command): void {
174
178
  if (opts.json) {
175
179
  console.log(JSON.stringify(payload, null, 2));
176
180
  } else {
177
- console.log(`${payload.address}\nETH=${payload.ethBalance}\nUSDC=${payload.usdcBalance}\nTrust=${payload.trustScore} ${payload.trustTier}`);
178
- if (payload.walletContractAddress) console.log(`Contract=${payload.walletContractAddress}`);
179
- if (contractFrozen !== null) console.log(`Frozen=${contractFrozen}`);
180
- if (contractGuardian && contractGuardian !== ethers.ZeroAddress) console.log(`Guardian=${contractGuardian}`);
181
+ const treeItems: { label: string; value: string; last?: boolean }[] = [
182
+ { label: "Address", value: payload.address },
183
+ { label: "Network", value: payload.network },
184
+ { label: "ETH", value: payload.ethBalance + " ETH" },
185
+ { label: "USDC", value: payload.usdcBalance + " USDC" },
186
+ { label: "Trust", value: `${payload.trustScore} ${payload.trustTier}` },
187
+ ];
188
+ if (payload.walletContractAddress) treeItems.push({ label: "Contract", value: payload.walletContractAddress });
189
+ if (contractFrozen !== null) treeItems.push({ label: "Frozen", value: contractFrozen ? c.red("YES") : c.green("no") });
190
+ if (contractGuardian && contractGuardian !== ethers.ZeroAddress) treeItems.push({ label: "Guardian", value: contractGuardian });
191
+ treeItems[treeItems.length - 1].last = true;
192
+ renderTree(treeItems);
181
193
  }
182
194
  });
183
195
 
@@ -212,7 +224,7 @@ export function registerWalletCommands(program: Command): void {
212
224
  if (opts.json) {
213
225
  console.log(JSON.stringify({ ok: false, error: `Could not delete ${wcStoragePath}: ${msg}` }));
214
226
  } else {
215
- console.warn(`⚠ Could not delete ${wcStoragePath}: ${msg}`);
227
+ console.warn(" " + c.warning + " " + c.yellow(`Could not delete ${wcStoragePath}: ${msg}`));
216
228
  console.warn(" You may need to delete it manually.");
217
229
  }
218
230
  return;
@@ -221,10 +233,10 @@ export function registerWalletCommands(program: Command): void {
221
233
  if (opts.json) {
222
234
  console.log(JSON.stringify({ ok: true, hadSession, storageWiped }));
223
235
  } else {
224
- console.log(" WalletConnect session cleared");
225
- if (storageWiped) console.log(` Storage wiped: ${wcStoragePath}`);
226
- else console.log(" (No storage file found — already clean)");
227
- console.log("\nNext: run any wallet command and scan the fresh QR code.");
236
+ console.log(" " + c.success + c.white(" WalletConnect session cleared"));
237
+ if (storageWiped) console.log(" " + c.dim("Storage wiped:") + " " + c.white(wcStoragePath));
238
+ else console.log(" " + c.dim("(No storage file found — already clean)"));
239
+ console.log("\n" + c.dim("Next: run any wallet command and scan the fresh QR code."));
228
240
  }
229
241
  });
230
242
 
@@ -249,9 +261,11 @@ export function registerWalletCommands(program: Command): void {
249
261
  walletFactoryAddress: defaults.walletFactoryAddress,
250
262
  };
251
263
  saveConfig(config);
252
- console.log(`Address: ${generated.address}`);
253
- console.log(`Config saved to ${getConfigPath()}`);
254
- console.log(`Next: fund your wallet with ETH, then run: arc402 wallet deploy`);
264
+ renderTree([
265
+ { label: "Address", value: generated.address },
266
+ { label: "Config", value: getConfigPath(), last: true },
267
+ ]);
268
+ console.log(c.dim("Next: fund your wallet with ETH, then run: arc402 wallet deploy"));
255
269
  });
256
270
 
257
271
  // ─── import ────────────────────────────────────────────────────────────────
@@ -281,9 +295,11 @@ export function registerWalletCommands(program: Command): void {
281
295
  walletFactoryAddress: defaults.walletFactoryAddress,
282
296
  };
283
297
  saveConfig(config);
284
- console.log(`Address: ${imported.address}`);
285
- console.log(`Config saved to ${getConfigPath()}`);
286
- console.warn(`WARN: Store your private key safely — anyone with it controls your wallet`);
298
+ renderTree([
299
+ { label: "Address", value: imported.address },
300
+ { label: "Config", value: getConfigPath(), last: true },
301
+ ]);
302
+ console.warn(" " + c.warning + " " + c.yellow("Store your private key safely — anyone with it controls your wallet"));
287
303
  });
288
304
 
289
305
  // ─── fund ──────────────────────────────────────────────────────────────────
@@ -319,7 +335,10 @@ export function registerWalletCommands(program: Command): void {
319
335
  if (opts.json) {
320
336
  console.log(JSON.stringify({ address, balance: formatted, balanceWei: ethBalance.toString() }));
321
337
  } else {
322
- console.log(`Balance: ${formatted} ETH`);
338
+ renderTree([
339
+ { label: "Address", value: address },
340
+ { label: "Balance", value: `${formatted} ETH`, last: true },
341
+ ]);
323
342
  }
324
343
  });
325
344
 
@@ -518,16 +537,19 @@ export function registerWalletCommands(program: Command): void {
518
537
  config.walletContractAddress = senderAddress;
519
538
  config.ownerAddress = ownerAddress;
520
539
  saveConfig(config);
521
- console.log(`\n ARC402Wallet deployed (sponsored) at: ${senderAddress}`);
522
- console.log("Gas sponsorship active — initial setup ops are free");
523
- console.log(`Owner: ${ownerAddress}`);
524
- console.log(`\n⚠ IMPORTANT: Onboarding ceremony was not run on this wallet.`);
525
- console.log(` Category spend limits have NOT been configured. All executeSpend and`);
526
- console.log(` executeTokenSpend calls will fail with "PolicyEngine: category not configured"`);
527
- console.log(` until you run governance setup manually via WalletConnect:`);
528
- console.log(`\n arc402 wallet governance setup`);
529
- console.log(`\n This must be done before making any spend from this wallet.`);
530
- console.log(`\nNext: arc402 wallet set-passkey <x> <y> --sponsored`);
540
+ console.log("\n" + c.success + c.white(" ARC402Wallet deployed (sponsored)"));
541
+ renderTree([
542
+ { label: "Wallet", value: senderAddress },
543
+ { label: "Owner", value: ownerAddress },
544
+ { label: "Gas", value: "Sponsorship active initial setup ops are free", last: true },
545
+ ]);
546
+ console.log(" " + c.warning + " " + c.yellow("IMPORTANT: Onboarding ceremony was not run on this wallet."));
547
+ console.log(c.dim(" Category spend limits have NOT been configured. All executeSpend and"));
548
+ console.log(c.dim(` executeTokenSpend calls will fail with "PolicyEngine: category not configured"`));
549
+ console.log(c.dim(" until you run governance setup manually via WalletConnect:"));
550
+ console.log("\n" + c.dim(" arc402 wallet governance setup"));
551
+ console.log("\n" + c.dim(" This must be done before making any spend from this wallet."));
552
+ console.log("\n" + c.dim("Next: arc402 wallet set-passkey <x> <y> --sponsored"));
531
553
  printOpenShellHint();
532
554
  } else if (opts.smartWallet) {
533
555
  const { txHash, account } = await requestCoinbaseSmartWalletSignature(
@@ -564,10 +586,13 @@ export function registerWalletCommands(program: Command): void {
564
586
  config.walletContractAddress = walletAddress;
565
587
  config.ownerAddress = account;
566
588
  saveConfig(config);
567
- console.log(`ARC402Wallet deployed at: ${walletAddress}`);
568
- console.log(`Owner: ${account} (your Base Smart Wallet)`);
569
- console.log(`Your wallet contract is ready for policy enforcement`);
570
- console.log(`\nNext: run 'arc402 wallet set-guardian' to configure the emergency guardian key.`);
589
+ console.log("\n" + c.success + c.white(" ARC402Wallet deployed"));
590
+ renderTree([
591
+ { label: "Wallet", value: walletAddress },
592
+ { label: "Owner", value: account + c.dim(" (Base Smart Wallet)"), last: true },
593
+ ]);
594
+ console.log(c.dim("Your wallet contract is ready for policy enforcement"));
595
+ console.log(c.dim("\nNext: run 'arc402 wallet set-guardian' to configure the emergency guardian key."));
571
596
  printOpenShellHint();
572
597
  } else if (config.walletConnectProjectId) {
573
598
  const telegramOpts = config.telegramBotToken && config.telegramChatId
@@ -584,7 +609,7 @@ export function registerWalletCommands(program: Command): void {
584
609
 
585
610
  const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
586
611
  const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
587
- console.log(`\n Connected: ${shortAddr} on ${networkName}`);
612
+ console.log("\n" + c.success + c.white(` Connected: ${shortAddr} on ${networkName}`));
588
613
 
589
614
  if (telegramOpts) {
590
615
  // Send "connected" message with a deploy confirmation button.
@@ -633,8 +658,11 @@ export function registerWalletCommands(program: Command): void {
633
658
  config.walletContractAddress = walletAddress;
634
659
  config.ownerAddress = account;
635
660
  saveConfig(config);
636
- console.log(`\n ARC402Wallet deployed at: ${walletAddress}`);
637
- console.log(`Owner: ${account} (your phone wallet)`);
661
+ console.log("\n" + c.success + c.white(" ARC402Wallet deployed"));
662
+ renderTree([
663
+ { label: "Wallet", value: walletAddress },
664
+ { label: "Owner", value: account + c.dim(" (phone wallet)"), last: true },
665
+ ]);
638
666
 
639
667
  // ── Mandatory onboarding ceremony (same WalletConnect session) ────────
640
668
  console.log("\nStarting mandatory onboarding ceremony in this WalletConnect session...");
@@ -644,28 +672,28 @@ export function registerWalletCommands(program: Command): void {
644
672
  config,
645
673
  provider,
646
674
  async (call, description) => {
647
- console.log(` Sending: ${description}`);
675
+ console.log(" " + c.dim(`Sending: ${description}`));
648
676
  const hash = await sendTransactionWithSession(client, session, account, chainId, call);
649
677
  await provider.waitForTransaction(hash, 1);
650
- console.log(` ✓ ${description}: ${hash}`);
678
+ console.log(" " + c.success + " " + c.dim(description) + " " + c.dim(hash));
651
679
  return hash;
652
680
  },
653
681
  );
654
682
 
655
- console.log(`Your wallet contract is ready for policy enforcement`);
683
+ console.log(c.dim("Your wallet contract is ready for policy enforcement"));
656
684
  const paymasterUrl2 = config.paymasterUrl ?? NETWORK_DEFAULTS[config.network]?.paymasterUrl;
657
685
  const deployedBalance = await provider.getBalance(walletAddress);
658
686
  if (paymasterUrl2 && deployedBalance < BigInt(1_000_000_000_000_000)) {
659
- console.log("Gas sponsorship active — initial setup ops are free");
687
+ console.log(c.dim("Gas sponsorship active — initial setup ops are free"));
660
688
  }
661
- console.log(`\nNext: run 'arc402 wallet set-guardian' to configure the emergency guardian key.`);
689
+ console.log(c.dim("\nNext: run 'arc402 wallet set-guardian' to configure the emergency guardian key."));
662
690
  printOpenShellHint();
663
691
  } else {
664
692
  console.warn("⚠ WalletConnect not configured. Using stored private key (insecure).");
665
693
  console.warn(" Run `arc402 config set walletConnectProjectId <id>` to enable phone wallet signing.");
666
694
  const { signer, address } = await requireSigner(config);
667
695
  const factory = new ethers.Contract(factoryAddress, WALLET_FACTORY_ABI, signer);
668
- console.log(`Deploying ARC402Wallet via factory at ${factoryAddress}...`);
696
+ const deploySpinner = startSpinner(`Deploying ARC402Wallet via factory at ${factoryAddress}...`);
669
697
  const tx = await factory.createWallet("0x0000000071727De22E5E9d8BAf0edAc6f37da032");
670
698
  const receipt = await tx.wait();
671
699
  let walletAddress: string | null = null;
@@ -679,9 +707,10 @@ export function registerWalletCommands(program: Command): void {
679
707
  } catch { /* skip unparseable logs */ }
680
708
  }
681
709
  if (!walletAddress) {
682
- console.error("Could not find WalletCreated event in receipt. Check the transaction on-chain.");
710
+ deploySpinner.fail("Could not find WalletCreated event in receipt. Check the transaction on-chain.");
683
711
  process.exit(1);
684
712
  }
713
+ deploySpinner.succeed("Wallet deployed");
685
714
 
686
715
  // Generate guardian key (separate from hot key) and call setGuardian
687
716
  const guardianWallet = ethers.Wallet.createRandom();
@@ -704,16 +733,19 @@ export function registerWalletCommands(program: Command): void {
704
733
  config,
705
734
  provider2,
706
735
  async (call, description) => {
707
- console.log(` Sending: ${description}`);
736
+ console.log(" " + c.dim(`Sending: ${description}`));
708
737
  const tx2 = await signer.sendTransaction({ to: call.to, data: call.data, value: call.value === "0x0" ? 0n : BigInt(call.value) });
709
738
  await tx2.wait(1);
710
- console.log(` ✓ ${description}: ${tx2.hash}`);
739
+ console.log(" " + c.success + " " + c.dim(description) + " " + c.dim(tx2.hash));
711
740
  return tx2.hash;
712
741
  },
713
742
  );
714
743
 
715
- console.log(`ARC402Wallet deployed at: ${walletAddress}`);
716
- console.log(`Guardian key generated: ${guardianWallet.address}`);
744
+ console.log(` ${c.success} ARC402Wallet deployed`);
745
+ renderTree([
746
+ { label: "Wallet", value: walletAddress },
747
+ { label: "Guardian", value: guardianWallet.address, last: true },
748
+ ]);
717
749
  console.log(`Guardian private key saved to config (keep it safe — used for emergency freeze only)`);
718
750
  console.log(`Your wallet contract is ready for policy enforcement`);
719
751
  printOpenShellHint();
@@ -925,9 +957,9 @@ export function registerWalletCommands(program: Command): void {
925
957
  );
926
958
 
927
959
  await provider.waitForTransaction(txHash);
928
- console.log(`\n Active policy updated`);
929
- console.log(` Tx: ${txHash}`);
930
- console.log(` Policy: ${policyIdHex}`);
960
+ console.log("\n" + c.success + c.white(" Active policy updated"));
961
+ console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
962
+ console.log(" " + c.dim("Policy:") + " " + c.white(policyIdHex));
931
963
  });
932
964
 
933
965
  // ─── freeze (guardian key — emergency wallet freeze) ──────────────────────
@@ -1011,11 +1043,11 @@ export function registerWalletCommands(program: Command): void {
1011
1043
 
1012
1044
  const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
1013
1045
  const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
1014
- console.log(`\n Connected: ${shortAddr} on ${networkName}`);
1015
- console.log(`\nWallet to unfreeze: ${config.walletContractAddress}`);
1046
+ console.log("\n" + c.success + c.white(` Connected: ${shortAddr} on ${networkName}`));
1047
+ console.log("\n" + c.dim("Wallet to unfreeze:") + " " + c.white(config.walletContractAddress ?? ""));
1016
1048
  // WalletConnect approval already confirmed intent — sending automatically
1017
1049
 
1018
- console.log("Sending transaction...");
1050
+ console.log(c.dim("Sending transaction..."));
1019
1051
  const txHash = await sendTransactionWithSession(client, session, account, chainId, {
1020
1052
  to: config.walletContractAddress,
1021
1053
  data: walletInterface.encodeFunctionData("unfreeze", []),
@@ -1026,8 +1058,8 @@ export function registerWalletCommands(program: Command): void {
1026
1058
  if (opts.json) {
1027
1059
  console.log(JSON.stringify({ txHash, walletAddress: config.walletContractAddress }));
1028
1060
  } else {
1029
- console.log(`\n Wallet ${config.walletContractAddress} unfrozen`);
1030
- console.log(` Tx: ${txHash}`);
1061
+ console.log("\n" + c.success + c.white(` Wallet ${config.walletContractAddress} unfrozen`));
1062
+ console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
1031
1063
  }
1032
1064
  });
1033
1065
 
@@ -1084,10 +1116,10 @@ export function registerWalletCommands(program: Command): void {
1084
1116
 
1085
1117
  const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
1086
1118
  const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
1087
- console.log(`\n Connected: ${shortAddr} on ${networkName}`);
1119
+ console.log("\n" + c.success + c.white(` Connected: ${shortAddr} on ${networkName}`));
1088
1120
  // WalletConnect approval already confirmed intent — sending automatically
1089
1121
 
1090
- console.log("Sending transaction...");
1122
+ console.log(c.dim("Sending transaction..."));
1091
1123
  const txHash = await sendTransactionWithSession(client, session, account, chainId, {
1092
1124
  to: config.walletContractAddress,
1093
1125
  data: walletInterface.encodeFunctionData("setGuardian", [guardianWallet.address]),
@@ -1098,10 +1130,10 @@ export function registerWalletCommands(program: Command): void {
1098
1130
  config.guardianPrivateKey = guardianWallet.privateKey;
1099
1131
  config.guardianAddress = guardianWallet.address;
1100
1132
  saveConfig(config);
1101
- console.log(`\n Guardian set to: ${guardianWallet.address}`);
1102
- console.log(` Tx: ${txHash}`);
1103
- console.log(` Guardian private key saved to config.`);
1104
- console.log(` WARN: The guardian key can freeze your wallet. Store it separately from your hot key.`);
1133
+ console.log("\n" + c.success + c.white(` Guardian set to: ${guardianWallet.address}`));
1134
+ console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
1135
+ console.log(" " + c.dim("Guardian private key saved to config."));
1136
+ console.log(" " + c.warning + " " + c.yellow("The guardian key can freeze your wallet. Store it separately from your hot key."));
1105
1137
  });
1106
1138
 
1107
1139
  // ─── policy-engine freeze / unfreeze (legacy — for PolicyEngine-level freeze) ──
@@ -1198,11 +1230,11 @@ export function registerWalletCommands(program: Command): void {
1198
1230
 
1199
1231
  const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
1200
1232
  const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
1201
- console.log(`\n Connected: ${shortAddr} on ${networkName}`);
1233
+ console.log("\n" + c.success + c.white(` Connected: ${shortAddr} on ${networkName}`));
1202
1234
 
1203
1235
  // WalletConnect approval already confirmed intent — sending automatically
1204
1236
 
1205
- console.log("Sending transaction...");
1237
+ console.log(c.dim("Sending transaction..."));
1206
1238
  const txHash = await sendTransactionWithSession(client, session, account, chainId, {
1207
1239
  to: config.walletContractAddress,
1208
1240
  data: calldata,
@@ -1210,9 +1242,9 @@ export function registerWalletCommands(program: Command): void {
1210
1242
  });
1211
1243
 
1212
1244
  const unlockAt = new Date(Date.now() + 2 * 24 * 60 * 60 * 1000);
1213
- console.log(`\n Registry upgrade proposed`);
1214
- console.log(` Tx: ${txHash}`);
1215
- console.log(` Unlock at: ${unlockAt.toISOString()} (approximately)`);
1245
+ console.log("\n" + c.success + c.white(" Registry upgrade proposed"));
1246
+ console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
1247
+ console.log(" " + c.dim("Unlock at:") + " " + c.white(unlockAt.toISOString()) + c.dim(" (approximately)"));
1216
1248
  console.log(`\nNext steps:`);
1217
1249
  console.log(` Wait 2 days, then run:`);
1218
1250
  console.log(` arc402 wallet execute-registry-upgrade`);
@@ -1296,9 +1328,9 @@ export function registerWalletCommands(program: Command): void {
1296
1328
  confirmedRegistry = await walletContract.registry();
1297
1329
  } catch { /* use pendingRegistry as fallback */ }
1298
1330
 
1299
- console.log(`\n Registry upgrade executed`);
1300
- console.log(` Tx: ${txHash}`);
1301
- console.log(` New registry: ${confirmedRegistry}`);
1331
+ console.log("\n" + c.success + c.white(" Registry upgrade executed"));
1332
+ console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
1333
+ console.log(" " + c.dim("New registry:") + " " + c.white(confirmedRegistry));
1302
1334
  if (confirmedRegistry.toLowerCase() === pendingRegistry.toLowerCase()) {
1303
1335
  console.log(` Registry updated successfully — addresses now resolve through new registry.`);
1304
1336
  } else {
@@ -1352,7 +1384,7 @@ export function registerWalletCommands(program: Command): void {
1352
1384
  } catch { /* ignore */ }
1353
1385
 
1354
1386
  if (alreadyWhitelisted) {
1355
- console.log(`✓ ${checksumTarget} is already whitelisted for ${config.walletContractAddress}`);
1387
+ console.log(" " + c.success + " " + c.white(checksumTarget) + c.dim(` is already whitelisted for ${config.walletContractAddress}`));
1356
1388
  process.exit(0);
1357
1389
  }
1358
1390
 
@@ -1387,10 +1419,12 @@ export function registerWalletCommands(program: Command): void {
1387
1419
  if (opts.json) {
1388
1420
  console.log(JSON.stringify({ ok: true, txHash, wallet: config.walletContractAddress, target: checksumTarget }));
1389
1421
  } else {
1390
- console.log(`\n Contract whitelisted`);
1391
- console.log(` Tx: ${txHash}`);
1392
- console.log(` Wallet: ${config.walletContractAddress}`);
1393
- console.log(` Target: ${checksumTarget}`);
1422
+ console.log("\n" + c.success + c.white(" Contract whitelisted"));
1423
+ renderTree([
1424
+ { label: "Tx", value: txHash },
1425
+ { label: "Wallet", value: config.walletContractAddress ?? "" },
1426
+ { label: "Target", value: checksumTarget, last: true },
1427
+ ]);
1394
1428
  }
1395
1429
  });
1396
1430
 
@@ -1449,9 +1483,9 @@ export function registerWalletCommands(program: Command): void {
1449
1483
  );
1450
1484
 
1451
1485
  await provider.waitForTransaction(txHash);
1452
- console.log(`\n X402 interceptor updated`);
1453
- console.log(` Tx: ${txHash}`);
1454
- console.log(` Interceptor: ${checksumAddress}`);
1486
+ console.log("\n" + c.success + c.white(" X402 interceptor updated"));
1487
+ console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
1488
+ console.log(" " + c.dim("Interceptor:") + " " + c.white(checksumAddress));
1455
1489
  });
1456
1490
 
1457
1491
  // ─── set-velocity-limit ────────────────────────────────────────────────────
@@ -1514,9 +1548,9 @@ export function registerWalletCommands(program: Command): void {
1514
1548
  );
1515
1549
 
1516
1550
  await provider.waitForTransaction(txHash);
1517
- console.log(`\n Velocity limit updated`);
1518
- console.log(` Tx: ${txHash}`);
1519
- console.log(` New limit: ${limitEth} ETH per rolling window`);
1551
+ console.log("\n" + c.success + c.white(" Velocity limit updated"));
1552
+ console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
1553
+ console.log(" " + c.dim("New limit:") + " " + c.white(`${limitEth} ETH per rolling window`));
1520
1554
  });
1521
1555
 
1522
1556
  // ─── register-policy ───────────────────────────────────────────────────────
@@ -1588,9 +1622,9 @@ export function registerWalletCommands(program: Command): void {
1588
1622
  );
1589
1623
 
1590
1624
  await provider.waitForTransaction(txHash);
1591
- console.log(`\n Wallet registered on PolicyEngine`);
1592
- console.log(` Tx: ${txHash}`);
1593
- console.log(`\nNext: run 'arc402 wallet policy set-limit' to configure spending limits.`);
1625
+ console.log("\n" + c.success + c.white(" Wallet registered on PolicyEngine"));
1626
+ console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
1627
+ console.log(c.dim("\nNext: run 'arc402 wallet policy set-limit' to configure spending limits."));
1594
1628
  });
1595
1629
 
1596
1630
  // ─── cancel-registry-upgrade ───────────────────────────────────────────────
@@ -1660,8 +1694,8 @@ export function registerWalletCommands(program: Command): void {
1660
1694
  config
1661
1695
  );
1662
1696
 
1663
- console.log(`\n Registry upgrade cancelled`);
1664
- console.log(` Tx: ${txHash}`);
1697
+ console.log("\n" + c.success + c.white(" Registry upgrade cancelled"));
1698
+ console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
1665
1699
  });
1666
1700
 
1667
1701
  // ─── governance setup ──────────────────────────────────────────────────────
@@ -1915,17 +1949,17 @@ export function registerWalletCommands(program: Command): void {
1915
1949
  saveConfig(config);
1916
1950
  }
1917
1951
 
1918
- console.log(`\n Governance setup complete`);
1952
+ console.log("\n" + c.success + c.white(" Governance setup complete"));
1919
1953
  if (usedBatch) {
1920
- console.log(` Batch tx: ${txHashes[0]}`);
1954
+ console.log(" " + c.dim("Batch tx:") + " " + c.white(txHashes[0]));
1921
1955
  } else {
1922
- txHashes.forEach((h, i) => console.log(` Tx ${i + 1}: ${h}`));
1956
+ txHashes.forEach((h, i) => console.log(" " + c.dim(`Tx ${i + 1}:`) + " " + c.white(h)));
1923
1957
  }
1924
1958
  if (guardianWallet) {
1925
- console.log(` Guardian key saved to config — address: ${guardianWallet.address}`);
1926
- console.log(` WARN: Store the guardian private key separately from your hot key.`);
1959
+ console.log(" " + c.success + c.dim(` Guardian key saved to config — address: ${guardianWallet.address}`));
1960
+ console.log(" " + c.warning + " " + c.yellow("Store the guardian private key separately from your hot key."));
1927
1961
  }
1928
- console.log(`\nVerify with: arc402 wallet status && arc402 wallet policy show`);
1962
+ console.log(c.dim("\nVerify with: arc402 wallet status && arc402 wallet policy show"));
1929
1963
  });
1930
1964
 
1931
1965
  // ─── authorize-machine-key ─────────────────────────────────────────────────
@@ -1962,7 +1996,7 @@ export function registerWalletCommands(program: Command): void {
1962
1996
  } catch { /* ignore */ }
1963
1997
 
1964
1998
  if (alreadyAuthorized) {
1965
- console.log(`\n ${checksumKey} is already authorized as a machine key on ${config.walletContractAddress}`);
1999
+ console.log("\n" + c.success + " " + c.white(checksumKey) + c.dim(` is already authorized as a machine key on ${config.walletContractAddress}`));
1966
2000
  process.exit(0);
1967
2001
  }
1968
2002
 
@@ -1990,24 +2024,26 @@ export function registerWalletCommands(program: Command): void {
1990
2024
  }
1991
2025
  );
1992
2026
 
1993
- console.log(`\n Connected: ${account}`);
1994
- console.log("Sending authorizeMachineKey transaction...");
2027
+ console.log("\n" + c.success + c.white(` Connected: ${account}`));
2028
+ console.log(c.dim("Sending authorizeMachineKey transaction..."));
1995
2029
 
1996
2030
  const hash = await sendTransactionWithSession(client, session, account, chainId, txData);
1997
- console.log(`\nTransaction submitted: ${hash}`);
1998
- console.log("Waiting for confirmation...");
2031
+ console.log("\n" + c.dim("Transaction submitted:") + " " + c.white(hash));
2032
+ console.log(c.dim("Waiting for confirmation..."));
1999
2033
 
2000
2034
  const receipt = await provider.waitForTransaction(hash, 1, 60000);
2001
2035
  if (!receipt || receipt.status !== 1) {
2002
- console.error("Transaction failed.");
2036
+ console.error(c.failure + " " + c.red("Transaction failed."));
2003
2037
  process.exit(1);
2004
2038
  }
2005
2039
 
2006
2040
  const confirmed = await walletContract.authorizedMachineKeys(checksumKey);
2007
- console.log(`\n Machine key authorized: ${confirmed ? "YES" : "NO"}`);
2008
- console.log(` Wallet: ${config.walletContractAddress}`);
2009
- console.log(` Machine key: ${checksumKey}`);
2010
- console.log(` Tx: ${hash}`);
2041
+ console.log("\n" + c.success + c.white(` Machine key authorized: ${confirmed ? "YES" : "NO"}`));
2042
+ renderTree([
2043
+ { label: "Wallet", value: config.walletContractAddress ?? "" },
2044
+ { label: "Machine key", value: checksumKey },
2045
+ { label: "Tx", value: hash, last: true },
2046
+ ]);
2011
2047
 
2012
2048
  await client.disconnect({ topic: session.topic, reason: { code: 6000, message: "done" } });
2013
2049
  process.exit(0);
@@ -2070,8 +2106,8 @@ export function registerWalletCommands(program: Command): void {
2070
2106
  { telegramOpts, prompt: `Revoke machine key ${checksumKey} on ARC402Wallet` }
2071
2107
  );
2072
2108
 
2073
- console.log(`\n Connected: ${account}`);
2074
- console.log("Sending revokeMachineKey transaction...");
2109
+ console.log("\n" + c.success + c.white(` Connected: ${account}`));
2110
+ console.log(c.dim("Sending revokeMachineKey transaction..."));
2075
2111
 
2076
2112
  const hash = await sendTransactionWithSession(client, session, account, chainId, {
2077
2113
  to: config.walletContractAddress,
@@ -2079,20 +2115,22 @@ export function registerWalletCommands(program: Command): void {
2079
2115
  value: "0x0",
2080
2116
  });
2081
2117
 
2082
- console.log(`\nTransaction submitted: ${hash}`);
2083
- console.log("Waiting for confirmation...");
2118
+ console.log("\n" + c.dim("Transaction submitted:") + " " + c.white(hash));
2119
+ console.log(c.dim("Waiting for confirmation..."));
2084
2120
 
2085
2121
  const receipt = await provider.waitForTransaction(hash, 1, 60000);
2086
2122
  if (!receipt || receipt.status !== 1) {
2087
- console.error("Transaction failed.");
2123
+ console.error(c.failure + " " + c.red("Transaction failed."));
2088
2124
  process.exit(1);
2089
2125
  }
2090
2126
 
2091
2127
  const stillAuthorized = await walletContract.authorizedMachineKeys(checksumKey);
2092
- console.log(`\n Machine key revoked: ${stillAuthorized ? "NO (still authorized — check tx)" : "YES"}`);
2093
- console.log(` Wallet: ${config.walletContractAddress}`);
2094
- console.log(` Machine key: ${checksumKey}`);
2095
- console.log(` Tx: ${hash}`);
2128
+ console.log("\n" + c.success + c.white(` Machine key revoked: ${stillAuthorized ? "NO (still authorized — check tx)" : "YES"}`));
2129
+ renderTree([
2130
+ { label: "Wallet", value: config.walletContractAddress ?? "" },
2131
+ { label: "Machine key", value: checksumKey },
2132
+ { label: "Tx", value: hash, last: true },
2133
+ ]);
2096
2134
 
2097
2135
  await client.disconnect({ topic: session.topic, reason: { code: 6000, message: "done" } });
2098
2136
  process.exit(0);
@@ -2218,11 +2256,13 @@ export function registerWalletCommands(program: Command): void {
2218
2256
  if (opts.json) {
2219
2257
  console.log(JSON.stringify({ walletAddress: walletAddr, contextId, taskType: opts.taskType, txHash: receipt?.hash }));
2220
2258
  } else {
2221
- console.log(`✓ Context opened`);
2222
- console.log(` contextId: ${contextId}`);
2223
- console.log(` taskType: ${opts.taskType}`);
2224
- console.log(` Tx: ${receipt?.hash}`);
2225
- console.log(`\nNote: Each context allows only one spend. Call \`arc402 wallet attest\` then \`arc402 wallet drain\` (or executeSpend directly).`);
2259
+ console.log(" " + c.success + c.white(" Context opened"));
2260
+ renderTree([
2261
+ { label: "contextId", value: contextId },
2262
+ { label: "taskType", value: opts.taskType },
2263
+ { label: "Tx", value: receipt?.hash ?? "", last: true },
2264
+ ]);
2265
+ console.log(c.dim("\nNote: Each context allows only one spend. Call `arc402 wallet attest` then `arc402 wallet drain` (or executeSpend directly)."));
2226
2266
  }
2227
2267
  });
2228
2268
 
@@ -2293,14 +2333,16 @@ export function registerWalletCommands(program: Command): void {
2293
2333
  txHash: receipt?.hash,
2294
2334
  }));
2295
2335
  } else {
2296
- console.log(`✓ Attestation created`);
2297
- console.log(` attestationId: ${attestationId}`);
2298
- console.log(` recipient: ${checksumRecipient}`);
2299
- console.log(` amount: ${opts.amount} ETH`);
2300
- console.log(` token: ${tokenAddress === ethers.ZeroAddress ? "ETH" : tokenAddress}`);
2301
- console.log(` expiresAt: ${new Date(expiresAt * 1000).toISOString()}`);
2302
- console.log(` Tx: ${receipt?.hash}`);
2303
- console.log(`\nUse this attestationId in \`arc402 wallet drain\` or your spend flow.`);
2336
+ console.log(" " + c.success + c.white(" Attestation created"));
2337
+ renderTree([
2338
+ { label: "attestationId", value: attestationId },
2339
+ { label: "recipient", value: checksumRecipient },
2340
+ { label: "amount", value: opts.amount + " ETH" },
2341
+ { label: "token", value: tokenAddress === ethers.ZeroAddress ? "ETH" : tokenAddress },
2342
+ { label: "expiresAt", value: new Date(expiresAt * 1000).toISOString() },
2343
+ { label: "Tx", value: receipt?.hash ?? "", last: true },
2344
+ ]);
2345
+ console.log(c.dim("\nUse this attestationId in `arc402 wallet drain` or your spend flow."));
2304
2346
  }
2305
2347
  });
2306
2348
 
@@ -2428,9 +2470,9 @@ export function registerWalletCommands(program: Command): void {
2428
2470
  if (opts.json) {
2429
2471
  console.log(JSON.stringify({ walletAddress: walletAddr, txHash: receipt?.hash, contextOpen: false }));
2430
2472
  } else {
2431
- console.log(`✓ Context closed`);
2432
- console.log(` Tx: ${receipt?.hash}`);
2433
- console.log(` Wallet: ${walletAddr}`);
2473
+ console.log(" " + c.success + c.white(" Context closed"));
2474
+ console.log(" " + c.dim("Tx:") + " " + c.white(receipt?.hash ?? ""));
2475
+ console.log(" " + c.dim("Wallet:") + " " + c.white(walletAddr));
2434
2476
  }
2435
2477
  });
2436
2478
 
@@ -2536,23 +2578,23 @@ export function registerWalletCommands(program: Command): void {
2536
2578
  // ── Step 1: context cleanup ────────────────────────────────────────────
2537
2579
  const isOpen: boolean = await walletContract.contextOpen();
2538
2580
  if (isOpen) {
2539
- console.log("Stale context found — closing it first...");
2581
+ console.log(c.dim("Stale context found — closing it first..."));
2540
2582
  const closeTx = await walletContract.closeContext();
2541
2583
  await closeTx.wait(2);
2542
- console.log(` Closed: ${closeTx.hash}`);
2584
+ console.log(" " + c.success + c.dim(` Closed: ${closeTx.hash}`));
2543
2585
  }
2544
2586
 
2545
2587
  // ── Step 2: openContext ────────────────────────────────────────────────
2546
2588
  const contextId = ethers.keccak256(ethers.toUtf8Bytes(`drain-${Date.now()}`));
2547
- console.log("Opening context...");
2589
+ console.log(c.dim("Opening context..."));
2548
2590
  const openTx = await walletContract.openContext(contextId, "drain");
2549
2591
  const openReceipt = await openTx.wait(1);
2550
- console.log(` openContext: ${openReceipt?.hash}`);
2592
+ console.log(" " + c.success + c.dim(` openContext: ${openReceipt?.hash}`));
2551
2593
 
2552
2594
  // ── Step 3: attest (direct on wallet — onlyOwnerOrMachineKey, NOT via executeContractCall)
2553
2595
  const attestationId = ethers.hexlify(ethers.randomBytes(32));
2554
2596
  const expiry = Math.floor(Date.now() / 1000) + 600; // 10 min TTL
2555
- console.log("Creating attestation (direct on wallet)...");
2597
+ console.log(c.dim("Creating attestation (direct on wallet)..."));
2556
2598
  const attestTx = await walletContract.attest(
2557
2599
  attestationId,
2558
2600
  "spend",
@@ -2563,10 +2605,10 @@ export function registerWalletCommands(program: Command): void {
2563
2605
  expiry,
2564
2606
  );
2565
2607
  const attestReceipt = await attestTx.wait(1);
2566
- console.log(` attest: ${attestReceipt?.hash}`);
2608
+ console.log(" " + c.success + c.dim(` attest: ${attestReceipt?.hash}`));
2567
2609
 
2568
2610
  // ── Step 4: executeSpend ───────────────────────────────────────────────
2569
- console.log("Executing spend...");
2611
+ console.log(c.dim("Executing spend..."));
2570
2612
  let spendReceiptHash: string | undefined;
2571
2613
  try {
2572
2614
  const spendTx = await walletContract.executeSpend(
@@ -2580,13 +2622,13 @@ export function registerWalletCommands(program: Command): void {
2580
2622
  } catch (e) {
2581
2623
  handleWalletError(e);
2582
2624
  }
2583
- console.log(` executeSpend: ${spendReceiptHash}`);
2625
+ console.log(" " + c.success + c.dim(` executeSpend: ${spendReceiptHash}`));
2584
2626
 
2585
2627
  // ── Step 5: closeContext ───────────────────────────────────────────────
2586
- console.log("Closing context...");
2628
+ console.log(c.dim("Closing context..."));
2587
2629
  const closeTx2 = await walletContract.closeContext();
2588
2630
  const closeReceipt = await closeTx2.wait(1);
2589
- console.log(` closeContext: ${closeReceipt?.hash}`);
2631
+ console.log(" " + c.success + c.dim(` closeContext: ${closeReceipt?.hash}`));
2590
2632
 
2591
2633
  const newBalance = await provider.getBalance(walletAddr);
2592
2634
  if (opts.json) {
@@ -2605,9 +2647,11 @@ export function registerWalletCommands(program: Command): void {
2605
2647
  remainingBalance: ethers.formatEther(newBalance),
2606
2648
  }));
2607
2649
  } else {
2608
- console.log(`\n Drain complete`);
2609
- console.log(` Sent: ${ethers.formatEther(drainAmount)} ETH → ${checksumRecipient}`);
2610
- console.log(` Remaining: ${ethers.formatEther(newBalance)} ETH`);
2650
+ console.log("\n" + c.success + c.white(" Drain complete"));
2651
+ renderTree([
2652
+ { label: "Sent", value: `${ethers.formatEther(drainAmount)} ETH → ${checksumRecipient}` },
2653
+ { label: "Remaining", value: `${ethers.formatEther(newBalance)} ETH`, last: true },
2654
+ ]);
2611
2655
  }
2612
2656
  });
2613
2657
 
@@ -2735,23 +2779,23 @@ export function registerWalletCommands(program: Command): void {
2735
2779
  // ── Step 1: context cleanup ──────────────────────────────────────────────
2736
2780
  const isOpenT: boolean = await walletContractT.contextOpen();
2737
2781
  if (isOpenT) {
2738
- console.log("Stale context found — closing it first...");
2782
+ console.log(c.dim("Stale context found — closing it first..."));
2739
2783
  const closeTxT = await walletContractT.closeContext();
2740
2784
  await closeTxT.wait(2);
2741
- console.log(` Closed: ${closeTxT.hash}`);
2785
+ console.log(" " + c.success + c.dim(` Closed: ${closeTxT.hash}`));
2742
2786
  }
2743
2787
 
2744
2788
  // ── Step 2: openContext ──────────────────────────────────────────────────
2745
2789
  const contextIdT = ethers.keccak256(ethers.toUtf8Bytes(`drain-token-${Date.now()}`));
2746
- console.log("Opening context...");
2790
+ console.log(c.dim("Opening context..."));
2747
2791
  const openTxT = await walletContractT.openContext(contextIdT, "drain");
2748
2792
  const openReceiptT = await openTxT.wait(1);
2749
- console.log(` openContext: ${openReceiptT?.hash}`);
2793
+ console.log(" " + c.success + c.dim(` openContext: ${openReceiptT?.hash}`));
2750
2794
 
2751
2795
  // ── Step 3: attest with token address ────────────────────────────────────
2752
2796
  const attestationIdT = ethers.hexlify(ethers.randomBytes(32));
2753
2797
  const expiryT = Math.floor(Date.now() / 1000) + 600; // 10 min TTL
2754
- console.log("Creating attestation (with token address)...");
2798
+ console.log(c.dim("Creating attestation (with token address)..."));
2755
2799
  const attestTxT = await walletContractT.attest(
2756
2800
  attestationIdT,
2757
2801
  "spend",
@@ -2762,10 +2806,10 @@ export function registerWalletCommands(program: Command): void {
2762
2806
  expiryT,
2763
2807
  );
2764
2808
  const attestReceiptT = await attestTxT.wait(1);
2765
- console.log(` attest: ${attestReceiptT?.hash}`);
2809
+ console.log(" " + c.success + c.dim(` attest: ${attestReceiptT?.hash}`));
2766
2810
 
2767
2811
  // ── Step 4: executeTokenSpend ────────────────────────────────────────────
2768
- console.log("Executing token spend...");
2812
+ console.log(c.dim("Executing token spend..."));
2769
2813
  const spendTxT = await walletContractT.executeTokenSpend(
2770
2814
  checksumRecipient,
2771
2815
  tokenAmount,
@@ -2774,13 +2818,13 @@ export function registerWalletCommands(program: Command): void {
2774
2818
  attestationIdT,
2775
2819
  );
2776
2820
  const spendReceiptT = await spendTxT.wait(1);
2777
- console.log(` executeTokenSpend: ${spendReceiptT?.hash}`);
2821
+ console.log(" " + c.success + c.dim(` executeTokenSpend: ${spendReceiptT?.hash}`));
2778
2822
 
2779
2823
  // ── Step 5: closeContext ─────────────────────────────────────────────────
2780
- console.log("Closing context...");
2824
+ console.log(c.dim("Closing context..."));
2781
2825
  const closeTxT2 = await walletContractT.closeContext();
2782
2826
  const closeReceiptT = await closeTxT2.wait(1);
2783
- console.log(` closeContext: ${closeReceiptT?.hash}`);
2827
+ console.log(" " + c.success + c.dim(` closeContext: ${closeReceiptT?.hash}`));
2784
2828
 
2785
2829
  const newTokenBalance: bigint = await erc20.balanceOf(walletAddr);
2786
2830
  if (opts.json) {
@@ -2800,10 +2844,12 @@ export function registerWalletCommands(program: Command): void {
2800
2844
  remainingTokenBalance: ethers.formatUnits(newTokenBalance, decimals),
2801
2845
  }));
2802
2846
  } else {
2803
- console.log(`\n Token drain complete`);
2804
- console.log(` Sent: ${amountArg} → ${checksumRecipient}`);
2805
- console.log(` Token: ${tokenAddress}`);
2806
- console.log(` Remaining: ${ethers.formatUnits(newTokenBalance, decimals)}`);
2847
+ console.log("\n" + c.success + c.white(" Token drain complete"));
2848
+ renderTree([
2849
+ { label: "Sent", value: `${amountArg} → ${checksumRecipient}` },
2850
+ { label: "Token", value: tokenAddress },
2851
+ { label: "Remaining", value: ethers.formatUnits(newTokenBalance, decimals), last: true },
2852
+ ]);
2807
2853
  }
2808
2854
  });
2809
2855
 
@@ -2866,25 +2912,27 @@ export function registerWalletCommands(program: Command): void {
2866
2912
  }
2867
2913
  );
2868
2914
 
2869
- console.log(`\n Connected: ${account}`);
2870
- console.log("Sending setPasskey transaction...");
2915
+ console.log("\n" + c.success + c.white(` Connected: ${account}`));
2916
+ console.log(c.dim("Sending setPasskey transaction..."));
2871
2917
 
2872
2918
  const hash = await sendTransactionWithSession(client, session, account, chainId, txData);
2873
- console.log(`\nTransaction submitted: ${hash}`);
2874
- console.log("Waiting for confirmation...");
2919
+ console.log("\n" + c.dim("Transaction submitted:") + " " + c.white(hash));
2920
+ console.log(c.dim("Waiting for confirmation..."));
2875
2921
 
2876
2922
  const receipt = await provider.waitForTransaction(hash, 1, 60000);
2877
2923
  if (!receipt || receipt.status !== 1) {
2878
- console.error("Transaction failed.");
2924
+ console.error(c.failure + " " + c.red("Transaction failed."));
2879
2925
  process.exit(1);
2880
2926
  }
2881
2927
 
2882
- console.log(`\n Passkey activated on ARC402Wallet`);
2883
- console.log(` Wallet: ${config.walletContractAddress}`);
2884
- console.log(` pubKeyX: ${pubKeyX}`);
2885
- console.log(` pubKeyY: ${pubKeyY}`);
2886
- console.log(` Tx: ${hash}`);
2887
- console.log(`\nGovernance ops now require Face ID instead of MetaMask.`);
2928
+ console.log("\n" + c.success + c.white(" Passkey activated on ARC402Wallet"));
2929
+ renderTree([
2930
+ { label: "Wallet", value: config.walletContractAddress ?? "" },
2931
+ { label: "pubKeyX", value: pubKeyX },
2932
+ { label: "pubKeyY", value: pubKeyY },
2933
+ { label: "Tx", value: hash, last: true },
2934
+ ]);
2935
+ console.log(c.dim("\nGovernance ops now require Face ID instead of MetaMask."));
2888
2936
 
2889
2937
  await client.disconnect({ topic: session.topic, reason: { code: 6000, message: "done" } });
2890
2938
  process.exit(0);