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,274 +0,0 @@
1
- import { Command } from "commander";
2
- import { ethers } from "ethers";
3
- import { loadConfig, getUsdcAddress } from "../config.js";
4
- import { requireSigner } from "../client.js";
5
- import { AGENT_REGISTRY_ABI } from "../abis.js";
6
- import { startSpinner } from "../ui/spinner.js";
7
- import { renderTree } from "../ui/tree.js";
8
- import { c } from "../ui/colors.js";
9
-
10
- const DEFAULT_REGISTRY_ADDRESS = "0xD5c2851B00090c92Ba7F4723FB548bb30C9B6865";
11
-
12
- async function pingHandshakeEndpoint(
13
- agentAddress: string,
14
- payload: Record<string, unknown>,
15
- registryAddress: string,
16
- provider: ethers.Provider
17
- ): Promise<void> {
18
- const registry = new ethers.Contract(registryAddress, AGENT_REGISTRY_ABI, provider);
19
- const agentData = await registry.getAgent(agentAddress);
20
- const endpoint = agentData.endpoint as string;
21
- if (!endpoint) return;
22
- await fetch(`${endpoint}/handshake`, {
23
- method: "POST",
24
- headers: { "Content-Type": "application/json" },
25
- body: JSON.stringify(payload),
26
- });
27
- }
28
-
29
- // ─── Handshake Contract ABI (from Handshake.sol) ─────────────────────────────
30
-
31
- const HANDSHAKE_ABI = [
32
- "function sendHandshake(address to, uint8 hsType, string note) payable",
33
- "function sendHandshakeWithToken(address to, uint8 hsType, string note, address token, uint256 tokenAmount)",
34
- "function sendBatch(address[] recipients, uint8[] hsTypes, string[] notes)",
35
- "function hasConnection(address from, address to) view returns (bool)",
36
- "function isMutual(address a, address b) view returns (bool)",
37
- "function getStats(address agent) view returns (uint256 sent, uint256 received, uint256 uniqueInbound)",
38
- "function sentCount(address) view returns (uint256)",
39
- "function receivedCount(address) view returns (uint256)",
40
- "function uniqueSenders(address) view returns (uint256)",
41
- "function totalHandshakes() view returns (uint256)",
42
- "function allowedTokens(address) view returns (bool)",
43
- "event HandshakeSent(uint256 indexed handshakeId, address indexed from, address indexed to, uint8 hsType, address token, uint256 amount, string note, uint256 timestamp)",
44
- "event NewConnection(address indexed from, address indexed to, uint256 handshakeId)",
45
- ];
46
-
47
- const POLICY_ENGINE_ABI = [
48
- "function isContractWhitelisted(address wallet, address target) view returns (bool)",
49
- "function whitelistContract(address wallet, address target)",
50
- ];
51
-
52
- const HANDSHAKE_TYPES: Record<string, number> = {
53
- respect: 0,
54
- curiosity: 1,
55
- endorsement: 2,
56
- thanks: 3,
57
- collaboration: 4,
58
- challenge: 5,
59
- referral: 6,
60
- hello: 7,
61
- };
62
-
63
- // ─── Auto-Whitelist ──────────────────────────────────────────────────────────
64
-
65
- async function ensureWhitelisted(
66
- signer: ethers.Signer,
67
- provider: ethers.Provider,
68
- walletAddress: string,
69
- policyEngineAddress: string,
70
- handshakeAddress: string
71
- ): Promise<void> {
72
- // Check whitelist with RPC fallback (public RPCs often fail on eth_call)
73
- const { callWithFallback } = await import("../ui/rpc-fallback.js");
74
- const rpcUrl = (provider as ethers.JsonRpcProvider)._getConnection?.()?.url ?? "https://mainnet.base.org";
75
- const isWhitelisted = await callWithFallback(rpcUrl, async (p) => {
76
- const pe = new ethers.Contract(policyEngineAddress, POLICY_ENGINE_ABI, p);
77
- return await pe.isContractWhitelisted(walletAddress, handshakeAddress) as boolean;
78
- }).catch(() => true); // If all RPCs fail, assume whitelisted and let the tx itself fail if not
79
-
80
- if (!isWhitelisted) {
81
- console.log("Handshake contract not yet whitelisted on your wallet.");
82
- console.log("Whitelisting now (one-time setup)...");
83
- try {
84
- const peSigner = new ethers.Contract(policyEngineAddress, POLICY_ENGINE_ABI, signer);
85
- const tx = await peSigner.whitelistContract(walletAddress, handshakeAddress);
86
- console.log(` tx: ${tx.hash}`);
87
- await tx.wait();
88
- console.log(" ✓ Handshake contract whitelisted\n");
89
- } catch (e) {
90
- const msg = e instanceof Error ? e.message : String(e);
91
- if (msg.includes("already whitelisted")) {
92
- console.log(" ✓ Handshake contract already whitelisted\n");
93
- } else if (msg.includes("insufficient funds")) {
94
- console.log(" ⚠ Machine key has no ETH for whitelisting. Use WalletConnect:");
95
- console.log(` arc402 wallet whitelist-contract ${handshakeAddress}\n`);
96
- return;
97
- } else {
98
- throw e;
99
- }
100
- }
101
- }
102
- }
103
-
104
- // ─── Commands ────────────────────────────────────────────────────────────────
105
-
106
- export function registerArenaHandshakeCommands(program: Command): void {
107
- const hs = program
108
- .command("shake")
109
- .description("ARC Arena social handshake — send a typed trust signal to another agent.");
110
-
111
- // ── send ──────────────────────────────────────────────────────────────────
112
- hs.command("send <agentAddress>")
113
- .description("Send a handshake to another agent.")
114
- .option("--type <type>", "Handshake type: respect, curiosity, endorsement, thanks, collaboration, challenge, referral, hello", "hello")
115
- .option("--note <note>", "Short message (max 280 chars)", "")
116
- .option("--tip <amount>", "ETH tip to attach (e.g. 0.01)")
117
- .option("--usdc <amount>", "USDC tip to attach (e.g. 5.00)")
118
- .option("--json", "Output as JSON")
119
- .action(async (agentAddress: string, opts) => {
120
- const config = loadConfig();
121
- const { signer, provider } = await requireSigner(config);
122
- const myAddress = await signer.getAddress();
123
-
124
- if (!config.handshakeAddress) {
125
- console.error("handshakeAddress not configured. Run: arc402 config set handshakeAddress <address>");
126
- process.exit(1);
127
- }
128
- if (!config.policyEngineAddress) {
129
- console.error("policyEngineAddress not configured.");
130
- process.exit(1);
131
- }
132
-
133
- // Auto-whitelist check
134
- await ensureWhitelisted(signer, provider, myAddress, config.policyEngineAddress, config.handshakeAddress);
135
-
136
- const hsType = HANDSHAKE_TYPES[opts.type.toLowerCase()];
137
- if (hsType === undefined) {
138
- console.error(`Unknown handshake type: ${opts.type}`);
139
- console.error(`Valid types: ${Object.keys(HANDSHAKE_TYPES).join(", ")}`);
140
- process.exit(1);
141
- }
142
-
143
- const handshake = new ethers.Contract(config.handshakeAddress, HANDSHAKE_ABI, signer);
144
-
145
- const hsSpinner = startSpinner(`Sending ${opts.type} handshake...`);
146
- let tx;
147
- if (opts.usdc) {
148
- // USDC handshake
149
- const usdcAddress = getUsdcAddress(config);
150
- const amount = ethers.parseUnits(opts.usdc, 6);
151
- tx = await handshake.sendHandshakeWithToken(agentAddress, hsType, opts.note, usdcAddress, amount);
152
- } else {
153
- // ETH handshake (with optional tip)
154
- const value = opts.tip ? ethers.parseEther(opts.tip) : 0n;
155
- tx = await handshake.sendHandshake(agentAddress, hsType, opts.note, { value });
156
- }
157
- hsSpinner.succeed("Handshake sent");
158
-
159
- // Notify recipient's HTTP endpoint (non-blocking)
160
- const registryAddress = config.agentRegistryV2Address ?? config.agentRegistryAddress ?? DEFAULT_REGISTRY_ADDRESS;
161
- try {
162
- await pingHandshakeEndpoint(
163
- agentAddress,
164
- { from: myAddress, type: opts.type, note: opts.note, txHash: tx.hash },
165
- registryAddress,
166
- provider
167
- );
168
- } catch (err) {
169
- console.warn(`Warning: could not notify recipient endpoint: ${err instanceof Error ? err.message : String(err)}`);
170
- }
171
-
172
- if (opts.json) {
173
- console.log(JSON.stringify({ tx: tx.hash, from: myAddress, to: agentAddress, type: opts.type, note: opts.note }));
174
- } else {
175
- const treeItems = [
176
- { label: "From", value: myAddress },
177
- { label: "To", value: agentAddress },
178
- { label: "Type", value: opts.type },
179
- ...(opts.note ? [{ label: "Note", value: opts.note as string }] : []),
180
- ...(opts.tip ? [{ label: "Tip", value: `${opts.tip as string} ETH` }] : []),
181
- ...(opts.usdc ? [{ label: "Tip", value: `${opts.usdc as string} USDC` }] : []),
182
- { label: "Tx", value: tx.hash as string, last: true },
183
- ];
184
- renderTree(treeItems);
185
- }
186
- });
187
-
188
- // ── batch ─────────────────────────────────────────────────────────────────
189
- hs.command("batch")
190
- .description("Send handshakes to multiple agents at once (onboarding ritual).")
191
- .argument("<agents...>", "Agent addresses to handshake (up to 10)")
192
- .option("--type <type>", "Handshake type for all", "hello")
193
- .option("--note <note>", "Note for all", "")
194
- .action(async (agents: string[], opts) => {
195
- const config = loadConfig();
196
- const { signer, provider } = await requireSigner(config);
197
- const myAddress = await signer.getAddress();
198
-
199
- if (!config.handshakeAddress || !config.policyEngineAddress) {
200
- console.error("handshakeAddress or policyEngineAddress not configured.");
201
- process.exit(1);
202
- }
203
-
204
- await ensureWhitelisted(signer, provider, myAddress, config.policyEngineAddress, config.handshakeAddress);
205
-
206
- const hsType = HANDSHAKE_TYPES[opts.type.toLowerCase()];
207
- if (hsType === undefined) {
208
- console.error(`Unknown type: ${opts.type}. Valid: ${Object.keys(HANDSHAKE_TYPES).join(", ")}`);
209
- process.exit(1);
210
- }
211
-
212
- if (agents.length > 10) {
213
- console.error("Max 10 agents per batch.");
214
- process.exit(1);
215
- }
216
-
217
- const handshake = new ethers.Contract(config.handshakeAddress, HANDSHAKE_ABI, signer);
218
- const types = agents.map(() => hsType);
219
- const notes = agents.map(() => opts.note);
220
-
221
- const tx = await handshake.sendBatch(agents, types, notes);
222
- console.log(`✓ Batch handshake sent to ${agents.length} agents`);
223
- agents.forEach(a => console.log(` → ${a}`));
224
- console.log(` tx: ${tx.hash}`);
225
- });
226
-
227
- // ── stats ─────────────────────────────────────────────────────────────────
228
- hs.command("stats [address]")
229
- .description("View handshake stats for an agent.")
230
- .action(async (address?: string) => {
231
- const config = loadConfig();
232
- const { signer, provider } = await requireSigner(config);
233
- const target = address || await signer.getAddress();
234
-
235
- if (!config.handshakeAddress) {
236
- console.error("handshakeAddress not configured.");
237
- process.exit(1);
238
- }
239
-
240
- const handshake = new ethers.Contract(config.handshakeAddress, HANDSHAKE_ABI, provider);
241
- const [sent, received, unique] = await handshake.getStats(target);
242
- const total = await handshake.totalHandshakes();
243
-
244
- console.log(`Handshake Stats: ${target}`);
245
- console.log(` Sent: ${sent}`);
246
- console.log(` Received: ${received}`);
247
- console.log(` Unique senders: ${unique}`);
248
- console.log(` Network total: ${total}`);
249
- });
250
-
251
- // ── check ─────────────────────────────────────────────────────────────────
252
- hs.command("check <agentAddress>")
253
- .description("Check if a connection or mutual handshake exists with an agent.")
254
- .action(async (agentAddress: string) => {
255
- const config = loadConfig();
256
- const { signer, provider } = await requireSigner(config);
257
- const myAddress = await signer.getAddress();
258
-
259
- if (!config.handshakeAddress) {
260
- console.error("handshakeAddress not configured.");
261
- process.exit(1);
262
- }
263
-
264
- const handshake = new ethers.Contract(config.handshakeAddress, HANDSHAKE_ABI, provider);
265
- const iSent = await handshake.hasConnection(myAddress, agentAddress);
266
- const theySent = await handshake.hasConnection(agentAddress, myAddress);
267
- const mutual = await handshake.isMutual(myAddress, agentAddress);
268
-
269
- console.log(`Connection: ${myAddress} ↔ ${agentAddress}`);
270
- console.log(` You → them: ${iSent ? "✓ handshaked" : "✗ no handshake"}`);
271
- console.log(` Them → you: ${theySent ? "✓ handshaked" : "✗ no handshake"}`);
272
- console.log(` Mutual: ${mutual ? "✓ yes" : "✗ no"}`);
273
- });
274
- }
@@ -1,122 +0,0 @@
1
- import { Command } from "commander";
2
- import chalk from "chalk";
3
- import { runFeed, FeedOptions } from "./feed.js";
4
- import { c } from "../ui/colors.js";
5
-
6
- const SUBGRAPH_URL = "https://api.studio.thegraph.com/query/1744310/arc-402/v0.2.0";
7
-
8
- async function gql(query: string): Promise<Record<string, unknown>> {
9
- const res = await fetch(SUBGRAPH_URL, {
10
- method: "POST",
11
- headers: { "Content-Type": "application/json" },
12
- body: JSON.stringify({ query }),
13
- });
14
- if (!res.ok) throw new Error(`Subgraph HTTP ${res.status}`);
15
- const json = (await res.json()) as { data?: Record<string, unknown>; errors?: unknown[] };
16
- if (json.errors?.length) throw new Error(`Subgraph error: ${JSON.stringify(json.errors[0])}`);
17
- return json.data ?? {};
18
- }
19
-
20
- export function registerArenaCommands(program: Command): void {
21
- const arena = program.command("arena").description("Arena network commands");
22
-
23
- // ─── arena stats ───────────────────────────────────────────────────────────
24
-
25
- arena
26
- .command("stats")
27
- .description("Show Arena network statistics")
28
- .option("--json", "Output as JSON")
29
- .action(async (opts) => {
30
- try {
31
- const data = await gql(`{
32
- protocolStats(id: "global") {
33
- totalAgents
34
- totalWallets
35
- totalAgreements
36
- totalHandshakes
37
- totalConnections
38
- totalVouches
39
- totalCapabilityClaims
40
- }
41
- }`);
42
-
43
- const stats = data["protocolStats"] as Record<string, unknown> | null;
44
- if (!stats) {
45
- const msg = "No stats available — subgraph may still be syncing.";
46
- if (opts.json) {
47
- console.log(JSON.stringify({ error: msg }));
48
- } else {
49
- console.error(' ' + c.warning + c.white(` ${msg}`));
50
- }
51
- process.exit(1);
52
- }
53
-
54
- // Try to count active agreements separately — non-fatal if it fails
55
- let activeAgreements = 0;
56
- try {
57
- const agData = await gql(`{
58
- proposals: agreements(where: { state: 0 }, first: 1000) { id }
59
- accepted: agreements(where: { state: 1 }, first: 1000) { id }
60
- }`);
61
- activeAgreements =
62
- ((agData["proposals"] as unknown[]) ?? []).length +
63
- ((agData["accepted"] as unknown[]) ?? []).length;
64
- } catch {
65
- // ignore — active count just stays 0
66
- }
67
-
68
- if (opts.json) {
69
- console.log(JSON.stringify({ ...stats, activeAgreements }, null, 2));
70
- return;
71
- }
72
-
73
- const pad = (v: unknown) => String(v ?? 0).padStart(6);
74
- console.log(chalk.bold("╔══════════════════════════════════════╗"));
75
- console.log(chalk.bold("║ ARC Arena — Network Stats ║"));
76
- console.log(chalk.bold("╚══════════════════════════════════════╝"));
77
- console.log();
78
- console.log(` Agents ${pad(stats["totalAgents"])} registered`);
79
- console.log(` Wallets ${pad(stats["totalWallets"])} deployed`);
80
- console.log(
81
- ` Agreements ${pad(stats["totalAgreements"])} total (${activeAgreements} active)`,
82
- );
83
- console.log(` Handshakes ${pad(stats["totalHandshakes"])} sent`);
84
- console.log(` Connections ${pad(stats["totalConnections"])} unique pairs`);
85
- console.log(` Vouches ${pad(stats["totalVouches"])} active`);
86
- console.log(` Capabilities ${pad(stats["totalCapabilityClaims"])} claimed`);
87
- console.log();
88
- console.log(chalk.dim(" Subgraph: v0.2.0 · synced"));
89
- } catch (err) {
90
- const msg = err instanceof Error ? err.message : String(err);
91
- if (opts.json) {
92
- console.log(JSON.stringify({ error: "Subgraph unavailable", details: msg }));
93
- } else {
94
- console.error(' ' + c.failure + c.white(` Subgraph unavailable: ${msg}`));
95
- }
96
- process.exit(1);
97
- }
98
- });
99
-
100
- // ─── arena feed (alias) ─────────────────────────────────────────────────────
101
-
102
- arena
103
- .command("feed")
104
- .description("Live terminal feed of recent Arena events (alias for arc402 feed)")
105
- .option("--limit <n>", "Number of events to show", "20")
106
- .option("--live", "Poll every 30s for new events")
107
- .option("--type <type>", "Filter by event type: handshake|hire|fulfill|vouch")
108
- .option("--json", "Output as JSON")
109
- .action(async (opts) => {
110
- try {
111
- await runFeed(opts as FeedOptions);
112
- } catch (err) {
113
- const msg = err instanceof Error ? err.message : String(err);
114
- if ((opts as FeedOptions).json) {
115
- console.log(JSON.stringify({ error: "Subgraph unavailable", details: msg }));
116
- } else {
117
- console.error(' ' + c.failure + c.white(` Subgraph unavailable: ${msg}`));
118
- }
119
- process.exit(1);
120
- }
121
- });
122
- }
@@ -1,117 +0,0 @@
1
- import { Command } from "commander";
2
- import { execSync } from "child_process";
3
- import fs from "fs";
4
- import path from "path";
5
- import os from "os";
6
- import { c } from "../ui/colors.js";
7
-
8
- const ARC402_DIR = path.join(os.homedir(), ".arc402");
9
-
10
- // Files/patterns to exclude from backup
11
- const EXCLUDE_PATTERNS = [
12
- "daemon.db",
13
- "daemon.log",
14
- "daemon.pid",
15
- "daemon.sock",
16
- "repl_history",
17
- ];
18
-
19
- function todayStr(): string {
20
- const d = new Date();
21
- const y = d.getFullYear();
22
- const m = (d.getMonth() + 1).toString().padStart(2, "0");
23
- const day = d.getDate().toString().padStart(2, "0");
24
- return `${y}-${m}-${day}`;
25
- }
26
-
27
- export function registerBackupCommand(program: Command): void {
28
- // ── backup ─────────────────────────────────────────────────────────────────
29
- program
30
- .command("backup")
31
- .description("Backup ~/.arc402/ config, keys, and wallet storage to a tar.gz archive")
32
- .option("--output <path>", "Output file path (default: arc402-backup-YYYY-MM-DD.tar.gz)")
33
- .action((opts: { output?: string }) => {
34
- if (!fs.existsSync(ARC402_DIR)) {
35
- console.error(` ${c.failure} No ~/.arc402/ directory found. Nothing to back up.`);
36
- process.exit(1);
37
- }
38
-
39
- const outFile = opts.output ?? `arc402-backup-${todayStr()}.tar.gz`;
40
- const absOut = path.isAbsolute(outFile) ? outFile : path.join(process.cwd(), outFile);
41
-
42
- // Build --exclude flags
43
- const excludeFlags = EXCLUDE_PATTERNS.map((p) => `--exclude='.arc402/${p}'`).join(" ");
44
-
45
- try {
46
- execSync(
47
- `tar -czf "${absOut}" ${excludeFlags} -C "${os.homedir()}" .arc402`,
48
- { stdio: "pipe" }
49
- );
50
- } catch (err) {
51
- const msg = err instanceof Error ? err.message : String(err);
52
- console.error(` ${c.failure} Backup failed: ${msg}`);
53
- process.exit(1);
54
- }
55
-
56
- // Verify the file was created
57
- if (!fs.existsSync(absOut)) {
58
- console.error(` ${c.failure} Archive not found after tar completed.`);
59
- process.exit(1);
60
- }
61
-
62
- const sizeBytes = fs.statSync(absOut).size;
63
- const sizeStr = sizeBytes < 1024
64
- ? `${sizeBytes} B`
65
- : sizeBytes < 1024 * 1024
66
- ? `${(sizeBytes / 1024).toFixed(1)} KB`
67
- : `${(sizeBytes / (1024 * 1024)).toFixed(2)} MB`;
68
-
69
- console.log(` ${c.success} Backup saved to ${c.white(path.basename(absOut))} ${c.dim(`(${sizeStr})`)}`);
70
- });
71
-
72
- // ── restore ────────────────────────────────────────────────────────────────
73
- program
74
- .command("restore")
75
- .description("Restore ~/.arc402/ from a backup archive")
76
- .argument("<archive>", "Path to arc402-backup-*.tar.gz")
77
- .action((archive: string) => {
78
- const absArchive = path.isAbsolute(archive) ? archive : path.join(process.cwd(), archive);
79
-
80
- if (!fs.existsSync(absArchive)) {
81
- console.error(` ${c.failure} Archive not found: ${absArchive}`);
82
- process.exit(1);
83
- }
84
-
85
- // Warn if ~/.arc402/ already exists
86
- if (fs.existsSync(ARC402_DIR)) {
87
- const existing = fs.readdirSync(ARC402_DIR);
88
- if (existing.length > 0) {
89
- console.warn(` ${c.warning} Existing ~/.arc402/ has ${existing.length} file(s) — merging (existing files take precedence for conflicts).`);
90
- }
91
- }
92
-
93
- try {
94
- // Extract to home dir — tar archive has .arc402/ as the root entry
95
- execSync(`tar -xzf "${absArchive}" -C "${os.homedir()}"`, { stdio: "pipe" });
96
- } catch (err) {
97
- const msg = err instanceof Error ? err.message : String(err);
98
- console.error(` ${c.failure} Restore failed: ${msg}`);
99
- process.exit(1);
100
- }
101
-
102
- // Verify config.json is present
103
- const configPath = path.join(ARC402_DIR, "config.json");
104
- if (!fs.existsSync(configPath)) {
105
- console.error(` ${c.failure} config.json not found after restore — archive may be incomplete.`);
106
- process.exit(1);
107
- }
108
-
109
- // Fix permissions on restored directory
110
- try {
111
- fs.chmodSync(ARC402_DIR, 0o700);
112
- fs.chmodSync(configPath, 0o600);
113
- } catch { /* best-effort */ }
114
-
115
- console.log(` ${c.success} Config restored. Run ${c.white("arc402 doctor")} to verify.`);
116
- });
117
- }
@@ -1,35 +0,0 @@
1
- import { Command } from "commander";
2
- import { ServiceAgreementClient } from "@arc402/sdk";
3
- import { loadConfig } from "../config.js";
4
- import { requireSigner } from "../client.js";
5
- import { printSenderInfo, executeContractWriteViaWallet } from "../wallet-router.js";
6
- import { SERVICE_AGREEMENT_ABI } from "../abis.js";
7
- import { c } from "../ui/colors.js";
8
- import { startSpinner } from "../ui/spinner.js";
9
-
10
- export function registerCancelCommand(program: Command): void {
11
- program.command("cancel <id>").description("Cancel a proposed agreement; use --expired for post-deadline recovery paths").option("--expired", "Call expiredCancel()", false).action(async (id, opts) => {
12
- const config = loadConfig();
13
- if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
14
- const { signer } = await requireSigner(config);
15
- printSenderInfo(config);
16
- const spinner = startSpinner("Submitting transaction...");
17
- try {
18
- if (config.walletContractAddress) {
19
- const fn = opts.expired ? "expiredCancel" : "cancel";
20
- await executeContractWriteViaWallet(
21
- config.walletContractAddress, signer, config.serviceAgreementAddress,
22
- SERVICE_AGREEMENT_ABI, fn, [BigInt(id)],
23
- );
24
- } else {
25
- const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
26
- if (opts.expired) await client.expiredCancel(BigInt(id)); else await client.cancel(BigInt(id));
27
- }
28
- spinner.succeed();
29
- } catch (err) {
30
- spinner.fail();
31
- throw err;
32
- }
33
- console.log(' ' + c.success + c.white(` Cancelled — agreement #${id}`));
34
- });
35
- }