arc402-cli 0.9.18 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -2
- package/dist/abis.d.ts +1 -0
- package/dist/abis.d.ts.map +1 -1
- package/dist/abis.js +45 -14
- package/dist/abis.js.map +1 -1
- package/dist/bundler.d.ts +1 -1
- package/dist/bundler.d.ts.map +1 -1
- package/dist/bundler.js +61 -27
- package/dist/bundler.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +9 -5
- package/dist/client.js.map +1 -1
- package/dist/coinbase-smart-wallet.js +4 -1
- package/dist/coinbase-smart-wallet.js.map +1 -1
- package/dist/commands/accept.js +28 -25
- package/dist/commands/accept.js.map +1 -1
- package/dist/commands/agent-handshake.js +18 -15
- package/dist/commands/agent-handshake.js.map +1 -1
- package/dist/commands/agent.js +104 -98
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/agreements.js +98 -62
- package/dist/commands/agreements.js.map +1 -1
- package/dist/commands/arbitrator.js +81 -45
- package/dist/commands/arbitrator.js.map +1 -1
- package/dist/commands/arena-handshake.d.ts.map +1 -1
- package/dist/commands/arena-handshake.js +35 -53
- package/dist/commands/arena-handshake.js.map +1 -1
- package/dist/commands/arena.js +18 -12
- package/dist/commands/arena.js.map +1 -1
- package/dist/commands/backup.js +36 -30
- package/dist/commands/backup.js.map +1 -1
- package/dist/commands/cancel.js +18 -15
- package/dist/commands/cancel.js.map +1 -1
- package/dist/commands/channel.js +81 -45
- package/dist/commands/channel.js.map +1 -1
- package/dist/commands/coldstart.js +34 -31
- package/dist/commands/coldstart.js.map +1 -1
- package/dist/commands/compute.d.ts +14 -0
- package/dist/commands/compute.d.ts.map +1 -0
- package/dist/commands/compute.js +466 -0
- package/dist/commands/compute.js.map +1 -0
- package/dist/commands/config.js +30 -24
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/contract-interaction.js +15 -12
- package/dist/commands/contract-interaction.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +135 -98
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/deliver.js +76 -37
- package/dist/commands/deliver.js.map +1 -1
- package/dist/commands/discover.js +27 -24
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/dispute.js +110 -104
- package/dist/commands/dispute.js.map +1 -1
- package/dist/commands/doctor.js +55 -16
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/endpoint.js +95 -56
- package/dist/commands/endpoint.js.map +1 -1
- package/dist/commands/feed.js +18 -11
- package/dist/commands/feed.js.map +1 -1
- package/dist/commands/hire.js +40 -37
- package/dist/commands/hire.js.map +1 -1
- package/dist/commands/migrate.js +33 -30
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/negotiate.d.ts.map +1 -1
- package/dist/commands/negotiate.js +36 -34
- package/dist/commands/negotiate.js.map +1 -1
- package/dist/commands/openshell.js +104 -68
- package/dist/commands/openshell.js.map +1 -1
- package/dist/commands/owner.js +20 -17
- package/dist/commands/owner.js.map +1 -1
- package/dist/commands/policy.js +43 -41
- package/dist/commands/policy.js.map +1 -1
- package/dist/commands/relay.d.ts.map +1 -1
- package/dist/commands/relay.js +51 -18
- package/dist/commands/relay.js.map +1 -1
- package/dist/commands/remediate.js +23 -20
- package/dist/commands/remediate.js.map +1 -1
- package/dist/commands/reputation.js +27 -25
- package/dist/commands/reputation.js.map +1 -1
- package/dist/commands/setup.js +104 -65
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/trust.js +20 -17
- package/dist/commands/trust.js.map +1 -1
- package/dist/commands/verify.js +21 -18
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/wallet.d.ts.map +1 -1
- package/dist/commands/wallet.js +645 -679
- package/dist/commands/wallet.js.map +1 -1
- package/dist/commands/watch.js +36 -33
- package/dist/commands/watch.js.map +1 -1
- package/dist/commands/watchtower.js +73 -37
- package/dist/commands/watchtower.js.map +1 -1
- package/dist/commands/workroom.d.ts.map +1 -1
- package/dist/commands/workroom.js +282 -143
- package/dist/commands/workroom.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +71 -22
- package/dist/config.js.map +1 -1
- package/dist/daemon/compute-metering.d.ts +61 -0
- package/dist/daemon/compute-metering.d.ts.map +1 -0
- package/dist/daemon/compute-metering.js +299 -0
- package/dist/daemon/compute-metering.js.map +1 -0
- package/dist/daemon/compute-session.d.ts +100 -0
- package/dist/daemon/compute-session.d.ts.map +1 -0
- package/dist/daemon/compute-session.js +231 -0
- package/dist/daemon/compute-session.js.map +1 -0
- package/dist/daemon/config.d.ts +19 -1
- package/dist/daemon/config.d.ts.map +1 -1
- package/dist/daemon/config.js +90 -16
- package/dist/daemon/config.js.map +1 -1
- package/dist/daemon/credentials.d.ts +24 -0
- package/dist/daemon/credentials.d.ts.map +1 -0
- package/dist/daemon/credentials.js +80 -0
- package/dist/daemon/credentials.js.map +1 -0
- package/dist/daemon/delivery-client.d.ts +35 -0
- package/dist/daemon/delivery-client.d.ts.map +1 -0
- package/dist/daemon/delivery-client.js +231 -0
- package/dist/daemon/delivery-client.js.map +1 -0
- package/dist/daemon/file-delivery.d.ts +98 -0
- package/dist/daemon/file-delivery.d.ts.map +1 -0
- package/dist/daemon/file-delivery.js +461 -0
- package/dist/daemon/file-delivery.js.map +1 -0
- package/dist/daemon/hire-listener.d.ts +3 -3
- package/dist/daemon/hire-listener.d.ts.map +1 -1
- package/dist/daemon/hire-listener.js +47 -13
- package/dist/daemon/hire-listener.js.map +1 -1
- package/dist/daemon/index.d.ts +2 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +526 -53
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/job-lifecycle.d.ts +1 -1
- package/dist/daemon/job-lifecycle.d.ts.map +1 -1
- package/dist/daemon/job-lifecycle.js +51 -11
- package/dist/daemon/job-lifecycle.js.map +1 -1
- package/dist/daemon/notify.d.ts +1 -1
- package/dist/daemon/notify.d.ts.map +1 -1
- package/dist/daemon/notify.js +53 -19
- package/dist/daemon/notify.js.map +1 -1
- package/dist/daemon/token-metering.js +47 -8
- package/dist/daemon/token-metering.js.map +1 -1
- package/dist/daemon/userops.d.ts +2 -2
- package/dist/daemon/userops.d.ts.map +1 -1
- package/dist/daemon/userops.js +27 -23
- package/dist/daemon/userops.js.map +1 -1
- package/dist/daemon/wallet-monitor.d.ts +1 -1
- package/dist/daemon/wallet-monitor.d.ts.map +1 -1
- package/dist/daemon/wallet-monitor.js +12 -8
- package/dist/daemon/wallet-monitor.js.map +1 -1
- package/dist/daemon/worker-executor.d.ts +71 -0
- package/dist/daemon/worker-executor.d.ts.map +1 -0
- package/dist/daemon/worker-executor.js +382 -0
- package/dist/daemon/worker-executor.js.map +1 -0
- package/dist/drain-v4.js +64 -26
- package/dist/drain-v4.js.map +1 -1
- package/dist/endpoint-config.js +63 -20
- package/dist/endpoint-config.js.map +1 -1
- package/dist/endpoint-notify.js +48 -9
- package/dist/endpoint-notify.js.map +1 -1
- package/dist/index.js +50 -18
- package/dist/index.js.map +1 -1
- package/dist/openshell-runtime.d.ts.map +1 -1
- package/dist/openshell-runtime.js +82 -38
- package/dist/openshell-runtime.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +85 -78
- package/dist/program.js.map +1 -1
- package/dist/repl.js +31 -25
- package/dist/repl.js.map +1 -1
- package/dist/signing.js +6 -3
- package/dist/signing.js.map +1 -1
- package/dist/telegram-notify.js +40 -3
- package/dist/telegram-notify.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +56 -89
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/Footer.js +7 -4
- package/dist/tui/Footer.js.map +1 -1
- package/dist/tui/Header.d.ts +1 -1
- package/dist/tui/Header.d.ts.map +1 -1
- package/dist/tui/Header.js +14 -9
- package/dist/tui/Header.js.map +1 -1
- package/dist/tui/InputLine.d.ts +2 -1
- package/dist/tui/InputLine.d.ts.map +1 -1
- package/dist/tui/InputLine.js +47 -97
- package/dist/tui/InputLine.js.map +1 -1
- package/dist/tui/Viewport.d.ts +1 -2
- package/dist/tui/Viewport.d.ts.map +1 -1
- package/dist/tui/Viewport.js +26 -6
- package/dist/tui/Viewport.js.map +1 -1
- package/dist/tui/WalletConnectPairing.js +19 -16
- package/dist/tui/WalletConnectPairing.js.map +1 -1
- package/dist/tui/components/Button.js +9 -6
- package/dist/tui/components/Button.js.map +1 -1
- package/dist/tui/components/CeremonyView.js +8 -5
- package/dist/tui/components/CeremonyView.js.map +1 -1
- package/dist/tui/components/CompletionDropdown.js +9 -6
- package/dist/tui/components/CompletionDropdown.js.map +1 -1
- package/dist/tui/components/ConfirmPrompt.js +8 -5
- package/dist/tui/components/ConfirmPrompt.js.map +1 -1
- package/dist/tui/components/CustomTextInput.js +14 -11
- package/dist/tui/components/CustomTextInput.js.map +1 -1
- package/dist/tui/components/InteractiveTable.js +12 -9
- package/dist/tui/components/InteractiveTable.js.map +1 -1
- package/dist/tui/components/StepSpinner.js +13 -10
- package/dist/tui/components/StepSpinner.js.map +1 -1
- package/dist/tui/components/Toast.js +12 -8
- package/dist/tui/components/Toast.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +21 -28
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/useChat.js +19 -13
- package/dist/tui/useChat.js.map +1 -1
- package/dist/tui/useCommand.d.ts +2 -3
- package/dist/tui/useCommand.d.ts.map +1 -1
- package/dist/tui/useCommand.js +24 -100
- package/dist/tui/useCommand.js.map +1 -1
- package/dist/tui/useNotifications.js +8 -5
- package/dist/tui/useNotifications.js.map +1 -1
- package/dist/tui/useScroll.d.ts.map +1 -1
- package/dist/tui/useScroll.js +12 -15
- package/dist/tui/useScroll.js.map +1 -1
- package/dist/ui/banner.d.ts +0 -12
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +19 -35
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/colors.js +19 -13
- package/dist/ui/colors.js.map +1 -1
- package/dist/ui/format.js +14 -6
- package/dist/ui/format.js.map +1 -1
- package/dist/ui/qr-render.js +11 -4
- package/dist/ui/qr-render.js.map +1 -1
- package/dist/ui/rpc-fallback.js +11 -6
- package/dist/ui/rpc-fallback.js.map +1 -1
- package/dist/ui/spinner.js +12 -6
- package/dist/ui/spinner.js.map +1 -1
- package/dist/ui/tree.js +6 -3
- package/dist/ui/tree.js.map +1 -1
- package/dist/utils/format.js +41 -27
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/hash.js +42 -4
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/time.js +6 -2
- package/dist/utils/time.js.map +1 -1
- package/dist/wallet-router.d.ts +1 -1
- package/dist/wallet-router.d.ts.map +1 -1
- package/dist/wallet-router.js +19 -12
- package/dist/wallet-router.js.map +1 -1
- package/dist/walletconnect-session.d.ts +1 -1
- package/dist/walletconnect-session.d.ts.map +1 -1
- package/dist/walletconnect-session.js +11 -6
- package/dist/walletconnect-session.js.map +1 -1
- package/dist/walletconnect.d.ts +5 -6
- package/dist/walletconnect.d.ts.map +1 -1
- package/dist/walletconnect.js +35 -32
- package/dist/walletconnect.js.map +1 -1
- package/package.json +11 -10
- package/INK6-UX-SPEC.md +0 -446
- package/MIGRATION-SPEC.md +0 -108
- package/TUI-SPEC.md +0 -214
- package/scripts/authorize-machine-key.ts +0 -43
- package/scripts/drain-wallet.ts +0 -149
- package/scripts/execute-spend-only.ts +0 -81
- package/scripts/register-agent-userop.ts +0 -186
- package/src/abis.ts +0 -187
- package/src/bundler.ts +0 -235
- package/src/client.ts +0 -36
- package/src/coinbase-smart-wallet.ts +0 -51
- package/src/commands/accept.ts +0 -64
- package/src/commands/agent-handshake.ts +0 -72
- package/src/commands/agent.ts +0 -691
- package/src/commands/agreements.ts +0 -350
- package/src/commands/arbitrator.ts +0 -180
- package/src/commands/arena-handshake.ts +0 -274
- package/src/commands/arena.ts +0 -122
- package/src/commands/backup.ts +0 -117
- package/src/commands/cancel.ts +0 -35
- package/src/commands/channel.ts +0 -218
- package/src/commands/coldstart.ts +0 -165
- package/src/commands/config.ts +0 -68
- package/src/commands/contract-interaction.ts +0 -166
- package/src/commands/daemon.ts +0 -1054
- package/src/commands/deliver.ts +0 -148
- package/src/commands/discover.ts +0 -350
- package/src/commands/dispute.ts +0 -375
- package/src/commands/doctor.ts +0 -172
- package/src/commands/endpoint.ts +0 -620
- package/src/commands/feed.ts +0 -229
- package/src/commands/hire.ts +0 -245
- package/src/commands/migrate.ts +0 -177
- package/src/commands/negotiate.ts +0 -272
- package/src/commands/openshell.ts +0 -1055
- package/src/commands/owner.ts +0 -35
- package/src/commands/policy.ts +0 -263
- package/src/commands/relay.ts +0 -277
- package/src/commands/remediate.ts +0 -24
- package/src/commands/reputation.ts +0 -79
- package/src/commands/setup.ts +0 -343
- package/src/commands/trust.ts +0 -27
- package/src/commands/verify.ts +0 -91
- package/src/commands/wallet.ts +0 -3548
- package/src/commands/watch.ts +0 -220
- package/src/commands/watchtower.ts +0 -248
- package/src/commands/workroom.ts +0 -963
- package/src/config.ts +0 -220
- package/src/daemon/config.ts +0 -344
- package/src/daemon/hire-listener.ts +0 -226
- package/src/daemon/index.ts +0 -1089
- package/src/daemon/job-lifecycle.ts +0 -215
- package/src/daemon/notify.ts +0 -297
- package/src/daemon/token-metering.ts +0 -183
- package/src/daemon/userops.ts +0 -119
- package/src/daemon/wallet-monitor.ts +0 -90
- package/src/drain-v4.ts +0 -159
- package/src/endpoint-config.ts +0 -83
- package/src/endpoint-notify.ts +0 -129
- package/src/index.ts +0 -74
- package/src/openshell-runtime.ts +0 -281
- package/src/program.ts +0 -88
- package/src/repl.ts +0 -178
- package/src/signing.ts +0 -28
- package/src/telegram-notify.ts +0 -88
- package/src/tui/App.tsx +0 -263
- package/src/tui/Footer.tsx +0 -18
- package/src/tui/Header.tsx +0 -45
- package/src/tui/InputLine.tsx +0 -243
- package/src/tui/Viewport.tsx +0 -51
- package/src/tui/WalletConnectPairing.tsx +0 -114
- package/src/tui/components/Button.tsx +0 -38
- package/src/tui/components/CeremonyView.tsx +0 -39
- package/src/tui/components/CompletionDropdown.tsx +0 -56
- package/src/tui/components/ConfirmPrompt.tsx +0 -36
- package/src/tui/components/CustomTextInput.tsx +0 -132
- package/src/tui/components/InteractiveTable.tsx +0 -106
- package/src/tui/components/StepSpinner.tsx +0 -84
- package/src/tui/components/Toast.tsx +0 -59
- package/src/tui/index.tsx +0 -90
- package/src/tui/useChat.ts +0 -103
- package/src/tui/useCommand.ts +0 -238
- package/src/tui/useNotifications.ts +0 -28
- package/src/tui/useScroll.ts +0 -69
- package/src/ui/banner.ts +0 -78
- package/src/ui/colors.ts +0 -30
- package/src/ui/format.ts +0 -78
- package/src/ui/qr-render.ts +0 -92
- package/src/ui/rpc-fallback.ts +0 -59
- package/src/ui/spinner.ts +0 -56
- package/src/ui/tree.ts +0 -16
- package/src/utils/format.ts +0 -48
- package/src/utils/hash.ts +0 -5
- package/src/utils/time.ts +0 -15
- package/src/wallet-router.ts +0 -178
- package/src/walletconnect-session.ts +0 -27
- package/src/walletconnect.ts +0 -309
- package/test/time.test.js +0 -11
- package/tsconfig.json +0 -33
package/src/config.ts
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
import * as os from "os";
|
|
4
|
-
import { randomUUID } from "crypto";
|
|
5
|
-
|
|
6
|
-
export interface Arc402Config {
|
|
7
|
-
network: "base-mainnet" | "base-sepolia";
|
|
8
|
-
rpcUrl: string;
|
|
9
|
-
privateKey?: string;
|
|
10
|
-
guardianPrivateKey?: string;
|
|
11
|
-
guardianAddress?: string;
|
|
12
|
-
walletConnectProjectId?: string;
|
|
13
|
-
ownerAddress?: string;
|
|
14
|
-
agentRegistryAddress?: string;
|
|
15
|
-
agentRegistryV2Address?: string;
|
|
16
|
-
serviceAgreementAddress?: string;
|
|
17
|
-
disputeArbitrationAddress?: string;
|
|
18
|
-
disputeModuleAddress?: string;
|
|
19
|
-
trustRegistryAddress: string;
|
|
20
|
-
trustRegistryV2Address?: string;
|
|
21
|
-
intentAttestationAddress?: string;
|
|
22
|
-
settlementCoordinatorAddress?: string;
|
|
23
|
-
sessionChannelsAddress?: string;
|
|
24
|
-
reputationOracleAddress?: string;
|
|
25
|
-
sponsorshipAttestationAddress?: string;
|
|
26
|
-
capabilityRegistryAddress?: string;
|
|
27
|
-
governanceAddress?: string;
|
|
28
|
-
agreementTreeAddress?: string;
|
|
29
|
-
policyEngineAddress?: string;
|
|
30
|
-
walletFactoryAddress?: string;
|
|
31
|
-
walletContractAddress?: string;
|
|
32
|
-
watchtowerRegistryAddress?: string;
|
|
33
|
-
governedTokenWhitelistAddress?: string;
|
|
34
|
-
vouchingRegistryAddress?: string;
|
|
35
|
-
migrationRegistryAddress?: string;
|
|
36
|
-
handshakeAddress?: string;
|
|
37
|
-
paymasterUrl?: string; // CDP paymaster endpoint
|
|
38
|
-
cdpKeyName?: string; // CDP API key name (org/.../apiKeys/...)
|
|
39
|
-
cdpPrivateKey?: string; // CDP EC private key — base64 DER SEC1 (store in CDP_PRIVATE_KEY env var)
|
|
40
|
-
subdomainApi?: string; // defaults to https://api.arc402.xyz
|
|
41
|
-
telegramBotToken?: string;
|
|
42
|
-
telegramChatId?: string;
|
|
43
|
-
telegramThreadId?: number;
|
|
44
|
-
/** Tracks onboarding progress so `wallet deploy` can resume after interruption. */
|
|
45
|
-
onboardingProgress?: {
|
|
46
|
-
walletAddress: string;
|
|
47
|
-
step: number; // last completed step number (2=machineKey, 3=passkey, 4=policy, 5=agent)
|
|
48
|
-
completedSteps: string[];
|
|
49
|
-
};
|
|
50
|
-
wcSession?: {
|
|
51
|
-
topic: string;
|
|
52
|
-
expiry: number; // Unix timestamp
|
|
53
|
-
account: string; // Phone wallet address
|
|
54
|
-
chainId: number;
|
|
55
|
-
};
|
|
56
|
-
deviceId?: string; // UUID identifying the device this config was created on
|
|
57
|
-
lastCliVersion?: string; // Last CLI version that wrote this config (for upgrade detection)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const CONFIG_DIR = path.join(os.homedir(), ".arc402");
|
|
61
|
-
const CONFIG_PATH = process.env.ARC402_CONFIG || path.join(CONFIG_DIR, "config.json");
|
|
62
|
-
const DEVICE_ID_PATH = path.join(CONFIG_DIR, "device.id");
|
|
63
|
-
|
|
64
|
-
// WalletConnect project ID — get your own at cloud.walletconnect.com
|
|
65
|
-
const DEFAULT_WC_PROJECT_ID = "455e9425343b9156fce1428250c9a54a";
|
|
66
|
-
export const getWcProjectId = () => process.env.WC_PROJECT_ID ?? DEFAULT_WC_PROJECT_ID;
|
|
67
|
-
|
|
68
|
-
export const getConfigPath = () => CONFIG_PATH;
|
|
69
|
-
|
|
70
|
-
/** Returns this device's stable UUID, creating it on first call. */
|
|
71
|
-
function getOrCreateDeviceId(): string {
|
|
72
|
-
if (fs.existsSync(DEVICE_ID_PATH)) {
|
|
73
|
-
return fs.readFileSync(DEVICE_ID_PATH, "utf-8").trim();
|
|
74
|
-
}
|
|
75
|
-
const id = randomUUID();
|
|
76
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
77
|
-
fs.writeFileSync(DEVICE_ID_PATH, id, { mode: 0o600 });
|
|
78
|
-
return id;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function loadConfig(): Arc402Config {
|
|
82
|
-
const thisDeviceId = getOrCreateDeviceId();
|
|
83
|
-
|
|
84
|
-
if (!fs.existsSync(CONFIG_PATH)) {
|
|
85
|
-
// Auto-create with Base Mainnet defaults — zero friction
|
|
86
|
-
const defaults = NETWORK_DEFAULTS["base-mainnet"] ?? {};
|
|
87
|
-
const d = defaults as unknown as Record<string,string>;
|
|
88
|
-
const autoConfig: Arc402Config = {
|
|
89
|
-
network: "base-mainnet",
|
|
90
|
-
rpcUrl: defaults.rpcUrl ?? "https://mainnet.base.org",
|
|
91
|
-
walletConnectProjectId: getWcProjectId(),
|
|
92
|
-
ownerAddress: undefined,
|
|
93
|
-
policyEngineAddress: defaults.policyEngineAddress,
|
|
94
|
-
trustRegistryAddress: defaults.trustRegistryAddress ?? "",
|
|
95
|
-
agentRegistryAddress: d.agentRegistryV2Address ?? defaults.agentRegistryAddress,
|
|
96
|
-
serviceAgreementAddress: defaults.serviceAgreementAddress,
|
|
97
|
-
reputationOracleAddress: defaults.reputationOracleAddress,
|
|
98
|
-
sponsorshipAttestationAddress: defaults.sponsorshipAttestationAddress,
|
|
99
|
-
capabilityRegistryAddress: defaults.capabilityRegistryAddress,
|
|
100
|
-
governanceAddress: defaults.governanceAddress,
|
|
101
|
-
walletFactoryAddress: defaults.walletFactoryAddress,
|
|
102
|
-
sessionChannelsAddress: defaults.sessionChannelsAddress,
|
|
103
|
-
disputeModuleAddress: defaults.disputeModuleAddress,
|
|
104
|
-
deviceId: thisDeviceId,
|
|
105
|
-
};
|
|
106
|
-
saveConfig(autoConfig);
|
|
107
|
-
console.log(`◈ Config auto-created at ${CONFIG_PATH} (Base Mainnet)`);
|
|
108
|
-
console.log("⚠ Base Mainnet — real funds at risk. Use arc402 config init for testnet.");
|
|
109
|
-
return autoConfig;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8")) as Arc402Config;
|
|
113
|
-
|
|
114
|
-
// Multi-device awareness: warn if config was created on a different device
|
|
115
|
-
if (config.deviceId && config.deviceId !== thisDeviceId) {
|
|
116
|
-
console.warn("⚠ This config was created on a different device. Some keys may not work.");
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Backfill deviceId if missing (older config)
|
|
120
|
-
if (!config.deviceId) {
|
|
121
|
-
config.deviceId = thisDeviceId;
|
|
122
|
-
saveConfig(config);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return config;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function saveConfig(config: Arc402Config): void {
|
|
129
|
-
const configDir = path.dirname(CONFIG_PATH);
|
|
130
|
-
fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
|
|
131
|
-
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
132
|
-
if (config.privateKey) {
|
|
133
|
-
console.warn("⚠ Private key stored in plaintext at ~/.arc402/config.json");
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export const configExists = () => fs.existsSync(CONFIG_PATH);
|
|
138
|
-
|
|
139
|
-
// Public Base RPC — stale state, do not use for production. Alchemy recommended.
|
|
140
|
-
export const PUBLIC_BASE_RPC = "https://mainnet.base.org";
|
|
141
|
-
export const ALCHEMY_BASE_RPC = "https://mainnet.base.org";
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Warn at runtime if the configured RPC is the public Base endpoint.
|
|
145
|
-
* Public Base RPC has delayed state propagation — use Alchemy for production.
|
|
146
|
-
*/
|
|
147
|
-
export function warnIfPublicRpc(config: Arc402Config): void {
|
|
148
|
-
if (config.rpcUrl === PUBLIC_BASE_RPC || config.rpcUrl === "https://sepolia.base.org") {
|
|
149
|
-
console.warn("WARN: Using public Base RPC — state reads may be stale. Set rpcUrl to an Alchemy endpoint for production.");
|
|
150
|
-
console.warn(` Recommended: arc402 config set rpcUrl ${ALCHEMY_BASE_RPC}`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export const NETWORK_DEFAULTS: Record<string, Partial<Arc402Config> & { usdcAddress: string }> = {
|
|
155
|
-
"base-mainnet": {
|
|
156
|
-
rpcUrl: ALCHEMY_BASE_RPC,
|
|
157
|
-
usdcAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
158
|
-
paymasterUrl: "https://api.developer.coinbase.com/rpc/v1/base/dca85088-a2ac-4ec3-8647-5154b150e7a9",
|
|
159
|
-
// Base Mainnet deployments — v2 deployed 2026-03-15
|
|
160
|
-
policyEngineAddress: "0xAA5Ef3489C929bFB3BFf5D5FE15aa62d3763c847",
|
|
161
|
-
trustRegistryAddress: "0x22366D6dabb03062Bc0a5E893EfDff15D8E329b1", // TrustRegistryV3 — v2
|
|
162
|
-
trustRegistryV2Address: "0xdA1D377991B2E580991B0DD381CdD635dd71aC39", // old v2, kept for reference
|
|
163
|
-
intentAttestationAddress: "0x7ad8db6C5f394542E8e9658F86C85cC99Cf6D460",
|
|
164
|
-
settlementCoordinatorAddress: "0xd52d8Be9728976E0D70C89db9F8ACeb5B5e97cA2", // SettlementCoordinatorV2
|
|
165
|
-
agentRegistryAddress: "0xcc0D8731ccCf6CFfF4e66F6d68cA86330Ea8B622", // ARC402RegistryV2
|
|
166
|
-
agentRegistryV2Address: "0xD5c2851B00090c92Ba7F4723FB548bb30C9B6865", // AgentRegistry
|
|
167
|
-
walletFactoryAddress: "0xcB52B5d746eEc05e141039E92e3dBefeAe496051", // WalletFactoryV5 — redeployed 2026-03-19 (optimized bytecode, FOUNDRY_PROFILE=deploy)
|
|
168
|
-
sponsorshipAttestationAddress: "0xD6c2edE89Ea71aE19Db2Be848e172b444Ed38f22",
|
|
169
|
-
serviceAgreementAddress: "0xC98B402CAB9156da68A87a69E3B4bf167A3CCcF6",
|
|
170
|
-
sessionChannelsAddress: "0x578f8d1bd82E8D6268E329d664d663B4d985BE61",
|
|
171
|
-
disputeModuleAddress: "0x5ebd301cEF0C908AB17Fd183aD9c274E4B34e9d6",
|
|
172
|
-
reputationOracleAddress: "0x359F76a54F9A345546E430e4d6665A7dC9DaECd4",
|
|
173
|
-
governanceAddress: "0xE931DD2EEb9Af9353Dd5E2c1250492A0135E0EC4", // ARC402Governance
|
|
174
|
-
guardianAddress: "0xED0A033B79626cdf9570B6c3baC7f699cD0032D8", // ARC402Guardian
|
|
175
|
-
walletContractAddress: "0xfd5C8c0a08fDcdeD2fe03e0DC9FA55595667F313", // ARC402Wallet instance
|
|
176
|
-
agreementTreeAddress: "0x6a82240512619B25583b9e95783410cf782915b1",
|
|
177
|
-
capabilityRegistryAddress: "0x7becb642668B80502dD957A594E1dD0aC414c1a3",
|
|
178
|
-
disputeArbitrationAddress: "0xF61b75E4903fbC81169FeF8b7787C13cB7750601",
|
|
179
|
-
governedTokenWhitelistAddress: "0xeB58896337244Bb408362Fea727054f9e7157451",
|
|
180
|
-
watchtowerRegistryAddress: "0xbC811d1e3c5C5b67CA57df1DFb08847b1c8c458A",
|
|
181
|
-
vouchingRegistryAddress: "0x94519194Bf17865770faD59eF581feC512Ae99c9",
|
|
182
|
-
migrationRegistryAddress: "0xb60B62357b90F254f555f03B162a30E22890e3B5",
|
|
183
|
-
handshakeAddress: "0x4F5A38Bb746d7E5d49d8fd26CA6beD141Ec2DDb3",
|
|
184
|
-
},
|
|
185
|
-
"base-sepolia": {
|
|
186
|
-
rpcUrl: "https://sepolia.base.org",
|
|
187
|
-
usdcAddress: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
188
|
-
// v2 deployment — Base Sepolia (chain 84532) — deployed 2026-03-15
|
|
189
|
-
// Unchanged v1 contracts:
|
|
190
|
-
policyEngineAddress: "0x44102e70c2A366632d98Fe40d892a2501fC7fFF2",
|
|
191
|
-
intentAttestationAddress: "0x942c807Cc6E0240A061e074b61345618aBadc457",
|
|
192
|
-
settlementCoordinatorAddress: "0x52b565797975781f069368Df40d6633b2aD03390",
|
|
193
|
-
agentRegistryV2Address: "0x07D526f8A8e148570509aFa249EFF295045A0cc9", // AgentRegistry
|
|
194
|
-
reputationOracleAddress: "0x410e650113fd163389C956BC7fC51c5642617187",
|
|
195
|
-
walletFactoryAddress: "0xD560C22aD5372Aa830ee5ffBFa4a5D9f528e7B87",
|
|
196
|
-
sponsorshipAttestationAddress:"0xc0d927745AcF8DEeE551BE11A12c97c492DDC989",
|
|
197
|
-
governanceAddress: "0x504b3D73A8dFbcAB9551d8a11Bb0B07C90C4c926",
|
|
198
|
-
guardianAddress: "0x5c1D2cD6B9B291b436BF1b109A711F0E477EB6fe",
|
|
199
|
-
walletContractAddress: "0xc77854f9091A25eD1f35EA24E9bdFb64d0850E45",
|
|
200
|
-
agreementTreeAddress: "0x8F46F31FcEbd60f526308AD20e4a008887709720",
|
|
201
|
-
capabilityRegistryAddress: "0x6a413e74b65828A014dD8DA61861Bf9E1b6372D2",
|
|
202
|
-
governedTokenWhitelistAddress:"0x64C15CA701167C7c901a8a5575a5232b37CAF213",
|
|
203
|
-
watchtowerRegistryAddress: "0x70c4E53E3A916eB8A695630f129B943af9C61C57",
|
|
204
|
-
// v2 contracts (new/redeployed 2026-03-15):
|
|
205
|
-
trustRegistryAddress: "0xf2aE072BB8575c23B0efbF44bDc8188aA900cA7a", // TrustRegistryV3
|
|
206
|
-
agentRegistryAddress: "0x0461b2b7A1E50866962CB07326000A94009c58Ff", // ARC402RegistryV2
|
|
207
|
-
serviceAgreementAddress: "0xbbb1DA355D810E9baEF1a7D072B2132E4755976B",
|
|
208
|
-
sessionChannelsAddress: "0x5EF144AE2C8456d014e6E3F293c162410C043564",
|
|
209
|
-
disputeModuleAddress: "0x01866144495fBBbBB7aaD81605de051B2A62594A",
|
|
210
|
-
disputeArbitrationAddress: "0xa4f6F77927Da53a25926A5f0bffBEB0210108cA8",
|
|
211
|
-
vouchingRegistryAddress: "0x96432aDc7aC06256297AdF11B94C47f68b2F13A2",
|
|
212
|
-
migrationRegistryAddress: "0x3aeAaD32386D6fC40eeb5c2C27a5aCFE6aDf9ABD",
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
export const getUsdcAddress = (config: Arc402Config) => NETWORK_DEFAULTS[config.network]?.usdcAddress ?? "";
|
|
217
|
-
|
|
218
|
-
export function getSubdomainApi(config: Arc402Config): string {
|
|
219
|
-
return config.subdomainApi ?? "https://api.arc402.xyz";
|
|
220
|
-
}
|
package/src/daemon/config.ts
DELETED
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Daemon configuration loader.
|
|
3
|
-
* Parses ~/.arc402/daemon.toml, enforces env: prefix for secrets,
|
|
4
|
-
* resolves env: values from the environment.
|
|
5
|
-
*/
|
|
6
|
-
import * as fs from "fs";
|
|
7
|
-
import * as path from "path";
|
|
8
|
-
import * as os from "os";
|
|
9
|
-
import { ethers } from "ethers";
|
|
10
|
-
import { parse as parseToml } from "smol-toml";
|
|
11
|
-
|
|
12
|
-
export const DAEMON_DIR = path.join(os.homedir(), ".arc402");
|
|
13
|
-
export const DAEMON_TOML = path.join(DAEMON_DIR, "daemon.toml");
|
|
14
|
-
export const DAEMON_PID = path.join(DAEMON_DIR, "daemon.pid");
|
|
15
|
-
export const DAEMON_LOG = path.join(DAEMON_DIR, "daemon.log");
|
|
16
|
-
export const DAEMON_DB = path.join(DAEMON_DIR, "daemon.db");
|
|
17
|
-
export const DAEMON_SOCK = path.join(DAEMON_DIR, "daemon.sock");
|
|
18
|
-
|
|
19
|
-
export interface DaemonConfig {
|
|
20
|
-
wallet: {
|
|
21
|
-
contract_address: string;
|
|
22
|
-
owner_address: string;
|
|
23
|
-
machine_key: string; // must be "env:VAR_NAME"
|
|
24
|
-
};
|
|
25
|
-
network: {
|
|
26
|
-
rpc_url: string;
|
|
27
|
-
chain_id: number;
|
|
28
|
-
entry_point: string;
|
|
29
|
-
};
|
|
30
|
-
bundler: {
|
|
31
|
-
mode: "external" | "arc402" | "self";
|
|
32
|
-
endpoint: string;
|
|
33
|
-
earn_fees: boolean;
|
|
34
|
-
eth_float: string;
|
|
35
|
-
sweep_threshold: string;
|
|
36
|
-
sweep_to: string;
|
|
37
|
-
rpc_url: string;
|
|
38
|
-
};
|
|
39
|
-
relay: {
|
|
40
|
-
enabled: boolean;
|
|
41
|
-
listen_port: number;
|
|
42
|
-
endpoint: string;
|
|
43
|
-
max_concurrent_agreements: number;
|
|
44
|
-
poll_interval_seconds: number;
|
|
45
|
-
relay_url: string;
|
|
46
|
-
};
|
|
47
|
-
watchtower: {
|
|
48
|
-
enabled: boolean;
|
|
49
|
-
poll_interval_seconds: number;
|
|
50
|
-
challenge_confirmation_blocks: number;
|
|
51
|
-
external_watchtower_url: string;
|
|
52
|
-
update_interval_states: number;
|
|
53
|
-
};
|
|
54
|
-
policy: {
|
|
55
|
-
auto_accept: boolean;
|
|
56
|
-
max_price_eth: string;
|
|
57
|
-
allowed_capabilities: string[];
|
|
58
|
-
require_min_trust_score: number;
|
|
59
|
-
min_hire_lead_time_seconds: number;
|
|
60
|
-
};
|
|
61
|
-
notifications: {
|
|
62
|
-
telegram_bot_token: string;
|
|
63
|
-
telegram_chat_id: string;
|
|
64
|
-
notify_on_hire_request: boolean;
|
|
65
|
-
notify_on_hire_accepted: boolean;
|
|
66
|
-
notify_on_hire_rejected: boolean;
|
|
67
|
-
notify_on_delivery: boolean;
|
|
68
|
-
notify_on_dispute: boolean;
|
|
69
|
-
notify_on_channel_challenge: boolean;
|
|
70
|
-
notify_on_low_balance: boolean;
|
|
71
|
-
low_balance_threshold_eth: string;
|
|
72
|
-
discord: { webhook_url: string };
|
|
73
|
-
webhook: { url: string; headers: Record<string, string> };
|
|
74
|
-
email: { smtp_host: string; smtp_port: number; smtp_user: string; smtp_pass: string; to: string };
|
|
75
|
-
};
|
|
76
|
-
work: {
|
|
77
|
-
handler: "exec" | "http" | "noop";
|
|
78
|
-
exec_command: string;
|
|
79
|
-
http_url: string;
|
|
80
|
-
http_auth_token: string;
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function resolveEnvValue(value: string, field: string): string {
|
|
85
|
-
if (!value.startsWith("env:")) return value;
|
|
86
|
-
const varName = value.slice(4);
|
|
87
|
-
const resolved = process.env[varName];
|
|
88
|
-
if (!resolved) {
|
|
89
|
-
throw new Error(`Environment variable ${varName} is not set (required for ${field})`);
|
|
90
|
-
}
|
|
91
|
-
return resolved;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function tryResolveEnvValue(value: string): string {
|
|
95
|
-
if (!value.startsWith("env:")) return value;
|
|
96
|
-
const varName = value.slice(4);
|
|
97
|
-
return process.env[varName] ?? "";
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function str(v: unknown, def = ""): string {
|
|
101
|
-
return typeof v === "string" ? v : def;
|
|
102
|
-
}
|
|
103
|
-
function num(v: unknown, def: number): number {
|
|
104
|
-
return typeof v === "number" ? v : def;
|
|
105
|
-
}
|
|
106
|
-
function bool(v: unknown, def: boolean): boolean {
|
|
107
|
-
return typeof v === "boolean" ? v : def;
|
|
108
|
-
}
|
|
109
|
-
function strArr(v: unknown): string[] {
|
|
110
|
-
return Array.isArray(v) ? (v as string[]) : [];
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function withDefaults(raw: Record<string, unknown>): DaemonConfig {
|
|
114
|
-
const w = (raw.wallet as Record<string, unknown>) ?? {};
|
|
115
|
-
const n = (raw.network as Record<string, unknown>) ?? {};
|
|
116
|
-
const b = (raw.bundler as Record<string, unknown>) ?? {};
|
|
117
|
-
const r = (raw.relay as Record<string, unknown>) ?? {};
|
|
118
|
-
const wt = (raw.watchtower as Record<string, unknown>) ?? {};
|
|
119
|
-
const p = (raw.policy as Record<string, unknown>) ?? {};
|
|
120
|
-
const notif = (raw.notifications as Record<string, unknown>) ?? {};
|
|
121
|
-
const notifDiscord = (notif.discord as Record<string, unknown>) ?? {};
|
|
122
|
-
const notifWebhook = (notif.webhook as Record<string, unknown>) ?? {};
|
|
123
|
-
const notifEmail = (notif.email as Record<string, unknown>) ?? {};
|
|
124
|
-
const work = (raw.work as Record<string, unknown>) ?? {};
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
wallet: {
|
|
128
|
-
contract_address: str(w.contract_address),
|
|
129
|
-
owner_address: str(w.owner_address),
|
|
130
|
-
machine_key: str(w.machine_key, "env:ARC402_MACHINE_KEY"),
|
|
131
|
-
},
|
|
132
|
-
network: {
|
|
133
|
-
rpc_url: str(n.rpc_url, "https://mainnet.base.org"),
|
|
134
|
-
chain_id: num(n.chain_id, 8453),
|
|
135
|
-
entry_point: str(n.entry_point, "0x0000000071727De22E5E9d8BAf0edAc6f37da032"),
|
|
136
|
-
},
|
|
137
|
-
bundler: {
|
|
138
|
-
mode: (str(b.mode, "external")) as "external" | "arc402" | "self",
|
|
139
|
-
endpoint: str(b.endpoint),
|
|
140
|
-
earn_fees: bool(b.earn_fees, false),
|
|
141
|
-
eth_float: str(b.eth_float, "0.01"),
|
|
142
|
-
sweep_threshold: str(b.sweep_threshold, "0.005"),
|
|
143
|
-
sweep_to: str(b.sweep_to),
|
|
144
|
-
rpc_url: str(b.rpc_url),
|
|
145
|
-
},
|
|
146
|
-
relay: {
|
|
147
|
-
enabled: bool(r.enabled, true),
|
|
148
|
-
listen_port: num(r.listen_port, 4402),
|
|
149
|
-
endpoint: str(r.endpoint),
|
|
150
|
-
max_concurrent_agreements: num(r.max_concurrent_agreements, 10),
|
|
151
|
-
poll_interval_seconds: num(r.poll_interval_seconds, 2),
|
|
152
|
-
relay_url: str(r.relay_url),
|
|
153
|
-
},
|
|
154
|
-
watchtower: {
|
|
155
|
-
enabled: bool(wt.enabled, true),
|
|
156
|
-
poll_interval_seconds: num(wt.poll_interval_seconds, 60),
|
|
157
|
-
challenge_confirmation_blocks: num(wt.challenge_confirmation_blocks, 2),
|
|
158
|
-
external_watchtower_url: str(wt.external_watchtower_url),
|
|
159
|
-
update_interval_states: num(wt.update_interval_states, 10),
|
|
160
|
-
},
|
|
161
|
-
policy: {
|
|
162
|
-
auto_accept: bool(p.auto_accept, false),
|
|
163
|
-
max_price_eth: str(p.max_price_eth, "0.1"),
|
|
164
|
-
allowed_capabilities: strArr(p.allowed_capabilities),
|
|
165
|
-
require_min_trust_score: num(p.require_min_trust_score, 50),
|
|
166
|
-
min_hire_lead_time_seconds: num(p.min_hire_lead_time_seconds, 300),
|
|
167
|
-
},
|
|
168
|
-
notifications: {
|
|
169
|
-
telegram_bot_token: str(notif.telegram_bot_token, "env:TELEGRAM_BOT_TOKEN"),
|
|
170
|
-
telegram_chat_id: str(notif.telegram_chat_id, "env:TELEGRAM_CHAT_ID"),
|
|
171
|
-
notify_on_hire_request: bool(notif.notify_on_hire_request, true),
|
|
172
|
-
notify_on_hire_accepted: bool(notif.notify_on_hire_accepted, true),
|
|
173
|
-
notify_on_hire_rejected: bool(notif.notify_on_hire_rejected, true),
|
|
174
|
-
notify_on_delivery: bool(notif.notify_on_delivery, true),
|
|
175
|
-
notify_on_dispute: bool(notif.notify_on_dispute, true),
|
|
176
|
-
notify_on_channel_challenge: bool(notif.notify_on_channel_challenge, true),
|
|
177
|
-
notify_on_low_balance: bool(notif.notify_on_low_balance, true),
|
|
178
|
-
low_balance_threshold_eth: str(notif.low_balance_threshold_eth, "0.005"),
|
|
179
|
-
discord: { webhook_url: str(notifDiscord.webhook_url) },
|
|
180
|
-
webhook: {
|
|
181
|
-
url: str(notifWebhook.url),
|
|
182
|
-
headers: (notifWebhook.headers as Record<string, string>) ?? {},
|
|
183
|
-
},
|
|
184
|
-
email: {
|
|
185
|
-
smtp_host: str(notifEmail.smtp_host),
|
|
186
|
-
smtp_port: num(notifEmail.smtp_port, 587),
|
|
187
|
-
smtp_user: str(notifEmail.smtp_user),
|
|
188
|
-
smtp_pass: str(notifEmail.smtp_pass, "env:SMTP_PASS"),
|
|
189
|
-
to: str(notifEmail.to),
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
work: {
|
|
193
|
-
handler: (str(work.handler, "noop")) as "exec" | "http" | "noop",
|
|
194
|
-
exec_command: str(work.exec_command),
|
|
195
|
-
http_url: str(work.http_url),
|
|
196
|
-
http_auth_token: str(work.http_auth_token),
|
|
197
|
-
},
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export function loadDaemonConfig(configPath = DAEMON_TOML): DaemonConfig {
|
|
202
|
-
if (!fs.existsSync(configPath)) {
|
|
203
|
-
throw new Error(`daemon.toml not found at ${configPath}. Run: arc402 daemon init`);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const raw = fs.readFileSync(configPath, "utf-8");
|
|
207
|
-
let parsed: Record<string, unknown>;
|
|
208
|
-
try {
|
|
209
|
-
parsed = parseToml(raw) as Record<string, unknown>;
|
|
210
|
-
} catch (err) {
|
|
211
|
-
throw new Error(`Failed to parse daemon.toml: ${err instanceof Error ? err.message : String(err)}`);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const config = withDefaults(parsed);
|
|
215
|
-
|
|
216
|
-
// Required fields
|
|
217
|
-
if (!config.wallet.contract_address) {
|
|
218
|
-
throw new Error("daemon.toml: wallet.contract_address is required");
|
|
219
|
-
}
|
|
220
|
-
if (!config.network.rpc_url) {
|
|
221
|
-
throw new Error("daemon.toml: network.rpc_url is required");
|
|
222
|
-
}
|
|
223
|
-
if (!config.network.chain_id) {
|
|
224
|
-
throw new Error("daemon.toml: network.chain_id is required");
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Machine key MUST use env: prefix — never hardcoded
|
|
228
|
-
if (!config.wallet.machine_key.startsWith("env:")) {
|
|
229
|
-
throw new Error("ERROR: machine_key must use env: prefix — never hardcode keys");
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Resolve optional env: values silently (missing = disabled feature)
|
|
233
|
-
config.notifications.telegram_bot_token = tryResolveEnvValue(config.notifications.telegram_bot_token);
|
|
234
|
-
config.notifications.telegram_chat_id = tryResolveEnvValue(config.notifications.telegram_chat_id);
|
|
235
|
-
config.notifications.discord.webhook_url = tryResolveEnvValue(config.notifications.discord.webhook_url);
|
|
236
|
-
config.notifications.webhook.url = tryResolveEnvValue(config.notifications.webhook.url);
|
|
237
|
-
config.notifications.email.smtp_pass = tryResolveEnvValue(config.notifications.email.smtp_pass);
|
|
238
|
-
config.work.http_auth_token = tryResolveEnvValue(config.work.http_auth_token);
|
|
239
|
-
|
|
240
|
-
return config;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export function loadMachineKey(config: DaemonConfig): { privateKey: string; address: string } {
|
|
244
|
-
const envVarName = config.wallet.machine_key.startsWith("env:")
|
|
245
|
-
? config.wallet.machine_key.slice(4)
|
|
246
|
-
: "ARC402_MACHINE_KEY";
|
|
247
|
-
|
|
248
|
-
const privateKey = process.env[envVarName];
|
|
249
|
-
if (!privateKey) {
|
|
250
|
-
throw new Error(`Machine key not found. Set environment variable: ${envVarName}`);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// ethers imported at top level
|
|
254
|
-
let address: string;
|
|
255
|
-
try {
|
|
256
|
-
const w = new ethers.Wallet(privateKey);
|
|
257
|
-
address = w.address;
|
|
258
|
-
} catch {
|
|
259
|
-
throw new Error(`Invalid machine key format in ${envVarName}`);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return { privateKey, address };
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
export const TEMPLATE_DAEMON_TOML = `# ~/.arc402/daemon.toml
|
|
266
|
-
# ARC-402 Daemon Configuration
|
|
267
|
-
# Generated by: arc402 daemon init
|
|
268
|
-
#
|
|
269
|
-
# SECURITY: Never put private keys here. Use environment variables.
|
|
270
|
-
|
|
271
|
-
[wallet]
|
|
272
|
-
contract_address = "" # ARC402Wallet contract address (required)
|
|
273
|
-
owner_address = "" # Owner EOA address — for display and verification only
|
|
274
|
-
machine_key = "env:ARC402_MACHINE_KEY" # Machine key loaded from environment. NEVER hardcode here.
|
|
275
|
-
|
|
276
|
-
[network]
|
|
277
|
-
rpc_url = "https://mainnet.base.org" # Public Base RPC (default)
|
|
278
|
-
chain_id = 8453 # Base mainnet. Use 84532 for Base Sepolia.
|
|
279
|
-
entry_point = "0x0000000071727De22E5E9d8BAf0edAc6f37da032" # ERC-4337 EntryPoint v0.7
|
|
280
|
-
|
|
281
|
-
[bundler]
|
|
282
|
-
mode = "external" # external | arc402 | self
|
|
283
|
-
endpoint = "" # Required when mode = external. Pimlico, Alchemy, etc.
|
|
284
|
-
earn_fees = false # self mode only: bundle for other network agents
|
|
285
|
-
eth_float = "0.01" # Minimum ETH to maintain in bundler EOA for gas fronting
|
|
286
|
-
sweep_threshold = "0.005" # Sweep fees to wallet when bundler EOA exceeds this (ETH)
|
|
287
|
-
sweep_to = "" # Sweep destination. Defaults to wallet.contract_address.
|
|
288
|
-
rpc_url = "" # self mode: private RPC. Defaults to network.rpc_url if empty.
|
|
289
|
-
|
|
290
|
-
[relay]
|
|
291
|
-
enabled = true
|
|
292
|
-
listen_port = 4402 # Port for incoming relay messages
|
|
293
|
-
endpoint = "" # Your public URL — run: arc402 setup endpoint
|
|
294
|
-
# Example: https://gigabrain.arc402.xyz
|
|
295
|
-
max_concurrent_agreements = 10 # Refuse new hire requests when this many are in-flight
|
|
296
|
-
poll_interval_seconds = 2 # How often to poll relay for incoming messages
|
|
297
|
-
relay_url = "" # The relay to poll. Defaults to agent metadata relay if empty.
|
|
298
|
-
|
|
299
|
-
[watchtower]
|
|
300
|
-
enabled = true
|
|
301
|
-
poll_interval_seconds = 60 # How often to poll chain for stale-close events
|
|
302
|
-
challenge_confirmation_blocks = 2 # Wait N block confirmations before accepting close as final
|
|
303
|
-
external_watchtower_url = "" # Register open channels here as backup (Tier 2 watchtower)
|
|
304
|
-
update_interval_states = 10 # Forward state to external watchtower every N state changes
|
|
305
|
-
|
|
306
|
-
[policy]
|
|
307
|
-
auto_accept = false # If true: auto-accept all hire requests within policy bounds
|
|
308
|
-
max_price_eth = "0.1" # Refuse any hire priced above this (ETH)
|
|
309
|
-
allowed_capabilities = [] # Empty list = accept any capability. Non-empty = whitelist.
|
|
310
|
-
require_min_trust_score = 50 # Refuse hirers whose wallet trust score is below this (0–100)
|
|
311
|
-
min_hire_lead_time_seconds = 300 # Refuse hires with delivery deadline < this many seconds away
|
|
312
|
-
|
|
313
|
-
[notifications]
|
|
314
|
-
telegram_bot_token = "env:TELEGRAM_BOT_TOKEN" # Load from env, not hardcoded
|
|
315
|
-
telegram_chat_id = "env:TELEGRAM_CHAT_ID" # Load from env, not hardcoded
|
|
316
|
-
notify_on_hire_request = true # Notify when a hire request arrives (pending approval)
|
|
317
|
-
notify_on_hire_accepted = true # Notify when daemon accepts a hire
|
|
318
|
-
notify_on_hire_rejected = true # Notify when daemon rejects a hire
|
|
319
|
-
notify_on_delivery = true # Notify when work is delivered and fulfill() submitted
|
|
320
|
-
notify_on_dispute = true # Notify when a dispute is raised (by either party)
|
|
321
|
-
notify_on_channel_challenge = true # Notify when watchtower submits a channel challenge
|
|
322
|
-
notify_on_low_balance = false # Disabled by default — enable if you want balance alerts
|
|
323
|
-
low_balance_threshold_eth = "0.005" # Balance alert threshold
|
|
324
|
-
|
|
325
|
-
[notifications.discord]
|
|
326
|
-
webhook_url = "" # Discord channel webhook URL (leave empty to disable)
|
|
327
|
-
|
|
328
|
-
[notifications.webhook]
|
|
329
|
-
url = "" # POST JSON {title, body, timestamp} to this URL (leave empty to disable)
|
|
330
|
-
# headers = { Authorization = "Bearer ..." } # Optional headers
|
|
331
|
-
|
|
332
|
-
[notifications.email]
|
|
333
|
-
smtp_host = "" # SMTP server hostname (leave empty to disable)
|
|
334
|
-
smtp_port = 587
|
|
335
|
-
smtp_user = "" # SMTP login / from address
|
|
336
|
-
smtp_pass = "env:SMTP_PASS" # Load from env, not hardcoded
|
|
337
|
-
to = "" # Recipient address
|
|
338
|
-
|
|
339
|
-
[work]
|
|
340
|
-
handler = "noop" # exec | http | noop
|
|
341
|
-
exec_command = "" # called with agreementId and spec as args (exec mode)
|
|
342
|
-
http_url = "" # POST {agreementId, specHash, deadline} as JSON (http mode)
|
|
343
|
-
http_auth_token = "env:WORKER_AUTH_TOKEN"
|
|
344
|
-
`;
|