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,35 +0,0 @@
1
- import { Command } from "commander";
2
- import { DisputeArbitrationClient } from "@arc402/sdk";
3
- import { loadConfig } from "../config.js";
4
- import { requireSigner } from "../client.js";
5
- import { c } from '../ui/colors.js';
6
- import { startSpinner } from '../ui/spinner.js';
7
- import { formatAddress } from '../ui/format.js';
8
-
9
- export function registerOwnerCommands(program: Command): void {
10
- const owner = program.command("owner").description("Protocol ownership management (DisputeArbitration two-step transfer)");
11
-
12
- owner.command("propose-transfer <newOwner>")
13
- .description("Step 1: Propose ownership transfer of DisputeArbitration to a new address. New owner must call accept-transfer to complete.")
14
- .action(async (newOwner, _opts) => {
15
- const config = loadConfig();
16
- if (!config.disputeArbitrationAddress) throw new Error("disputeArbitrationAddress missing in config");
17
- const { signer } = await requireSigner(config);
18
- const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, signer);
19
- const spinner = startSpinner('Proposing ownership transfer…');
20
- await client.proposeOwner(newOwner);
21
- spinner.succeed(c.success + c.white(' Ownership transfer proposed to ' + formatAddress(newOwner)));
22
- });
23
-
24
- owner.command("accept-transfer")
25
- .description("Step 2: Accept pending ownership of DisputeArbitration. Must be called from the pending owner's key.")
26
- .action(async (_opts) => {
27
- const config = loadConfig();
28
- if (!config.disputeArbitrationAddress) throw new Error("disputeArbitrationAddress missing in config");
29
- const { signer } = await requireSigner(config);
30
- const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, signer);
31
- const spinner = startSpinner('Accepting ownership…');
32
- await client.acceptOwnership();
33
- spinner.succeed(c.success + c.white(' Ownership accepted'));
34
- });
35
- }
@@ -1,263 +0,0 @@
1
- import { Command } from "commander";
2
- import { ethers } from "ethers";
3
- import { loadConfig } from "../config.js";
4
- import { getClient, requireSigner } from "../client.js";
5
- import { c } from '../ui/colors.js';
6
- import { startSpinner } from '../ui/spinner.js';
7
- import { formatAddress } from '../ui/format.js';
8
-
9
- const POLICY_ENGINE_EXTENDED_ABI = [
10
- "function addToBlocklist(address wallet, address provider) external",
11
- "function removeFromBlocklist(address wallet, address provider) external",
12
- "function isBlocked(address wallet, address provider) external view returns (bool)",
13
- "function addPreferred(address wallet, string capability, address provider) external",
14
- "function removePreferred(address wallet, string capability, address provider) external",
15
- "function getPreferred(address wallet, string capability) external view returns (address[])",
16
- "function isPreferred(address wallet, string capability, address provider) external view returns (bool)",
17
- "event ProviderBlocked(address indexed wallet, address indexed provider)",
18
- "event ProviderUnblocked(address indexed wallet, address indexed provider)",
19
- "event ProviderPreferred(address indexed wallet, address indexed provider, string capability)",
20
- "event ProviderUnpreferred(address indexed wallet, address indexed provider, string capability)",
21
- ] as const;
22
-
23
- function getPolicyEngine(address: string, runner: ethers.ContractRunner) {
24
- return new ethers.Contract(address, POLICY_ENGINE_EXTENDED_ABI, runner);
25
- }
26
-
27
- const policy = new Command("policy").description("Personal policy enforcement: blocklist and shortlist");
28
-
29
- // ─── blocklist ────────────────────────────────────────────────────────────────
30
-
31
- const blocklist = policy.command("blocklist").description("Hard-stop blocklist: addresses your agent will never accept work from");
32
-
33
- blocklist
34
- .command("add <address>")
35
- .description("Block a provider address")
36
- .option("--json")
37
- .action(async (address, opts) => {
38
- const config = loadConfig();
39
- if (!config.policyEngineAddress) {
40
- console.error("policyEngineAddress not configured. Run `arc402 config set policyEngineAddress <address>`.");
41
- process.exit(1);
42
- }
43
- const { signer, address: wallet } = await requireSigner(config);
44
- const contract = getPolicyEngine(config.policyEngineAddress, signer);
45
- const already = await contract.isBlocked(wallet, address);
46
- if (already) {
47
- if (opts.json) return console.log(JSON.stringify({ address, blocked: true, alreadyBlocked: true }));
48
- return console.log(' ' + c.dim('Already blocked: ' + formatAddress(address)));
49
- }
50
- await (await contract.addToBlocklist(wallet, address)).wait();
51
- if (opts.json) return console.log(JSON.stringify({ address, blocked: true }));
52
- console.log(' ' + c.success + c.white(' Blocked: ' + formatAddress(address)));
53
- });
54
-
55
- blocklist
56
- .command("remove <address>")
57
- .description("Remove a provider from your blocklist")
58
- .option("--json")
59
- .action(async (address, opts) => {
60
- const config = loadConfig();
61
- if (!config.policyEngineAddress) {
62
- console.error("policyEngineAddress not configured. Run `arc402 config set policyEngineAddress <address>`.");
63
- process.exit(1);
64
- }
65
- const { signer, address: wallet } = await requireSigner(config);
66
- const contract = getPolicyEngine(config.policyEngineAddress, signer);
67
- const isBlockedNow = await contract.isBlocked(wallet, address);
68
- if (!isBlockedNow) {
69
- if (opts.json) return console.log(JSON.stringify({ address, blocked: false, notBlocked: true }));
70
- return console.log(' ' + c.dim('Not on blocklist: ' + formatAddress(address)));
71
- }
72
- await (await contract.removeFromBlocklist(wallet, address)).wait();
73
- if (opts.json) return console.log(JSON.stringify({ address, blocked: false }));
74
- console.log(' ' + c.success + c.white(' Unblocked: ' + formatAddress(address)));
75
- });
76
-
77
- blocklist
78
- .command("check <address>")
79
- .description("Check if an address is on your blocklist")
80
- .option("--json")
81
- .action(async (address, opts) => {
82
- const config = loadConfig();
83
- if (!config.policyEngineAddress) {
84
- console.error("policyEngineAddress not configured.");
85
- process.exit(1);
86
- }
87
- const { provider } = await getClient(config);
88
- const { address: wallet } = await requireSigner(config);
89
- const contract = getPolicyEngine(config.policyEngineAddress, provider);
90
- const blocked = await contract.isBlocked(wallet, address);
91
- if (opts.json) return console.log(JSON.stringify({ address, blocked }));
92
- if (blocked) {
93
- console.log(' ' + c.warning + c.white(' ' + formatAddress(address) + ' is BLOCKED'));
94
- } else {
95
- console.log(' ' + c.success + c.white(' ' + formatAddress(address) + ' is not blocked'));
96
- }
97
- });
98
-
99
- blocklist
100
- .command("list")
101
- .description("List all addresses on your blocklist (scans on-chain events)")
102
- .option("--from-block <n>", "Start block for event log query (default: latest-9000 to stay within public RPC limits)")
103
- .option("--json")
104
- .action(async (opts) => {
105
- const config = loadConfig();
106
- if (!config.policyEngineAddress) {
107
- console.error("policyEngineAddress not configured.");
108
- process.exit(1);
109
- }
110
- const { provider } = await getClient(config);
111
- const { address: wallet } = await requireSigner(config);
112
- const contract = getPolicyEngine(config.policyEngineAddress, provider);
113
-
114
- const latestBlock = await provider.getBlockNumber();
115
- const fromBlock = opts.fromBlock !== undefined ? parseInt(opts.fromBlock, 10) : Math.max(0, latestBlock - 9000);
116
-
117
- const [blockedEvents, unblockedEvents] = await Promise.all([
118
- contract.queryFilter(contract.filters.ProviderBlocked(wallet), fromBlock),
119
- contract.queryFilter(contract.filters.ProviderUnblocked(wallet), fromBlock),
120
- ]);
121
- const unblocked = new Set(
122
- unblockedEvents.map((e) => (e as ethers.EventLog).args.provider.toLowerCase())
123
- );
124
- const addresses = blockedEvents
125
- .map((e) => (e as ethers.EventLog).args.provider as string)
126
- .filter((p) => !unblocked.has(p.toLowerCase()));
127
-
128
- if (opts.json) return console.log(JSON.stringify({ wallet, blocked: addresses }, null, 2));
129
- if (addresses.length === 0) return console.log("No addresses on your blocklist");
130
- addresses.forEach((a) => console.log(a));
131
- });
132
-
133
- // ─── shortlist ────────────────────────────────────────────────────────────────
134
-
135
- const shortlist = policy.command("shortlist").description("Preferred providers per capability (preferred or exclusive)");
136
-
137
- shortlist
138
- .command("add <address>")
139
- .description("Add a provider to your shortlist for a capability")
140
- .requiredOption("--capability <name>", "Capability name (e.g. code.review)")
141
- .option("--note <text>", "Optional note (stored off-chain only)")
142
- .option("--json")
143
- .action(async (address, opts) => {
144
- const config = loadConfig();
145
- if (!config.policyEngineAddress) {
146
- console.error("policyEngineAddress not configured. Run `arc402 config set policyEngineAddress <address>`.");
147
- process.exit(1);
148
- }
149
- const { signer, address: wallet } = await requireSigner(config);
150
- const contract = getPolicyEngine(config.policyEngineAddress, signer);
151
- const alreadyPreferred = await contract.isPreferred(wallet, opts.capability, address);
152
- if (alreadyPreferred) {
153
- if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred: true, alreadyPreferred: true }));
154
- return console.log(' ' + c.dim('Already shortlisted: ' + formatAddress(address) + ' for ' + opts.capability));
155
- }
156
- await (await contract.addPreferred(wallet, opts.capability, address)).wait();
157
- if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred: true }));
158
- console.log(' ' + c.success + c.white(' Shortlisted: ' + formatAddress(address) + ' for ' + opts.capability));
159
- });
160
-
161
- shortlist
162
- .command("remove <address>")
163
- .description("Remove a provider from your shortlist for a capability")
164
- .requiredOption("--capability <name>", "Capability name")
165
- .option("--json")
166
- .action(async (address, opts) => {
167
- const config = loadConfig();
168
- if (!config.policyEngineAddress) {
169
- console.error("policyEngineAddress not configured. Run `arc402 config set policyEngineAddress <address>`.");
170
- process.exit(1);
171
- }
172
- const { signer, address: wallet } = await requireSigner(config);
173
- const contract = getPolicyEngine(config.policyEngineAddress, signer);
174
- const isPreferredNow = await contract.isPreferred(wallet, opts.capability, address);
175
- if (!isPreferredNow) {
176
- if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred: false, notPreferred: true }));
177
- return console.log(' ' + c.dim('Not shortlisted: ' + formatAddress(address) + ' for ' + opts.capability));
178
- }
179
- await (await contract.removePreferred(wallet, opts.capability, address)).wait();
180
- if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred: false }));
181
- console.log(' ' + c.success + c.white(' Removed from shortlist: ' + formatAddress(address) + ' for ' + opts.capability));
182
- });
183
-
184
- shortlist
185
- .command("check <address>")
186
- .description("Check if an address is shortlisted for a capability")
187
- .requiredOption("--capability <name>", "Capability name")
188
- .option("--json")
189
- .action(async (address, opts) => {
190
- const config = loadConfig();
191
- if (!config.policyEngineAddress) {
192
- console.error("policyEngineAddress not configured.");
193
- process.exit(1);
194
- }
195
- const { provider } = await getClient(config);
196
- const { address: wallet } = await requireSigner(config);
197
- const contract = getPolicyEngine(config.policyEngineAddress, provider);
198
- const preferred = await contract.isPreferred(wallet, opts.capability, address);
199
- if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred }));
200
- if (preferred) {
201
- console.log(' ' + c.success + c.white(' ' + formatAddress(address) + ' is shortlisted for ' + opts.capability));
202
- } else {
203
- console.log(' ' + c.warning + c.white(' ' + formatAddress(address) + ' is NOT shortlisted for ' + opts.capability));
204
- }
205
- });
206
-
207
- shortlist
208
- .command("list")
209
- .description("List shortlisted providers, optionally filtered by capability")
210
- .option("--capability <name>", "Filter by capability name")
211
- .option("--from-block <n>", "Start block for event log query (default: latest-9000 to stay within public RPC limits)")
212
- .option("--json")
213
- .action(async (opts) => {
214
- const config = loadConfig();
215
- if (!config.policyEngineAddress) {
216
- console.error("policyEngineAddress not configured.");
217
- process.exit(1);
218
- }
219
- const { provider } = await getClient(config);
220
- const { address: wallet } = await requireSigner(config);
221
- const contract = getPolicyEngine(config.policyEngineAddress, provider);
222
-
223
- if (opts.capability) {
224
- const addresses = await contract.getPreferred(wallet, opts.capability) as string[];
225
- if (opts.json) return console.log(JSON.stringify({ wallet, capability: opts.capability, preferred: addresses }, null, 2));
226
- if (addresses.length === 0) return console.log(`No providers shortlisted for ${opts.capability}`);
227
- addresses.forEach((a) => console.log(a));
228
- return;
229
- }
230
-
231
- // No capability filter — reconstruct from events
232
- const latestBlock = await provider.getBlockNumber();
233
- const fromBlock = opts.fromBlock !== undefined ? parseInt(opts.fromBlock, 10) : Math.max(0, latestBlock - 9000);
234
- const [preferredEvents, unpreferredEvents] = await Promise.all([
235
- contract.queryFilter(contract.filters.ProviderPreferred(wallet), fromBlock),
236
- contract.queryFilter(contract.filters.ProviderUnpreferred(wallet), fromBlock),
237
- ]);
238
- const removed = new Set(
239
- unpreferredEvents.map((e) => {
240
- const args = (e as ethers.EventLog).args;
241
- return `${(args.provider as string).toLowerCase()}::${args.capability as string}`;
242
- })
243
- );
244
- const byCapability: Record<string, string[]> = {};
245
- for (const e of preferredEvents) {
246
- const args = (e as ethers.EventLog).args;
247
- const addr = args.provider as string;
248
- const cap = args.capability as string;
249
- if (removed.has(`${addr.toLowerCase()}::${cap}`)) continue;
250
- if (!byCapability[cap]) byCapability[cap] = [];
251
- if (!byCapability[cap].includes(addr)) byCapability[cap].push(addr);
252
- }
253
-
254
- if (opts.json) return console.log(JSON.stringify({ wallet, shortlist: byCapability }, null, 2));
255
- const caps = Object.keys(byCapability);
256
- if (caps.length === 0) return console.log("No providers on your shortlist");
257
- for (const cap of caps) {
258
- console.log(`${cap}:`);
259
- byCapability[cap].forEach((a) => console.log(` ${a}`));
260
- }
261
- });
262
-
263
- export default policy;
@@ -1,277 +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 * as http from "http";
6
- import * as https from "https";
7
- import { spawn } from "child_process";
8
- import { c } from '../ui/colors.js';
9
-
10
- import { fileURLToPath } from "node:url";
11
- const __filename = fileURLToPath(import.meta.url);
12
- const __dirname = path.dirname(__filename);
13
-
14
- const PID_FILE = path.join(os.homedir(), ".arc402", "relay.pid");
15
-
16
- // ─── HTTP helper (no external deps) ──────────────────────────────────────────
17
-
18
- function relayRequest(
19
- relayUrl: string,
20
- method: string,
21
- urlPath: string,
22
- body?: object
23
- ): Promise<{ status: number; data: unknown }> {
24
- return new Promise((resolve, reject) => {
25
- const parsed = new URL(urlPath, relayUrl);
26
- const isHttps = parsed.protocol === "https:";
27
- const mod = isHttps ? https : http;
28
- const bodyStr = body ? JSON.stringify(body) : undefined;
29
- const options: http.RequestOptions = {
30
- hostname: parsed.hostname,
31
- port: parsed.port || (isHttps ? 443 : 80),
32
- path: parsed.pathname + (parsed.search || ""),
33
- method,
34
- headers: {
35
- "Content-Type": "application/json",
36
- ...(bodyStr ? { "Content-Length": String(Buffer.byteLength(bodyStr)) } : {}),
37
- },
38
- };
39
- const req = mod.request(options, (res) => {
40
- let raw = "";
41
- res.on("data", (c: Buffer) => { raw += c.toString(); });
42
- res.on("end", () => {
43
- try {
44
- resolve({ status: res.statusCode ?? 0, data: JSON.parse(raw) });
45
- } catch {
46
- resolve({ status: res.statusCode ?? 0, data: raw });
47
- }
48
- });
49
- });
50
- req.on("error", reject);
51
- if (bodyStr) req.write(bodyStr);
52
- req.end();
53
- });
54
- }
55
-
56
- // ─── Daemon loop (runs in-process when spawned with ARC402_RELAY_DAEMON=1) ───
57
-
58
- async function runDaemonLoop(opts: {
59
- relayUrl: string;
60
- address: string;
61
- pollInterval: number;
62
- onMessage: string;
63
- }): Promise<void> {
64
- let lastSeen: string | null = null;
65
-
66
- const poll = async () => {
67
- try {
68
- const qs = `?address=${encodeURIComponent(opts.address)}` +
69
- (lastSeen ? `&since=${encodeURIComponent(lastSeen)}` : "");
70
- const result = await relayRequest(opts.relayUrl, "GET", `/poll${qs}`);
71
- const data = result.data as { messages?: Array<{ messageId: string; payload: unknown }> };
72
- const messages = data.messages || [];
73
- for (const msg of messages) {
74
- lastSeen = msg.messageId;
75
- // Spawn the handler script with message JSON on stdin
76
- const child = spawn(opts.onMessage, [], {
77
- stdio: ["pipe", "inherit", "inherit"],
78
- shell: true,
79
- });
80
- child.stdin.write(JSON.stringify(msg));
81
- child.stdin.end();
82
- }
83
- } catch {
84
- // Silent retry — relay may be temporarily unreachable
85
- }
86
- };
87
-
88
- // Initial poll immediately, then on interval
89
- await poll();
90
- setInterval(poll, opts.pollInterval);
91
-
92
- // Keep process alive
93
- process.stdin.resume();
94
- }
95
-
96
- // ─── Command registration ─────────────────────────────────────────────────────
97
-
98
- export function registerRelayCommands(program: Command): void {
99
- const relay = program
100
- .command("relay")
101
- .description("Send and receive messages via an ARC-402 relay (Spec 21)");
102
-
103
- // ── relay send ──────────────────────────────────────────────────────────────
104
- relay
105
- .command("send")
106
- .description("Send a message to an address via the relay")
107
- .requiredOption("--to <address>", "Recipient address")
108
- .requiredOption("--payload <json>", "JSON payload string")
109
- .requiredOption("--relay <url>", "Relay server URL")
110
- .option("--json", "Machine-parseable output")
111
- .action(async (opts) => {
112
- let payload: unknown;
113
- try {
114
- payload = JSON.parse(opts.payload);
115
- } catch {
116
- console.error("Error: --payload must be valid JSON");
117
- process.exit(1);
118
- }
119
-
120
- const result = await relayRequest(opts.relay, "POST", "/send", {
121
- to: opts.to,
122
- payload,
123
- });
124
-
125
- if (result.status !== 200) {
126
- console.error(`Relay error (${result.status}): ${JSON.stringify(result.data)}`);
127
- process.exit(1);
128
- }
129
-
130
- if (opts.json) {
131
- console.log(JSON.stringify(result.data));
132
- } else {
133
- const d = result.data as { messageId?: string };
134
- console.log(' ' + c.success + c.white(' Sent — messageId: ' + d.messageId));
135
- }
136
- });
137
-
138
- // ── relay poll ──────────────────────────────────────────────────────────────
139
- relay
140
- .command("poll")
141
- .description("Poll for messages addressed to an address")
142
- .requiredOption("--address <address>", "Address to poll for")
143
- .requiredOption("--relay <url>", "Relay server URL")
144
- .option("--since <messageId>", "Only return messages after this messageId")
145
- .option("--json", "Machine-parseable output")
146
- .action(async (opts) => {
147
- const qs = `?address=${encodeURIComponent(opts.address)}` +
148
- (opts.since ? `&since=${encodeURIComponent(opts.since)}` : "");
149
-
150
- const result = await relayRequest(opts.relay, "GET", `/poll${qs}`);
151
-
152
- if (result.status !== 200) {
153
- console.error(`Relay error (${result.status}): ${JSON.stringify(result.data)}`);
154
- process.exit(1);
155
- }
156
-
157
- const data = result.data as { messages?: unknown[] };
158
- const messages = data.messages || [];
159
-
160
- if (opts.json) {
161
- console.log(JSON.stringify(data));
162
- return;
163
- }
164
-
165
- if (messages.length === 0) {
166
- console.log(' ' + c.dim('No messages.'));
167
- return;
168
- }
169
-
170
- for (const msg of messages as Array<{ messageId: string; from: string; timestamp: number }>) {
171
- const ts = new Date(msg.timestamp).toISOString();
172
- console.log(`[${ts}] ${msg.messageId.slice(0, 12)}... from=${msg.from}`);
173
- }
174
- });
175
-
176
- // ── relay daemon ────────────────────────────────────────────────────────────
177
- const daemon = relay
178
- .command("daemon")
179
- .description("Persistent relay polling daemon");
180
-
181
- daemon
182
- .command("start")
183
- .description("Start the relay daemon in the background")
184
- .requiredOption("--relay <url>", "Relay server URL")
185
- .requiredOption("--address <address>", "Address to poll for messages")
186
- .requiredOption("--poll-interval <ms>", "Polling interval in milliseconds", "2000")
187
- .requiredOption("--on-message <script>", "Script to invoke for each incoming message (receives JSON on stdin)")
188
- .option("--json", "Machine-parseable output")
189
- .action((opts) => {
190
- // Check if already running
191
- if (fs.existsSync(PID_FILE)) {
192
- try {
193
- const existingPid = parseInt(fs.readFileSync(PID_FILE, "utf8").trim(), 10);
194
- process.kill(existingPid, 0); // Check if alive
195
- console.error(`Daemon already running (PID ${existingPid}). Run 'arc402 relay daemon stop' first.`);
196
- process.exit(1);
197
- } catch {
198
- // PID file is stale — clean it up
199
- fs.unlinkSync(PID_FILE);
200
- }
201
- }
202
-
203
- // Spawn a detached child process
204
- const child = spawn(process.execPath, [__filename], {
205
- detached: true,
206
- stdio: "ignore",
207
- env: {
208
- ...process.env,
209
- ARC402_RELAY_DAEMON: "1",
210
- ARC402_RELAY_URL: opts.relay,
211
- ARC402_RELAY_ADDRESS: opts.address,
212
- ARC402_RELAY_INTERVAL: opts.pollInterval,
213
- ARC402_RELAY_HANDLER: opts.onMessage,
214
- },
215
- });
216
- child.unref();
217
-
218
- fs.mkdirSync(path.dirname(PID_FILE), { recursive: true });
219
- fs.writeFileSync(PID_FILE, String(child.pid), { mode: 0o600 });
220
-
221
- if (opts.json) {
222
- console.log(JSON.stringify({ started: true, pid: child.pid, pidFile: PID_FILE }));
223
- } else {
224
- console.log(' ' + c.success + c.white(' Daemon started (PID ' + child.pid + ')'));
225
- }
226
- });
227
-
228
- daemon
229
- .command("stop")
230
- .description("Stop the relay daemon")
231
- .option("--json", "Machine-parseable output")
232
- .action((opts) => {
233
- if (!fs.existsSync(PID_FILE)) {
234
- if (opts.json) {
235
- console.log(JSON.stringify({ stopped: false, reason: "no pid file" }));
236
- } else {
237
- console.log(' ' + c.dim('No running daemon found.'));
238
- }
239
- return;
240
- }
241
-
242
- const pid = parseInt(fs.readFileSync(PID_FILE, "utf8").trim(), 10);
243
- try {
244
- process.kill(pid, "SIGTERM");
245
- fs.unlinkSync(PID_FILE);
246
- if (opts.json) {
247
- console.log(JSON.stringify({ stopped: true, pid }));
248
- } else {
249
- console.log(' ' + c.success + c.white(' Daemon stopped (PID ' + pid + ')'));
250
- }
251
- } catch (err: unknown) {
252
- const msg = err instanceof Error ? err.message : String(err);
253
- if (opts.json) {
254
- console.log(JSON.stringify({ stopped: false, pid, error: msg }));
255
- } else {
256
- console.error(`Failed to stop daemon: ${msg}`);
257
- // Clean up stale PID file
258
- fs.unlinkSync(PID_FILE);
259
- }
260
- }
261
- });
262
- }
263
-
264
- // ─── Daemon entry point ───────────────────────────────────────────────────────
265
- // When spawned as a background process via daemon start
266
-
267
- if (process.env.ARC402_RELAY_DAEMON === "1") {
268
- runDaemonLoop({
269
- relayUrl: process.env.ARC402_RELAY_URL || "",
270
- address: process.env.ARC402_RELAY_ADDRESS || "",
271
- pollInterval: parseInt(process.env.ARC402_RELAY_INTERVAL || "2000", 10),
272
- onMessage: process.env.ARC402_RELAY_HANDLER || "echo",
273
- }).catch((err) => {
274
- process.stderr.write(`Daemon error: ${err}\n`);
275
- process.exit(1);
276
- });
277
- }
@@ -1,24 +0,0 @@
1
- import { Command } from "commander";
2
- import { ProviderResponseType, ServiceAgreementClient } from "@arc402/sdk";
3
- import { loadConfig } from "../config.js";
4
- import { getClient, requireSigner } from "../client.js";
5
- import { hashFile, hashString } from "../utils/hash.js";
6
- import { c } from '../ui/colors.js';
7
- import { startSpinner } from '../ui/spinner.js';
8
-
9
- export function registerRemediateCommands(program: Command): void {
10
- const remediate = program.command("remediate").description("Negotiated remediation before formal dispute");
11
- remediate.command("request <id>").requiredOption("--text <feedback>").option("--uri <uri>", "Structured feedback URI", "").option("--file <path>").option("--previous <hash>", "Previous transcript hash", "0x0000000000000000000000000000000000000000000000000000000000000000").action(async (id, opts) => {
12
- const config = loadConfig(); if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config"); const { signer } = await requireSigner(config); const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
13
- const hash = opts.file ? hashFile(opts.file) : hashString(opts.text); await client.requestRevision(BigInt(id), hash, opts.uri, opts.previous); console.log(' ' + c.success + c.white(' Revision requested — agreement #' + id));
14
- });
15
- remediate.command("respond <id>").requiredOption("--type <type>", "revise|defend|counter|partial-settlement|human-review|escalate").requiredOption("--text <response>").option("--uri <uri>", "Structured response URI", "").option("--file <path>").option("--previous <hash>", "Previous transcript hash", "0x0000000000000000000000000000000000000000000000000000000000000000").option("--provider-payout <amount>", "Wei/token units for partial settlement", "0").action(async (id, opts) => {
16
- const config = loadConfig(); if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config"); const { signer } = await requireSigner(config); const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
17
- const map: Record<string, ProviderResponseType> = { revise: ProviderResponseType.REVISE, defend: ProviderResponseType.DEFEND, counter: ProviderResponseType.COUNTER, 'partial-settlement': ProviderResponseType.PARTIAL_SETTLEMENT, 'human-review': ProviderResponseType.REQUEST_HUMAN_REVIEW, escalate: ProviderResponseType.ESCALATE };
18
- const hash = opts.file ? hashFile(opts.file) : hashString(opts.text); await client.respondToRevision(BigInt(id), map[String(opts.type)], hash, opts.uri, opts.previous, BigInt(opts.providerPayout)); console.log(' ' + c.success + c.white(' Response recorded — agreement #' + id));
19
- });
20
- remediate.command("status <id>").option("--json").action(async (id, opts) => {
21
- const config = loadConfig(); if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config"); const { provider } = await getClient(config); const client = new ServiceAgreementClient(config.serviceAgreementAddress, provider);
22
- const remediation = await client.getRemediationCase(BigInt(id)); const out = { remediation }; console.log(JSON.stringify(out, (_k, value) => typeof value === 'bigint' ? value.toString() : value, opts.json ? 2 : 2));
23
- });
24
- }