arc402-cli 0.9.19 → 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 (359) 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.d.ts.map +1 -1
  161. package/dist/endpoint-notify.js +49 -15
  162. package/dist/endpoint-notify.js.map +1 -1
  163. package/dist/index.js +50 -18
  164. package/dist/index.js.map +1 -1
  165. package/dist/openshell-runtime.d.ts.map +1 -1
  166. package/dist/openshell-runtime.js +82 -38
  167. package/dist/openshell-runtime.js.map +1 -1
  168. package/dist/program.d.ts.map +1 -1
  169. package/dist/program.js +85 -78
  170. package/dist/program.js.map +1 -1
  171. package/dist/repl.js +31 -25
  172. package/dist/repl.js.map +1 -1
  173. package/dist/signing.js +6 -3
  174. package/dist/signing.js.map +1 -1
  175. package/dist/telegram-notify.js +40 -3
  176. package/dist/telegram-notify.js.map +1 -1
  177. package/dist/tui/App.d.ts.map +1 -1
  178. package/dist/tui/App.js +56 -89
  179. package/dist/tui/App.js.map +1 -1
  180. package/dist/tui/Footer.js +7 -4
  181. package/dist/tui/Footer.js.map +1 -1
  182. package/dist/tui/Header.d.ts +1 -1
  183. package/dist/tui/Header.d.ts.map +1 -1
  184. package/dist/tui/Header.js +14 -9
  185. package/dist/tui/Header.js.map +1 -1
  186. package/dist/tui/InputLine.d.ts +2 -1
  187. package/dist/tui/InputLine.d.ts.map +1 -1
  188. package/dist/tui/InputLine.js +47 -97
  189. package/dist/tui/InputLine.js.map +1 -1
  190. package/dist/tui/Viewport.d.ts +1 -2
  191. package/dist/tui/Viewport.d.ts.map +1 -1
  192. package/dist/tui/Viewport.js +26 -6
  193. package/dist/tui/Viewport.js.map +1 -1
  194. package/dist/tui/WalletConnectPairing.js +19 -16
  195. package/dist/tui/WalletConnectPairing.js.map +1 -1
  196. package/dist/tui/components/Button.js +9 -6
  197. package/dist/tui/components/Button.js.map +1 -1
  198. package/dist/tui/components/CeremonyView.js +8 -5
  199. package/dist/tui/components/CeremonyView.js.map +1 -1
  200. package/dist/tui/components/CompletionDropdown.js +9 -6
  201. package/dist/tui/components/CompletionDropdown.js.map +1 -1
  202. package/dist/tui/components/ConfirmPrompt.js +8 -5
  203. package/dist/tui/components/ConfirmPrompt.js.map +1 -1
  204. package/dist/tui/components/CustomTextInput.js +14 -11
  205. package/dist/tui/components/CustomTextInput.js.map +1 -1
  206. package/dist/tui/components/InteractiveTable.js +12 -9
  207. package/dist/tui/components/InteractiveTable.js.map +1 -1
  208. package/dist/tui/components/StepSpinner.js +13 -10
  209. package/dist/tui/components/StepSpinner.js.map +1 -1
  210. package/dist/tui/components/Toast.js +12 -8
  211. package/dist/tui/components/Toast.js.map +1 -1
  212. package/dist/tui/index.d.ts.map +1 -1
  213. package/dist/tui/index.js +21 -28
  214. package/dist/tui/index.js.map +1 -1
  215. package/dist/tui/useChat.js +19 -13
  216. package/dist/tui/useChat.js.map +1 -1
  217. package/dist/tui/useCommand.d.ts +2 -3
  218. package/dist/tui/useCommand.d.ts.map +1 -1
  219. package/dist/tui/useCommand.js +24 -100
  220. package/dist/tui/useCommand.js.map +1 -1
  221. package/dist/tui/useNotifications.js +8 -5
  222. package/dist/tui/useNotifications.js.map +1 -1
  223. package/dist/tui/useScroll.d.ts.map +1 -1
  224. package/dist/tui/useScroll.js +12 -15
  225. package/dist/tui/useScroll.js.map +1 -1
  226. package/dist/ui/banner.d.ts +0 -12
  227. package/dist/ui/banner.d.ts.map +1 -1
  228. package/dist/ui/banner.js +19 -35
  229. package/dist/ui/banner.js.map +1 -1
  230. package/dist/ui/colors.js +19 -13
  231. package/dist/ui/colors.js.map +1 -1
  232. package/dist/ui/format.js +14 -6
  233. package/dist/ui/format.js.map +1 -1
  234. package/dist/ui/qr-render.js +11 -4
  235. package/dist/ui/qr-render.js.map +1 -1
  236. package/dist/ui/rpc-fallback.js +11 -6
  237. package/dist/ui/rpc-fallback.js.map +1 -1
  238. package/dist/ui/spinner.js +12 -6
  239. package/dist/ui/spinner.js.map +1 -1
  240. package/dist/ui/tree.js +6 -3
  241. package/dist/ui/tree.js.map +1 -1
  242. package/dist/utils/format.js +41 -27
  243. package/dist/utils/format.js.map +1 -1
  244. package/dist/utils/hash.js +42 -4
  245. package/dist/utils/hash.js.map +1 -1
  246. package/dist/utils/time.js +6 -2
  247. package/dist/utils/time.js.map +1 -1
  248. package/dist/wallet-router.d.ts +1 -1
  249. package/dist/wallet-router.d.ts.map +1 -1
  250. package/dist/wallet-router.js +19 -12
  251. package/dist/wallet-router.js.map +1 -1
  252. package/dist/walletconnect-session.d.ts +1 -1
  253. package/dist/walletconnect-session.d.ts.map +1 -1
  254. package/dist/walletconnect-session.js +11 -6
  255. package/dist/walletconnect-session.js.map +1 -1
  256. package/dist/walletconnect.d.ts +5 -6
  257. package/dist/walletconnect.d.ts.map +1 -1
  258. package/dist/walletconnect.js +35 -32
  259. package/dist/walletconnect.js.map +1 -1
  260. package/package.json +11 -10
  261. package/INK6-UX-SPEC.md +0 -446
  262. package/MIGRATION-SPEC.md +0 -108
  263. package/TUI-SPEC.md +0 -214
  264. package/scripts/authorize-machine-key.ts +0 -43
  265. package/scripts/drain-wallet.ts +0 -149
  266. package/scripts/execute-spend-only.ts +0 -81
  267. package/scripts/register-agent-userop.ts +0 -186
  268. package/src/abis.ts +0 -187
  269. package/src/bundler.ts +0 -235
  270. package/src/client.ts +0 -36
  271. package/src/coinbase-smart-wallet.ts +0 -51
  272. package/src/commands/accept.ts +0 -64
  273. package/src/commands/agent-handshake.ts +0 -72
  274. package/src/commands/agent.ts +0 -691
  275. package/src/commands/agreements.ts +0 -350
  276. package/src/commands/arbitrator.ts +0 -180
  277. package/src/commands/arena-handshake.ts +0 -274
  278. package/src/commands/arena.ts +0 -122
  279. package/src/commands/backup.ts +0 -117
  280. package/src/commands/cancel.ts +0 -35
  281. package/src/commands/channel.ts +0 -218
  282. package/src/commands/coldstart.ts +0 -165
  283. package/src/commands/config.ts +0 -68
  284. package/src/commands/contract-interaction.ts +0 -166
  285. package/src/commands/daemon.ts +0 -1054
  286. package/src/commands/deliver.ts +0 -148
  287. package/src/commands/discover.ts +0 -350
  288. package/src/commands/dispute.ts +0 -375
  289. package/src/commands/doctor.ts +0 -172
  290. package/src/commands/endpoint.ts +0 -620
  291. package/src/commands/feed.ts +0 -229
  292. package/src/commands/hire.ts +0 -245
  293. package/src/commands/migrate.ts +0 -177
  294. package/src/commands/negotiate.ts +0 -272
  295. package/src/commands/openshell.ts +0 -1055
  296. package/src/commands/owner.ts +0 -35
  297. package/src/commands/policy.ts +0 -263
  298. package/src/commands/relay.ts +0 -277
  299. package/src/commands/remediate.ts +0 -24
  300. package/src/commands/reputation.ts +0 -79
  301. package/src/commands/setup.ts +0 -343
  302. package/src/commands/trust.ts +0 -27
  303. package/src/commands/verify.ts +0 -91
  304. package/src/commands/wallet.ts +0 -3548
  305. package/src/commands/watch.ts +0 -220
  306. package/src/commands/watchtower.ts +0 -248
  307. package/src/commands/workroom.ts +0 -963
  308. package/src/config.ts +0 -220
  309. package/src/daemon/config.ts +0 -344
  310. package/src/daemon/hire-listener.ts +0 -226
  311. package/src/daemon/index.ts +0 -1089
  312. package/src/daemon/job-lifecycle.ts +0 -215
  313. package/src/daemon/notify.ts +0 -297
  314. package/src/daemon/token-metering.ts +0 -183
  315. package/src/daemon/userops.ts +0 -119
  316. package/src/daemon/wallet-monitor.ts +0 -90
  317. package/src/drain-v4.ts +0 -159
  318. package/src/endpoint-config.ts +0 -83
  319. package/src/endpoint-notify.ts +0 -134
  320. package/src/index.ts +0 -74
  321. package/src/openshell-runtime.ts +0 -281
  322. package/src/program.ts +0 -88
  323. package/src/repl.ts +0 -178
  324. package/src/signing.ts +0 -28
  325. package/src/telegram-notify.ts +0 -88
  326. package/src/tui/App.tsx +0 -263
  327. package/src/tui/Footer.tsx +0 -18
  328. package/src/tui/Header.tsx +0 -45
  329. package/src/tui/InputLine.tsx +0 -243
  330. package/src/tui/Viewport.tsx +0 -51
  331. package/src/tui/WalletConnectPairing.tsx +0 -114
  332. package/src/tui/components/Button.tsx +0 -38
  333. package/src/tui/components/CeremonyView.tsx +0 -39
  334. package/src/tui/components/CompletionDropdown.tsx +0 -56
  335. package/src/tui/components/ConfirmPrompt.tsx +0 -36
  336. package/src/tui/components/CustomTextInput.tsx +0 -132
  337. package/src/tui/components/InteractiveTable.tsx +0 -106
  338. package/src/tui/components/StepSpinner.tsx +0 -84
  339. package/src/tui/components/Toast.tsx +0 -59
  340. package/src/tui/index.tsx +0 -90
  341. package/src/tui/useChat.ts +0 -103
  342. package/src/tui/useCommand.ts +0 -238
  343. package/src/tui/useNotifications.ts +0 -28
  344. package/src/tui/useScroll.ts +0 -69
  345. package/src/ui/banner.ts +0 -78
  346. package/src/ui/colors.ts +0 -30
  347. package/src/ui/format.ts +0 -78
  348. package/src/ui/qr-render.ts +0 -92
  349. package/src/ui/rpc-fallback.ts +0 -59
  350. package/src/ui/spinner.ts +0 -56
  351. package/src/ui/tree.ts +0 -16
  352. package/src/utils/format.ts +0 -48
  353. package/src/utils/hash.ts +0 -5
  354. package/src/utils/time.ts +0 -15
  355. package/src/wallet-router.ts +0 -178
  356. package/src/walletconnect-session.ts +0 -27
  357. package/src/walletconnect.ts +0 -309
  358. package/test/time.test.js +0 -11
  359. package/tsconfig.json +0 -33
