@absol-labs/agent 0.11.0 → 0.12.0-rc.2

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 (366) hide show
  1. package/README.md +43 -51
  2. package/dist/capability/invocation-capability.d.ts +2 -2
  3. package/dist/capability/probe-capability.d.ts +225 -0
  4. package/dist/capability/probe-capability.d.ts.map +1 -0
  5. package/dist/capability/probe-capability.js +248 -0
  6. package/dist/capability/probe-capability.js.map +1 -0
  7. package/dist/cli/args.d.ts +11 -0
  8. package/dist/cli/args.d.ts.map +1 -1
  9. package/dist/cli/args.js +23 -0
  10. package/dist/cli/args.js.map +1 -1
  11. package/dist/cli/commands/claim.d.ts +32 -0
  12. package/dist/cli/commands/claim.d.ts.map +1 -1
  13. package/dist/cli/commands/claim.js +116 -28
  14. package/dist/cli/commands/claim.js.map +1 -1
  15. package/dist/cli/commands/close.d.ts.map +1 -1
  16. package/dist/cli/commands/close.js +35 -3
  17. package/dist/cli/commands/close.js.map +1 -1
  18. package/dist/cli/commands/invoke.d.ts +2 -0
  19. package/dist/cli/commands/invoke.d.ts.map +1 -1
  20. package/dist/cli/commands/invoke.js +2 -2
  21. package/dist/cli/commands/invoke.js.map +1 -1
  22. package/dist/cli/commands/mcp.d.ts.map +1 -1
  23. package/dist/cli/commands/mcp.js +15 -2
  24. package/dist/cli/commands/mcp.js.map +1 -1
  25. package/dist/cli/commands/open.d.ts.map +1 -1
  26. package/dist/cli/commands/open.js +58 -4
  27. package/dist/cli/commands/open.js.map +1 -1
  28. package/dist/cli/commands/pay.d.ts +34 -0
  29. package/dist/cli/commands/pay.d.ts.map +1 -0
  30. package/dist/cli/commands/pay.js +479 -0
  31. package/dist/cli/commands/pay.js.map +1 -0
  32. package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -1
  33. package/dist/cli/commands/reclaim-unverified.js +3 -2
  34. package/dist/cli/commands/reclaim-unverified.js.map +1 -1
  35. package/dist/cli/commands/reclaim.d.ts +23 -2
  36. package/dist/cli/commands/reclaim.d.ts.map +1 -1
  37. package/dist/cli/commands/reclaim.js +204 -20
  38. package/dist/cli/commands/reclaim.js.map +1 -1
  39. package/dist/cli/commands/refund.d.ts +31 -0
  40. package/dist/cli/commands/refund.d.ts.map +1 -0
  41. package/dist/cli/commands/refund.js +397 -0
  42. package/dist/cli/commands/refund.js.map +1 -0
  43. package/dist/cli/commands/status.d.ts.map +1 -1
  44. package/dist/cli/commands/status.js +21 -2
  45. package/dist/cli/commands/status.js.map +1 -1
  46. package/dist/cli/commands/streams.js +8 -12
  47. package/dist/cli/commands/streams.js.map +1 -1
  48. package/dist/cli/commands/watch.d.ts.map +1 -1
  49. package/dist/cli/commands/watch.js +4 -1
  50. package/dist/cli/commands/watch.js.map +1 -1
  51. package/dist/cli/config.d.ts +44 -26
  52. package/dist/cli/config.d.ts.map +1 -1
  53. package/dist/cli/config.js +88 -38
  54. package/dist/cli/config.js.map +1 -1
  55. package/dist/cli/context.d.ts +19 -0
  56. package/dist/cli/context.d.ts.map +1 -1
  57. package/dist/cli/deps.d.ts +53 -0
  58. package/dist/cli/deps.d.ts.map +1 -1
  59. package/dist/cli/deps.js +51 -1
  60. package/dist/cli/deps.js.map +1 -1
  61. package/dist/cli/errors.d.ts.map +1 -1
  62. package/dist/cli/errors.js +21 -1
  63. package/dist/cli/errors.js.map +1 -1
  64. package/dist/cli/escape-hatch.d.ts +6 -4
  65. package/dist/cli/escape-hatch.d.ts.map +1 -1
  66. package/dist/cli/escape-hatch.js +6 -2
  67. package/dist/cli/escape-hatch.js.map +1 -1
  68. package/dist/cli/listings.d.ts +18 -0
  69. package/dist/cli/listings.d.ts.map +1 -1
  70. package/dist/cli/listings.js +22 -12
  71. package/dist/cli/listings.js.map +1 -1
  72. package/dist/cli/preflight.d.ts +20 -14
  73. package/dist/cli/preflight.d.ts.map +1 -1
  74. package/dist/cli/preflight.js +34 -20
  75. package/dist/cli/preflight.js.map +1 -1
  76. package/dist/cli/privy.d.ts.map +1 -1
  77. package/dist/cli/privy.js +4 -2
  78. package/dist/cli/privy.js.map +1 -1
  79. package/dist/cli/progress.d.ts +13 -1
  80. package/dist/cli/progress.d.ts.map +1 -1
  81. package/dist/cli/progress.js +7 -1
  82. package/dist/cli/progress.js.map +1 -1
  83. package/dist/cli/reclaimability.d.ts +82 -0
  84. package/dist/cli/reclaimability.d.ts.map +1 -0
  85. package/dist/cli/reclaimability.js +80 -0
  86. package/dist/cli/reclaimability.js.map +1 -0
  87. package/dist/cli/run.d.ts +2 -1
  88. package/dist/cli/run.d.ts.map +1 -1
  89. package/dist/cli/run.js +62 -21
  90. package/dist/cli/run.js.map +1 -1
  91. package/dist/cli/scan-range.d.ts +2 -2
  92. package/dist/cli/scan-range.js +2 -2
  93. package/dist/cli/status.d.ts +106 -1
  94. package/dist/cli/status.d.ts.map +1 -1
  95. package/dist/cli/status.js +325 -44
  96. package/dist/cli/status.js.map +1 -1
  97. package/dist/cli/wallet.d.ts +2 -2
  98. package/dist/cli/wallet.d.ts.map +1 -1
  99. package/dist/cli/wallet.js +29 -5
  100. package/dist/cli/wallet.js.map +1 -1
  101. package/dist/discovery/rate-band.d.ts +74 -0
  102. package/dist/discovery/rate-band.d.ts.map +1 -0
  103. package/dist/discovery/rate-band.js +114 -0
  104. package/dist/discovery/rate-band.js.map +1 -0
  105. package/dist/escrow-generation.d.ts +81 -0
  106. package/dist/escrow-generation.d.ts.map +1 -0
  107. package/dist/escrow-generation.js +76 -0
  108. package/dist/escrow-generation.js.map +1 -0
  109. package/dist/frameworks/agentkit.d.ts +8 -4
  110. package/dist/frameworks/agentkit.d.ts.map +1 -1
  111. package/dist/frameworks/agentkit.js +27 -10
  112. package/dist/frameworks/agentkit.js.map +1 -1
  113. package/dist/frameworks/eliza.d.ts +3 -3
  114. package/dist/frameworks/eliza.d.ts.map +1 -1
  115. package/dist/frameworks/eliza.js +15 -6
  116. package/dist/frameworks/eliza.js.map +1 -1
  117. package/dist/frameworks/langchain.d.ts.map +1 -1
  118. package/dist/frameworks/langchain.js +8 -0
  119. package/dist/frameworks/langchain.js.map +1 -1
  120. package/dist/gateway/caller-auth-gateway.d.ts +83 -31
  121. package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
  122. package/dist/gateway/caller-auth-gateway.js +180 -27
  123. package/dist/gateway/caller-auth-gateway.js.map +1 -1
  124. package/dist/gateway/http-server.d.ts +128 -44
  125. package/dist/gateway/http-server.d.ts.map +1 -1
  126. package/dist/gateway/http-server.js +506 -155
  127. package/dist/gateway/http-server.js.map +1 -1
  128. package/dist/gateway/probe-auth.d.ts +112 -0
  129. package/dist/gateway/probe-auth.d.ts.map +1 -0
  130. package/dist/gateway/probe-auth.js +127 -0
  131. package/dist/gateway/probe-auth.js.map +1 -0
  132. package/dist/gateway/signed-rate-bounds.d.ts +51 -0
  133. package/dist/gateway/signed-rate-bounds.d.ts.map +1 -0
  134. package/dist/gateway/signed-rate-bounds.js +94 -0
  135. package/dist/gateway/signed-rate-bounds.js.map +1 -0
  136. package/dist/gateway/x402-opener-mode.d.ts +252 -0
  137. package/dist/gateway/x402-opener-mode.d.ts.map +1 -0
  138. package/dist/gateway/x402-opener-mode.js +772 -0
  139. package/dist/gateway/x402-opener-mode.js.map +1 -0
  140. package/dist/index.d.ts +6 -2
  141. package/dist/index.d.ts.map +1 -1
  142. package/dist/index.js +10 -5
  143. package/dist/index.js.map +1 -1
  144. package/dist/mcp/server.d.ts +64 -1
  145. package/dist/mcp/server.d.ts.map +1 -1
  146. package/dist/mcp/server.js +247 -37
  147. package/dist/mcp/server.js.map +1 -1
  148. package/dist/mcp/x402-tools.d.ts +109 -0
  149. package/dist/mcp/x402-tools.d.ts.map +1 -0
  150. package/dist/mcp/x402-tools.js +554 -0
  151. package/dist/mcp/x402-tools.js.map +1 -0
  152. package/dist/network.d.ts +119 -0
  153. package/dist/network.d.ts.map +1 -0
  154. package/dist/network.js +199 -0
  155. package/dist/network.js.map +1 -0
  156. package/dist/sdk/client.d.ts +13 -0
  157. package/dist/sdk/client.d.ts.map +1 -1
  158. package/dist/sdk/client.js +15 -0
  159. package/dist/sdk/client.js.map +1 -1
  160. package/dist/sdk/invoke.d.ts +4 -0
  161. package/dist/sdk/invoke.d.ts.map +1 -1
  162. package/dist/sdk/invoke.js +2 -5
  163. package/dist/sdk/invoke.js.map +1 -1
  164. package/dist/wallet/autonomous-wallet-broker.d.ts +3 -0
  165. package/dist/wallet/autonomous-wallet-broker.d.ts.map +1 -1
  166. package/dist/wallet/autonomous-wallet-broker.js +27 -23
  167. package/dist/wallet/autonomous-wallet-broker.js.map +1 -1
  168. package/dist/wallet/autonomous-wallet-protocol.d.ts +8 -2
  169. package/dist/wallet/autonomous-wallet-protocol.d.ts.map +1 -1
  170. package/dist/wallet/autonomous-wallet-protocol.js +9 -2
  171. package/dist/wallet/autonomous-wallet-protocol.js.map +1 -1
  172. package/dist/wallet/autonomous-wallet.d.ts.map +1 -1
  173. package/dist/wallet/autonomous-wallet.js +3 -2
  174. package/dist/wallet/autonomous-wallet.js.map +1 -1
  175. package/dist/wallet/broker-escrows.d.ts +222 -0
  176. package/dist/wallet/broker-escrows.d.ts.map +1 -0
  177. package/dist/wallet/broker-escrows.js +36 -0
  178. package/dist/wallet/broker-escrows.js.map +1 -0
  179. package/dist/wallet/lifecycle.d.ts +21 -5
  180. package/dist/wallet/lifecycle.d.ts.map +1 -1
  181. package/dist/wallet/lifecycle.js +32 -12
  182. package/dist/wallet/lifecycle.js.map +1 -1
  183. package/dist/wallet/privy-broker-server.d.ts.map +1 -1
  184. package/dist/wallet/privy-broker-server.js +31 -26
  185. package/dist/wallet/privy-broker-server.js.map +1 -1
  186. package/dist/wallet/privy-session-broker.d.ts +14 -5
  187. package/dist/wallet/privy-session-broker.d.ts.map +1 -1
  188. package/dist/wallet/privy-session-broker.js +29 -17
  189. package/dist/wallet/privy-session-broker.js.map +1 -1
  190. package/dist/wallet/privy-session-provider.d.ts +3 -1
  191. package/dist/wallet/privy-session-provider.d.ts.map +1 -1
  192. package/dist/wallet/privy-session-provider.js +5 -3
  193. package/dist/wallet/privy-session-provider.js.map +1 -1
  194. package/dist/wallet/provider.d.ts.map +1 -1
  195. package/dist/wallet/provider.js +15 -8
  196. package/dist/wallet/provider.js.map +1 -1
  197. package/dist/x402/facilitator.d.ts +3 -30
  198. package/dist/x402/facilitator.d.ts.map +1 -1
  199. package/dist/x402/facilitator.js +0 -27
  200. package/dist/x402/facilitator.js.map +1 -1
  201. package/dist/x402-buyer/guarded-fetch.d.ts +51 -0
  202. package/dist/x402-buyer/guarded-fetch.d.ts.map +1 -0
  203. package/dist/x402-buyer/guarded-fetch.js +147 -0
  204. package/dist/x402-buyer/guarded-fetch.js.map +1 -0
  205. package/dist/x402-buyer/index.d.ts +10 -0
  206. package/dist/x402-buyer/index.d.ts.map +1 -0
  207. package/dist/x402-buyer/index.js +10 -0
  208. package/dist/x402-buyer/index.js.map +1 -0
  209. package/dist/x402-buyer/pay.d.ts +157 -0
  210. package/dist/x402-buyer/pay.d.ts.map +1 -0
  211. package/dist/x402-buyer/pay.js +366 -0
  212. package/dist/x402-buyer/pay.js.map +1 -0
  213. package/dist/x402-opener/abi.d.ts +684 -0
  214. package/dist/x402-opener/abi.d.ts.map +1 -0
  215. package/dist/x402-opener/abi.js +880 -0
  216. package/dist/x402-opener/abi.js.map +1 -0
  217. package/dist/x402-opener/facilitator-entry.d.ts +3 -0
  218. package/dist/x402-opener/facilitator-entry.d.ts.map +1 -0
  219. package/dist/x402-opener/facilitator-entry.js +40 -0
  220. package/dist/x402-opener/facilitator-entry.js.map +1 -0
  221. package/dist/x402-opener/facilitator-server.d.ts +209 -0
  222. package/dist/x402-opener/facilitator-server.d.ts.map +1 -0
  223. package/dist/x402-opener/facilitator-server.js +762 -0
  224. package/dist/x402-opener/facilitator-server.js.map +1 -0
  225. package/dist/x402-opener/index.d.ts +14 -0
  226. package/dist/x402-opener/index.d.ts.map +1 -0
  227. package/dist/x402-opener/index.js +14 -0
  228. package/dist/x402-opener/index.js.map +1 -0
  229. package/dist/x402-opener/listing-resolver.d.ts +55 -0
  230. package/dist/x402-opener/listing-resolver.d.ts.map +1 -0
  231. package/dist/x402-opener/listing-resolver.js +125 -0
  232. package/dist/x402-opener/listing-resolver.js.map +1 -0
  233. package/dist/x402-opener/refund-relay.d.ts +266 -0
  234. package/dist/x402-opener/refund-relay.d.ts.map +1 -0
  235. package/dist/x402-opener/refund-relay.js +1341 -0
  236. package/dist/x402-opener/refund-relay.js.map +1 -0
  237. package/dist/x402-opener/relayer-queue.d.ts +14 -0
  238. package/dist/x402-opener/relayer-queue.d.ts.map +1 -0
  239. package/dist/x402-opener/relayer-queue.js +18 -0
  240. package/dist/x402-opener/relayer-queue.js.map +1 -0
  241. package/dist/x402-opener/scheme.d.ts +296 -0
  242. package/dist/x402-opener/scheme.d.ts.map +1 -0
  243. package/dist/x402-opener/scheme.js +1035 -0
  244. package/dist/x402-opener/scheme.js.map +1 -0
  245. package/dist/x402-opener/terms.d.ts +165 -0
  246. package/dist/x402-opener/terms.d.ts.map +1 -0
  247. package/dist/x402-opener/terms.js +304 -0
  248. package/dist/x402-opener/terms.js.map +1 -0
  249. package/dist/zktls/reclaim.d.ts +2 -2
  250. package/dist/zktls/t2-delivery-proof.d.ts +6 -6
  251. package/docs/agent-layer.md +3 -2
  252. package/docs/autonomous-privy-wallet.md +188 -0
  253. package/docs/cli.md +265 -34
  254. package/docs/langchain.md +5 -0
  255. package/docs/mcp-reference.md +91 -5
  256. package/docs/probe-capability.md +191 -0
  257. package/docs/quickstart.md +39 -4
  258. package/docs/threat-model.md +20 -0
  259. package/docs/x402.md +766 -593
  260. package/package.json +19 -17
  261. package/src/capability/probe-capability.ts +355 -0
  262. package/src/cli/args.ts +29 -0
  263. package/src/cli/commands/claim.ts +168 -33
  264. package/src/cli/commands/close.ts +36 -3
  265. package/src/cli/commands/invoke.ts +5 -2
  266. package/src/cli/commands/mcp.ts +18 -2
  267. package/src/cli/commands/open.ts +75 -4
  268. package/src/cli/commands/pay.ts +584 -0
  269. package/src/cli/commands/reclaim-unverified.ts +8 -2
  270. package/src/cli/commands/reclaim.ts +277 -19
  271. package/src/cli/commands/refund.ts +475 -0
  272. package/src/cli/commands/status.ts +28 -2
  273. package/src/cli/commands/streams.ts +10 -14
  274. package/src/cli/commands/watch.ts +11 -1
  275. package/src/cli/config.ts +139 -52
  276. package/src/cli/context.ts +16 -0
  277. package/src/cli/deps.ts +111 -1
  278. package/src/cli/errors.ts +24 -1
  279. package/src/cli/escape-hatch.ts +19 -5
  280. package/src/cli/listings.ts +43 -10
  281. package/src/cli/preflight.ts +36 -21
  282. package/src/cli/privy.ts +4 -2
  283. package/src/cli/progress.ts +21 -2
  284. package/src/cli/reclaimability.ts +154 -0
  285. package/src/cli/run.ts +77 -21
  286. package/src/cli/scan-range.ts +2 -2
  287. package/src/cli/status.ts +454 -44
  288. package/src/cli/wallet.ts +45 -8
  289. package/src/discovery/rate-band.ts +172 -0
  290. package/src/escrow-generation.ts +135 -0
  291. package/src/frameworks/agentkit.ts +45 -11
  292. package/src/frameworks/eliza.ts +27 -5
  293. package/src/frameworks/langchain.ts +14 -0
  294. package/src/gateway/caller-auth-gateway.ts +320 -68
  295. package/src/gateway/http-server.ts +717 -220
  296. package/src/gateway/probe-auth.ts +191 -0
  297. package/src/gateway/signed-rate-bounds.ts +164 -0
  298. package/src/gateway/x402-opener-mode.ts +1171 -0
  299. package/src/index.ts +82 -19
  300. package/src/mcp/server.ts +351 -42
  301. package/src/mcp/x402-tools.ts +785 -0
  302. package/src/network.ts +302 -0
  303. package/src/sdk/client.ts +25 -0
  304. package/src/sdk/invoke.ts +6 -5
  305. package/src/wallet/autonomous-wallet-broker.ts +46 -20
  306. package/src/wallet/autonomous-wallet-protocol.ts +11 -2
  307. package/src/wallet/autonomous-wallet.ts +4 -2
  308. package/src/wallet/broker-escrows.ts +66 -0
  309. package/src/wallet/lifecycle.ts +53 -18
  310. package/src/wallet/privy-broker-server.ts +35 -25
  311. package/src/wallet/privy-session-broker.ts +58 -25
  312. package/src/wallet/privy-session-provider.ts +7 -3
  313. package/src/wallet/provider.ts +20 -15
  314. package/src/x402/facilitator.ts +3 -43
  315. package/src/x402-buyer/guarded-fetch.ts +213 -0
  316. package/src/x402-buyer/index.ts +9 -0
  317. package/src/x402-buyer/pay.ts +555 -0
  318. package/src/x402-opener/abi.ts +881 -0
  319. package/src/x402-opener/facilitator-entry.ts +48 -0
  320. package/src/x402-opener/facilitator-server.ts +1114 -0
  321. package/src/x402-opener/index.ts +13 -0
  322. package/src/x402-opener/listing-resolver.ts +202 -0
  323. package/src/x402-opener/refund-relay.ts +1873 -0
  324. package/src/x402-opener/relayer-queue.ts +18 -0
  325. package/src/x402-opener/scheme.ts +1551 -0
  326. package/src/x402-opener/terms.ts +453 -0
  327. package/dist/gateway/x402-mode.d.ts +0 -123
  328. package/dist/gateway/x402-mode.d.ts.map +0 -1
  329. package/dist/gateway/x402-mode.js +0 -212
  330. package/dist/gateway/x402-mode.js.map +0 -1
  331. package/dist/x402/delivery-oracle.d.ts +0 -108
  332. package/dist/x402/delivery-oracle.d.ts.map +0 -1
  333. package/dist/x402/delivery-oracle.js +0 -174
  334. package/dist/x402/delivery-oracle.js.map +0 -1
  335. package/dist/x402/facilitator-server-entry.d.ts +0 -3
  336. package/dist/x402/facilitator-server-entry.d.ts.map +0 -1
  337. package/dist/x402/facilitator-server-entry.js +0 -27
  338. package/dist/x402/facilitator-server-entry.js.map +0 -1
  339. package/dist/x402/facilitator-server.d.ts +0 -73
  340. package/dist/x402/facilitator-server.d.ts.map +0 -1
  341. package/dist/x402/facilitator-server.js +0 -305
  342. package/dist/x402/facilitator-server.js.map +0 -1
  343. package/dist/x402/payment-requirements.d.ts +0 -106
  344. package/dist/x402/payment-requirements.d.ts.map +0 -1
  345. package/dist/x402/payment-requirements.js +0 -138
  346. package/dist/x402/payment-requirements.js.map +0 -1
  347. package/dist/x402/relayer.d.ts +0 -41
  348. package/dist/x402/relayer.d.ts.map +0 -1
  349. package/dist/x402/relayer.js +0 -64
  350. package/dist/x402/relayer.js.map +0 -1
  351. package/dist/x402/resource-index.d.ts +0 -75
  352. package/dist/x402/resource-index.d.ts.map +0 -1
  353. package/dist/x402/resource-index.js +0 -126
  354. package/dist/x402/resource-index.js.map +0 -1
  355. package/dist/x402/verified-delivery-facilitator.d.ts +0 -285
  356. package/dist/x402/verified-delivery-facilitator.d.ts.map +0 -1
  357. package/dist/x402/verified-delivery-facilitator.js +0 -423
  358. package/dist/x402/verified-delivery-facilitator.js.map +0 -1
  359. package/src/gateway/x402-mode.ts +0 -350
  360. package/src/x402/delivery-oracle.ts +0 -285
  361. package/src/x402/facilitator-server-entry.ts +0 -35
  362. package/src/x402/facilitator-server.ts +0 -445
  363. package/src/x402/payment-requirements.ts +0 -231
  364. package/src/x402/relayer.ts +0 -122
  365. package/src/x402/resource-index.ts +0 -228
  366. package/src/x402/verified-delivery-facilitator.ts +0 -744
