arc402-cli 0.4.0 → 0.4.2
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/arbitrator.d.ts.map +1 -1
- package/dist/commands/arbitrator.js +62 -13
- package/dist/commands/arbitrator.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/config.d.ts.map +1 -1
- package/dist/commands/config.js +1 -0
- package/dist/commands/config.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/hire.d.ts.map +1 -1
- package/dist/commands/hire.js +12 -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 +2 -1
- 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.js +6 -5
- package/dist/commands/relay.js.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 +202 -165
- package/dist/commands/wallet.js.map +1 -1
- 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 +1 -0
- package/dist/config.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/arbitrator.ts +45 -10
- package/src/commands/arena.ts +4 -3
- package/src/commands/cancel.ts +19 -10
- package/src/commands/config.ts +1 -0
- package/src/commands/deliver.ts +16 -3
- package/src/commands/discover.ts +2 -0
- package/src/commands/dispute.ts +12 -10
- package/src/commands/hire.ts +9 -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 +2 -1
- package/src/commands/policy.ts +18 -10
- package/src/commands/relay.ts +5 -5
- package/src/commands/remediate.ts +2 -2
- package/src/commands/reputation.ts +9 -5
- package/src/commands/trust.ts +10 -1
- package/src/commands/verify.ts +5 -4
- package/src/commands/wallet.ts +203 -165
- package/src/commands/watchtower.ts +25 -13
- package/src/commands/workroom.ts +121 -95
- package/src/config.ts +2 -1
package/src/commands/wallet.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { sendTelegramMessage } from "../telegram-notify";
|
|
|
20
20
|
import { renderTree } from "../ui/tree";
|
|
21
21
|
import { startSpinner } from "../ui/spinner";
|
|
22
22
|
import { c } from "../ui/colors";
|
|
23
|
+
import { formatAddress } from "../ui/format";
|
|
23
24
|
|
|
24
25
|
const POLICY_ENGINE_DEFAULT = "0x44102e70c2A366632d98Fe40d892a2501fC7fFF2";
|
|
25
26
|
|
|
@@ -69,9 +70,9 @@ async function runWalletOnboardingCeremony(
|
|
|
69
70
|
alreadyDefiEnabled = await policyGov.defiAccessEnabled(walletAddress);
|
|
70
71
|
} catch { /* assume not enabled */ }
|
|
71
72
|
|
|
72
|
-
console.log("\n── Onboarding ceremony ────────────────────────────────────────");
|
|
73
|
-
console.log(
|
|
74
|
-
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));
|
|
75
76
|
|
|
76
77
|
// Step 1: registerWallet (if not already done)
|
|
77
78
|
if (!alreadyRegistered) {
|
|
@@ -89,7 +90,7 @@ async function runWalletOnboardingCeremony(
|
|
|
89
90
|
value: "0x0",
|
|
90
91
|
}, "registerWallet on PolicyEngine");
|
|
91
92
|
} else {
|
|
92
|
-
console.log("
|
|
93
|
+
console.log(" " + c.success + c.dim(" registerWallet — already done by constructor"));
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
// Step 2: enableDefiAccess (if not already done)
|
|
@@ -100,7 +101,7 @@ async function runWalletOnboardingCeremony(
|
|
|
100
101
|
value: "0x0",
|
|
101
102
|
}, "enableDefiAccess on PolicyEngine");
|
|
102
103
|
} else {
|
|
103
|
-
console.log("
|
|
104
|
+
console.log(" " + c.success + c.dim(" enableDefiAccess — already done by constructor"));
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
// Steps 3–6: category limits (always set — idempotent)
|
|
@@ -116,10 +117,10 @@ async function runWalletOnboardingCeremony(
|
|
|
116
117
|
}, `setCategoryLimitFor: ${name} → ${amountEth} ETH`);
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
console.log("── Onboarding complete ─────────────────────────────────────────");
|
|
120
|
-
console.log("
|
|
121
|
-
console.log("
|
|
122
|
-
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"));
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
function printOpenShellHint(): void {
|
|
@@ -177,10 +178,18 @@ export function registerWalletCommands(program: Command): void {
|
|
|
177
178
|
if (opts.json) {
|
|
178
179
|
console.log(JSON.stringify(payload, null, 2));
|
|
179
180
|
} else {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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);
|
|
184
193
|
}
|
|
185
194
|
});
|
|
186
195
|
|
|
@@ -215,7 +224,7 @@ export function registerWalletCommands(program: Command): void {
|
|
|
215
224
|
if (opts.json) {
|
|
216
225
|
console.log(JSON.stringify({ ok: false, error: `Could not delete ${wcStoragePath}: ${msg}` }));
|
|
217
226
|
} else {
|
|
218
|
-
console.warn(
|
|
227
|
+
console.warn(" " + c.warning + " " + c.yellow(`Could not delete ${wcStoragePath}: ${msg}`));
|
|
219
228
|
console.warn(" You may need to delete it manually.");
|
|
220
229
|
}
|
|
221
230
|
return;
|
|
@@ -224,10 +233,10 @@ export function registerWalletCommands(program: Command): void {
|
|
|
224
233
|
if (opts.json) {
|
|
225
234
|
console.log(JSON.stringify({ ok: true, hadSession, storageWiped }));
|
|
226
235
|
} else {
|
|
227
|
-
console.log("
|
|
228
|
-
if (storageWiped) console.log(
|
|
229
|
-
else console.log("
|
|
230
|
-
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."));
|
|
231
240
|
}
|
|
232
241
|
});
|
|
233
242
|
|
|
@@ -252,9 +261,11 @@ export function registerWalletCommands(program: Command): void {
|
|
|
252
261
|
walletFactoryAddress: defaults.walletFactoryAddress,
|
|
253
262
|
};
|
|
254
263
|
saveConfig(config);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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"));
|
|
258
269
|
});
|
|
259
270
|
|
|
260
271
|
// ─── import ────────────────────────────────────────────────────────────────
|
|
@@ -284,9 +295,11 @@ export function registerWalletCommands(program: Command): void {
|
|
|
284
295
|
walletFactoryAddress: defaults.walletFactoryAddress,
|
|
285
296
|
};
|
|
286
297
|
saveConfig(config);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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"));
|
|
290
303
|
});
|
|
291
304
|
|
|
292
305
|
// ─── fund ──────────────────────────────────────────────────────────────────
|
|
@@ -524,16 +537,19 @@ export function registerWalletCommands(program: Command): void {
|
|
|
524
537
|
config.walletContractAddress = senderAddress;
|
|
525
538
|
config.ownerAddress = ownerAddress;
|
|
526
539
|
saveConfig(config);
|
|
527
|
-
console.log(
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
console.log(
|
|
534
|
-
console.log(
|
|
535
|
-
console.log(
|
|
536
|
-
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"));
|
|
537
553
|
printOpenShellHint();
|
|
538
554
|
} else if (opts.smartWallet) {
|
|
539
555
|
const { txHash, account } = await requestCoinbaseSmartWalletSignature(
|
|
@@ -570,10 +586,13 @@ export function registerWalletCommands(program: Command): void {
|
|
|
570
586
|
config.walletContractAddress = walletAddress;
|
|
571
587
|
config.ownerAddress = account;
|
|
572
588
|
saveConfig(config);
|
|
573
|
-
console.log(
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
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."));
|
|
577
596
|
printOpenShellHint();
|
|
578
597
|
} else if (config.walletConnectProjectId) {
|
|
579
598
|
const telegramOpts = config.telegramBotToken && config.telegramChatId
|
|
@@ -590,7 +609,7 @@ export function registerWalletCommands(program: Command): void {
|
|
|
590
609
|
|
|
591
610
|
const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
|
|
592
611
|
const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
|
|
593
|
-
console.log(
|
|
612
|
+
console.log("\n" + c.success + c.white(` Connected: ${shortAddr} on ${networkName}`));
|
|
594
613
|
|
|
595
614
|
if (telegramOpts) {
|
|
596
615
|
// Send "connected" message with a deploy confirmation button.
|
|
@@ -639,8 +658,11 @@ export function registerWalletCommands(program: Command): void {
|
|
|
639
658
|
config.walletContractAddress = walletAddress;
|
|
640
659
|
config.ownerAddress = account;
|
|
641
660
|
saveConfig(config);
|
|
642
|
-
console.log(
|
|
643
|
-
|
|
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
|
+
]);
|
|
644
666
|
|
|
645
667
|
// ── Mandatory onboarding ceremony (same WalletConnect session) ────────
|
|
646
668
|
console.log("\nStarting mandatory onboarding ceremony in this WalletConnect session...");
|
|
@@ -650,21 +672,21 @@ export function registerWalletCommands(program: Command): void {
|
|
|
650
672
|
config,
|
|
651
673
|
provider,
|
|
652
674
|
async (call, description) => {
|
|
653
|
-
console.log(`
|
|
675
|
+
console.log(" " + c.dim(`Sending: ${description}`));
|
|
654
676
|
const hash = await sendTransactionWithSession(client, session, account, chainId, call);
|
|
655
677
|
await provider.waitForTransaction(hash, 1);
|
|
656
|
-
console.log(
|
|
678
|
+
console.log(" " + c.success + " " + c.dim(description) + " " + c.dim(hash));
|
|
657
679
|
return hash;
|
|
658
680
|
},
|
|
659
681
|
);
|
|
660
682
|
|
|
661
|
-
console.log(
|
|
683
|
+
console.log(c.dim("Your wallet contract is ready for policy enforcement"));
|
|
662
684
|
const paymasterUrl2 = config.paymasterUrl ?? NETWORK_DEFAULTS[config.network]?.paymasterUrl;
|
|
663
685
|
const deployedBalance = await provider.getBalance(walletAddress);
|
|
664
686
|
if (paymasterUrl2 && deployedBalance < BigInt(1_000_000_000_000_000)) {
|
|
665
|
-
console.log("Gas sponsorship active — initial setup ops are free");
|
|
687
|
+
console.log(c.dim("Gas sponsorship active — initial setup ops are free"));
|
|
666
688
|
}
|
|
667
|
-
console.log(
|
|
689
|
+
console.log(c.dim("\nNext: run 'arc402 wallet set-guardian' to configure the emergency guardian key."));
|
|
668
690
|
printOpenShellHint();
|
|
669
691
|
} else {
|
|
670
692
|
console.warn("⚠ WalletConnect not configured. Using stored private key (insecure).");
|
|
@@ -711,10 +733,10 @@ export function registerWalletCommands(program: Command): void {
|
|
|
711
733
|
config,
|
|
712
734
|
provider2,
|
|
713
735
|
async (call, description) => {
|
|
714
|
-
console.log(`
|
|
736
|
+
console.log(" " + c.dim(`Sending: ${description}`));
|
|
715
737
|
const tx2 = await signer.sendTransaction({ to: call.to, data: call.data, value: call.value === "0x0" ? 0n : BigInt(call.value) });
|
|
716
738
|
await tx2.wait(1);
|
|
717
|
-
console.log(
|
|
739
|
+
console.log(" " + c.success + " " + c.dim(description) + " " + c.dim(tx2.hash));
|
|
718
740
|
return tx2.hash;
|
|
719
741
|
},
|
|
720
742
|
);
|
|
@@ -935,9 +957,9 @@ export function registerWalletCommands(program: Command): void {
|
|
|
935
957
|
);
|
|
936
958
|
|
|
937
959
|
await provider.waitForTransaction(txHash);
|
|
938
|
-
console.log(
|
|
939
|
-
console.log(
|
|
940
|
-
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));
|
|
941
963
|
});
|
|
942
964
|
|
|
943
965
|
// ─── freeze (guardian key — emergency wallet freeze) ──────────────────────
|
|
@@ -1021,11 +1043,11 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1021
1043
|
|
|
1022
1044
|
const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
|
|
1023
1045
|
const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
|
|
1024
|
-
console.log(
|
|
1025
|
-
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 ?? ""));
|
|
1026
1048
|
// WalletConnect approval already confirmed intent — sending automatically
|
|
1027
1049
|
|
|
1028
|
-
console.log("Sending transaction...");
|
|
1050
|
+
console.log(c.dim("Sending transaction..."));
|
|
1029
1051
|
const txHash = await sendTransactionWithSession(client, session, account, chainId, {
|
|
1030
1052
|
to: config.walletContractAddress,
|
|
1031
1053
|
data: walletInterface.encodeFunctionData("unfreeze", []),
|
|
@@ -1036,8 +1058,8 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1036
1058
|
if (opts.json) {
|
|
1037
1059
|
console.log(JSON.stringify({ txHash, walletAddress: config.walletContractAddress }));
|
|
1038
1060
|
} else {
|
|
1039
|
-
console.log(
|
|
1040
|
-
console.log(
|
|
1061
|
+
console.log("\n" + c.success + c.white(` Wallet ${config.walletContractAddress} unfrozen`));
|
|
1062
|
+
console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
|
|
1041
1063
|
}
|
|
1042
1064
|
});
|
|
1043
1065
|
|
|
@@ -1094,10 +1116,10 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1094
1116
|
|
|
1095
1117
|
const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
|
|
1096
1118
|
const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
|
|
1097
|
-
console.log(
|
|
1119
|
+
console.log("\n" + c.success + c.white(` Connected: ${shortAddr} on ${networkName}`));
|
|
1098
1120
|
// WalletConnect approval already confirmed intent — sending automatically
|
|
1099
1121
|
|
|
1100
|
-
console.log("Sending transaction...");
|
|
1122
|
+
console.log(c.dim("Sending transaction..."));
|
|
1101
1123
|
const txHash = await sendTransactionWithSession(client, session, account, chainId, {
|
|
1102
1124
|
to: config.walletContractAddress,
|
|
1103
1125
|
data: walletInterface.encodeFunctionData("setGuardian", [guardianWallet.address]),
|
|
@@ -1108,10 +1130,10 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1108
1130
|
config.guardianPrivateKey = guardianWallet.privateKey;
|
|
1109
1131
|
config.guardianAddress = guardianWallet.address;
|
|
1110
1132
|
saveConfig(config);
|
|
1111
|
-
console.log(
|
|
1112
|
-
console.log(
|
|
1113
|
-
console.log(
|
|
1114
|
-
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."));
|
|
1115
1137
|
});
|
|
1116
1138
|
|
|
1117
1139
|
// ─── policy-engine freeze / unfreeze (legacy — for PolicyEngine-level freeze) ──
|
|
@@ -1208,11 +1230,11 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1208
1230
|
|
|
1209
1231
|
const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
|
|
1210
1232
|
const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
|
|
1211
|
-
console.log(
|
|
1233
|
+
console.log("\n" + c.success + c.white(` Connected: ${shortAddr} on ${networkName}`));
|
|
1212
1234
|
|
|
1213
1235
|
// WalletConnect approval already confirmed intent — sending automatically
|
|
1214
1236
|
|
|
1215
|
-
console.log("Sending transaction...");
|
|
1237
|
+
console.log(c.dim("Sending transaction..."));
|
|
1216
1238
|
const txHash = await sendTransactionWithSession(client, session, account, chainId, {
|
|
1217
1239
|
to: config.walletContractAddress,
|
|
1218
1240
|
data: calldata,
|
|
@@ -1220,9 +1242,9 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1220
1242
|
});
|
|
1221
1243
|
|
|
1222
1244
|
const unlockAt = new Date(Date.now() + 2 * 24 * 60 * 60 * 1000);
|
|
1223
|
-
console.log(
|
|
1224
|
-
console.log(
|
|
1225
|
-
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)"));
|
|
1226
1248
|
console.log(`\nNext steps:`);
|
|
1227
1249
|
console.log(` Wait 2 days, then run:`);
|
|
1228
1250
|
console.log(` arc402 wallet execute-registry-upgrade`);
|
|
@@ -1306,9 +1328,9 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1306
1328
|
confirmedRegistry = await walletContract.registry();
|
|
1307
1329
|
} catch { /* use pendingRegistry as fallback */ }
|
|
1308
1330
|
|
|
1309
|
-
console.log(
|
|
1310
|
-
console.log(
|
|
1311
|
-
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));
|
|
1312
1334
|
if (confirmedRegistry.toLowerCase() === pendingRegistry.toLowerCase()) {
|
|
1313
1335
|
console.log(` Registry updated successfully — addresses now resolve through new registry.`);
|
|
1314
1336
|
} else {
|
|
@@ -1362,7 +1384,7 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1362
1384
|
} catch { /* ignore */ }
|
|
1363
1385
|
|
|
1364
1386
|
if (alreadyWhitelisted) {
|
|
1365
|
-
console.log(
|
|
1387
|
+
console.log(" " + c.success + " " + c.white(checksumTarget) + c.dim(` is already whitelisted for ${config.walletContractAddress}`));
|
|
1366
1388
|
process.exit(0);
|
|
1367
1389
|
}
|
|
1368
1390
|
|
|
@@ -1397,10 +1419,12 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1397
1419
|
if (opts.json) {
|
|
1398
1420
|
console.log(JSON.stringify({ ok: true, txHash, wallet: config.walletContractAddress, target: checksumTarget }));
|
|
1399
1421
|
} else {
|
|
1400
|
-
console.log(
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
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
|
+
]);
|
|
1404
1428
|
}
|
|
1405
1429
|
});
|
|
1406
1430
|
|
|
@@ -1459,9 +1483,9 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1459
1483
|
);
|
|
1460
1484
|
|
|
1461
1485
|
await provider.waitForTransaction(txHash);
|
|
1462
|
-
console.log(
|
|
1463
|
-
console.log(
|
|
1464
|
-
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));
|
|
1465
1489
|
});
|
|
1466
1490
|
|
|
1467
1491
|
// ─── set-velocity-limit ────────────────────────────────────────────────────
|
|
@@ -1524,9 +1548,9 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1524
1548
|
);
|
|
1525
1549
|
|
|
1526
1550
|
await provider.waitForTransaction(txHash);
|
|
1527
|
-
console.log(
|
|
1528
|
-
console.log(
|
|
1529
|
-
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`));
|
|
1530
1554
|
});
|
|
1531
1555
|
|
|
1532
1556
|
// ─── register-policy ───────────────────────────────────────────────────────
|
|
@@ -1598,9 +1622,9 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1598
1622
|
);
|
|
1599
1623
|
|
|
1600
1624
|
await provider.waitForTransaction(txHash);
|
|
1601
|
-
console.log(
|
|
1602
|
-
console.log(
|
|
1603
|
-
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."));
|
|
1604
1628
|
});
|
|
1605
1629
|
|
|
1606
1630
|
// ─── cancel-registry-upgrade ───────────────────────────────────────────────
|
|
@@ -1670,8 +1694,8 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1670
1694
|
config
|
|
1671
1695
|
);
|
|
1672
1696
|
|
|
1673
|
-
console.log(
|
|
1674
|
-
console.log(
|
|
1697
|
+
console.log("\n" + c.success + c.white(" Registry upgrade cancelled"));
|
|
1698
|
+
console.log(" " + c.dim("Tx:") + " " + c.white(txHash));
|
|
1675
1699
|
});
|
|
1676
1700
|
|
|
1677
1701
|
// ─── governance setup ──────────────────────────────────────────────────────
|
|
@@ -1925,17 +1949,17 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1925
1949
|
saveConfig(config);
|
|
1926
1950
|
}
|
|
1927
1951
|
|
|
1928
|
-
console.log(
|
|
1952
|
+
console.log("\n" + c.success + c.white(" Governance setup complete"));
|
|
1929
1953
|
if (usedBatch) {
|
|
1930
|
-
console.log(
|
|
1954
|
+
console.log(" " + c.dim("Batch tx:") + " " + c.white(txHashes[0]));
|
|
1931
1955
|
} else {
|
|
1932
|
-
txHashes.forEach((h, i) => console.log(`
|
|
1956
|
+
txHashes.forEach((h, i) => console.log(" " + c.dim(`Tx ${i + 1}:`) + " " + c.white(h)));
|
|
1933
1957
|
}
|
|
1934
1958
|
if (guardianWallet) {
|
|
1935
|
-
console.log(`
|
|
1936
|
-
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."));
|
|
1937
1961
|
}
|
|
1938
|
-
console.log(
|
|
1962
|
+
console.log(c.dim("\nVerify with: arc402 wallet status && arc402 wallet policy show"));
|
|
1939
1963
|
});
|
|
1940
1964
|
|
|
1941
1965
|
// ─── authorize-machine-key ─────────────────────────────────────────────────
|
|
@@ -1972,7 +1996,7 @@ export function registerWalletCommands(program: Command): void {
|
|
|
1972
1996
|
} catch { /* ignore */ }
|
|
1973
1997
|
|
|
1974
1998
|
if (alreadyAuthorized) {
|
|
1975
|
-
console.log(
|
|
1999
|
+
console.log("\n" + c.success + " " + c.white(checksumKey) + c.dim(` is already authorized as a machine key on ${config.walletContractAddress}`));
|
|
1976
2000
|
process.exit(0);
|
|
1977
2001
|
}
|
|
1978
2002
|
|
|
@@ -2000,24 +2024,26 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2000
2024
|
}
|
|
2001
2025
|
);
|
|
2002
2026
|
|
|
2003
|
-
console.log(
|
|
2004
|
-
console.log("Sending authorizeMachineKey transaction...");
|
|
2027
|
+
console.log("\n" + c.success + c.white(` Connected: ${account}`));
|
|
2028
|
+
console.log(c.dim("Sending authorizeMachineKey transaction..."));
|
|
2005
2029
|
|
|
2006
2030
|
const hash = await sendTransactionWithSession(client, session, account, chainId, txData);
|
|
2007
|
-
console.log(
|
|
2008
|
-
console.log("Waiting for confirmation...");
|
|
2031
|
+
console.log("\n" + c.dim("Transaction submitted:") + " " + c.white(hash));
|
|
2032
|
+
console.log(c.dim("Waiting for confirmation..."));
|
|
2009
2033
|
|
|
2010
2034
|
const receipt = await provider.waitForTransaction(hash, 1, 60000);
|
|
2011
2035
|
if (!receipt || receipt.status !== 1) {
|
|
2012
|
-
console.error("Transaction failed.");
|
|
2036
|
+
console.error(c.failure + " " + c.red("Transaction failed."));
|
|
2013
2037
|
process.exit(1);
|
|
2014
2038
|
}
|
|
2015
2039
|
|
|
2016
2040
|
const confirmed = await walletContract.authorizedMachineKeys(checksumKey);
|
|
2017
|
-
console.log(
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
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
|
+
]);
|
|
2021
2047
|
|
|
2022
2048
|
await client.disconnect({ topic: session.topic, reason: { code: 6000, message: "done" } });
|
|
2023
2049
|
process.exit(0);
|
|
@@ -2080,8 +2106,8 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2080
2106
|
{ telegramOpts, prompt: `Revoke machine key ${checksumKey} on ARC402Wallet` }
|
|
2081
2107
|
);
|
|
2082
2108
|
|
|
2083
|
-
console.log(
|
|
2084
|
-
console.log("Sending revokeMachineKey transaction...");
|
|
2109
|
+
console.log("\n" + c.success + c.white(` Connected: ${account}`));
|
|
2110
|
+
console.log(c.dim("Sending revokeMachineKey transaction..."));
|
|
2085
2111
|
|
|
2086
2112
|
const hash = await sendTransactionWithSession(client, session, account, chainId, {
|
|
2087
2113
|
to: config.walletContractAddress,
|
|
@@ -2089,20 +2115,22 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2089
2115
|
value: "0x0",
|
|
2090
2116
|
});
|
|
2091
2117
|
|
|
2092
|
-
console.log(
|
|
2093
|
-
console.log("Waiting for confirmation...");
|
|
2118
|
+
console.log("\n" + c.dim("Transaction submitted:") + " " + c.white(hash));
|
|
2119
|
+
console.log(c.dim("Waiting for confirmation..."));
|
|
2094
2120
|
|
|
2095
2121
|
const receipt = await provider.waitForTransaction(hash, 1, 60000);
|
|
2096
2122
|
if (!receipt || receipt.status !== 1) {
|
|
2097
|
-
console.error("Transaction failed.");
|
|
2123
|
+
console.error(c.failure + " " + c.red("Transaction failed."));
|
|
2098
2124
|
process.exit(1);
|
|
2099
2125
|
}
|
|
2100
2126
|
|
|
2101
2127
|
const stillAuthorized = await walletContract.authorizedMachineKeys(checksumKey);
|
|
2102
|
-
console.log(
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
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
|
+
]);
|
|
2106
2134
|
|
|
2107
2135
|
await client.disconnect({ topic: session.topic, reason: { code: 6000, message: "done" } });
|
|
2108
2136
|
process.exit(0);
|
|
@@ -2228,11 +2256,13 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2228
2256
|
if (opts.json) {
|
|
2229
2257
|
console.log(JSON.stringify({ walletAddress: walletAddr, contextId, taskType: opts.taskType, txHash: receipt?.hash }));
|
|
2230
2258
|
} else {
|
|
2231
|
-
console.log(
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
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)."));
|
|
2236
2266
|
}
|
|
2237
2267
|
});
|
|
2238
2268
|
|
|
@@ -2303,14 +2333,16 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2303
2333
|
txHash: receipt?.hash,
|
|
2304
2334
|
}));
|
|
2305
2335
|
} else {
|
|
2306
|
-
console.log(
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
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."));
|
|
2314
2346
|
}
|
|
2315
2347
|
});
|
|
2316
2348
|
|
|
@@ -2438,9 +2470,9 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2438
2470
|
if (opts.json) {
|
|
2439
2471
|
console.log(JSON.stringify({ walletAddress: walletAddr, txHash: receipt?.hash, contextOpen: false }));
|
|
2440
2472
|
} else {
|
|
2441
|
-
console.log(
|
|
2442
|
-
console.log(
|
|
2443
|
-
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));
|
|
2444
2476
|
}
|
|
2445
2477
|
});
|
|
2446
2478
|
|
|
@@ -2546,23 +2578,23 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2546
2578
|
// ── Step 1: context cleanup ────────────────────────────────────────────
|
|
2547
2579
|
const isOpen: boolean = await walletContract.contextOpen();
|
|
2548
2580
|
if (isOpen) {
|
|
2549
|
-
console.log("Stale context found — closing it first...");
|
|
2581
|
+
console.log(c.dim("Stale context found — closing it first..."));
|
|
2550
2582
|
const closeTx = await walletContract.closeContext();
|
|
2551
2583
|
await closeTx.wait(2);
|
|
2552
|
-
console.log(`
|
|
2584
|
+
console.log(" " + c.success + c.dim(` Closed: ${closeTx.hash}`));
|
|
2553
2585
|
}
|
|
2554
2586
|
|
|
2555
2587
|
// ── Step 2: openContext ────────────────────────────────────────────────
|
|
2556
2588
|
const contextId = ethers.keccak256(ethers.toUtf8Bytes(`drain-${Date.now()}`));
|
|
2557
|
-
console.log("Opening context...");
|
|
2589
|
+
console.log(c.dim("Opening context..."));
|
|
2558
2590
|
const openTx = await walletContract.openContext(contextId, "drain");
|
|
2559
2591
|
const openReceipt = await openTx.wait(1);
|
|
2560
|
-
console.log(`
|
|
2592
|
+
console.log(" " + c.success + c.dim(` openContext: ${openReceipt?.hash}`));
|
|
2561
2593
|
|
|
2562
2594
|
// ── Step 3: attest (direct on wallet — onlyOwnerOrMachineKey, NOT via executeContractCall)
|
|
2563
2595
|
const attestationId = ethers.hexlify(ethers.randomBytes(32));
|
|
2564
2596
|
const expiry = Math.floor(Date.now() / 1000) + 600; // 10 min TTL
|
|
2565
|
-
console.log("Creating attestation (direct on wallet)...");
|
|
2597
|
+
console.log(c.dim("Creating attestation (direct on wallet)..."));
|
|
2566
2598
|
const attestTx = await walletContract.attest(
|
|
2567
2599
|
attestationId,
|
|
2568
2600
|
"spend",
|
|
@@ -2573,10 +2605,10 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2573
2605
|
expiry,
|
|
2574
2606
|
);
|
|
2575
2607
|
const attestReceipt = await attestTx.wait(1);
|
|
2576
|
-
console.log(`
|
|
2608
|
+
console.log(" " + c.success + c.dim(` attest: ${attestReceipt?.hash}`));
|
|
2577
2609
|
|
|
2578
2610
|
// ── Step 4: executeSpend ───────────────────────────────────────────────
|
|
2579
|
-
console.log("Executing spend...");
|
|
2611
|
+
console.log(c.dim("Executing spend..."));
|
|
2580
2612
|
let spendReceiptHash: string | undefined;
|
|
2581
2613
|
try {
|
|
2582
2614
|
const spendTx = await walletContract.executeSpend(
|
|
@@ -2590,13 +2622,13 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2590
2622
|
} catch (e) {
|
|
2591
2623
|
handleWalletError(e);
|
|
2592
2624
|
}
|
|
2593
|
-
console.log(`
|
|
2625
|
+
console.log(" " + c.success + c.dim(` executeSpend: ${spendReceiptHash}`));
|
|
2594
2626
|
|
|
2595
2627
|
// ── Step 5: closeContext ───────────────────────────────────────────────
|
|
2596
|
-
console.log("Closing context...");
|
|
2628
|
+
console.log(c.dim("Closing context..."));
|
|
2597
2629
|
const closeTx2 = await walletContract.closeContext();
|
|
2598
2630
|
const closeReceipt = await closeTx2.wait(1);
|
|
2599
|
-
console.log(`
|
|
2631
|
+
console.log(" " + c.success + c.dim(` closeContext: ${closeReceipt?.hash}`));
|
|
2600
2632
|
|
|
2601
2633
|
const newBalance = await provider.getBalance(walletAddr);
|
|
2602
2634
|
if (opts.json) {
|
|
@@ -2615,9 +2647,11 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2615
2647
|
remainingBalance: ethers.formatEther(newBalance),
|
|
2616
2648
|
}));
|
|
2617
2649
|
} else {
|
|
2618
|
-
console.log(
|
|
2619
|
-
|
|
2620
|
-
|
|
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
|
+
]);
|
|
2621
2655
|
}
|
|
2622
2656
|
});
|
|
2623
2657
|
|
|
@@ -2745,23 +2779,23 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2745
2779
|
// ── Step 1: context cleanup ──────────────────────────────────────────────
|
|
2746
2780
|
const isOpenT: boolean = await walletContractT.contextOpen();
|
|
2747
2781
|
if (isOpenT) {
|
|
2748
|
-
console.log("Stale context found — closing it first...");
|
|
2782
|
+
console.log(c.dim("Stale context found — closing it first..."));
|
|
2749
2783
|
const closeTxT = await walletContractT.closeContext();
|
|
2750
2784
|
await closeTxT.wait(2);
|
|
2751
|
-
console.log(`
|
|
2785
|
+
console.log(" " + c.success + c.dim(` Closed: ${closeTxT.hash}`));
|
|
2752
2786
|
}
|
|
2753
2787
|
|
|
2754
2788
|
// ── Step 2: openContext ──────────────────────────────────────────────────
|
|
2755
2789
|
const contextIdT = ethers.keccak256(ethers.toUtf8Bytes(`drain-token-${Date.now()}`));
|
|
2756
|
-
console.log("Opening context...");
|
|
2790
|
+
console.log(c.dim("Opening context..."));
|
|
2757
2791
|
const openTxT = await walletContractT.openContext(contextIdT, "drain");
|
|
2758
2792
|
const openReceiptT = await openTxT.wait(1);
|
|
2759
|
-
console.log(`
|
|
2793
|
+
console.log(" " + c.success + c.dim(` openContext: ${openReceiptT?.hash}`));
|
|
2760
2794
|
|
|
2761
2795
|
// ── Step 3: attest with token address ────────────────────────────────────
|
|
2762
2796
|
const attestationIdT = ethers.hexlify(ethers.randomBytes(32));
|
|
2763
2797
|
const expiryT = Math.floor(Date.now() / 1000) + 600; // 10 min TTL
|
|
2764
|
-
console.log("Creating attestation (with token address)...");
|
|
2798
|
+
console.log(c.dim("Creating attestation (with token address)..."));
|
|
2765
2799
|
const attestTxT = await walletContractT.attest(
|
|
2766
2800
|
attestationIdT,
|
|
2767
2801
|
"spend",
|
|
@@ -2772,10 +2806,10 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2772
2806
|
expiryT,
|
|
2773
2807
|
);
|
|
2774
2808
|
const attestReceiptT = await attestTxT.wait(1);
|
|
2775
|
-
console.log(`
|
|
2809
|
+
console.log(" " + c.success + c.dim(` attest: ${attestReceiptT?.hash}`));
|
|
2776
2810
|
|
|
2777
2811
|
// ── Step 4: executeTokenSpend ────────────────────────────────────────────
|
|
2778
|
-
console.log("Executing token spend...");
|
|
2812
|
+
console.log(c.dim("Executing token spend..."));
|
|
2779
2813
|
const spendTxT = await walletContractT.executeTokenSpend(
|
|
2780
2814
|
checksumRecipient,
|
|
2781
2815
|
tokenAmount,
|
|
@@ -2784,13 +2818,13 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2784
2818
|
attestationIdT,
|
|
2785
2819
|
);
|
|
2786
2820
|
const spendReceiptT = await spendTxT.wait(1);
|
|
2787
|
-
console.log(`
|
|
2821
|
+
console.log(" " + c.success + c.dim(` executeTokenSpend: ${spendReceiptT?.hash}`));
|
|
2788
2822
|
|
|
2789
2823
|
// ── Step 5: closeContext ─────────────────────────────────────────────────
|
|
2790
|
-
console.log("Closing context...");
|
|
2824
|
+
console.log(c.dim("Closing context..."));
|
|
2791
2825
|
const closeTxT2 = await walletContractT.closeContext();
|
|
2792
2826
|
const closeReceiptT = await closeTxT2.wait(1);
|
|
2793
|
-
console.log(`
|
|
2827
|
+
console.log(" " + c.success + c.dim(` closeContext: ${closeReceiptT?.hash}`));
|
|
2794
2828
|
|
|
2795
2829
|
const newTokenBalance: bigint = await erc20.balanceOf(walletAddr);
|
|
2796
2830
|
if (opts.json) {
|
|
@@ -2810,10 +2844,12 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2810
2844
|
remainingTokenBalance: ethers.formatUnits(newTokenBalance, decimals),
|
|
2811
2845
|
}));
|
|
2812
2846
|
} else {
|
|
2813
|
-
console.log(
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
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
|
+
]);
|
|
2817
2853
|
}
|
|
2818
2854
|
});
|
|
2819
2855
|
|
|
@@ -2876,25 +2912,27 @@ export function registerWalletCommands(program: Command): void {
|
|
|
2876
2912
|
}
|
|
2877
2913
|
);
|
|
2878
2914
|
|
|
2879
|
-
console.log(
|
|
2880
|
-
console.log("Sending setPasskey transaction...");
|
|
2915
|
+
console.log("\n" + c.success + c.white(` Connected: ${account}`));
|
|
2916
|
+
console.log(c.dim("Sending setPasskey transaction..."));
|
|
2881
2917
|
|
|
2882
2918
|
const hash = await sendTransactionWithSession(client, session, account, chainId, txData);
|
|
2883
|
-
console.log(
|
|
2884
|
-
console.log("Waiting for confirmation...");
|
|
2919
|
+
console.log("\n" + c.dim("Transaction submitted:") + " " + c.white(hash));
|
|
2920
|
+
console.log(c.dim("Waiting for confirmation..."));
|
|
2885
2921
|
|
|
2886
2922
|
const receipt = await provider.waitForTransaction(hash, 1, 60000);
|
|
2887
2923
|
if (!receipt || receipt.status !== 1) {
|
|
2888
|
-
console.error("Transaction failed.");
|
|
2924
|
+
console.error(c.failure + " " + c.red("Transaction failed."));
|
|
2889
2925
|
process.exit(1);
|
|
2890
2926
|
}
|
|
2891
2927
|
|
|
2892
|
-
console.log(
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
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."));
|
|
2898
2936
|
|
|
2899
2937
|
await client.disconnect({ topic: session.topic, reason: { code: 6000, message: "done" } });
|
|
2900
2938
|
process.exit(0);
|