@@ -1,220 +0,0 @@
1
- import { Command } from "commander";
2
- import { ethers } from "ethers";
3
- import { loadConfig } from "../config.js";
4
- import { getClient } from "../client.js";
5
- import { c } from "../ui/colors.js";
6
-
7
- // ─── Minimal ABIs for event watching ─────────────────────────────────────────
8
-
9
- const AGENT_REGISTRY_WATCH_ABI = [
10
- "event AgentRegistered(address indexed wallet, string name, string serviceType, uint256 timestamp)",
11
- "event AgentUpdated(address indexed wallet, string name, string serviceType)",
12
- "event AgentDeactivated(address indexed wallet)",
13
- ];
14
-
15
- const SERVICE_AGREEMENT_WATCH_ABI = [
16
- "event AgreementProposed(uint256 indexed id, address indexed client, address indexed provider, string serviceType, uint256 price, address token, uint256 deadline)",
17
- "event AgreementAccepted(uint256 indexed id, address indexed provider)",
18
- "event AgreementFulfilled(uint256 indexed id, address indexed provider, bytes32 deliverablesHash)",
19
- "event AgreementDisputed(uint256 indexed id, address indexed initiator, string reason)",
20
- "event AgreementCancelled(uint256 indexed id, address indexed client)",
21
- ];
22
-
23
- const HANDSHAKE_WATCH_ABI = [
24
- "event HandshakeSent(uint256 indexed handshakeId, address indexed from, address indexed to, uint8 hsType, address token, uint256 amount, string note, uint256 timestamp)",
25
- ];
26
-
27
- const DISPUTE_MODULE_WATCH_ABI = [
28
- "event DisputeRaised(uint256 indexed agreementId, address indexed initiator, string reason)",
29
- "event DisputeResolved(uint256 indexed agreementId, bool favorProvider, string resolution)",
30
- ];
31
-
32
- const HS_TYPE_LABELS: Record<number, string> = {
33
- 0: "Respected",
34
- 1: "Curious",
35
- 2: "Endorsed",
36
- 3: "Thanked",
37
- 4: "Collaborated",
38
- 5: "Challenged",
39
- 6: "Referred",
40
- 7: "Hello",
41
- };
42
-
43
- function shortAddr(addr: string): string {
44
- return addr.length > 10 ? `${addr.slice(0, 6)}...${addr.slice(-4)}` : addr;
45
- }
46
-
47
- function nowHHMM(): string {
48
- const d = new Date();
49
- const h = d.getHours().toString().padStart(2, "0");
50
- const m = d.getMinutes().toString().padStart(2, "0");
51
- return `${h}:${m}`;
52
- }
53
-
54
- function printEvent(label: string, detail: string, status?: "ok" | "warn" | "err"): void {
55
- const ts = c.dim(`[${nowHHMM()}]`);
56
- const col = status === "ok" ? c.green : status === "err" ? c.red : status === "warn" ? c.yellow : c.white;
57
- process.stdout.write(` ${ts} ${col(label)} ${c.dim(detail)}\n`);
58
- }
59
-
60
- export function registerWatchCommand(program: Command): void {
61
- program
62
- .command("watch")
63
- .description("Watch wallet activity in real-time (live onchain event feed)")
64
- .action(async () => {
65
- const config = loadConfig();
66
- const { provider } = await getClient(config);
67
- const myWallet = (config.walletContractAddress ?? "").toLowerCase();
68
- const shortMe = myWallet ? shortAddr(config.walletContractAddress!) : "(no wallet)";
69
-
70
- const line = "─".repeat(22);
71
- console.log(`\n ${c.mark} ${c.white("ARC-402 Live Feed")} ${c.dim(line)}`);
72
- console.log(` ${c.dim("Watching")} ${c.brightCyan(shortMe)} ${c.dim("on")} ${c.dim(config.network)}`);
73
- console.log(` ${c.dim("Ctrl+C to exit")}\n`);
74
-
75
- // ── Build contract instances ───────────────────────────────────────────
76
-
77
- const contractLabels: string[] = [];
78
-
79
- if (config.agentRegistryAddress) contractLabels.push("AgentRegistry");
80
- if (config.serviceAgreementAddress) contractLabels.push("ServiceAgreement");
81
- if (config.handshakeAddress) contractLabels.push("Handshake");
82
- if (config.disputeModuleAddress) contractLabels.push("DisputeModule");
83
-
84
- if (contractLabels.length === 0) {
85
- console.log(` ${c.warning} No contract addresses configured. Run arc402 config init.`);
86
- process.exit(1);
87
- }
88
-
89
- console.log(` ${c.dim(`Monitoring ${contractLabels.length} contract${contractLabels.length !== 1 ? "s" : ""}: ${contractLabels.join(", ")}`)}\n`);
90
-
91
- // ── Helpers ────────────────────────────────────────────────────────────
92
-
93
- function isMe(addr: string): boolean {
94
- return myWallet !== "" && addr.toLowerCase() === myWallet;
95
- }
96
-
97
- function fmtAddr(addr: string): string {
98
- return isMe(addr) ? c.brightCyan("you") : c.dim(shortAddr(addr));
99
- }
100
-
101
- // ── AgentRegistry ──────────────────────────────────────────────────────
102
-
103
- if (config.agentRegistryAddress) {
104
- const reg = new ethers.Contract(config.agentRegistryAddress, AGENT_REGISTRY_WATCH_ABI, provider);
105
-
106
- reg.on("AgentRegistered", (wallet: string, name: string, serviceType: string) => {
107
- printEvent(`Agent registered: ${name}`, `${fmtAddr(wallet)} ${c.dim(serviceType)}`, "ok");
108
- });
109
-
110
- reg.on("AgentUpdated", (wallet: string, name: string, serviceType: string) => {
111
- printEvent(`Agent updated: ${name}`, `${fmtAddr(wallet)} ${c.dim(serviceType)}`);
112
- });
113
-
114
- reg.on("AgentDeactivated", (wallet: string) => {
115
- printEvent(`Agent deactivated`, fmtAddr(wallet), "warn");
116
- });
117
- }
118
-
119
- // ── ServiceAgreement ───────────────────────────────────────────────────
120
-
121
- if (config.serviceAgreementAddress) {
122
- const sa = new ethers.Contract(config.serviceAgreementAddress, SERVICE_AGREEMENT_WATCH_ABI, provider);
123
-
124
- sa.on("AgreementProposed", (id: bigint, client: string, agentProvider: string, serviceType: string) => {
125
- const involved = isMe(client) || isMe(agentProvider);
126
- printEvent(
127
- `Agreement #${id} proposed`,
128
- `${fmtAddr(client)} → ${fmtAddr(agentProvider)} ${c.dim(serviceType)}`,
129
- involved ? "ok" : undefined
130
- );
131
- });
132
-
133
- sa.on("AgreementAccepted", (id: bigint, agentProvider: string) => {
134
- printEvent(`Agreement #${id} → ${c.green("ACCEPTED")}`, fmtAddr(agentProvider));
135
- });
136
-
137
- sa.on("AgreementFulfilled", (id: bigint, agentProvider: string, deliverablesHash: string) => {
138
- printEvent(
139
- `Agreement #${id} → ${c.green("DELIVERED")}`,
140
- `${fmtAddr(agentProvider)} ${c.dim(deliverablesHash.slice(0, 10) + "...")}`,
141
- "ok"
142
- );
143
- });
144
-
145
- sa.on("AgreementDisputed", (id: bigint, initiator: string, reason: string) => {
146
- printEvent(
147
- `Agreement #${id} → ${c.red("DISPUTED")}`,
148
- `${fmtAddr(initiator)} ${c.dim(reason.slice(0, 40))}`,
149
- "err"
150
- );
151
- });
152
-
153
- sa.on("AgreementCancelled", (id: bigint, client: string) => {
154
- printEvent(`Agreement #${id} → ${c.yellow("CANCELLED")}`, fmtAddr(client), "warn");
155
- });
156
- }
157
-
158
- // ── Handshake ──────────────────────────────────────────────────────────
159
-
160
- if (config.handshakeAddress) {
161
- const hs = new ethers.Contract(config.handshakeAddress, HANDSHAKE_WATCH_ABI, provider);
162
-
163
- hs.on("HandshakeSent", (_id: bigint, from: string, to: string, hsType: number, _token: string, _amount: bigint, note: string) => {
164
- const typeLabel = HS_TYPE_LABELS[hsType] ?? `type ${hsType}`;
165
- const toMe = isMe(to);
166
- const noteStr = note ? ` ${c.dim(`(${note.slice(0, 30)})`)}` : "";
167
- printEvent(
168
- `Handshake from ${fmtAddr(from)} → ${fmtAddr(to)}`,
169
- `${c.dim(typeLabel)}${noteStr}`,
170
- toMe ? "ok" : undefined
171
- );
172
- });
173
- }
174
-
175
- // ── DisputeModule ──────────────────────────────────────────────────────
176
-
177
- if (config.disputeModuleAddress) {
178
- const dm = new ethers.Contract(config.disputeModuleAddress, DISPUTE_MODULE_WATCH_ABI, provider);
179
-
180
- dm.on("DisputeRaised", (agreementId: bigint, initiator: string, reason: string) => {
181
- printEvent(
182
- `Dispute raised on #${agreementId}`,
183
- `${fmtAddr(initiator)} ${c.dim(reason.slice(0, 40))}`,
184
- "err"
185
- );
186
- });
187
-
188
- dm.on("DisputeResolved", (agreementId: bigint, favorProvider: boolean, resolution: string) => {
189
- printEvent(
190
- `Dispute #${agreementId} → ${c.green("RESOLVED")}`,
191
- `${c.dim(favorProvider ? "provider wins" : "client wins")} ${c.dim(resolution.slice(0, 30))}`,
192
- "ok"
193
- );
194
- });
195
- }
196
-
197
- // ── Block heartbeat (shows feed is alive) ──────────────────────────────
198
-
199
- let lastBlock = 0;
200
- provider.on("block", (blockNumber: number) => {
201
- if (blockNumber > lastBlock) {
202
- lastBlock = blockNumber;
203
- if (blockNumber % 10 === 0) {
204
- process.stdout.write(` ${c.dim(`· block ${blockNumber}`)}\n`);
205
- }
206
- }
207
- });
208
-
209
- // ── Clean exit ─────────────────────────────────────────────────────────
210
-
211
- process.on("SIGINT", () => {
212
- console.log(`\n ${c.dim("Feed stopped.")}`);
213
- provider.removeAllListeners();
214
- process.exit(0);
215
- });
216
-
217
- // Keep process alive
218
- process.stdin.resume();
219
- });
220
- }
@@ -1,248 +0,0 @@
1
- import { Command } from "commander";
2
- import * as fs from "fs";
3
- import * as path from "path";
4
- import * as os from "os";
5
- import { loadConfig } from "../config.js";
6
- import { requireSigner, getClient } from "../client.js";
7
- import { WatchtowerClient, ChannelClient } from "@arc402/sdk";
8
- import { c } from '../ui/colors.js';
9
- import { startSpinner } from '../ui/spinner.js';
10
- import { renderTree } from '../ui/tree.js';
11
- import { formatAddress } from '../ui/format.js';
12
-
13
- const CHANNEL_STATES_DIR = path.join(os.homedir(), ".arc402", "channel-states");
14
-
15
- function loadStateFile(filePath: string): { [key: string]: unknown; cumulativePayment: bigint; sequenceNumber: number } {
16
- const raw = fs.readFileSync(filePath, "utf-8");
17
- const obj = JSON.parse(raw) as Record<string, unknown>;
18
- return {
19
- ...obj,
20
- cumulativePayment: BigInt(obj.cumulativePayment as string),
21
- sequenceNumber: Number(obj.sequenceNumber),
22
- };
23
- }
24
-
25
- export function registerWatchtowerCommands(program: Command): void {
26
- const wt = program
27
- .command("watchtower")
28
- .description("Watchtower management — register, status, and monitor channels for bad-faith closes");
29
-
30
- // ─── register ──────────────────────────────────────────────────────────────
31
-
32
- wt.command("register")
33
- .description("Register this node as a watchtower in the on-chain WatchtowerRegistry")
34
- .requiredOption("--name <name>", "Watchtower display name")
35
- .option("--description <desc>", "Short description", "ARC-402 watchtower node")
36
- .option("--capabilities <caps>", "Comma-separated capability tags", "challenge")
37
- .option("--json", "JSON output")
38
- .action(async (opts) => {
39
- const config = loadConfig();
40
- if (!config.watchtowerRegistryAddress) throw new Error("watchtowerRegistryAddress missing in config");
41
- if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
42
- const { signer } = await requireSigner(config);
43
- const client = new WatchtowerClient(
44
- config.watchtowerRegistryAddress,
45
- config.serviceAgreementAddress,
46
- signer
47
- );
48
- const capabilities = opts.capabilities
49
- .split(",")
50
- .map((s: string) => s.trim())
51
- .filter(Boolean);
52
- const regSpinner = startSpinner('Registering watchtower…');
53
- const result = await client.registerWatchtower({
54
- name: opts.name,
55
- description: opts.description,
56
- capabilities,
57
- });
58
- if (opts.json || program.opts().json) {
59
- regSpinner.stop();
60
- console.log(JSON.stringify(result));
61
- } else {
62
- regSpinner.succeed(c.success + c.white(' Registered as watchtower'));
63
- renderTree([
64
- { label: 'Name', value: opts.name },
65
- { label: 'Tx', value: result.txHash, last: true },
66
- ]);
67
- }
68
- });
69
-
70
- // ─── status ────────────────────────────────────────────────────────────────
71
-
72
- wt.command("status [address]")
73
- .description("Check watchtower registration status (defaults to your own address)")
74
- .option("--json", "JSON output")
75
- .action(async (address, opts) => {
76
- const config = loadConfig();
77
- if (!config.watchtowerRegistryAddress) throw new Error("watchtowerRegistryAddress missing in config");
78
- if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
79
- const { provider, address: myAddress } = await getClient(config);
80
- const client = new WatchtowerClient(
81
- config.watchtowerRegistryAddress,
82
- config.serviceAgreementAddress,
83
- provider
84
- );
85
- const target = address ?? myAddress;
86
- if (!target) {
87
- console.error("No address provided and no private key configured");
88
- process.exit(1);
89
- }
90
- const status = await client.getWatchtowerStatus(target);
91
- if (opts.json || program.opts().json) {
92
- console.log(JSON.stringify(status, null, 2));
93
- } else {
94
- console.log('\n ' + c.mark + c.white(' Watchtower — ' + formatAddress(status.addr)));
95
- const statusItems: { label: string; value: string; last?: boolean }[] = [
96
- { label: 'Name', value: status.name },
97
- { label: 'Description', value: status.description },
98
- { label: 'Capabilities', value: status.capabilities.join(', ') || '(none)' },
99
- { label: 'Active', value: String(status.active) },
100
- ];
101
- if (status.registeredAt) {
102
- statusItems.push({ label: 'Registered', value: new Date(status.registeredAt * 1000).toISOString(), last: true });
103
- } else {
104
- statusItems[statusItems.length - 1].last = true;
105
- }
106
- renderTree(statusItems);
107
- }
108
- });
109
-
110
- // ─── watch ─────────────────────────────────────────────────────────────────
111
-
112
- wt.command("watch <channelId>")
113
- .description("Monitor a session channel for bad-faith closes and auto-submit a challenge")
114
- .option(
115
- "--state <path>",
116
- "Path to latest signed state JSON (defaults to ~/.arc402/channel-states/<channelId>.json)"
117
- )
118
- .option("--interval <ms>", "Polling interval in milliseconds", "12000")
119
- .option("--json", "JSON output")
120
- .action(async (channelId, opts) => {
121
- const config = loadConfig();
122
- if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
123
- if (!config.watchtowerRegistryAddress) throw new Error("watchtowerRegistryAddress missing in config");
124
- const { signer, address } = await requireSigner(config);
125
-
126
- const watchtowerClient = new WatchtowerClient(
127
- config.watchtowerRegistryAddress,
128
- config.serviceAgreementAddress,
129
- signer
130
- );
131
- const channelClient = new ChannelClient(config.serviceAgreementAddress, signer);
132
-
133
- const statePath = opts.state ?? path.join(CHANNEL_STATES_DIR, `${channelId}.json`);
134
- if (!fs.existsSync(statePath)) {
135
- console.error(`No state file at ${statePath}`);
136
- console.error(`Store state first: arc402 channel store-state ${channelId} <state.json>`);
137
- process.exit(1);
138
- }
139
- const state = loadStateFile(statePath);
140
- const interval = Math.max(1000, Number(opts.interval));
141
-
142
- if (!opts.json) {
143
- console.log(`watching: ${channelId}`);
144
- console.log(` stored seq: ${state.sequenceNumber}`);
145
- console.log(` poll interval: ${interval}ms`);
146
- console.log(` press Ctrl+C to stop`);
147
- }
148
-
149
- let challenged = false;
150
-
151
- const poll = async () => {
152
- if (challenged) return;
153
- try {
154
- const ch = await channelClient.getChannelStatus(channelId);
155
-
156
- if (ch.status === "SETTLED") {
157
- if (!opts.json) {
158
- console.log(`[${new Date().toISOString()}] channel settled — stopping watch`);
159
- }
160
- return;
161
- }
162
-
163
- if (ch.status === "CLOSING" || ch.status === "CHALLENGED") {
164
- if (ch.lastSequenceNumber < (state.sequenceNumber as number)) {
165
- if (!opts.json) {
166
- console.log(
167
- `[${new Date().toISOString()}] stale close detected ` +
168
- `(on-chain seq=${ch.lastSequenceNumber}, stored seq=${state.sequenceNumber}) — challenging...`
169
- );
170
- }
171
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
172
- const result = await watchtowerClient.submitChallenge(channelId, state as any, address);
173
- challenged = true;
174
- if (opts.json) {
175
- console.log(JSON.stringify({ event: "challenge_submitted", channelId, txHash: result.txHash }));
176
- } else {
177
- console.log(' ' + c.success + c.white(' Challenge submitted — tx ' + result.txHash.slice(0, 12) + '...'));
178
- }
179
- return;
180
- } else {
181
- if (!opts.json) {
182
- console.log(
183
- `[${new Date().toISOString()}] channel closing with seq=${ch.lastSequenceNumber} — no challenge needed`
184
- );
185
- }
186
- }
187
- }
188
- } catch (err) {
189
- if (!opts.json) {
190
- console.error(`[${new Date().toISOString()}] poll error: ${err}`);
191
- }
192
- }
193
- setTimeout(poll, interval);
194
- };
195
-
196
- poll();
197
- });
198
-
199
- // ─── authorize ─────────────────────────────────────────────────────────────
200
-
201
- wt.command("authorize <channelId> <watchtower>")
202
- .description("Authorize a watchtower address to challenge on your behalf for a channel")
203
- .option("--json", "JSON output")
204
- .action(async (channelId, watchtower, opts) => {
205
- const config = loadConfig();
206
- if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
207
- if (!config.watchtowerRegistryAddress) throw new Error("watchtowerRegistryAddress missing in config");
208
- const { signer } = await requireSigner(config);
209
- const client = new WatchtowerClient(
210
- config.watchtowerRegistryAddress,
211
- config.serviceAgreementAddress,
212
- signer
213
- );
214
- const authSpinner = startSpinner('Authorizing watchtower…');
215
- const result = await client.authorizeWatchtower(channelId, watchtower);
216
- if (opts.json || program.opts().json) {
217
- authSpinner.stop();
218
- console.log(JSON.stringify(result));
219
- } else {
220
- authSpinner.succeed(c.success + c.white(' Authorized: ' + formatAddress(watchtower)));
221
- }
222
- });
223
-
224
- // ─── revoke ────────────────────────────────────────────────────────────────
225
-
226
- wt.command("revoke <channelId> <watchtower>")
227
- .description("Revoke a watchtower's authorization for a channel")
228
- .option("--json", "JSON output")
229
- .action(async (channelId, watchtower, opts) => {
230
- const config = loadConfig();
231
- if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
232
- if (!config.watchtowerRegistryAddress) throw new Error("watchtowerRegistryAddress missing in config");
233
- const { signer } = await requireSigner(config);
234
- const client = new WatchtowerClient(
235
- config.watchtowerRegistryAddress,
236
- config.serviceAgreementAddress,
237
- signer
238
- );
239
- const revokeSpinner = startSpinner('Revoking watchtower…');
240
- const result = await client.revokeWatchtower(channelId, watchtower);
241
- if (opts.json || program.opts().json) {
242
- revokeSpinner.stop();
243
- console.log(JSON.stringify(result));
244
- } else {
245
- revokeSpinner.succeed(c.success + c.white(' Revoked: ' + formatAddress(watchtower)));
246
- }
247
- });
248
- }