@@ -1,14 +1,10 @@
1
+ import type { MetrikNetwork } from "@absol-labs/sdk";
2
+
3
+ import { gasFundingHint, usdcFundingHint } from "../network.js";
1
4
  import { formatUsdc } from "./amounts.js";
2
5
  import { CliError } from "./errors.js";
3
6
  import type { CliReadClient } from "./deps.js";
4
7
 
5
- /** Where a Base Sepolia test wallet gets its gas. */
6
- export const BASE_SEPOLIA_FAUCET_URL =
7
- "https://www.alchemy.com/faucets/base-sepolia";
8
-
9
- /** Where a Base Sepolia test wallet gets the USDC it escrows. */
10
- export const CIRCLE_USDC_FAUCET_URL = "https://faucet.circle.com";
11
-
12
8
  /**
13
9
  * Refuse to broadcast from a wallet that cannot pay for gas.
14
10
  *
@@ -16,20 +12,29 @@ export const CIRCLE_USDC_FAUCET_URL = "https://faucet.circle.com";
16
12
  * phrasing — `USDC approve transaction failed: Execution reverted with reason:
17
13
  * gas required exceeds allowance (0)` — which reads like a USDC allowance
18
14
  * problem and sends the reader looking at approvals. The actual fact is "this
19
- * address holds no ETH", and it is knowable with one read before anything is
15
+ * address holds no gas", and it is knowable with one read before anything is
20
16
  * signed.
21
17
  *
18
+ * The gas token is read from the network's registry metadata, never assumed to
19
+ * be ETH. Where gas IS the settlement token (`gasToken.isSettlementToken`),
20
+ * there is only one balance: the USDC balance is the gas balance, so that is
21
+ * the one read.
22
+ *
22
23
  * Deliberately only a ZERO check, not an estimate: predicting the gas a hire
23
- * will cost means simulating it, and a wallet with a little ETH that still runs
24
+ * will cost means simulating it, and a wallet with a little gas that still runs
24
25
  * short should get the real revert rather than a guess from this CLI.
25
26
  */
