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
package/TUI-SPEC.md DELETED
@@ -1,214 +0,0 @@
1
- # ARC-402 TUI Specification — Ink-based Terminal UI
2
-
3
- **Date:** 2026-03-22
4
- **Status:** Ready for implementation
5
- **Pattern:** Fixed header/footer with scrollable viewport (split-pane TUI)
6
- **Library:** Ink (React for CLIs) — same architecture as Claude Code
7
-
8
- ---
9
-
10
- ## Architecture
11
-
12
- ```
13
- ┌─────────────────────────────────────────────────┐
14
- │ HEADER (fixed, 8-10 rows) │
15
- │ ┌─────────────────────────────────────────────┐ │
16
- │ │ ██████╗ ██████╗ ██████╗ ... │ │
17
- │ │ agent-to-agent arcing · v0.7.3 │ │
18
- │ │ ◈ ──────────────────────────────────────── │ │
19
- │ │ Network Base Mainnet Wallet 0xA34B.. │ │
20
- │ └─────────────────────────────────────────────┘ │
21
- ├─────────────────────────────────────────────────┤
22
- │ VIEWPORT (scrollable, fills remaining space) │
23
- │ │
24
- │ ◈ arc402 > wallet status │
25
- │ ├ Address 0xA34B...a5dc │
26
- │ ├ ETH 0.002 ETH │
27
- │ └ Trust 100 Restricted │
28
- │ │
29
- │ ◈ arc402 > shake send --to 0xa9e0... │
30
- │ ◈ Submitting handshake... │
31
- │ ✓ Handshake sent — tx 0xabc1... │
32
- │ │
33
- │ ◈ arc402 > doctor │
34
- │ ├ Config ✓ │
35
- │ ├ RPC ✓ Base Mainnet │
36
- │ └ Daemon ✗ Not running │
37
- │ │
38
- ├─────────────────────────────────────────────────┤
39
- │ FOOTER (fixed, 1-2 rows) │
40
- │ ◈ arc402 > _ │
41
- └─────────────────────────────────────────────────┘
42
- ```
43
-
44
- ---
45
-
46
- ## Component Tree (Ink/React)
47
-
48
- ```tsx
49
- <App>
50
- <Box flexDirection="column" height="100%">
51
-
52
- {/* HEADER — fixed height, never scrolls */}
53
- <Header
54
- version={version}
55
- network={config.network}
56
- wallet={config.walletContractAddress}
57
- balance={balance}
58
- />
59
-
60
- <Box borderStyle="single" borderTop borderBottom={false} borderLeft={false} borderRight={false}>
61
- <Text dimColor>─</Text>
62
- </Box>
63
-
64
- {/* VIEWPORT — flexGrow, scrollable */}
65
- <Viewport
66
- lines={outputBuffer}
67
- scrollOffset={scrollOffset}
68
- />
69
-
70
- {/* FOOTER — fixed height, input pinned */}
71
- <Footer>
72
- <InputLine
73
- value={inputValue}
74
- onChange={setInputValue}
75
- onSubmit={handleCommand}
76
- history={history}
77
- />
78
- </Footer>
79
-
80
- </Box>
81
- </App>
82
- ```
83
-
84
- ---
85
-
86
- ## Components
87
-
88
- ### `<Header />`
89
- - Renders the ASCII art banner (cyan)
90
- - Version from package.json
91
- - Network, wallet (truncated), balance
92
- - Fixed height: exactly `bannerLines.length + 3` rows
93
- - Never re-renders unless config changes
94
-
95
- ### `<Viewport />`
96
- - `flexGrow: 1` — fills all remaining terminal rows
97
- - Maintains an internal `outputBuffer: string[]`
98
- - Renders a window slice: `buffer.slice(scrollOffset, scrollOffset + viewportHeight)`
99
- - Scroll up/down with Page Up/Page Down or mouse wheel
100
- - Auto-scrolls to bottom when new output arrives (unless user scrolled up)
101
- - Supports ANSI colors in output lines (chalk passes through)
102
-
103
- ### `<Footer />`
104
- - Fixed height: 1 row (or 2 with status bar)
105
- - Contains `<InputLine />`
106
- - Prompt: `◈ arc402 > ` (◈ cyan, arc402 dim, > white)
107
-
108
- ### `<InputLine />`
109
- - Uses `ink-text-input` for text input with cursor
110
- - Up/down arrow: command history navigation
111
- - Tab: command completion
112
- - Enter: dispatch command
113
- - Ctrl+C: graceful exit
114
-
115
- ---
116
-
117
- ## Behavior
118
-
119
- ### Command Dispatch
120
- 1. User types command + Enter
121
- 2. Command + output appended to `outputBuffer` as: `◈ arc402 > {command}` then output lines
122
- 3. Commander parses and executes (stdout/stderr captured and routed to viewport)
123
- 4. Viewport auto-scrolls to bottom
124
- 5. Input line clears, cursor returns
125
-
126
- ### Stdout/Stderr Capture
127
- - During command execution, monkey-patch `process.stdout.write` and `process.stderr.write`
128
- - Route all output to `outputBuffer` instead of raw terminal
129
- - Restore after command completes
130
- - This ensures spinners, tree output, console.log all render in the viewport
131
-
132
- ### Scroll Behavior
133
- - **Auto-scroll:** viewport stays at bottom as new lines arrive
134
- - **Manual scroll:** Page Up / Page Down moves viewport
135
- - **Scroll indicator:** if not at bottom, show `↓ more` in bottom-right
136
- - **Return to bottom:** any new command output snaps back to bottom
137
-
138
- ### Chat Integration
139
- - Non-command input detected → POST to OpenClaw gateway
140
- - Response streamed line-by-line into viewport
141
- - Prefixed with `◈ ` in dim
142
-
143
- ### Resize Handling
144
- - Listen for `SIGWINCH`
145
- - Recalculate viewport height
146
- - Re-render (Ink handles this natively)
147
-
148
- ---
149
-
150
- ## Dependencies
151
-
152
- ```json
153
- {
154
- "ink": "^4.0.0",
155
- "ink-text-input": "^5.0.0",
156
- "react": "^18.0.0"
157
- }
158
- ```
159
-
160
- ~150KB total. Well-maintained. Same stack as Claude Code.
161
-
162
- ---
163
-
164
- ## File Structure
165
-
166
- ```
167
- cli/src/
168
- tui/
169
- App.tsx — root component
170
- Header.tsx — banner + status
171
- Viewport.tsx — scrollable output area
172
- Footer.tsx — input line wrapper
173
- InputLine.tsx — text input with history + completion
174
- useCommand.ts — hook: dispatch to commander, capture output
175
- useChat.ts — hook: OpenClaw gateway chat
176
- useScroll.ts — hook: scroll state management
177
- index.tsx — render <App /> with Ink
178
- repl.ts — KEEP as fallback for --print mode and non-TTY
179
- index.ts — route: TTY → tui/, non-TTY/--print → repl.ts
180
- ```
181
-
182
- ---
183
-
184
- ## Migration Plan
185
-
186
- 1. Keep existing `repl.ts` as fallback (--print mode, piped input)
187
- 2. New `tui/` directory with Ink components
188
- 3. `index.ts` checks: if TTY and no --print → launch Ink TUI, else → use simple REPL
189
- 4. All existing commands unchanged — only the rendering layer changes
190
- 5. `repl.ts` simplified back to basic readline (no ANSI tricks)
191
-
192
- ---
193
-
194
- ## Exit Behavior
195
-
196
- - Ctrl+C → `\x1b[?1049l` (leave alternate screen) → show goodbye → exit
197
- - All terminal state restored on exit (cursor visible, normal scroll, etc.)
198
- - Alternate screen means the TUI disappears on exit, revealing the original terminal — clean
199
-
200
- ---
201
-
202
- ## What This Does NOT Change
203
-
204
- - Command implementations (wallet.ts, agent.ts, etc.) — untouched
205
- - Config system — untouched
206
- - Daemon — untouched
207
- - SDKs — untouched
208
- - One-shot mode (`arc402 wallet deploy` without REPL) — untouched
209
-
210
- Only the interactive shell rendering layer changes.
211
-
212
- ---
213
-
214
- *Build this exactly as specified. The spec is the contract.*
@@ -1,43 +0,0 @@
1
- import { ethers } from "ethers";
2
- import { loadConfig } from "../src/config";
3
- import { connectPhoneWallet, sendTransactionWithSession } from "../src/walletconnect";
4
-
5
- const WALLET = "0xC3207bFe22cba39AeC4e8540c97c29B028103c7F";
6
- const HOT_KEY = "0x747024C2e59C523E3B1621A4b3F92366C1E28A30";
7
- const CHAIN_ID = 8453;
8
-
9
- async function main() {
10
- const config = loadConfig();
11
- const iface = new ethers.Interface(["function authorizeMachineKey(address key) external"]);
12
-
13
- const tx = {
14
- to: WALLET,
15
- data: iface.encodeFunctionData("authorizeMachineKey", [HOT_KEY]),
16
- value: "0x0",
17
- };
18
-
19
- const tgOpts = {
20
- botToken: config.telegramBotToken!,
21
- chatId: config.telegramChatId!,
22
- threadId: config.telegramThreadId,
23
- };
24
-
25
- console.log(`Authorizing hot key ${HOT_KEY} as machine key on ${WALLET}\n`);
26
-
27
- const { client, session, account } = await connectPhoneWallet(
28
- config.walletConnectProjectId!,
29
- CHAIN_ID,
30
- config,
31
- {
32
- telegramOpts: tgOpts,
33
- prompt: "⛓ BASE — authorizeMachineKey (one-time). After this the hot key runs autonomously.",
34
- }
35
- );
36
-
37
- console.log("Connected:", account);
38
- const hash = await sendTransactionWithSession(client, session, account, CHAIN_ID, tx);
39
- console.log("✅ Done:", hash);
40
- process.exit(0);
41
- }
42
-
43
- main().catch(e => { console.error(e.message ?? e); process.exit(1); });
@@ -1,149 +0,0 @@
1
- /**
2
- * drain-wallet.ts
3
- * Drain all ETH from the ARC402Wallet contract to the deployer wallet.
4
- * Uses WalletConnect — sends MetaMask approval button to Telegram.
5
- *
6
- * Flow:
7
- * 1. Read wallet balance
8
- * 2. Build openContext + attest + executeSpend calldata
9
- * 3. Connect via WalletConnect (sends Telegram button)
10
- * 4. Send all 3 txs sequentially for owner approval
11
- */
12
-
13
- import { ethers } from "ethers";
14
- import { loadConfig } from "../src/config";
15
- import { connectPhoneWallet, sendTransactionWithSession } from "../src/walletconnect";
16
-
17
- const DEPLOYER = "0x59A32A792d0f25B0E0a4A4aFbFDf514b94B102fB";
18
- const WALLET = "0xC3207bFe22cba39AeC4e8540c97c29B028103c7F";
19
- const RPC = "https://base-mainnet.g.alchemy.com/v2/YIA2uRCsFI-j5pqH-aRzflrACSlV1Qrs";
20
- const CHAIN_ID = 8453;
21
-
22
- const WALLET_ABI = [
23
- "function openContext(bytes32 contextId, string calldata taskType) external",
24
- "function closeContext() external",
25
- "function attest(bytes32 attestationId, string calldata action, string calldata reason, address recipient, uint256 amount, address token, uint256 expiresAt) external returns (bytes32)",
26
- "function executeSpend(address payable recipient, uint256 amount, string calldata category, bytes32 attestationId) external",
27
- "function contextOpen() external view returns (bool)",
28
- ];
29
-
30
- async function main() {
31
- const config = loadConfig();
32
-
33
- const balance = await new ethers.JsonRpcProvider(RPC).getBalance(WALLET);
34
-
35
- if (balance === 0n) {
36
- console.log("Wallet is already empty.");
37
- process.exit(0);
38
- }
39
-
40
- // Reserve gas for 3 transactions (~300k gas @ ~0.01 gwei = ~0.003 ETH buffer)
41
- const gasReserve = ethers.parseEther("0.0001");
42
- const sendAmount = balance - gasReserve;
43
-
44
- if (sendAmount <= 0n) {
45
- console.log(`Balance too low to drain safely: ${ethers.formatEther(balance)} ETH`);
46
- process.exit(0);
47
- }
48
-
49
- console.log(`\nDraining ${ethers.formatEther(sendAmount)} ETH from wallet contract`);
50
- console.log(` From: ${WALLET}`);
51
- console.log(` To: ${DEPLOYER}\n`);
52
-
53
- const iface = new ethers.Interface(WALLET_ABI);
54
-
55
- const contextId = ethers.keccak256(ethers.toUtf8Bytes(`drain-${Date.now()}`));
56
- const attestId = ethers.keccak256(ethers.toUtf8Bytes(`attest-${Date.now()}`));
57
- const expiresAt = Math.floor(Date.now() / 1000) + 3600; // 1 hour
58
-
59
- // Close any existing open context first (from prior partial run)
60
- const provider = new ethers.JsonRpcProvider(RPC);
61
- const contextOpenRaw = await provider.call({ to: WALLET, data: iface.encodeFunctionData("contextOpen") });
62
- const contextAlreadyOpen = ethers.AbiCoder.defaultAbiCoder().decode(["bool"], contextOpenRaw)[0];
63
-
64
- const txCloseContext = contextAlreadyOpen ? {
65
- to: WALLET,
66
- data: iface.encodeFunctionData("closeContext"),
67
- value: "0x0",
68
- } : null;
69
-
70
- const txOpenContext = {
71
- to: WALLET,
72
- data: iface.encodeFunctionData("openContext", [contextId, "drain"]),
73
- value: "0x0",
74
- };
75
-
76
- const txAttest = {
77
- to: WALLET,
78
- data: iface.encodeFunctionData("attest", [
79
- attestId,
80
- "drain",
81
- "drain to deployer",
82
- DEPLOYER,
83
- sendAmount,
84
- ethers.ZeroAddress,
85
- expiresAt,
86
- ]),
87
- value: "0x0",
88
- };
89
-
90
- const txSpend = {
91
- to: WALLET,
92
- data: iface.encodeFunctionData("executeSpend", [
93
- DEPLOYER,
94
- sendAmount,
95
- "drain",
96
- attestId,
97
- ]),
98
- value: "0x0",
99
- };
100
-
101
- const tgOpts = {
102
- botToken: config.telegramBotToken!,
103
- chatId: config.telegramChatId!,
104
- threadId: config.telegramThreadId,
105
- };
106
-
107
- console.log("Connecting WalletConnect — fresh session, Base network enforced...\n");
108
-
109
- const { client, session, account } = await connectPhoneWallet(
110
- config.walletConnectProjectId!,
111
- CHAIN_ID,
112
- config,
113
- {
114
- telegramOpts: tgOpts,
115
- prompt: `⛓ BASE NETWORK ONLY\nApprove drain of ${ethers.formatEther(sendAmount)} ETH → deployer wallet\n\n⚠️ Make sure MetaMask is on BASE before approving`,
116
- }
117
- );
118
-
119
- console.log(`\nConnected: ${account}`);
120
-
121
- let txCount = 1;
122
- const total = (txCloseContext ? 4 : 3);
123
-
124
- if (txCloseContext) {
125
- console.log(`Sending tx ${txCount++}/${total}: closeContext (cleaning up prior run)...`);
126
- const hClose = await sendTransactionWithSession(client, session, account, CHAIN_ID, txCloseContext);
127
- console.log(` ✓ ${hClose}`);
128
- }
129
-
130
- console.log(`Sending tx ${txCount++}/${total}: openContext...`);
131
- const h1 = await sendTransactionWithSession(client, session, account, CHAIN_ID, txOpenContext);
132
- console.log(` ✓ ${h1}`);
133
-
134
- console.log(`Sending tx ${txCount++}/${total}: attest...`);
135
- const h2 = await sendTransactionWithSession(client, session, account, CHAIN_ID, txAttest);
136
- console.log(` ✓ ${h2}`);
137
-
138
- console.log(`Sending tx ${txCount++}/${total}: executeSpend...`);
139
- const h3 = await sendTransactionWithSession(client, session, account, CHAIN_ID, txSpend);
140
- console.log(` ✓ ${h3}`);
141
-
142
- console.log(`\n✅ Done. ${ethers.formatEther(sendAmount)} ETH sent to deployer.`);
143
- process.exit(0);
144
- }
145
-
146
- main().catch(e => {
147
- console.error(e.message ?? e);
148
- process.exit(1);
149
- });
@@ -1,81 +0,0 @@
1
- /**
2
- * execute-spend-only.ts
3
- * Send ONLY the executeSpend tx — context and attest already confirmed on-chain.
4
- * Uses the attestation ID from the last successful attest tx.
5
- */
6
-
7
- import { ethers } from "ethers";
8
- import { loadConfig } from "../src/config";
9
- import { connectPhoneWallet, sendTransactionWithSession } from "../src/walletconnect";
10
-
11
- const DEPLOYER = "0x59A32A792d0f25B0E0a4A4aFbFDf514b94B102fB";
12
- const WALLET = "0xC3207bFe22cba39AeC4e8540c97c29B028103c7F";
13
- const RPC = "https://base-mainnet.g.alchemy.com/v2/YIA2uRCsFI-j5pqH-aRzflrACSlV1Qrs";
14
- const CHAIN_ID = 8453;
15
-
16
- // Attest tx was: 0x28dbff33aa65b0617c4f25810f06f76bfcf0a430f461b...
17
- // Recover attestId from the drain script's timestamp-based keccak
18
- // The attest tx confirmed — we need to recover the attestId used.
19
- // Re-derive it: the script used `attest-${Date.now()}` at time of that run.
20
- // Instead, read it from the IntentAttestation contract by checking events.
21
-
22
- const INTENT_ATTEST_ABI = [
23
- "event AttestationCreated(bytes32 indexed attestationId, address indexed wallet, address recipient, uint256 amount, address token)",
24
- "function verify(bytes32 attestationId, address wallet, address recipient, uint256 amount, address token) external view returns (bool)",
25
- ];
26
-
27
- const WALLET_ABI = [
28
- "function executeSpend(address payable recipient, uint256 amount, string calldata category, bytes32 attestationId) external",
29
- ];
30
-
31
- const INTENT_ATTEST_ADDR = "0x7ad8db6C5f394542E8e9658F86C85cC99Cf6D460";
32
-
33
- async function main() {
34
- const config = loadConfig();
35
- const provider = new ethers.JsonRpcProvider(RPC);
36
-
37
- // Find the most recent AttestationCreated event for this wallet → DEPLOYER
38
- const attestContract = new ethers.Contract(INTENT_ATTEST_ADDR, INTENT_ATTEST_ABI, provider);
39
- const block = await provider.getBlockNumber();
40
- // Hardcoded from confirmed attest tx 0x28dbff33...c17
41
- const attestId = "0x9d8bdb5f551f63e986e5d0c980fd68f4e445b9f7902f71226ec08ce24bceebb0";
42
- const amount = ethers.parseEther("0.00015");
43
-
44
- console.log(`Found attestation: ${attestId}`);
45
- console.log(`Amount: ${ethers.formatEther(amount)} ETH`);
46
- console.log(`Sending executeSpend → ${DEPLOYER}\n`);
47
-
48
- const iface = new ethers.Interface(WALLET_ABI);
49
- const txSpend = {
50
- to: WALLET,
51
- data: iface.encodeFunctionData("executeSpend", [DEPLOYER, amount, "drain", attestId]),
52
- value: "0x0",
53
- };
54
-
55
- const tgOpts = {
56
- botToken: config.telegramBotToken!,
57
- chatId: config.telegramChatId!,
58
- threadId: config.telegramThreadId,
59
- };
60
-
61
- const { client, session, account } = await connectPhoneWallet(
62
- config.walletConnectProjectId!,
63
- CHAIN_ID,
64
- config,
65
- {
66
- telegramOpts: tgOpts,
67
- prompt: `⛓ BASE ONLY — Final tx: executeSpend ${ethers.formatEther(amount)} ETH → deployer\n\n⚠️ Keep MetaMask on Base and approve`,
68
- }
69
- );
70
-
71
- console.log(`Connected: ${account}`);
72
- console.log("Sending executeSpend...");
73
- const hash = await sendTransactionWithSession(client, session, account, CHAIN_ID, txSpend);
74
- console.log(`\n✅ Done: ${hash}`);
75
- process.exit(0);
76
- }
77
-
78
- main().catch(e => {
79
- console.error(e.message ?? e);
80
- process.exit(1);
81
- });
@@ -1,186 +0,0 @@
1
- /**
2
- * register-agent-userop.ts
3
- * Register GigaBrain in AgentRegistry via ERC-4337 UserOperation.
4
- * Machine key signs → Pimlico bundler → EntryPoint executes → wallet is msg.sender.
5
- */
6
-
7
- import { ethers } from "ethers";
8
- import { loadConfig } from "../src/config";
9
- import { BundlerClient, buildUserOp } from "../src/bundler";
10
- import { ARC402_WALLET_EXECUTE_ABI, AGENT_REGISTRY_ABI } from "../src/abis";
11
-
12
- const ENTRY_POINT = "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
13
- const CHAIN_ID = 8453;
14
-
15
- // EntryPoint v0.7 nonce getter ABI
16
- const EP_ABI = [
17
- "function getNonce(address sender, uint192 key) external view returns (uint256)",
18
- "function depositTo(address account) external payable",
19
- "function balanceOf(address account) external view returns (uint256)",
20
- ];
21
-
22
- async function main() {
23
- const config = loadConfig();
24
- if (!config.walletContractAddress) throw new Error("walletContractAddress not in config");
25
- if (!config.privateKey) throw new Error("privateKey not in config");
26
-
27
- const provider = new ethers.JsonRpcProvider(config.rpcUrl);
28
- const machineKey = new ethers.Wallet(config.privateKey, provider);
29
- const walletAddress = config.walletContractAddress;
30
-
31
- const agentRegistryAddress =
32
- config.agentRegistryV2Address ??
33
- "0xD5c2851B00090c92Ba7F4723FB548bb30C9B6865";
34
-
35
- console.log("Wallet: ", walletAddress);
36
- console.log("Machine key: ", machineKey.address);
37
- console.log("AgentRegistry: ", agentRegistryAddress);
38
-
39
- // ── 1. Check ETH balance ───────────────────────────────────────────────────
40
- const balance = await provider.getBalance(walletAddress);
41
- console.log("Wallet balance: ", ethers.formatEther(balance), "ETH");
42
- if (balance < ethers.parseEther("0.0005")) {
43
- throw new Error("Wallet balance too low — need at least 0.0005 ETH");
44
- }
45
-
46
- // ── 2. Get nonce from EntryPoint ───────────────────────────────────────────
47
- const ep = new ethers.Contract(ENTRY_POINT, EP_ABI, provider);
48
- const nonce: bigint = await ep.getNonce(walletAddress, 0);
49
- console.log("Nonce: ", nonce.toString());
50
-
51
- // ── 3. Encode AgentRegistry.register() calldata ───────────────────────────
52
- const registryIface = new ethers.Interface(AGENT_REGISTRY_ABI);
53
- const registerCalldata = registryIface.encodeFunctionData("register", [
54
- "GigaBrain", // name
55
- [], // capabilities (empty for now)
56
- "ai.assistant", // serviceType
57
- "https://gigabrain.arc402.xyz", // endpoint
58
- "", // metadataURI
59
- ]);
60
-
61
- // ── 4. Encode ARC402Wallet.executeContractCall() — this is the UserOp callData ──
62
- const walletIface = new ethers.Interface(ARC402_WALLET_EXECUTE_ABI);
63
- const userOpCallData = walletIface.encodeFunctionData("executeContractCall", [{
64
- target: agentRegistryAddress,
65
- data: registerCalldata,
66
- value: BigInt(0),
67
- minReturnValue: BigInt(0),
68
- maxApprovalAmount: BigInt(0),
69
- approvalToken: ethers.ZeroAddress,
70
- }]);
71
-
72
- console.log("UserOp callData built ✓");
73
-
74
- // ── 5. Build UserOp — fetch live gas price from Pimlico ───────────────────
75
- // Declare bundlerUrl here so it's available for gas price fetch AND sending
76
- const bundlerUrl = (config as unknown as Record<string, unknown>)["bundlerUrl"] as string | undefined ?? "https://public.pimlico.io/v2/8453/rpc";
77
- const gasPriceRes = await fetch(bundlerUrl, {
78
- method: "POST",
79
- headers: { "Content-Type": "application/json" },
80
- body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "pimlico_getUserOperationGasPrice", params: [] }),
81
- });
82
- const gasPriceJson = await gasPriceRes.json() as { result?: { fast?: { maxFeePerGas: string; maxPriorityFeePerGas: string } } };
83
- const fast = gasPriceJson.result?.fast;
84
- if (!fast) throw new Error("Could not fetch gas price from bundler");
85
- console.log("Gas price (fast): maxFee=", fast.maxFeePerGas, "maxPriority=", fast.maxPriorityFeePerGas);
86
-
87
- const userOp = await buildUserOp(userOpCallData, walletAddress, nonce, config);
88
- // Override with bundler-recommended gas prices
89
- userOp.maxFeePerGas = fast.maxFeePerGas;
90
- userOp.maxPriorityFeePerGas = fast.maxPriorityFeePerGas;
91
- // Bump callGasLimit — executeContractCall + AgentRegistry.register needs ~330k
92
- userOp.callGasLimit = ethers.toBeHex(500_000);
93
- userOp.verificationGasLimit = ethers.toBeHex(200_000);
94
-
95
- // ── 6. Sign UserOp with machine key ───────────────────────────────────────
96
- // ERC-4337 v0.7: hash = keccak256(abi.encode(userOpHash, entryPoint, chainId))
97
- // where userOpHash = keccak256(packed(userOp fields))
98
- const packedFields = ethers.AbiCoder.defaultAbiCoder().encode(
99
- ["address","uint256","bytes32","bytes32","bytes32","uint256","bytes32","bytes32"],
100
- [
101
- userOp.sender,
102
- BigInt(userOp.nonce),
103
- ethers.keccak256(ethers.concat(
104
- userOp.factory ? [userOp.factory, userOp.factoryData ?? "0x"] : []
105
- )),
106
- ethers.keccak256(userOp.callData),
107
- ethers.concat([
108
- ethers.zeroPadValue(ethers.toBeHex(userOp.callGasLimit), 16),
109
- ethers.zeroPadValue(ethers.toBeHex(userOp.verificationGasLimit), 16),
110
- ]),
111
- BigInt(userOp.preVerificationGas),
112
- ethers.concat([
113
- ethers.zeroPadValue(ethers.toBeHex(userOp.maxPriorityFeePerGas), 16),
114
- ethers.zeroPadValue(ethers.toBeHex(userOp.maxFeePerGas), 16),
115
- ]),
116
- ethers.keccak256(
117
- userOp.paymaster
118
- ? ethers.concat([
119
- userOp.paymaster,
120
- ethers.zeroPadValue(ethers.toBeHex(userOp.paymasterVerificationGasLimit ?? "0x0"), 16),
121
- ethers.zeroPadValue(ethers.toBeHex(userOp.paymasterPostOpGasLimit ?? "0x0"), 16),
122
- userOp.paymasterData ?? "0x",
123
- ])
124
- : "0x"
125
- ),
126
- ]
127
- );
128
- const userOpHash = ethers.keccak256(
129
- ethers.AbiCoder.defaultAbiCoder().encode(
130
- ["bytes32","address","uint256"],
131
- [
132
- ethers.keccak256(packedFields),
133
- ENTRY_POINT,
134
- CHAIN_ID,
135
- ]
136
- )
137
- );
138
- console.log("UserOp hash: ", userOpHash);
139
-
140
- // validateUserOp uses toEthSignedMessageHash — sign the eth-prefixed hash
141
- const signature = await machineKey.signMessage(ethers.getBytes(userOpHash));
142
- userOp.signature = signature;
143
- console.log("Signed ✓");
144
-
145
- // ── 7. Send to bundler ─────────────────────────────────────────────────────
146
- const bundler = new BundlerClient(bundlerUrl, ENTRY_POINT, CHAIN_ID);
147
-
148
- console.log("Sending UserOperation to bundler...");
149
- let opHash: string;
150
- try {
151
- opHash = await bundler.sendUserOperation(userOp);
152
- } catch (e) {
153
- const msg = e instanceof Error ? e.message : String(e);
154
- throw new Error(`Bundler rejected UserOp: ${msg}`);
155
- }
156
- console.log("UserOp hash: ", opHash);
157
- console.log("Waiting for confirmation (up to 60s)...");
158
-
159
- const receipt = await bundler.getUserOperationReceipt(opHash);
160
- if (!receipt.success) {
161
- throw new Error(`UserOp failed on-chain. Tx: ${receipt.receipt.transactionHash}`);
162
- }
163
- console.log("✓ AgentRegistry.register() confirmed");
164
- console.log(" Tx:", receipt.receipt.transactionHash);
165
-
166
- // ── 8. Claim subdomain ─────────────────────────────────────────────────────
167
- console.log("\nClaiming gigabrain.arc402.xyz...");
168
- const res = await fetch("https://api.arc402.xyz/register-subdomain", {
169
- method: "POST",
170
- headers: { "Content-Type": "application/json" },
171
- body: JSON.stringify({
172
- subdomain: "gigabrain",
173
- walletAddress,
174
- tunnelTarget: "https://gigabrain.arc402.xyz",
175
- }),
176
- });
177
- const body = await res.json() as Record<string, unknown>;
178
- if (!res.ok) {
179
- console.error("✗ Subdomain claim failed:", body["error"] ?? body);
180
- process.exit(1);
181
- }
182
- console.log("✓ Subdomain claimed:", body["subdomain"]);
183
- console.log("\nAll done. GigaBrain is registered and live.");
184
- }
185
-
186
- main().catch(e => { console.error(e); process.exit(1); });