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/config.ts
CHANGED
|
@@ -2,31 +2,48 @@ import { Command } from "commander";
|
|
|
2
2
|
import prompts from "prompts";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import { Arc402Config, NETWORK_DEFAULTS, configExists, loadConfig, saveConfig, getSubdomainApi } from "../config";
|
|
5
|
+
import { c } from '../ui/colors';
|
|
5
6
|
|
|
6
7
|
export function registerConfigCommands(program: Command): void {
|
|
7
8
|
const config = program.command("config").description("Manage ARC-402 CLI configuration");
|
|
8
9
|
config.command("init").description("Interactive setup for ~/.arc402/config.json").action(async () => {
|
|
9
10
|
const existing: Partial<Arc402Config> = configExists() ? loadConfig() : {};
|
|
10
11
|
const answers = await prompts([
|
|
11
|
-
{ type: "select", name: "network", message: "Network", choices: [{ title: "Base
|
|
12
|
-
{ type: "text", name: "rpcUrl", message: "RPC URL", initial: (_: unknown, values: Record<string, string>) => existing.rpcUrl ?? NETWORK_DEFAULTS[values.network]?.rpcUrl ?? "" },
|
|
13
|
-
{ type: "text", name: "agentRegistryAddress", message: "AgentRegistry address (optional)", initial: existing.agentRegistryAddress ?? "" },
|
|
14
|
-
{ type: "text", name: "serviceAgreementAddress", message: "ServiceAgreement address (optional)", initial: existing.serviceAgreementAddress ?? "" },
|
|
15
|
-
{ type: "text", name: "trustRegistryAddress", message: "TrustRegistry / TrustRegistryV3 address", initial: (_: unknown, values: Record<string, string>) => existing.trustRegistryAddress ?? NETWORK_DEFAULTS[values.network]?.trustRegistryAddress ?? "" },
|
|
16
|
-
{ type: "text", name: "reputationOracleAddress", message: "ReputationOracle address (optional)", initial: existing.reputationOracleAddress ?? "" },
|
|
17
|
-
{ type: "text", name: "sponsorshipAttestationAddress", message: "SponsorshipAttestation address (optional)", initial: existing.sponsorshipAttestationAddress ?? "" },
|
|
18
|
-
{ type: "text", name: "capabilityRegistryAddress", message: "CapabilityRegistry address (optional)", initial: existing.capabilityRegistryAddress ?? "" },
|
|
19
|
-
{ type: "text", name: "governanceAddress", message: "ARC402Governance address (optional)", initial: existing.governanceAddress ?? "" },
|
|
20
|
-
{ type: "confirm", name: "storeKey", message: "Store private key in config?", initial: false },
|
|
21
|
-
{ type: (prev: boolean) => prev ? "password" : null, name: "privateKey", message: "Private key (0x...)" },
|
|
22
|
-
{ type: "text", name: "subdomainApi", message: "Subdomain API endpoint (optional, default: https://api.arc402.xyz):", initial: existing.subdomainApi ?? "" },
|
|
23
|
-
{ type: "text", name: "telegramBotToken", message: "Telegram bot token (optional, for approval notifications):", initial: existing.telegramBotToken ?? "" },
|
|
24
|
-
{ type: "text", name: "telegramChatId", message: "Telegram chat ID (optional):", initial: existing.telegramChatId ?? "" },
|
|
25
|
-
{ type: "text", name: "telegramThreadId", message: "Telegram thread ID (optional, for forum topics):", initial: existing.telegramThreadId?.toString() ?? "" },
|
|
12
|
+
{ type: "select", name: "network", message: "Network", choices: [{ title: "Base Mainnet", value: "base-mainnet" }, { title: "Base Sepolia (testnet)", value: "base-sepolia" }], initial: existing.network === "base-sepolia" ? 1 : 0 },
|
|
26
13
|
]);
|
|
27
|
-
|
|
14
|
+
|
|
15
|
+
if (!answers.network) { console.log(chalk.red("✗ Setup cancelled")); return; }
|
|
16
|
+
|
|
17
|
+
const defaults = NETWORK_DEFAULTS[answers.network] ?? {};
|
|
18
|
+
const cfg: Arc402Config = {
|
|
19
|
+
network: answers.network,
|
|
20
|
+
walletConnectProjectId: "2bc39e3b38de7ef7deeed1e3dbbe6ad6",
|
|
21
|
+
rpcUrl: defaults.rpcUrl ?? "https://mainnet.base.org",
|
|
22
|
+
trustRegistryAddress: defaults.trustRegistryAddress ?? "",
|
|
23
|
+
agentRegistryAddress: defaults.agentRegistryV2Address ?? defaults.agentRegistryAddress,
|
|
24
|
+
serviceAgreementAddress: defaults.serviceAgreementAddress,
|
|
25
|
+
reputationOracleAddress: defaults.reputationOracleAddress,
|
|
26
|
+
sponsorshipAttestationAddress: defaults.sponsorshipAttestationAddress,
|
|
27
|
+
capabilityRegistryAddress: defaults.capabilityRegistryAddress,
|
|
28
|
+
governanceAddress: defaults.governanceAddress,
|
|
29
|
+
...(existing.privateKey ? { privateKey: existing.privateKey } : {}),
|
|
30
|
+
...(existing.subdomainApi ? { subdomainApi: existing.subdomainApi } : {}),
|
|
31
|
+
...(existing.telegramBotToken ? { telegramBotToken: existing.telegramBotToken } : {}),
|
|
32
|
+
...(existing.telegramChatId ? { telegramChatId: existing.telegramChatId } : {}),
|
|
33
|
+
...(existing.telegramThreadId ? { telegramThreadId: existing.telegramThreadId } : {}),
|
|
34
|
+
...(existing.walletContractAddress ? { walletContractAddress: existing.walletContractAddress } : {}),
|
|
35
|
+
};
|
|
28
36
|
saveConfig(cfg);
|
|
29
|
-
|
|
37
|
+
|
|
38
|
+
console.log();
|
|
39
|
+
console.log(' ' + c.success + c.white(' Config saved'));
|
|
40
|
+
console.log();
|
|
41
|
+
console.log(chalk.dim(" Network ") + chalk.white(answers.network === "base-mainnet" ? "Base Mainnet" : "Base Sepolia"));
|
|
42
|
+
console.log(chalk.dim(" RPC ") + chalk.white(cfg.rpcUrl!));
|
|
43
|
+
console.log(chalk.dim(" Contracts ") + chalk.white("All protocol addresses loaded"));
|
|
44
|
+
console.log();
|
|
45
|
+
console.log(chalk.dim(" Next: ") + chalk.white("arc402 wallet deploy"));
|
|
46
|
+
console.log();
|
|
30
47
|
});
|
|
31
48
|
config.command("show").description("Print current config").action(() => {
|
|
32
49
|
const cfg = loadConfig();
|
package/src/commands/daemon.ts
CHANGED
|
@@ -8,6 +8,9 @@ import { ethers } from "ethers";
|
|
|
8
8
|
import prompts from "prompts";
|
|
9
9
|
import { loadConfig } from "../config";
|
|
10
10
|
import { requireSigner } from "../client";
|
|
11
|
+
import { startSpinner } from "../ui/spinner";
|
|
12
|
+
import { renderTree } from "../ui/tree";
|
|
13
|
+
import { c } from "../ui/colors";
|
|
11
14
|
import { SERVICE_AGREEMENT_ABI } from "../abis";
|
|
12
15
|
import {
|
|
13
16
|
DAEMON_DIR,
|
|
@@ -344,15 +347,21 @@ async function startDaemonBackground(sandboxName?: string, runtimeRemoteRoot?: s
|
|
|
344
347
|
if (sandboxName) {
|
|
345
348
|
const remotePid = await readRemotePid(sandboxName);
|
|
346
349
|
if (remotePid) {
|
|
347
|
-
console.log(`ARC-402 daemon started
|
|
348
|
-
|
|
350
|
+
console.log(` ${c.success} ARC-402 daemon started (OpenShell)`);
|
|
351
|
+
renderTree([
|
|
352
|
+
{ label: "PID", value: String(remotePid) },
|
|
353
|
+
{ label: "Log", value: REMOTE_DAEMON_LOG, last: true },
|
|
354
|
+
]);
|
|
349
355
|
return;
|
|
350
356
|
}
|
|
351
357
|
} else {
|
|
352
358
|
const pid = readPid();
|
|
353
359
|
if (pid && isProcessAlive(pid)) {
|
|
354
|
-
console.log(`ARC-402 daemon started
|
|
355
|
-
|
|
360
|
+
console.log(` ${c.success} ARC-402 daemon started`);
|
|
361
|
+
renderTree([
|
|
362
|
+
{ label: "PID", value: String(pid) },
|
|
363
|
+
{ label: "Log", value: DAEMON_LOG, last: true },
|
|
364
|
+
]);
|
|
356
365
|
return;
|
|
357
366
|
}
|
|
358
367
|
}
|
|
@@ -408,34 +417,31 @@ async function stopDaemon(opts: { wait?: boolean } = {}): Promise<boolean> {
|
|
|
408
417
|
// ─── Output formatters ────────────────────────────────────────────────────────
|
|
409
418
|
|
|
410
419
|
function formatStatus(data: Record<string, unknown>): void {
|
|
411
|
-
const line = (label: string, value: string) =>
|
|
412
|
-
console.log(`${label.padEnd(20)}${value}`);
|
|
413
|
-
|
|
414
|
-
console.log("ARC-402 Daemon Status");
|
|
415
|
-
console.log("─────────────────────");
|
|
416
|
-
line("State:", String(data.state ?? "unknown"));
|
|
417
|
-
line("PID:", String(data.pid ?? "unknown"));
|
|
418
|
-
line("Uptime:", String(data.uptime ?? "unknown"));
|
|
419
|
-
line("Wallet:", String(data.wallet ?? "unknown"));
|
|
420
|
-
line("Machine Key:", String(data.machine_key_address ?? "unknown"));
|
|
421
|
-
console.log();
|
|
422
|
-
console.log("Subsystems:");
|
|
423
420
|
const relayStatus = data.relay_enabled
|
|
424
421
|
? `active — polling ${data.relay_url || "relay"} every ${data.relay_poll_seconds}s`
|
|
425
422
|
: "disabled";
|
|
426
423
|
const watchtowerStatus = data.watchtower_enabled ? "active" : "disabled";
|
|
427
424
|
const bundlerStatus = `${data.bundler_mode} — ${data.bundler_endpoint || "default"}`;
|
|
428
|
-
console.log(` Relay: ${relayStatus}`);
|
|
429
|
-
console.log(` Watchtower: ${watchtowerStatus}`);
|
|
430
|
-
console.log(` Bundler: ${bundlerStatus}`);
|
|
431
|
-
console.log();
|
|
432
425
|
const pending = Number(data.pending_approval ?? 0);
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
426
|
+
|
|
427
|
+
console.log(`${c.mark} ARC-402 Daemon Status`);
|
|
428
|
+
console.log();
|
|
429
|
+
renderTree([
|
|
430
|
+
{ label: "State", value: String(data.state ?? "unknown") },
|
|
431
|
+
{ label: "PID", value: String(data.pid ?? "unknown") },
|
|
432
|
+
{ label: "Uptime", value: String(data.uptime ?? "unknown") },
|
|
433
|
+
{ label: "Wallet", value: String(data.wallet ?? "unknown") },
|
|
434
|
+
{ label: "Key", value: String(data.machine_key_address ?? "unknown") },
|
|
435
|
+
{ label: "Relay", value: relayStatus },
|
|
436
|
+
{ label: "Watchtower", value: watchtowerStatus },
|
|
437
|
+
{ label: "Bundler", value: bundlerStatus },
|
|
438
|
+
{ label: "Agreements", value: String(data.active_agreements ?? 0) },
|
|
439
|
+
{
|
|
440
|
+
label: "Pending",
|
|
441
|
+
value: pending > 0 ? `${pending} ← arc402 daemon pending` : "0",
|
|
442
|
+
last: true,
|
|
443
|
+
},
|
|
444
|
+
]);
|
|
439
445
|
}
|
|
440
446
|
|
|
441
447
|
interface HireRow {
|
|
@@ -585,9 +591,9 @@ export function registerDaemonCommands(program: Command): void {
|
|
|
585
591
|
process.exit(0);
|
|
586
592
|
}
|
|
587
593
|
const { configPath, host } = buildOpenShellSshConfig(openShellCfg.sandbox.name);
|
|
588
|
-
|
|
594
|
+
const stopSpinnerRemote = startSpinner(`Stopping daemon (OpenShell PID ${remotePid})...`);
|
|
589
595
|
runCmd("ssh", ["-F", configPath, host, `kill ${remotePid}`], { timeout: 20000 });
|
|
590
|
-
|
|
596
|
+
stopSpinnerRemote.succeed("Stop signal sent");
|
|
591
597
|
return;
|
|
592
598
|
}
|
|
593
599
|
|
|
@@ -597,11 +603,12 @@ export function registerDaemonCommands(program: Command): void {
|
|
|
597
603
|
process.exit(0);
|
|
598
604
|
}
|
|
599
605
|
|
|
600
|
-
|
|
606
|
+
const stopSpinner = startSpinner(`Stopping daemon (PID ${pid})...`);
|
|
601
607
|
const stopped = await stopDaemon({ wait: true });
|
|
602
608
|
if (stopped) {
|
|
603
|
-
|
|
609
|
+
stopSpinner.succeed("Daemon stopped");
|
|
604
610
|
} else {
|
|
611
|
+
stopSpinner.fail("Failed to stop daemon cleanly");
|
|
605
612
|
console.error("Failed to stop daemon cleanly.");
|
|
606
613
|
process.exit(1);
|
|
607
614
|
}
|
|
@@ -656,15 +663,15 @@ export function registerDaemonCommands(program: Command): void {
|
|
|
656
663
|
console.log("Launch path: arc402 openshell init, then arc402 daemon start");
|
|
657
664
|
process.exit(1);
|
|
658
665
|
}
|
|
659
|
-
console.log(
|
|
660
|
-
console.log("─────────────────────");
|
|
661
|
-
console.log(`State: running (OpenShell sandbox)`);
|
|
662
|
-
console.log(`PID: ${remotePid}`);
|
|
663
|
-
console.log(`Sandbox: ${openShellCfg.sandbox.name}`);
|
|
664
|
-
console.log(`Runtime root: ${openShellCfg.runtime?.remote_root ?? DEFAULT_RUNTIME_REMOTE_ROOT}`);
|
|
665
|
-
console.log(`Log path: ${REMOTE_DAEMON_LOG}`);
|
|
666
|
+
console.log(`${c.mark} ARC-402 Daemon Status`);
|
|
666
667
|
console.log();
|
|
667
|
-
|
|
668
|
+
renderTree([
|
|
669
|
+
{ label: "State", value: "running (OpenShell sandbox)" },
|
|
670
|
+
{ label: "PID", value: String(remotePid) },
|
|
671
|
+
{ label: "Sandbox", value: openShellCfg.sandbox.name },
|
|
672
|
+
{ label: "Runtime", value: openShellCfg.runtime?.remote_root ?? DEFAULT_RUNTIME_REMOTE_ROOT },
|
|
673
|
+
{ label: "Log", value: REMOTE_DAEMON_LOG, last: true },
|
|
674
|
+
]);
|
|
668
675
|
return;
|
|
669
676
|
}
|
|
670
677
|
|
package/src/commands/deliver.ts
CHANGED
|
@@ -9,6 +9,9 @@ import { SERVICE_AGREEMENT_ABI } from "../abis";
|
|
|
9
9
|
import { readFile } from "fs/promises";
|
|
10
10
|
import prompts from "prompts";
|
|
11
11
|
import { resolveAgentEndpoint, notifyAgent, DEFAULT_REGISTRY_ADDRESS } from "../endpoint-notify";
|
|
12
|
+
import { c } from '../ui/colors';
|
|
13
|
+
import { startSpinner } from '../ui/spinner';
|
|
14
|
+
import { renderTree } from '../ui/tree';
|
|
12
15
|
|
|
13
16
|
export function registerDeliverCommand(program: Command): void {
|
|
14
17
|
program
|
|
@@ -88,8 +91,9 @@ export function registerDeliverCommand(program: Command): void {
|
|
|
88
91
|
const { ethers } = await import("ethers");
|
|
89
92
|
const hash = ethers.keccak256(buffer);
|
|
90
93
|
|
|
91
|
-
console.log(
|
|
94
|
+
console.log(' ' + c.dim('Encrypted upload:') + ' ' + c.white(uri));
|
|
92
95
|
|
|
96
|
+
const encSpinner = startSpinner('Committing deliverable…');
|
|
93
97
|
if (config.walletContractAddress) {
|
|
94
98
|
await executeContractWriteViaWallet(
|
|
95
99
|
config.walletContractAddress, signer, config.serviceAgreementAddress,
|
|
@@ -99,11 +103,17 @@ export function registerDeliverCommand(program: Command): void {
|
|
|
99
103
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
100
104
|
await client.commitDeliverable(BigInt(id), hash);
|
|
101
105
|
}
|
|
102
|
-
|
|
106
|
+
encSpinner.succeed(` Delivered — agreement #${id}`);
|
|
107
|
+
renderTree([
|
|
108
|
+
{ label: 'Hash', value: hash },
|
|
109
|
+
{ label: 'CID', value: cid },
|
|
110
|
+
{ label: 'URI', value: uri, last: true },
|
|
111
|
+
]);
|
|
103
112
|
return;
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
const hash = opts.output ? hashFile(opts.output) : hashString(opts.message ?? `agreement:${id}`);
|
|
116
|
+
const deliverSpinner = startSpinner(`${opts.fulfill ? 'Fulfilling' : 'Committing deliverable for'} agreement #${id}…`);
|
|
107
117
|
if (config.walletContractAddress) {
|
|
108
118
|
const fn = opts.fulfill ? "fulfill" : "commitDeliverable";
|
|
109
119
|
await executeContractWriteViaWallet(
|
|
@@ -114,7 +124,10 @@ export function registerDeliverCommand(program: Command): void {
|
|
|
114
124
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
115
125
|
if (opts.fulfill) await client.fulfill(BigInt(id), hash); else await client.commitDeliverable(BigInt(id), hash);
|
|
116
126
|
}
|
|
117
|
-
|
|
127
|
+
deliverSpinner.succeed(` ${opts.fulfill ? 'Fulfilled' : 'Delivered'} — agreement #${id}`);
|
|
128
|
+
renderTree([
|
|
129
|
+
{ label: 'Hash', value: hash, last: true },
|
|
130
|
+
]);
|
|
118
131
|
|
|
119
132
|
// Notify client's HTTP endpoint (non-blocking)
|
|
120
133
|
if (clientAddress) {
|
package/src/commands/discover.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { AgentRegistryClient, CapabilityRegistryClient, ReputationOracleClient,
|
|
|
4
4
|
import { loadConfig } from "../config";
|
|
5
5
|
import { getClient } from "../client";
|
|
6
6
|
import { getTrustTier, printTable, truncateAddress } from "../utils/format";
|
|
7
|
+
import { c } from '../ui/colors';
|
|
7
8
|
|
|
8
9
|
// Minimal ABI for the new getAgentsWithCapability function (Spec 18)
|
|
9
10
|
const CAPABILITY_REGISTRY_EXTRA_ABI = [
|
|
@@ -273,6 +274,7 @@ export function registerDiscoverCommand(program: Command): void {
|
|
|
273
274
|
));
|
|
274
275
|
}
|
|
275
276
|
|
|
277
|
+
console.log('\n ' + c.mark + c.white(' Discover Results') + c.dim(` — ${scored.length} agent${scored.length !== 1 ? 's' : ''} found`));
|
|
276
278
|
printTable(
|
|
277
279
|
["RANK", "ADDRESS", "NAME", "SERVICE", "TRUST", "SCORE", "CAPABILITIES"],
|
|
278
280
|
scored.map((agent) => {
|
package/src/commands/dispute.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { getClient, requireSigner } from "../client";
|
|
|
7
7
|
import { hashFile, hashString } from "../utils/hash";
|
|
8
8
|
import { printSenderInfo, executeContractWriteViaWallet } from "../wallet-router";
|
|
9
9
|
import { SERVICE_AGREEMENT_ABI } from "../abis";
|
|
10
|
+
import { c } from '../ui/colors';
|
|
11
|
+
import { startSpinner } from '../ui/spinner';
|
|
10
12
|
|
|
11
13
|
export function registerDisputeCommand(program: Command): void {
|
|
12
14
|
const dispute = program.command("dispute").description("Formal dispute workflow; remediation-first by default, with narrow hard-fail direct-dispute exceptions");
|
|
@@ -33,7 +35,7 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
33
35
|
const disputeClass = classMap[String(opts.class).toLowerCase()];
|
|
34
36
|
if (!mode || !disputeClass) throw new Error("Invalid --mode or --class");
|
|
35
37
|
const feeInTokens = await client.getFeeQuote(BigInt(opts.price), opts.token, mode, disputeClass);
|
|
36
|
-
console.log(`Fee quote
|
|
38
|
+
console.log(' ' + c.mark + c.white(` Fee quote — agreement #${agreementId}: ${feeInTokens.toString()} tokens`));
|
|
37
39
|
});
|
|
38
40
|
|
|
39
41
|
// Open with explicit mode/class
|
|
@@ -68,7 +70,7 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
68
70
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
69
71
|
await client.openDisputeWithMode(BigInt(agreementId), mode, disputeClass, opts.reason, BigInt(opts.fee));
|
|
70
72
|
}
|
|
71
|
-
console.log(
|
|
73
|
+
console.log(' ' + c.success + c.white(` Dispute opened — agreement #${agreementId}`));
|
|
72
74
|
});
|
|
73
75
|
|
|
74
76
|
// Join mutual dispute (respondent pays their half) — DisputeArbitration contract, no wallet routing
|
|
@@ -81,7 +83,7 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
81
83
|
const { signer } = await requireSigner(config);
|
|
82
84
|
const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, signer);
|
|
83
85
|
await client.joinMutualDispute(BigInt(agreementId), BigInt(opts.fee));
|
|
84
|
-
console.log(`
|
|
86
|
+
console.log(' ' + c.success + c.white(` Joined mutual dispute — agreement #${agreementId}`));
|
|
85
87
|
});
|
|
86
88
|
|
|
87
89
|
dispute.command("open <id>")
|
|
@@ -177,7 +179,7 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
177
179
|
await client.dispute(BigInt(id), opts.reason);
|
|
178
180
|
}
|
|
179
181
|
}
|
|
180
|
-
console.log(`
|
|
182
|
+
console.log(' ' + c.success + c.white(` Dispute opened — agreement #${id}`));
|
|
181
183
|
|
|
182
184
|
// J4-04: Display arbitration selection window deadline
|
|
183
185
|
try {
|
|
@@ -210,7 +212,7 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
210
212
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
211
213
|
await client.submitDisputeEvidence(BigInt(id), evidenceType, hash, opts.uri);
|
|
212
214
|
}
|
|
213
|
-
console.log(`
|
|
215
|
+
console.log(' ' + c.success + c.white(` Evidence submitted — agreement #${id}`));
|
|
214
216
|
});
|
|
215
217
|
|
|
216
218
|
// status — read-only, no wallet routing needed
|
|
@@ -263,7 +265,7 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
263
265
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
264
266
|
await client.nominateArbitrator(BigInt(id), opts.arbitrator);
|
|
265
267
|
}
|
|
266
|
-
console.log(`
|
|
268
|
+
console.log(' ' + c.success + c.white(` Arbitrator nominated — agreement #${id}`));
|
|
267
269
|
});
|
|
268
270
|
|
|
269
271
|
dispute.command("vote <id>")
|
|
@@ -309,7 +311,7 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
309
311
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
310
312
|
await client.castArbitrationVote(BigInt(id), vote, BigInt(opts.providerAward), BigInt(opts.clientAward));
|
|
311
313
|
}
|
|
312
|
-
console.log(`
|
|
314
|
+
console.log(' ' + c.success + c.white(` Vote recorded — agreement #${id}`));
|
|
313
315
|
});
|
|
314
316
|
|
|
315
317
|
dispute.command("human <id>")
|
|
@@ -329,7 +331,7 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
329
331
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
330
332
|
await client.requestHumanEscalation(BigInt(id), opts.reason);
|
|
331
333
|
}
|
|
332
|
-
console.log(`human
|
|
334
|
+
console.log(' ' + c.success + c.white(` Escalated to human — agreement #${id}`));
|
|
333
335
|
});
|
|
334
336
|
|
|
335
337
|
dispute.command("resolve <id>").description("Owner-only admin path if you are operating the dispute contract").requiredOption("--outcome <outcome>", "provider|refund|partial-provider|partial-client|mutual-cancel|human-review").option("--provider-award <amount>", "Wei/token units", "0").option("--client-award <amount>", "Wei/token units", "0").action(async (id, opts) => {
|
|
@@ -348,7 +350,7 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
348
350
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
349
351
|
await client.resolveDisputeDetailed(BigInt(id), mapping[String(opts.outcome)], BigInt(opts.providerAward), BigInt(opts.clientAward));
|
|
350
352
|
}
|
|
351
|
-
console.log(`
|
|
353
|
+
console.log(' ' + c.success + c.white(` Resolved — agreement #${id}`));
|
|
352
354
|
});
|
|
353
355
|
|
|
354
356
|
dispute.command("owner-resolve <agreementId>")
|
|
@@ -368,6 +370,6 @@ export function registerDisputeCommand(program: Command): void {
|
|
|
368
370
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
369
371
|
await client.ownerResolveDispute(BigInt(agreementId), !!opts.favorProvider);
|
|
370
372
|
}
|
|
371
|
-
console.log(`
|
|
373
|
+
console.log(' ' + c.success + c.white(` Owner resolved — agreement #${agreementId}`));
|
|
372
374
|
});
|
|
373
375
|
}
|
package/src/commands/endpoint.ts
CHANGED
|
@@ -17,6 +17,7 @@ import * as dns from "dns/promises";
|
|
|
17
17
|
import * as fs from "fs";
|
|
18
18
|
import * as net from "net";
|
|
19
19
|
import chalk from "chalk";
|
|
20
|
+
import { c } from '../ui/colors';
|
|
20
21
|
|
|
21
22
|
interface DoctorCheck {
|
|
22
23
|
layer: string;
|
|
@@ -477,7 +478,7 @@ export function registerEndpointCommands(program: Command): void {
|
|
|
477
478
|
});
|
|
478
479
|
saveEndpointConfig(cfg);
|
|
479
480
|
|
|
480
|
-
console.log(
|
|
481
|
+
console.log(c.success + c.white(' Endpoint scaffold written: ' + ENDPOINT_CONFIG_PATH));
|
|
481
482
|
console.log(` Agent name: ${cfg.agentName}`);
|
|
482
483
|
console.log(` Hostname: ${cfg.hostname}`);
|
|
483
484
|
console.log(` Public URL: ${cfg.publicUrl}`);
|
|
@@ -510,7 +511,7 @@ export function registerEndpointCommands(program: Command): void {
|
|
|
510
511
|
const allGood = checks.every((check) => check.ok);
|
|
511
512
|
const brokenLayers = Array.from(new Set(checks.filter((check) => !check.ok).map((check) => check.layer)));
|
|
512
513
|
|
|
513
|
-
console.log(
|
|
514
|
+
console.log('\n ' + c.mark + c.white(' ARC-402 Endpoint Status'));
|
|
514
515
|
console.log("─────────────────────");
|
|
515
516
|
console.log(`Agent name: ${cfg.agentName}`);
|
|
516
517
|
console.log(`Hostname: ${cfg.hostname}`);
|
|
@@ -571,7 +572,7 @@ export function registerEndpointCommands(program: Command): void {
|
|
|
571
572
|
});
|
|
572
573
|
saveEndpointConfig(cfg);
|
|
573
574
|
|
|
574
|
-
console.log(
|
|
575
|
+
console.log(c.success + c.white(' Endpoint config locked to ' + cfg.publicUrl));
|
|
575
576
|
console.log(` Hostname: ${cfg.hostname}`);
|
|
576
577
|
console.log(` Tunnel target: ${cfg.tunnelTarget}`);
|
|
577
578
|
console.log(` Wallet: ${cfg.walletAddress}`);
|
package/src/commands/feed.ts
CHANGED
package/src/commands/hire.ts
CHANGED
|
@@ -7,6 +7,10 @@ import { hashFile, hashString } from "../utils/hash";
|
|
|
7
7
|
import { parseDuration } from "../utils/time";
|
|
8
8
|
import { printSenderInfo, executeContractWriteViaWallet } from "../wallet-router";
|
|
9
9
|
import { AGENT_REGISTRY_ABI, SERVICE_AGREEMENT_ABI } from "../abis";
|
|
10
|
+
import { c } from '../ui/colors';
|
|
11
|
+
import { startSpinner } from '../ui/spinner';
|
|
12
|
+
import { renderTree, TreeItem } from '../ui/tree';
|
|
13
|
+
import { formatAddress } from '../ui/format';
|
|
10
14
|
|
|
11
15
|
const DEFAULT_REGISTRY_ADDRESS = "0xD5c2851B00090c92Ba7F4723FB548bb30C9B6865";
|
|
12
16
|
|
|
@@ -132,6 +136,8 @@ export function registerHireCommand(program: Command): void {
|
|
|
132
136
|
|
|
133
137
|
let agreementId: bigint;
|
|
134
138
|
|
|
139
|
+
const hireSpinner = startSpinner('Submitting agreement...');
|
|
140
|
+
|
|
135
141
|
if (config.walletContractAddress) {
|
|
136
142
|
// Smart wallet path — wallet handles per-tx USDC approval via maxApprovalAmount
|
|
137
143
|
const tx = await executeContractWriteViaWallet(
|
|
@@ -185,6 +191,8 @@ export function registerHireCommand(program: Command): void {
|
|
|
185
191
|
agreementId = result.agreementId;
|
|
186
192
|
}
|
|
187
193
|
|
|
194
|
+
hireSpinner.succeed('Agreement proposed');
|
|
195
|
+
|
|
188
196
|
// Notify provider's HTTP endpoint (non-blocking)
|
|
189
197
|
const hireRegistryAddress = config.agentRegistryV2Address ?? config.agentRegistryAddress ?? DEFAULT_REGISTRY_ADDRESS;
|
|
190
198
|
try {
|
|
@@ -224,7 +232,14 @@ export function registerHireCommand(program: Command): void {
|
|
|
224
232
|
return console.log(JSON.stringify(output, null, 2));
|
|
225
233
|
}
|
|
226
234
|
|
|
227
|
-
console.log(`
|
|
228
|
-
|
|
235
|
+
console.log(' ' + c.success + c.white(` Agreement #${agreementId!} proposed`));
|
|
236
|
+
const hireTreeItems: TreeItem[] = [
|
|
237
|
+
{ label: 'Agent', value: formatAddress(opts.agent) },
|
|
238
|
+
{ label: 'Task', value: opts.task.slice(0, 60) + (opts.task.length > 60 ? '...' : '') },
|
|
239
|
+
{ label: 'Service', value: opts.serviceType },
|
|
240
|
+
{ label: 'Hash', value: String(deliverablesHash), last: !transcriptHash },
|
|
241
|
+
];
|
|
242
|
+
if (transcriptHash) hireTreeItems.push({ label: 'Transcript', value: transcriptHash, last: true });
|
|
243
|
+
renderTree(hireTreeItems);
|
|
229
244
|
});
|
|
230
245
|
}
|
package/src/commands/migrate.ts
CHANGED
|
@@ -2,6 +2,10 @@ import { Command } from "commander";
|
|
|
2
2
|
import { ethers } from "ethers";
|
|
3
3
|
import { loadConfig } from "../config";
|
|
4
4
|
import { getClient, requireSigner } from "../client";
|
|
5
|
+
import { c } from '../ui/colors';
|
|
6
|
+
import { startSpinner } from '../ui/spinner';
|
|
7
|
+
import { renderTree } from '../ui/tree';
|
|
8
|
+
import { formatAddress } from '../ui/format';
|
|
5
9
|
|
|
6
10
|
const MIGRATION_REGISTRY_ABI = [
|
|
7
11
|
"function registerMigration(address oldWallet, address newWallet) external",
|
|
@@ -35,8 +39,10 @@ export function registerMigrateCommands(program: Command): void {
|
|
|
35
39
|
const { signer } = await requireSigner(config);
|
|
36
40
|
const contract = new ethers.Contract(config.migrationRegistryAddress, MIGRATION_REGISTRY_ABI, signer);
|
|
37
41
|
|
|
42
|
+
const migrateSpinner = startSpinner('Registering migration...');
|
|
38
43
|
const tx = await contract.registerMigration(oldWallet, newWallet);
|
|
39
44
|
const receipt = await tx.wait();
|
|
45
|
+
migrateSpinner.succeed('Migration registered');
|
|
40
46
|
|
|
41
47
|
const payload = {
|
|
42
48
|
oldWallet,
|
|
@@ -44,11 +50,11 @@ export function registerMigrateCommands(program: Command): void {
|
|
|
44
50
|
txHash: receipt.hash,
|
|
45
51
|
};
|
|
46
52
|
if (opts.json) return console.log(JSON.stringify(payload, null, 2));
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
renderTree([
|
|
54
|
+
{ label: 'Old', value: formatAddress(oldWallet) },
|
|
55
|
+
{ label: 'New', value: formatAddress(newWallet) },
|
|
56
|
+
{ label: 'Note', value: '10% trust score decay applied', last: true },
|
|
57
|
+
]);
|
|
52
58
|
});
|
|
53
59
|
|
|
54
60
|
// ─── migrate status <address> ──────────────────────────────────────────────
|
|
@@ -85,15 +91,15 @@ export function registerMigrateCommands(program: Command): void {
|
|
|
85
91
|
migratedFrom: wasSource ? migratedFrom : null,
|
|
86
92
|
};
|
|
87
93
|
if (opts.json) return console.log(JSON.stringify(payload, null, 2));
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
const statusItems: import('../ui/tree').TreeItem[] = [
|
|
95
|
+
{ label: 'Address', value: formatAddress(address) },
|
|
96
|
+
{ label: 'Active', value: formatAddress(activeWallet) },
|
|
97
|
+
{ label: 'Status', value: isCurrent ? 'current (no further migration)' : `migrated — resolves to ${formatAddress(activeWallet)}` },
|
|
98
|
+
];
|
|
99
|
+
if (hasMigrated) statusItems.push({ label: 'Migrated to', value: formatAddress(migratedTo) });
|
|
100
|
+
if (wasSource) statusItems.push({ label: 'Migrated from', value: formatAddress(migratedFrom) });
|
|
101
|
+
statusItems[statusItems.length - 1].last = true;
|
|
102
|
+
renderTree(statusItems);
|
|
97
103
|
});
|
|
98
104
|
|
|
99
105
|
// ─── migrate lineage <address> ────────────────────────────────────────────
|
|
@@ -158,18 +164,14 @@ export function registerMigrateCommands(program: Command): void {
|
|
|
158
164
|
};
|
|
159
165
|
if (opts.json) return console.log(JSON.stringify(payload, null, 2));
|
|
160
166
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (i < entries.length) {
|
|
169
|
-
const e = entries[i];
|
|
170
|
-
if (e.timestamp) console.log(` migrated: ${e.timestamp}`);
|
|
171
|
-
if (e.scoreAtMigration) console.log(` score at migration: ${e.scoreAtMigration} (decay: ${Number(e.decayBps) / 100}%)`);
|
|
172
|
-
}
|
|
167
|
+
const lineageItems = lineage.map((addr, i) => {
|
|
168
|
+
const roleLabel = i === 0 ? ' (origin)' : i === lineage.length - 1 ? ' (current)' : '';
|
|
169
|
+
const e = i < entries.length ? entries[i] : null;
|
|
170
|
+
let value = formatAddress(addr) + roleLabel;
|
|
171
|
+
if (e?.timestamp) value += ` · ${e.timestamp}`;
|
|
172
|
+
if (e?.scoreAtMigration) value += ` · score: ${e.scoreAtMigration} (decay: ${Number(e.decayBps) / 100}%)`;
|
|
173
|
+
return { label: `[${i}]`, value, last: i === lineage.length - 1 };
|
|
173
174
|
});
|
|
175
|
+
renderTree(lineageItems);
|
|
174
176
|
});
|
|
175
177
|
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { loadConfig } from "../config";
|
|
12
12
|
import { requireSigner, getClient } from "../client";
|
|
13
13
|
import { hashFile, hashString } from "../utils/hash";
|
|
14
|
+
import { c } from '../ui/colors';
|
|
14
15
|
|
|
15
16
|
const sessionManager = new SessionManager();
|
|
16
17
|
|
|
@@ -102,7 +103,7 @@ export function registerNegotiateCommands(program: Command): void {
|
|
|
102
103
|
if (opts.json) {
|
|
103
104
|
console.log(JSON.stringify({ sessionId: session.sessionId, message: proposal }));
|
|
104
105
|
} else {
|
|
105
|
-
console.log(
|
|
106
|
+
console.log(' ' + c.success + c.white(' Session started: ' + session.sessionId.slice(0, 12) + '...'));
|
|
106
107
|
console.log(`Signed PROPOSE:`);
|
|
107
108
|
console.log(JSON.stringify(proposal, null, 2));
|
|
108
109
|
}
|
|
@@ -138,7 +139,7 @@ export function registerNegotiateCommands(program: Command): void {
|
|
|
138
139
|
if (opts.json) {
|
|
139
140
|
console.log(JSON.stringify(counter));
|
|
140
141
|
} else {
|
|
141
|
-
console.log(
|
|
142
|
+
console.log(' ' + c.success + c.white(' Counter added to session'));
|
|
142
143
|
console.log(JSON.stringify(counter, null, 2));
|
|
143
144
|
}
|
|
144
145
|
});
|
|
@@ -177,8 +178,8 @@ export function registerNegotiateCommands(program: Command): void {
|
|
|
177
178
|
message: accept,
|
|
178
179
|
}));
|
|
179
180
|
} else {
|
|
180
|
-
console.log(
|
|
181
|
-
console.log(
|
|
181
|
+
console.log(' ' + c.success + c.white(' Session ACCEPTED — transcript locked'));
|
|
182
|
+
console.log(' ' + c.dim(' Transcript:') + ' ' + c.white(updatedSession.transcriptHash ?? ''));
|
|
182
183
|
if (opts.record) {
|
|
183
184
|
console.log(`\nTranscript hash is ready to commit on-chain.`);
|
|
184
185
|
console.log(`Run: arc402 hire --session ${sessionId} to propose() and record the transcript hash.`);
|
|
@@ -212,7 +213,7 @@ export function registerNegotiateCommands(program: Command): void {
|
|
|
212
213
|
if (opts.json) {
|
|
213
214
|
console.log(JSON.stringify(reject));
|
|
214
215
|
} else {
|
|
215
|
-
console.log(
|
|
216
|
+
console.log(' ' + c.failure + c.white(' Session REJECTED'));
|
|
216
217
|
console.log(`Reason: ${opts.reason}`);
|
|
217
218
|
}
|
|
218
219
|
});
|
|
@@ -239,9 +240,9 @@ export function registerNegotiateCommands(program: Command): void {
|
|
|
239
240
|
if (opts.json) {
|
|
240
241
|
console.log(JSON.stringify(result));
|
|
241
242
|
} else if (result.valid) {
|
|
242
|
-
console.log(
|
|
243
|
+
console.log(' ' + c.success + c.white(' Valid — signer: ' + result.recoveredSigner));
|
|
243
244
|
} else {
|
|
244
|
-
console.error(
|
|
245
|
+
console.error(' ' + c.failure + c.white(' Invalid — ' + result.error));
|
|
245
246
|
process.exit(1);
|
|
246
247
|
}
|
|
247
248
|
});
|