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.
- package/dist/commands/accept.d.ts.map +1 -1
- package/dist/commands/accept.js +17 -7
- package/dist/commands/accept.js.map +1 -1
- package/dist/commands/agent-handshake.d.ts.map +1 -1
- package/dist/commands/agent-handshake.js +9 -4
- package/dist/commands/agent-handshake.js.map +1 -1
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +14 -8
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/agreements.d.ts.map +1 -1
- package/dist/commands/agreements.js +51 -26
- package/dist/commands/agreements.js.map +1 -1
- package/dist/commands/arbitrator.d.ts.map +1 -1
- package/dist/commands/arbitrator.js +77 -20
- package/dist/commands/arbitrator.js.map +1 -1
- package/dist/commands/arena-handshake.d.ts.map +1 -1
- package/dist/commands/arena-handshake.js +14 -11
- package/dist/commands/arena-handshake.js.map +1 -1
- package/dist/commands/arena.d.ts.map +1 -1
- package/dist/commands/arena.js +4 -3
- package/dist/commands/arena.js.map +1 -1
- package/dist/commands/cancel.d.ts.map +1 -1
- package/dist/commands/cancel.js +20 -10
- package/dist/commands/cancel.js.map +1 -1
- package/dist/commands/channel.d.ts.map +1 -1
- package/dist/commands/channel.js +27 -17
- package/dist/commands/channel.js.map +1 -1
- package/dist/commands/coldstart.d.ts.map +1 -1
- package/dist/commands/coldstart.js +33 -22
- package/dist/commands/coldstart.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +34 -17
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +44 -37
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/deliver.d.ts.map +1 -1
- package/dist/commands/deliver.js +16 -3
- package/dist/commands/deliver.js.map +1 -1
- package/dist/commands/discover.d.ts.map +1 -1
- package/dist/commands/discover.js +2 -0
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/dispute.d.ts.map +1 -1
- package/dist/commands/dispute.js +11 -10
- package/dist/commands/dispute.js.map +1 -1
- package/dist/commands/endpoint.d.ts.map +1 -1
- package/dist/commands/endpoint.js +4 -3
- package/dist/commands/endpoint.js.map +1 -1
- package/dist/commands/feed.d.ts.map +1 -1
- package/dist/commands/feed.js.map +1 -1
- package/dist/commands/hire.d.ts.map +1 -1
- package/dist/commands/hire.js +15 -2
- package/dist/commands/hire.js.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +29 -29
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/negotiate.d.ts.map +1 -1
- package/dist/commands/negotiate.js +8 -7
- package/dist/commands/negotiate.js.map +1 -1
- package/dist/commands/openshell.d.ts.map +1 -1
- package/dist/commands/openshell.js +6 -5
- package/dist/commands/openshell.js.map +1 -1
- package/dist/commands/owner.d.ts.map +1 -1
- package/dist/commands/owner.js +7 -2
- package/dist/commands/owner.js.map +1 -1
- package/dist/commands/policy.d.ts.map +1 -1
- package/dist/commands/policy.js +22 -10
- package/dist/commands/policy.js.map +1 -1
- package/dist/commands/relay.d.ts.map +1 -1
- package/dist/commands/relay.js +6 -5
- package/dist/commands/relay.js.map +1 -1
- package/dist/commands/remediate.d.ts.map +1 -1
- package/dist/commands/remediate.js +3 -2
- package/dist/commands/remediate.js.map +1 -1
- package/dist/commands/reputation.d.ts.map +1 -1
- package/dist/commands/reputation.js +12 -5
- package/dist/commands/reputation.js.map +1 -1
- package/dist/commands/trust.d.ts.map +1 -1
- package/dist/commands/trust.js +16 -1
- package/dist/commands/trust.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +6 -4
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/wallet.d.ts.map +1 -1
- package/dist/commands/wallet.js +217 -170
- package/dist/commands/wallet.js.map +1 -1
- package/dist/commands/watch.d.ts +3 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +23 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/watchtower.d.ts.map +1 -1
- package/dist/commands/watchtower.js +30 -13
- package/dist/commands/watchtower.js.map +1 -1
- package/dist/commands/workroom.d.ts.map +1 -1
- package/dist/commands/workroom.js +123 -95
- package/dist/commands/workroom.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -2
- package/dist/config.js.map +1 -1
- package/dist/index.js +73 -38
- package/dist/index.js.map +1 -1
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +4 -2
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/tree.d.ts +7 -0
- package/dist/ui/tree.d.ts.map +1 -0
- package/dist/ui/tree.js +13 -0
- package/dist/ui/tree.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/accept.ts +19 -10
- package/src/commands/agent-handshake.ts +9 -4
- package/src/commands/agent.ts +15 -6
- package/src/commands/agreements.ts +51 -25
- package/src/commands/arbitrator.ts +71 -20
- package/src/commands/arena-handshake.ts +15 -8
- package/src/commands/arena.ts +4 -3
- package/src/commands/cancel.ts +19 -10
- package/src/commands/channel.ts +27 -17
- package/src/commands/coldstart.ts +29 -20
- package/src/commands/config.ts +34 -17
- package/src/commands/daemon.ts +45 -38
- package/src/commands/deliver.ts +16 -3
- package/src/commands/discover.ts +2 -0
- package/src/commands/dispute.ts +12 -10
- package/src/commands/endpoint.ts +4 -3
- package/src/commands/feed.ts +1 -0
- package/src/commands/hire.ts +17 -2
- package/src/commands/migrate.ts +28 -26
- package/src/commands/negotiate.ts +8 -7
- package/src/commands/openshell.ts +7 -5
- package/src/commands/owner.ts +7 -2
- package/src/commands/policy.ts +21 -10
- package/src/commands/relay.ts +6 -5
- package/src/commands/remediate.ts +4 -2
- package/src/commands/reputation.ts +13 -5
- package/src/commands/trust.ts +13 -1
- package/src/commands/verify.ts +7 -4
- package/src/commands/wallet.ts +218 -170
- package/src/commands/watch.ts +23 -0
- package/src/commands/watchtower.ts +29 -13
- package/src/commands/workroom.ts +121 -95
- package/src/config.ts +16 -2
- package/src/index.ts +43 -3
- package/src/ui/banner.ts +5 -2
- package/src/ui/tree.ts +16 -0
package/src/commands/wallet.ts
CHANGED
|
@@ -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(
|
|
71
|
-
console.log(
|
|
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("
|
|
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("
|
|
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("
|
|
118
|
-
console.log("
|
|
119
|
-
console.log("
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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(
|
|
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("
|
|
225
|
-
if (storageWiped) console.log(
|
|
226
|
-
else console.log("
|
|
227
|
-
console.log("\
|
|
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
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
-
|
|
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(
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
console.log(
|
|
528
|
-
console.log(
|
|
529
|
-
console.log(
|
|
530
|
-
console.log(
|
|
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(
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
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(
|
|
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(
|
|
637
|
-
|
|
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(`
|
|
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(
|
|
678
|
+
console.log(" " + c.success + " " + c.dim(description) + " " + c.dim(hash));
|
|
651
679
|
return hash;
|
|
652
680
|
},
|
|
653
681
|
);
|
|
654
682
|
|
|
655
|
-
console.log(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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(`
|
|
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(
|
|
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(`
|
|
716
|
-
|
|
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(
|
|
929
|
-
console.log(
|
|
930
|
-
console.log(
|
|
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(
|
|
1015
|
-
console.log(
|
|
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(
|
|
1030
|
-
console.log(
|
|
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(
|
|
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(
|
|
1102
|
-
console.log(
|
|
1103
|
-
console.log(
|
|
1104
|
-
console.log(
|
|
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(
|
|
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(
|
|
1214
|
-
console.log(
|
|
1215
|
-
console.log(
|
|
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(
|
|
1300
|
-
console.log(
|
|
1301
|
-
console.log(
|
|
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(
|
|
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(
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
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(
|
|
1453
|
-
console.log(
|
|
1454
|
-
console.log(
|
|
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(
|
|
1518
|
-
console.log(
|
|
1519
|
-
console.log(
|
|
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(
|
|
1592
|
-
console.log(
|
|
1593
|
-
console.log(
|
|
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(
|
|
1664
|
-
console.log(
|
|
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(
|
|
1952
|
+
console.log("\n" + c.success + c.white(" Governance setup complete"));
|
|
1919
1953
|
if (usedBatch) {
|
|
1920
|
-
console.log(
|
|
1954
|
+
console.log(" " + c.dim("Batch tx:") + " " + c.white(txHashes[0]));
|
|
1921
1955
|
} else {
|
|
1922
|
-
txHashes.forEach((h, i) => console.log(`
|
|
1956
|
+
txHashes.forEach((h, i) => console.log(" " + c.dim(`Tx ${i + 1}:`) + " " + c.white(h)));
|
|
1923
1957
|
}
|
|
1924
1958
|
if (guardianWallet) {
|
|
1925
|
-
console.log(`
|
|
1926
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
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(
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
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(
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
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(
|
|
2432
|
-
console.log(
|
|
2433
|
-
console.log(
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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(
|
|
2609
|
-
|
|
2610
|
-
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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(`
|
|
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(
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
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);
|