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.
Files changed (358) hide show
  1. package/README.md +41 -2
  2. package/dist/abis.d.ts +1 -0
  3. package/dist/abis.d.ts.map +1 -1
  4. package/dist/abis.js +45 -14
  5. package/dist/abis.js.map +1 -1
  6. package/dist/bundler.d.ts +1 -1
  7. package/dist/bundler.d.ts.map +1 -1
  8. package/dist/bundler.js +61 -27
  9. package/dist/bundler.js.map +1 -1
  10. package/dist/client.d.ts +1 -1
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +9 -5
  13. package/dist/client.js.map +1 -1
  14. package/dist/coinbase-smart-wallet.js +4 -1
  15. package/dist/coinbase-smart-wallet.js.map +1 -1
  16. package/dist/commands/accept.js +28 -25
  17. package/dist/commands/accept.js.map +1 -1
  18. package/dist/commands/agent-handshake.js +18 -15
  19. package/dist/commands/agent-handshake.js.map +1 -1
  20. package/dist/commands/agent.js +104 -98
  21. package/dist/commands/agent.js.map +1 -1
  22. package/dist/commands/agreements.js +98 -62
  23. package/dist/commands/agreements.js.map +1 -1
  24. package/dist/commands/arbitrator.js +81 -45
  25. package/dist/commands/arbitrator.js.map +1 -1
  26. package/dist/commands/arena-handshake.d.ts.map +1 -1
  27. package/dist/commands/arena-handshake.js +35 -53
  28. package/dist/commands/arena-handshake.js.map +1 -1
  29. package/dist/commands/arena.js +18 -12
  30. package/dist/commands/arena.js.map +1 -1
  31. package/dist/commands/backup.js +36 -30
  32. package/dist/commands/backup.js.map +1 -1
  33. package/dist/commands/cancel.js +18 -15
  34. package/dist/commands/cancel.js.map +1 -1
  35. package/dist/commands/channel.js +81 -45
  36. package/dist/commands/channel.js.map +1 -1
  37. package/dist/commands/coldstart.js +34 -31
  38. package/dist/commands/coldstart.js.map +1 -1
  39. package/dist/commands/compute.d.ts +14 -0
  40. package/dist/commands/compute.d.ts.map +1 -0
  41. package/dist/commands/compute.js +466 -0
  42. package/dist/commands/compute.js.map +1 -0
  43. package/dist/commands/config.js +30 -24
  44. package/dist/commands/config.js.map +1 -1
  45. package/dist/commands/contract-interaction.js +15 -12
  46. package/dist/commands/contract-interaction.js.map +1 -1
  47. package/dist/commands/daemon.d.ts.map +1 -1
  48. package/dist/commands/daemon.js +135 -98
  49. package/dist/commands/daemon.js.map +1 -1
  50. package/dist/commands/deliver.js +76 -37
  51. package/dist/commands/deliver.js.map +1 -1
  52. package/dist/commands/discover.js +27 -24
  53. package/dist/commands/discover.js.map +1 -1
  54. package/dist/commands/dispute.js +110 -104
  55. package/dist/commands/dispute.js.map +1 -1
  56. package/dist/commands/doctor.js +55 -16
  57. package/dist/commands/doctor.js.map +1 -1
  58. package/dist/commands/endpoint.js +95 -56
  59. package/dist/commands/endpoint.js.map +1 -1
  60. package/dist/commands/feed.js +18 -11
  61. package/dist/commands/feed.js.map +1 -1
  62. package/dist/commands/hire.js +40 -37
  63. package/dist/commands/hire.js.map +1 -1
  64. package/dist/commands/migrate.js +33 -30
  65. package/dist/commands/migrate.js.map +1 -1
  66. package/dist/commands/negotiate.d.ts.map +1 -1
  67. package/dist/commands/negotiate.js +36 -34
  68. package/dist/commands/negotiate.js.map +1 -1
  69. package/dist/commands/openshell.js +104 -68
  70. package/dist/commands/openshell.js.map +1 -1
  71. package/dist/commands/owner.js +20 -17
  72. package/dist/commands/owner.js.map +1 -1
  73. package/dist/commands/policy.js +43 -41
  74. package/dist/commands/policy.js.map +1 -1
  75. package/dist/commands/relay.d.ts.map +1 -1
  76. package/dist/commands/relay.js +51 -18
  77. package/dist/commands/relay.js.map +1 -1
  78. package/dist/commands/remediate.js +23 -20
  79. package/dist/commands/remediate.js.map +1 -1
  80. package/dist/commands/reputation.js +27 -25
  81. package/dist/commands/reputation.js.map +1 -1
  82. package/dist/commands/setup.js +104 -65
  83. package/dist/commands/setup.js.map +1 -1
  84. package/dist/commands/trust.js +20 -17
  85. package/dist/commands/trust.js.map +1 -1
  86. package/dist/commands/verify.js +21 -18
  87. package/dist/commands/verify.js.map +1 -1
  88. package/dist/commands/wallet.d.ts.map +1 -1
  89. package/dist/commands/wallet.js +645 -679
  90. package/dist/commands/wallet.js.map +1 -1
  91. package/dist/commands/watch.js +36 -33
  92. package/dist/commands/watch.js.map +1 -1
  93. package/dist/commands/watchtower.js +73 -37
  94. package/dist/commands/watchtower.js.map +1 -1
  95. package/dist/commands/workroom.d.ts.map +1 -1
  96. package/dist/commands/workroom.js +282 -143
  97. package/dist/commands/workroom.js.map +1 -1
  98. package/dist/config.d.ts +3 -0
  99. package/dist/config.d.ts.map +1 -1
  100. package/dist/config.js +71 -22
  101. package/dist/config.js.map +1 -1
  102. package/dist/daemon/compute-metering.d.ts +61 -0
  103. package/dist/daemon/compute-metering.d.ts.map +1 -0
  104. package/dist/daemon/compute-metering.js +299 -0
  105. package/dist/daemon/compute-metering.js.map +1 -0
  106. package/dist/daemon/compute-session.d.ts +100 -0
  107. package/dist/daemon/compute-session.d.ts.map +1 -0
  108. package/dist/daemon/compute-session.js +231 -0
  109. package/dist/daemon/compute-session.js.map +1 -0
  110. package/dist/daemon/config.d.ts +19 -1
  111. package/dist/daemon/config.d.ts.map +1 -1
  112. package/dist/daemon/config.js +90 -16
  113. package/dist/daemon/config.js.map +1 -1
  114. package/dist/daemon/credentials.d.ts +24 -0
  115. package/dist/daemon/credentials.d.ts.map +1 -0
  116. package/dist/daemon/credentials.js +80 -0
  117. package/dist/daemon/credentials.js.map +1 -0
  118. package/dist/daemon/delivery-client.d.ts +35 -0
  119. package/dist/daemon/delivery-client.d.ts.map +1 -0
  120. package/dist/daemon/delivery-client.js +231 -0
  121. package/dist/daemon/delivery-client.js.map +1 -0
  122. package/dist/daemon/file-delivery.d.ts +98 -0
  123. package/dist/daemon/file-delivery.d.ts.map +1 -0
  124. package/dist/daemon/file-delivery.js +461 -0
  125. package/dist/daemon/file-delivery.js.map +1 -0
  126. package/dist/daemon/hire-listener.d.ts +3 -3
  127. package/dist/daemon/hire-listener.d.ts.map +1 -1
  128. package/dist/daemon/hire-listener.js +47 -13
  129. package/dist/daemon/hire-listener.js.map +1 -1
  130. package/dist/daemon/index.d.ts +2 -1
  131. package/dist/daemon/index.d.ts.map +1 -1
  132. package/dist/daemon/index.js +526 -53
  133. package/dist/daemon/index.js.map +1 -1
  134. package/dist/daemon/job-lifecycle.d.ts +1 -1
  135. package/dist/daemon/job-lifecycle.d.ts.map +1 -1
  136. package/dist/daemon/job-lifecycle.js +51 -11
  137. package/dist/daemon/job-lifecycle.js.map +1 -1
  138. package/dist/daemon/notify.d.ts +1 -1
  139. package/dist/daemon/notify.d.ts.map +1 -1
  140. package/dist/daemon/notify.js +53 -19
  141. package/dist/daemon/notify.js.map +1 -1
  142. package/dist/daemon/token-metering.js +47 -8
  143. package/dist/daemon/token-metering.js.map +1 -1
  144. package/dist/daemon/userops.d.ts +2 -2
  145. package/dist/daemon/userops.d.ts.map +1 -1
  146. package/dist/daemon/userops.js +27 -23
  147. package/dist/daemon/userops.js.map +1 -1
  148. package/dist/daemon/wallet-monitor.d.ts +1 -1
  149. package/dist/daemon/wallet-monitor.d.ts.map +1 -1
  150. package/dist/daemon/wallet-monitor.js +12 -8
  151. package/dist/daemon/wallet-monitor.js.map +1 -1
  152. package/dist/daemon/worker-executor.d.ts +71 -0
  153. package/dist/daemon/worker-executor.d.ts.map +1 -0
  154. package/dist/daemon/worker-executor.js +382 -0
  155. package/dist/daemon/worker-executor.js.map +1 -0
  156. package/dist/drain-v4.js +64 -26
  157. package/dist/drain-v4.js.map +1 -1
  158. package/dist/endpoint-config.js +63 -20
  159. package/dist/endpoint-config.js.map +1 -1
  160. package/dist/endpoint-notify.js +48 -9
  161. package/dist/endpoint-notify.js.map +1 -1
  162. package/dist/index.js +50 -18
  163. package/dist/index.js.map +1 -1
  164. package/dist/openshell-runtime.d.ts.map +1 -1
  165. package/dist/openshell-runtime.js +82 -38
  166. package/dist/openshell-runtime.js.map +1 -1
  167. package/dist/program.d.ts.map +1 -1
  168. package/dist/program.js +85 -78
  169. package/dist/program.js.map +1 -1
  170. package/dist/repl.js +31 -25
  171. package/dist/repl.js.map +1 -1
  172. package/dist/signing.js +6 -3
  173. package/dist/signing.js.map +1 -1
  174. package/dist/telegram-notify.js +40 -3
  175. package/dist/telegram-notify.js.map +1 -1
  176. package/dist/tui/App.d.ts.map +1 -1
  177. package/dist/tui/App.js +56 -89
  178. package/dist/tui/App.js.map +1 -1
  179. package/dist/tui/Footer.js +7 -4
  180. package/dist/tui/Footer.js.map +1 -1
  181. package/dist/tui/Header.d.ts +1 -1
  182. package/dist/tui/Header.d.ts.map +1 -1
  183. package/dist/tui/Header.js +14 -9
  184. package/dist/tui/Header.js.map +1 -1
  185. package/dist/tui/InputLine.d.ts +2 -1
  186. package/dist/tui/InputLine.d.ts.map +1 -1
  187. package/dist/tui/InputLine.js +47 -97
  188. package/dist/tui/InputLine.js.map +1 -1
  189. package/dist/tui/Viewport.d.ts +1 -2
  190. package/dist/tui/Viewport.d.ts.map +1 -1
  191. package/dist/tui/Viewport.js +26 -6
  192. package/dist/tui/Viewport.js.map +1 -1
  193. package/dist/tui/WalletConnectPairing.js +19 -16
  194. package/dist/tui/WalletConnectPairing.js.map +1 -1
  195. package/dist/tui/components/Button.js +9 -6
  196. package/dist/tui/components/Button.js.map +1 -1
  197. package/dist/tui/components/CeremonyView.js +8 -5
  198. package/dist/tui/components/CeremonyView.js.map +1 -1
  199. package/dist/tui/components/CompletionDropdown.js +9 -6
  200. package/dist/tui/components/CompletionDropdown.js.map +1 -1
  201. package/dist/tui/components/ConfirmPrompt.js +8 -5
  202. package/dist/tui/components/ConfirmPrompt.js.map +1 -1
  203. package/dist/tui/components/CustomTextInput.js +14 -11
  204. package/dist/tui/components/CustomTextInput.js.map +1 -1
  205. package/dist/tui/components/InteractiveTable.js +12 -9
  206. package/dist/tui/components/InteractiveTable.js.map +1 -1
  207. package/dist/tui/components/StepSpinner.js +13 -10
  208. package/dist/tui/components/StepSpinner.js.map +1 -1
  209. package/dist/tui/components/Toast.js +12 -8
  210. package/dist/tui/components/Toast.js.map +1 -1
  211. package/dist/tui/index.d.ts.map +1 -1
  212. package/dist/tui/index.js +21 -28
  213. package/dist/tui/index.js.map +1 -1
  214. package/dist/tui/useChat.js +19 -13
  215. package/dist/tui/useChat.js.map +1 -1
  216. package/dist/tui/useCommand.d.ts +2 -3
  217. package/dist/tui/useCommand.d.ts.map +1 -1
  218. package/dist/tui/useCommand.js +24 -100
  219. package/dist/tui/useCommand.js.map +1 -1
  220. package/dist/tui/useNotifications.js +8 -5
  221. package/dist/tui/useNotifications.js.map +1 -1
  222. package/dist/tui/useScroll.d.ts.map +1 -1
  223. package/dist/tui/useScroll.js +12 -15
  224. package/dist/tui/useScroll.js.map +1 -1
  225. package/dist/ui/banner.d.ts +0 -12
  226. package/dist/ui/banner.d.ts.map +1 -1
  227. package/dist/ui/banner.js +19 -35
  228. package/dist/ui/banner.js.map +1 -1
  229. package/dist/ui/colors.js +19 -13
  230. package/dist/ui/colors.js.map +1 -1
  231. package/dist/ui/format.js +14 -6
  232. package/dist/ui/format.js.map +1 -1
  233. package/dist/ui/qr-render.js +11 -4
  234. package/dist/ui/qr-render.js.map +1 -1
  235. package/dist/ui/rpc-fallback.js +11 -6
  236. package/dist/ui/rpc-fallback.js.map +1 -1
  237. package/dist/ui/spinner.js +12 -6
  238. package/dist/ui/spinner.js.map +1 -1
  239. package/dist/ui/tree.js +6 -3
  240. package/dist/ui/tree.js.map +1 -1
  241. package/dist/utils/format.js +41 -27
  242. package/dist/utils/format.js.map +1 -1
  243. package/dist/utils/hash.js +42 -4
  244. package/dist/utils/hash.js.map +1 -1
  245. package/dist/utils/time.js +6 -2
  246. package/dist/utils/time.js.map +1 -1
  247. package/dist/wallet-router.d.ts +1 -1
  248. package/dist/wallet-router.d.ts.map +1 -1
  249. package/dist/wallet-router.js +19 -12
  250. package/dist/wallet-router.js.map +1 -1
  251. package/dist/walletconnect-session.d.ts +1 -1
  252. package/dist/walletconnect-session.d.ts.map +1 -1
  253. package/dist/walletconnect-session.js +11 -6
  254. package/dist/walletconnect-session.js.map +1 -1
  255. package/dist/walletconnect.d.ts +5 -6
  256. package/dist/walletconnect.d.ts.map +1 -1
  257. package/dist/walletconnect.js +35 -32
  258. package/dist/walletconnect.js.map +1 -1
  259. package/package.json +11 -10
  260. package/INK6-UX-SPEC.md +0 -446
  261. package/MIGRATION-SPEC.md +0 -108
  262. package/TUI-SPEC.md +0 -214
  263. package/scripts/authorize-machine-key.ts +0 -43
  264. package/scripts/drain-wallet.ts +0 -149
  265. package/scripts/execute-spend-only.ts +0 -81
  266. package/scripts/register-agent-userop.ts +0 -186
  267. package/src/abis.ts +0 -187
  268. package/src/bundler.ts +0 -235
  269. package/src/client.ts +0 -36
  270. package/src/coinbase-smart-wallet.ts +0 -51
  271. package/src/commands/accept.ts +0 -64
  272. package/src/commands/agent-handshake.ts +0 -72
  273. package/src/commands/agent.ts +0 -691
  274. package/src/commands/agreements.ts +0 -350
  275. package/src/commands/arbitrator.ts +0 -180
  276. package/src/commands/arena-handshake.ts +0 -274
  277. package/src/commands/arena.ts +0 -122
  278. package/src/commands/backup.ts +0 -117
  279. package/src/commands/cancel.ts +0 -35
  280. package/src/commands/channel.ts +0 -218
  281. package/src/commands/coldstart.ts +0 -165
  282. package/src/commands/config.ts +0 -68
  283. package/src/commands/contract-interaction.ts +0 -166
  284. package/src/commands/daemon.ts +0 -1054
  285. package/src/commands/deliver.ts +0 -148
  286. package/src/commands/discover.ts +0 -350
  287. package/src/commands/dispute.ts +0 -375
  288. package/src/commands/doctor.ts +0 -172
  289. package/src/commands/endpoint.ts +0 -620
  290. package/src/commands/feed.ts +0 -229
  291. package/src/commands/hire.ts +0 -245
  292. package/src/commands/migrate.ts +0 -177
  293. package/src/commands/negotiate.ts +0 -272
  294. package/src/commands/openshell.ts +0 -1055
  295. package/src/commands/owner.ts +0 -35
  296. package/src/commands/policy.ts +0 -263
  297. package/src/commands/relay.ts +0 -277
  298. package/src/commands/remediate.ts +0 -24
  299. package/src/commands/reputation.ts +0 -79
  300. package/src/commands/setup.ts +0 -343
  301. package/src/commands/trust.ts +0 -27
  302. package/src/commands/verify.ts +0 -91
  303. package/src/commands/wallet.ts +0 -3548
  304. package/src/commands/watch.ts +0 -220
  305. package/src/commands/watchtower.ts +0 -248
  306. package/src/commands/workroom.ts +0 -963
  307. package/src/config.ts +0 -220
  308. package/src/daemon/config.ts +0 -344
  309. package/src/daemon/hire-listener.ts +0 -226
  310. package/src/daemon/index.ts +0 -1089
  311. package/src/daemon/job-lifecycle.ts +0 -215
  312. package/src/daemon/notify.ts +0 -297
  313. package/src/daemon/token-metering.ts +0 -183
  314. package/src/daemon/userops.ts +0 -119
  315. package/src/daemon/wallet-monitor.ts +0 -90
  316. package/src/drain-v4.ts +0 -159
  317. package/src/endpoint-config.ts +0 -83
  318. package/src/endpoint-notify.ts +0 -129
  319. package/src/index.ts +0 -74
  320. package/src/openshell-runtime.ts +0 -281
  321. package/src/program.ts +0 -88
  322. package/src/repl.ts +0 -178
  323. package/src/signing.ts +0 -28
  324. package/src/telegram-notify.ts +0 -88
  325. package/src/tui/App.tsx +0 -263
  326. package/src/tui/Footer.tsx +0 -18
  327. package/src/tui/Header.tsx +0 -45
  328. package/src/tui/InputLine.tsx +0 -243
  329. package/src/tui/Viewport.tsx +0 -51
  330. package/src/tui/WalletConnectPairing.tsx +0 -114
  331. package/src/tui/components/Button.tsx +0 -38
  332. package/src/tui/components/CeremonyView.tsx +0 -39
  333. package/src/tui/components/CompletionDropdown.tsx +0 -56
  334. package/src/tui/components/ConfirmPrompt.tsx +0 -36
  335. package/src/tui/components/CustomTextInput.tsx +0 -132
  336. package/src/tui/components/InteractiveTable.tsx +0 -106
  337. package/src/tui/components/StepSpinner.tsx +0 -84
  338. package/src/tui/components/Toast.tsx +0 -59
  339. package/src/tui/index.tsx +0 -90
  340. package/src/tui/useChat.ts +0 -103
  341. package/src/tui/useCommand.ts +0 -238
  342. package/src/tui/useNotifications.ts +0 -28
  343. package/src/tui/useScroll.ts +0 -69
  344. package/src/ui/banner.ts +0 -78
  345. package/src/ui/colors.ts +0 -30
  346. package/src/ui/format.ts +0 -78
  347. package/src/ui/qr-render.ts +0 -92
  348. package/src/ui/rpc-fallback.ts +0 -59
  349. package/src/ui/spinner.ts +0 -56
  350. package/src/ui/tree.ts +0 -16
  351. package/src/utils/format.ts +0 -48
  352. package/src/utils/hash.ts +0 -5
  353. package/src/utils/time.ts +0 -15
  354. package/src/wallet-router.ts +0 -178
  355. package/src/walletconnect-session.ts +0 -27
  356. package/src/walletconnect.ts +0 -309
  357. package/test/time.test.js +0 -11
  358. 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
- }
@@ -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
- `;