26
27
  export async function assertCanPayGas(
27
28
  read: CliReadClient,
28
29
  address: `0x${string}`,
30
+ network: MetrikNetwork,
29
31
  ): Promise<void> {
32
+ const gasIsUsdc = network.gasToken.isSettlementToken;
30
33
  let balance: bigint;
31
34
  try {
32
- balance = await read.nativeBalance(address);
35
+ balance = gasIsUsdc
36
+ ? await read.usdcBalance(address)
37
+ : await read.nativeBalance(address);
33
38
  } catch {
34
39
  // A balance read is a courtesy, not a gate. If the RPC will not answer it,
35
40
  // let the command proceed and fail with the real error.
@@ -38,10 +43,12 @@ export async function assertCanPayGas(
38
43
  if (balance > 0n) return;
39
44
 
40
45
  throw new CliError(
41
- `wallet ${address} has 0 ETH on Base Sepolia, so it cannot pay for gas`,
46
+ `wallet ${address} has 0 ${network.gasToken.symbol} on ${network.name}, so it cannot pay for gas`,
42
47
  {
43
48
  exitCode: 3,
44
- hint: `fund it at ${BASE_SEPOLIA_FAUCET_URL}, then re-run. (Gas is ETH; the stream itself is escrowed in USDC, which is a separate balance.)`,
49
+ hint: gasIsUsdc
50
+ ? `${gasFundingHint(network)}, then re-run. (On ${network.name} gas is paid in USDC, the same balance a stream is escrowed from.)`
51
+ : `${gasFundingHint(network)}, then re-run. (Gas is ${network.gasToken.symbol}; the stream itself is escrowed in USDC, which is a separate balance.)`,
45
52
  },
46
53
  );
47
54
  }
@@ -49,12 +56,16 @@ export async function assertCanPayGas(
49
56
  /**
50
57
  * Refuse to broadcast a hire the wallet cannot fund.
51
58
  *
52
- * The sibling of `assertCanPayGas`, for the OTHER balance. Gas is ETH and the
53
- * deposit is USDC: they are separate balances on separate tokens, so a wallet
54
- * that passes the gas check can still hold no USDC at all. Without this the
55
- * `open` path sends the USDC approval FIRST — which succeeds, because approving
56
- * an amount you do not hold is legal — and then reverts inside `transferFrom`,
57
- * having already spent gas to learn something that was one `balanceOf` away.
59
+ * The sibling of `assertCanPayGas`, for the OTHER balance. On a network whose
60
+ * gas token is not USDC, gas and deposit are separate balances on separate
61
+ * tokens, so a wallet that passes the gas check can still hold no USDC at all.
62
+ * Without this the `open` path sends the USDC approval FIRST — which succeeds,
63
+ * because approving an amount you do not hold is legal — and then reverts
64
+ * inside `transferFrom`, having already spent gas to learn something that was
65
+ * one `balanceOf` away.
66
+ *
67
+ * Where gas IS USDC there is one balance, and it must cover the deposit AND
68
+ * leave something for gas, so the check is strict (`balance > budget`).
58
69
  *
59
70
  * Deliberately NOT an allowance check. The CLI's own open path grants the
60
71
  * bounded approval it needs (`approveTxHash` in the result), so a missing
@@ -66,7 +77,9 @@ export async function assertCanFundStream(
66
77
  read: CliReadClient,
67
78
  address: `0x${string}`,
68
79
  budgetUsdc: bigint,
80
+ network: MetrikNetwork,
69
81
  ): Promise<void> {
82
+ const gasIsUsdc = network.gasToken.isSettlementToken;
70
83
  let balance: bigint;
71
84
  try {
72
85
  balance = await read.usdcBalance(address);
@@ -76,13 +89,15 @@ export async function assertCanFundStream(
76
89
  // the real error surface.
77
90
  return;
78
91
  }
79
- if (balance >= budgetUsdc) return;
92
+ if (gasIsUsdc ? balance > budgetUsdc : balance >= budgetUsdc) return;
80
93
 
81
94
  throw new CliError(
82
- `wallet ${address} holds ${formatUsdc(balance)} but --budget is ${formatUsdc(budgetUsdc)}`,
95
+ `wallet ${address} holds ${formatUsdc(balance)} but --budget is ${formatUsdc(budgetUsdc)}${gasIsUsdc ? " (plus gas, which is also USDC here)" : ""}`,
83
96
  {
84
97
  exitCode: 3,
85
- hint: `the deposit is escrowed in USDC — fund the wallet at ${CIRCLE_USDC_FAUCET_URL} (Base Sepolia), then re-run. (Gas is a separate ETH balance.)`,
98
+ hint: gasIsUsdc
99
+ ? `the deposit and the gas are both USDC on ${network.name} — ${usdcFundingHint(network)}, then re-run.`
100
+ : `the deposit is escrowed in USDC — ${usdcFundingHint(network)}, then re-run. (Gas is a separate ${network.gasToken.symbol} balance.)`,
86
101
  },
87
102
  );
88
103
  }
package/src/cli/privy.ts CHANGED
@@ -18,6 +18,8 @@ import {
18
18
  type AutonomousWalletRecord,
19
19
  } from "../wallet/autonomous-wallet.js";
20
20
  import { createPrivySessionProvider } from "../wallet/privy-session-provider.js";
21
+ import { PRIVY_BROKER_CHAIN_ID } from "../wallet/privy-session-broker.js";
22
+ import { defaultNetwork } from "../network.js";
21
23
  import {
22
24
  createPrivyEmbeddedAccount,
23
25
  type PrivyEip1193Provider,
@@ -357,12 +359,12 @@ async function embeddedAccount(
357
359
  appId,
358
360
  address,
359
361
  provider,
360
- chainId: 84532,
362
+ chainId: PRIVY_BROKER_CHAIN_ID,
361
363
  });
362
364
  } catch (error) {
363
365
  throw configError(
364
366
  `the Privy wallet could not be prepared: ${describe(error)}`,
365
- `check ${PRIVY_ENV_VARS.join(", ")}. Metrik Privy wallets are Base Sepolia (84532) only.`,
367
+ `check ${PRIVY_ENV_VARS.join(", ")}. Metrik Privy wallets are on the broker's network only (${defaultNetwork().name}, chain ${PRIVY_BROKER_CHAIN_ID}).`,
366
368
  );
367
369
  }
368
370
  }
@@ -12,11 +12,24 @@
12
12
  * "stuck". stderr in BOTH modes, so `--json` stdout stays a single parseable
13
13
  * document.
14
14
  */
15
- export interface Heartbeat {
15
+ export interface Heartbeat extends ProgressActivity {
16
16
  /** Stops the ticker. Safe to call more than once. */
17
17
  readonly stop: () => void;
18
18
  }
19
19
 
20
+ /**
21
+ * What a command tells the heartbeat while it waits ON PURPOSE.
22
+ *
23
+ * A tick that says "slow RPC, not a hang" is wrong while the command is in a
24
+ * retry or poll it already announced (`reclaim` waiting for a checkpoint,
25
+ * `attempt 3/12`; `refund` letting the relay's settlement window close): then
26
+ * the honest line is "waiting for X (attempt n/N)", not a guess about a slow
27
+ * endpoint. `null` returns the tick to the generic wording.
28
+ */
29
+ export interface ProgressActivity {
30
+ readonly setActivity: (activity: string | null) => void;
31
+ }
32
+
20
33
  /** Silence before the first tick — below this, a command is simply fast. */
21
34
  export const HEARTBEAT_DELAY_MS = 8_000;
22
35
  /** Gap between ticks once it has started. */
@@ -49,12 +62,15 @@ export function startHeartbeat(
49
62
  const startedAt = now();
50
63
  let timer: ReturnType<typeof setTimeout> | undefined;
51
64
  let stopped = false;
65
+ let activity: string | null = null;
52
66
 
53
67
  const tick = (): void => {
54
68
  if (stopped) return;
55
69
  const elapsed = Math.round((now() - startedAt) / 1000);
56
70
  note(
57
- `… still working: ${label} (${elapsed}s elapsed). Slow RPC or oracle, not a hang — nothing is retried silently.`,
71
+ activity === null
72
+ ? `… still working: ${label} (${elapsed}s elapsed). Slow RPC or oracle, not a hang.`
73
+ : `… still working: ${label} (${elapsed}s elapsed) — ${activity}. This is the announced wait, not a hang.`,
58
74
  );
59
75
  schedule(intervalMs);
60
76
  };
@@ -66,6 +82,9 @@ export function startHeartbeat(
66
82
  schedule(delayMs);
67
83
 
68
84
  return {
85
+ setActivity(next) {
86
+ activity = next;
87
+ },
69
88
  stop() {
70
89
  stopped = true;
71
90
  if (timer !== undefined) clearTimer(timer);
@@ -0,0 +1,154 @@
1
+ import type { StreamV2 } from "@absol-labs/sdk";
2
+
3
+ import { formatDuration } from "./amounts.js";
4
+ import { formatTimestamp, readChainNow } from "./escape-hatch.js";
5
+ import { settlementCoverage } from "./status.js";
6
+ import type { CliReadClient } from "./deps.js";
7
+
8
+ /**
9
+ * Why a proof-based reclaim cannot go through right now, read from chain state
10
+ * rather than decoded out of a revert.
11
+ *
12
+ * `metrik reclaim` used to learn this only by sending the simulation and
13
+ * reading what came back. That works exactly as well as the endpoint's revert
14
+ * data does, and on the public Base Sepolia RPC it frequently does not work at
15
+ * all: an already-reclaimed stream, a stream that is still running, and a
16
+ * stream whose stop time is not checkpointed yet ALL came back as
17
+ *
18
+ * reclaim simulation failed: Execution reverted for an unknown reason.
19
+ *
20
+ * Three different situations, three completely different next actions — you
21
+ * already have the money / close it first / wait ~20 seconds — and one message
22
+ * that distinguishes none of them. Worse, the retry loop keys off the same
23
+ * undecoded revert, so the wait that this command advertises never engaged.
24
+ *
25
+ * Every one of these conditions is a pure function of state the CLI already
26
+ * reads elsewhere (`getStreamV2`, `latestCheckpointCheckedAt`, the chain clock,
27
+ * and {@link settlementCoverage}, which `metrik status` has always used to
28
+ * decide the same question). So the condition is named from that state, before
29
+ * a transaction is built, the way `reclaim-unverified` has always named
30
+ * "already reclaimed". No revert data required.
31
+ */
32
+ export type ReclaimBlocker =
33
+ /** `AlreadyReclaimed()` / `NothingToReclaim()`: the money is already back. */
34
+ | { readonly kind: "reclaimed" }
35
+ /** `StreamNotReclaimable()`: neither closed nor expired, so the clock runs. */
36
+ | {
37
+ readonly kind: "running";
38
+ readonly expiresAt: number;
39
+ readonly secondsRemaining: number;
40
+ }
41
+ /**
42
+ * `SettlementWindowOpen()`: the stream has stopped but no checkpoint reaches
43
+ * its stop time yet. The ONLY one of the three that is a wait rather than a
44
+ * refusal — the oracle publishes roughly every 15-22s.
45
+ */
46
+ | {
47
+ readonly kind: "awaiting-checkpoint";
48
+ readonly stopAt: number;
49
+ readonly coveredUpTo: number | null;
50
+ };
51
+
52
+ /**
53
+ * The blocker implied by this state, or `null` when nothing in the state blocks
54
+ * a reclaim. Pure, so every branch is testable without an RPC — the same reason
55
+ * {@link settlementCoverage} is.
56
+ *
57
+ * Order matters and follows the escrow: a reclaimed stream is terminal, a
58
+ * running stream cannot be reclaimed at any settlement state, and only then
59
+ * does checkpoint coverage decide.
60
+ */
61
+ export function classifyReclaimBlocker(
62
+ stream: Pick<StreamV2, "status" | "closedAt" | "expiresAt" | "reclaimed">,
63
+ latestCheckpointCheckedAt: number | null,
64
+ nowSeconds: number,
65
+ ): ReclaimBlocker | null {
66
+ if (stream.reclaimed) return { kind: "reclaimed" };
67
+ if (stream.status !== "closed" && nowSeconds < stream.expiresAt) {
68
+ return {
69
+ kind: "running",
70
+ expiresAt: stream.expiresAt,
71
+ secondsRemaining: stream.expiresAt - nowSeconds,
72
+ };
73
+ }
74
+ const coverage = settlementCoverage(
75
+ stream,
76
+ latestCheckpointCheckedAt,
77
+ nowSeconds,
78
+ );
79
+ if (coverage.pending && coverage.stopAt !== null) {
80
+ return {
81
+ kind: "awaiting-checkpoint",
82
+ stopAt: coverage.stopAt,
83
+ coveredUpTo: coverage.coveredUpTo,
84
+ };
85
+ }
86
+ return null;
87
+ }
88
+
89
+ /**
90
+ * Read the state the classifier needs and name the blocker.
91
+ *
92
+ * **Fails open.** A read that does not answer returns `null` — "nothing known
93
+ * to block this" — never a refusal. Refusing to return a buyer's money because
94
+ * a load-balanced endpoint would not answer a view call is the one outcome this
95
+ * command must never produce; the transaction itself remains the authority.
96
+ */
97
+ export async function readReclaimBlocker(
98
+ read: Pick<
99
+ CliReadClient,
100
+ "getStreamV2" | "latestCheckpointCheckedAt" | "latestBlockTimestamp"
101
+ >,
102
+ streamId: `0x${string}`,
103
+ fallbackNowSeconds: number,
104
+ ): Promise<ReclaimBlocker | null> {
105
+ const stream = await read.getStreamV2(streamId).catch(() => null);
106
+ if (stream === null) return null;
107
+ const now = await readChainNow(read, fallbackNowSeconds);
108
+ const latestCheckpointCheckedAt = await read
109
+ .latestCheckpointCheckedAt()
110
+ .catch(() => null);
111
+ return classifyReclaimBlocker(stream, latestCheckpointCheckedAt, now.seconds);
112
+ }
113
+
114
+ /**
115
+ * The refusal for a blocker that will not clear on its own, as message + hint.
116
+ *
117
+ * `awaiting-checkpoint` has no entry here on purpose: it clears by itself, so
118
+ * it is narrated by {@link describeAwaitingCheckpoint} and waited out, never
119
+ * raised as an error.
120
+ */
121
+ export function describeTerminalBlocker(
122
+ blocker: ReclaimBlocker,
123
+ streamId: `0x${string}`,
124
+ ): { readonly message: string; readonly hint: string } | null {
125
+ if (blocker.kind === "reclaimed") {
126
+ return {
127
+ message:
128
+ "this stream has already been reclaimed — there is nothing left to take back",
129
+ hint: `check where it went: metrik status ${streamId}`,
130
+ };
131
+ }
132
+ if (blocker.kind === "running") {
133
+ return {
134
+ message: `the stream is still running, so there is nothing to reclaim yet — the meter stops at ${formatTimestamp(
135
+ blocker.expiresAt,
136
+ )}, in ${formatDuration(blocker.secondsRemaining)}`,
137
+ hint: `stop the clock first — \`metrik close ${streamId}\`, or re-run this command with --close-first — or wait for it to expire. (If you closed it moments ago, the RPC endpoint may not have caught up yet: re-run this command.)`,
138
+ };
139
+ }
140
+ return null;
141
+ }
142
+
143
+ /** The wait, named: what stopped, how far the oracle has published. */
144
+ export function describeAwaitingCheckpoint(
145
+ blocker: Extract<ReclaimBlocker, { kind: "awaiting-checkpoint" }>,
146
+ ): string {
147
+ const covered =
148
+ blocker.coveredUpTo === null
149
+ ? "how far the oracle has published could not be read"
150
+ : `the oracle has published only to ${formatTimestamp(blocker.coveredUpTo)}`;
151
+ return `the stream stopped at ${formatTimestamp(
152
+ blocker.stopAt,
153
+ )} and ${covered}. Reclaim reverts until a checkpoint reaches the stop time — the oracle publishes roughly every 15-22s, so this waits.`;
154
+ }
package/src/cli/run.ts CHANGED
@@ -1,16 +1,28 @@
1
- import { assertKnownFlags, booleanFlag, parseArgs } from "./args.js";
1
+ import {
2
+ JSON_BODY_COMMANDS,
3
+ assertKnownFlags,
4
+ booleanFlag,
5
+ jsonOutputRequested,
6
+ parseArgs,
7
+ } from "./args.js";
2
8
  import {
3
9
  CONFIG_FLAGS,
4
10
  GLOBAL_FLAGS,
5
- TESTNET_CHAIN_IDS,
11
+ CLI_NETWORK_POLICY,
6
12
  resolveConfig,
7
13
  } from "./config.js";
14
+ import { describeAllowedNetworks } from "../network.js";
8
15
  import { CliError, describeError, usageError } from "./errors.js";
9
16
  import { createPrinter, type CliStreams } from "./output.js";
10
17
  import { startHeartbeat } from "./progress.js";
11
18
  import { defaultCliDependencies, type CliDependencies } from "./deps.js";
12
19
  import { packageVersion } from "./version.js";
13
- import { CDP_ENV_VARS, PRIVATE_KEY_ENV } from "./wallet.js";
20
+ import {
21
+ CDP_ENV_VARS,
22
+ PRIVATE_KEY_ENV,
23
+ PRIVY_SESSION_ENV_VARS,
24
+ PRIVY_WALLET_KEY_ENV,
25
+ } from "./wallet.js";
14
26
  import type { CommandSpec } from "./context.js";
15
27
 
16
28
  import { claimCommand } from "./commands/claim.js";
@@ -19,15 +31,39 @@ import { discoverCommand } from "./commands/discover.js";
19
31
  import { invokeCommand } from "./commands/invoke.js";
20
32
  import { mcpCommand } from "./commands/mcp.js";
21
33
  import { openCommand } from "./commands/open.js";
34
+ import { payCommand } from "./commands/pay.js";
22
35
  import { reclaimCommand } from "./commands/reclaim.js";
36
+ import { refundCommand } from "./commands/refund.js";
23
37
  import { reclaimUnverifiedCommand } from "./commands/reclaim-unverified.js";
24
38
  import { statusCommand } from "./commands/status.js";
25
39
  import { streamsCommand } from "./commands/streams.js";
26
40
  import { watchCommand } from "./commands/watch.js";
27
41
 
42
+ /**
43
+ * Every wallet source, named in the order they are resolved. Privy shipped in
44
+ * 0.11.0 as resolution step 3 and worked, but appeared in no user-facing text
45
+ * at all — so the only way to learn the CLI could use it was to read the
46
+ * source or the docs. An external reviewer running the published package
47
+ * concluded it did not exist.
48
+ */
49
+ const WALLET_SOURCES =
50
+ `${PRIVATE_KEY_ENV}, ${CDP_ENV_VARS.join(" + ")}, ` +
51
+ `or ${PRIVY_WALLET_KEY_ENV} (Privy; or a broker session via ${PRIVY_SESSION_ENV_VARS.join(" + ")}).`;
52
+
53
+ /**
54
+ * Said in the help, not only discovered at runtime. `claim` is the OPERATOR's
55
+ * side and a Privy broker policy allowlists BUYER actions only, so a Privy
56
+ * wallet cannot sign one — the broker refuses, and the client cannot raise its
57
+ * own ceiling. The command already warns when it runs; someone choosing a
58
+ * wallet needs it before that.
59
+ */
60
+ const PRIVY_CLAIM_NOTE =
61
+ "`metrik claim` does NOT work on a Privy wallet: the broker's transaction allowlist is buyer-only. Claim with the operator's own key.";
62
+
28
63
  /**
29
64
  * The command surface, in the order the product loop runs:
30
- * discover -> open -> invoke -> watch/status -> close -> reclaim, then the
65
+ * discover -> open (or pay, over x402) -> invoke -> watch/status -> close ->
66
+ * reclaim (or refund, through an x402 seller's gasless relay), then the
31
67
  * operator's own redemption (`claim`) and the buyer's last-resort exit
32
68
  * (`reclaim-unverified`). `streams` (which of them are mine?) sits inside that
33
69
  * loop; `mcp` (run the same loop from an MCP host) sits after it.
@@ -35,12 +71,14 @@ import { watchCommand } from "./commands/watch.js";
35
71
  export const COMMANDS: readonly CommandSpec[] = [
36
72
  discoverCommand,
37
73
  openCommand,
74
+ payCommand,
38
75
  statusCommand,
39
76
  streamsCommand,
40
77
  watchCommand,
41
78
  invokeCommand,
42
79
  closeCommand,
43
80
  reclaimCommand,
81
+ refundCommand,
44
82
  reclaimUnverifiedCommand,
45
83
  claimCommand,
46
84
  mcpCommand,
@@ -69,7 +107,7 @@ export async function runCli(options: RunCliOptions): Promise<number> {
69
107
  let json = false;
70
108
  try {
71
109
  const args = parseArgs(options.argv);
72
- json = booleanFlag(args, "json");
110
+ json = jsonOutputRequested(args);
73
111
  const out = createPrinter(streams, json);
74
112
 
75
113
  // `--version` is checked before the bare-invocation help branch: `metrik
@@ -110,7 +148,14 @@ export async function runCli(options: RunCliOptions): Promise<number> {
110
148
  // exception is a rule someone forgets to apply to the next command.
111
149
  const heartbeat = startHeartbeat(out.note, `metrik ${command.name}`);
112
150
  try {
113
- await command.run({ args, config, env, out, deps });
151
+ await command.run({
152
+ args,
153
+ config,
154
+ env,
155
+ out,
156
+ deps,
157
+ progress: heartbeat,
158
+ });
114
159
  } finally {
115
160
  heartbeat.stop();
116
161
  }
@@ -154,20 +199,25 @@ export function renderHelp(commandName?: string): string {
154
199
  "",
155
200
  command.flags.length === 0
156
201
  ? "Command flags: (none)"
157
- : `Command flags: ${command.flags.map((flag) => `--${flag}`).join(" ")}`,
202
+ : `Command flags: ${command.flags.map((flag) => command.flagHelp?.[flag] ?? `--${flag}`).join(" ")}`,
158
203
  `Settlement flags: ${CONFIG_FLAGS.map((flag) => `--${flag}`).join(" ")}`,
159
- "Output flags: --json",
160
- ...(command.signs
161
- ? [
162
- "",
163
- `Broadcasts a transaction. Requires a wallet in the environment: ${PRIVATE_KEY_ENV}, or ${CDP_ENV_VARS.join(" + ")}.`,
164
- ]
165
- : command.requiresKey === true
204
+ JSON_BODY_COMMANDS.has(command.name)
205
+ ? "Output flags: --json (bare, with no body; combinable with --json <body>)"
206
+ : "Output flags: --json",
207
+ ...(command.walletHelp !== undefined
208
+ ? ["", command.walletHelp.text]
209
+ : command.signs
166
210
  ? [
167
211
  "",
168
- `Broadcasts nothing, but signs an off-chain EIP-712 capability, so it requires a wallet in the environment: ${PRIVATE_KEY_ENV}, or ${CDP_ENV_VARS.join(" + ")}.`,
212
+ `Broadcasts a transaction. Requires a wallet in the environment: ${WALLET_SOURCES}`,
213
+ ...(command.name === "claim" ? [PRIVY_CLAIM_NOTE] : []),
169
214
  ]
170
- : []),
215
+ : command.requiresKey === true
216
+ ? [
217
+ "",
218
+ `Broadcasts nothing, but signs an off-chain EIP-712 capability, so it requires a wallet in the environment: ${WALLET_SOURCES}`,
219
+ ]
220
+ : []),
171
221
  ].join("\n");
172
222
  }
173
223
 
@@ -187,23 +237,29 @@ export function renderHelp(commandName?: string): string {
187
237
  "Commands:",
188
238
  ...COMMANDS.map(
189
239
  (spec) =>
190
- ` ${spec.name.padEnd(width)} ${spec.summary}${spec.signs ? " [broadcasts a tx]" : spec.requiresKey === true ? " [needs a key]" : ""}`,
240
+ ` ${spec.name.padEnd(width)} ${spec.summary}${spec.walletHelp !== undefined ? ` ${spec.walletHelp.tag}` : spec.signs ? " [broadcasts a tx]" : spec.requiresKey === true ? " [needs a key]" : ""}`,
191
241
  ),
192
242
  "",
193
243
  "Global flags:",
194
244
  " --json machine-readable output on stdout",
195
245
  " --help this text, or `metrik <command> --help`",
196
246
  "",
197
- "Settlement flags (all default to Metrik's Base Sepolia deployment):",
198
- " --chain-id --rpc-url --escrow --usdc --oracle-url --registry-url",
247
+ "Settlement flags (all default to the selected network's registry entry):",
248
+ " --network --chain-id --rpc-url --escrow --usdc --oracle-url --registry-url",
249
+ " --network takes a registry id, chain id or CAIP-2 id (env METRIK_NETWORK).",
199
250
  "",
200
251
  "Wallet (read from the environment only; never accepted as a flag):",
201
- ` ${PRIVATE_KEY_ENV} a Base Sepolia test key. Checked first.`,
252
+ ` ${PRIVATE_KEY_ENV} a testnet key. Checked first.`,
202
253
  ` ${CDP_ENV_VARS.join(", ")}`,
203
254
  " a Coinbase CDP Server Wallet v2 account. Used when no private key is set.",
255
+ ` ${PRIVY_WALLET_KEY_ENV}`,
256
+ " a Privy wallet you provisioned, reached through a broker. Checked third.",
257
+ ` A broker session instead: ${PRIVY_SESSION_ENV_VARS.join(", ")}.`,
258
+ ` ${PRIVY_CLAIM_NOTE}`,
259
+ " Nor do `metrik pay` (the broker does not sign EIP-3009) or `metrik refund --close` (nor the opener's Close).",
204
260
  " A credential on the command line lands in shell history; these never are.",
205
261
  "",
206
- `TESTNET ONLY: this CLI refuses any chain outside ${TESTNET_CHAIN_IDS.join(", ")} (Base Sepolia),`,
262
+ `TESTNET ONLY: this CLI refuses any chain outside the registered testnets: ${describeAllowedNetworks(CLI_NETWORK_POLICY)},`,
207
263
  "and re-checks the chain id the RPC actually serves before signing. There is no override.",
208
264
  ].join("\n");
209
265
  }
@@ -19,14 +19,14 @@
19
19
  * `buyer` and `operator` are INDEXED on `StreamOpened`, so a per-wallet scan is
20
20
  * a server-side topic filter whose response is tiny regardless of range. What
21
21
  * public RPCs cap is the per-call BLOCK RANGE, and a topic filter does not lift
22
- * it: `sepolia.base.org` answers a wider range with `-32614 "eth_getLogs is
22
+ * it: the public RPC answers a wider range with `-32614 "eth_getLogs is
23
23
  * limited to a 10,000 range"`. So the page size is the cap, not a guess below
24
24
  * it.
25
25
  */
26
26
 
27
27
  /**
28
28
  * getLogs page size. The window is `chunk + 1` blocks (bounds inclusive), so
29
- * 9 999 is the largest page `sepolia.base.org` accepts.
29
+ * 9 999 is the largest page the public RPC accepts.
30
30
  */
31
31
  export const LOG_SCAN_CHUNK = 9_999n;
32
32