@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
package/src/network.ts ADDED
@@ -0,0 +1,302 @@
1
+ import {
2
+ findNetwork,
3
+ MetrikClient,
4
+ networkDeployments,
5
+ type MetrikNetworkDeployment,
6
+ getNetwork,
7
+ listNetworks,
8
+ networkForCaip2,
9
+ networkForChainId,
10
+ type MetrikNetwork,
11
+ } from "@absol-labs/sdk";
12
+ import { defineChain, isAddress, isAddressEqual, type Chain } from "viem";
13
+
14
+ /**
15
+ * The agent layer's ONE view of where Metrik is deployed.
16
+ *
17
+ * Every chain id, CAIP-2 id, contract address, deploy block, default RPC, gas
18
+ * token and oracle origin this package uses comes from the `@absol-labs/sdk`
19
+ * network registry through this module. Nothing under `src/` may hardcode them
20
+ * (`test/no-hardcoded-chain.test.ts` fails the build if anything does), so a new
21
+ * deployment — the V3 escrow and factory included — is a registry/config change,
22
+ * not a code change here.
23
+ *
24
+ * What the agent adds on top of the registry is only what the registry does not
25
+ * describe: which network is the DEFAULT for a surface that is given none, and
26
+ * where a test wallet gets funded (a faucet is an off-chain courtesy, not a
27
+ * deployment fact).
28
+ */
29
+
30
+ /**
31
+ * The registry id every surface defaults to when no network is selected. An
32
+ * id, not a chain id: the registry resolves it to the chain, addresses and RPC.
33
+ */
34
+ export const DEFAULT_METRIK_NETWORK_ID = "baseSepolia";
35
+
36
+ /** Environment variable that selects the network by id, chain id or CAIP-2 id. */
37
+ export const METRIK_NETWORK_ENV = "METRIK_NETWORK";
38
+
39
+ /** What a surface is allowed to settle on, beyond "the registry knows it". */
40
+ export interface NetworkPolicy {
41
+ /**
42
+ * Refuse a registered network that is not a testnet. The CLI and the agent
43
+ * frameworks sign with keys read from the environment, so they keep the
44
+ * testnet-only rule; the registry's `testnet` flag is the source of truth.
45
+ */
46
+ readonly testnetOnly?: boolean;
47
+ }
48
+
49
+ /** A network the registry does not know, or one the build does not allow. */
50
+ export class UnsupportedNetworkError extends Error {
51
+ readonly selector: string;
52
+
53
+ constructor(selector: string, message: string) {
54
+ super(message);
55
+ this.name = "UnsupportedNetworkError";
56
+ this.selector = selector;
57
+ }
58
+ }
59
+
60
+ /** The network a surface uses when none is selected. */
61
+ export function defaultNetwork(): MetrikNetwork {
62
+ return getNetwork(DEFAULT_METRIK_NETWORK_ID);
63
+ }
64
+
65
+ /** Every registered network the policy allows, in registry order. */
66
+ export function allowedNetworks(policy: NetworkPolicy = {}): MetrikNetwork[] {
67
+ return listNetworks().filter(
68
+ (network) => policy.testnetOnly !== true || network.testnet,
69
+ );
70
+ }
71
+
72
+ /** `"<chainId> (<name>)"` for every allowed network, for error messages. */
73
+ export function describeAllowedNetworks(policy: NetworkPolicy = {}): string {
74
+ const allowed = allowedNetworks(policy);
75
+ if (allowed.length === 0) return "(none registered)";
76
+ return allowed
77
+ .map((network) => `${network.chain.id} (${network.name}, "${network.id}")`)
78
+ .join(", ");
79
+ }
80
+
81
+ /**
82
+ * Resolve a network selector — a registry id (e.g. the default
83
+ * {@link DEFAULT_METRIK_NETWORK_ID}), an EVM chain id (as a number or a decimal
84
+ * string), or a CAIP-2 id (`eip155:<chainId>`) — to a registered
85
+ * network the policy allows. `undefined` (or empty) selects the default.
86
+ *
87
+ * Fail closed: an unknown selector, or a known network the policy forbids, is an
88
+ * {@link UnsupportedNetworkError}, never a silent fallback to the default.
89
+ */
90
+ export function resolveAgentNetwork(
91
+ selector: string | number | undefined,
92
+ policy: NetworkPolicy = {},
93
+ ): MetrikNetwork {
94
+ const raw =
95
+ typeof selector === "number" ? String(selector) : selector?.trim();
96
+ const network =
97
+ raw === undefined || raw.length === 0
98
+ ? defaultNetwork()
99
+ : lookupNetwork(raw);
100
+ if (network === undefined) {
101
+ throw new UnsupportedNetworkError(
102
+ raw ?? "",
103
+ `unknown Metrik network "${raw}": the SDK network registry knows ${describeAllowedNetworks()}`,
104
+ );
105
+ }
106
+ assertNetworkAllowed(network, policy, raw ?? network.id);
107
+ return network;
108
+ }
109
+
110
+ /** The registered network on `chainId` the policy allows; throws otherwise. */
111
+ export function requireNetworkForChainId(
112
+ chainId: number,
113
+ policy: NetworkPolicy = {},
114
+ source = "the configured chain id",
115
+ ): MetrikNetwork {
116
+ const network = networkForChainId(chainId);
117
+ if (network === undefined) {
118
+ throw new UnsupportedNetworkError(
119
+ String(chainId),
120
+ `${source} ${chainId} is not a network the Metrik registry knows (registered: ${describeAllowedNetworks()})`,
121
+ );
122
+ }
123
+ assertNetworkAllowed(network, policy, source);
124
+ return network;
125
+ }
126
+
127
+ /** The registered network with this CAIP-2 id the policy allows; throws otherwise. */
128
+ export function requireNetworkForCaip2(
129
+ caip2: string,
130
+ policy: NetworkPolicy = {},
131
+ source = "the configured network",
132
+ ): MetrikNetwork {
133
+ const network = networkForCaip2(caip2);
134
+ if (network === undefined) {
135
+ throw new UnsupportedNetworkError(
136
+ caip2,
137
+ `${source} ${caip2} is not a network the Metrik registry knows (registered: ${describeAllowedNetworks()})`,
138
+ );
139
+ }
140
+ assertNetworkAllowed(network, policy, source);
141
+ return network;
142
+ }
143
+
144
+ function lookupNetwork(raw: string): MetrikNetwork | undefined {
145
+ if (/^\d+$/.test(raw)) return networkForChainId(Number(raw));
146
+ if (raw.startsWith("eip155:")) return networkForCaip2(raw);
147
+ return findNetwork(raw);
148
+ }
149
+
150
+ function assertNetworkAllowed(
151
+ network: MetrikNetwork,
152
+ policy: NetworkPolicy,
153
+ source: string,
154
+ ): void {
155
+ if (policy.testnetOnly === true && !network.testnet) {
156
+ throw new UnsupportedNetworkError(
157
+ source,
158
+ `refusing ${network.name} (chain ${network.chain.id}): this surface is testnet-only. Allowed: ${describeAllowedNetworks(policy)}`,
159
+ );
160
+ }
161
+ }
162
+
163
+ /**
164
+ * The network's registered deployment (the CURRENT one, or a `legacy` one that
165
+ * still holds streams) whose escrow is `escrow`, or `undefined`.
166
+ */
167
+ export function registeredDeployment(
168
+ network: MetrikNetwork,
169
+ escrow: string,
170
+ ): (MetrikNetworkDeployment & { readonly legacy: boolean }) | undefined {
171
+ if (!isAddress(escrow)) return undefined;
172
+ const deployments = networkDeployments(network);
173
+ const index = deployments.findIndex((entry) =>
174
+ isAddressEqual(entry.escrow.address, escrow),
175
+ );
176
+ return index < 0
177
+ ? undefined
178
+ : { ...(deployments[index] as MetrikNetworkDeployment), legacy: index > 0 };
179
+ }
180
+
181
+ /**
182
+ * Whether `escrow` is one of the network's registered escrows — the current
183
+ * one or a legacy one (whose streams can still be read, closed and
184
+ * reclaimed; the SDK refuses NEW opens on it unless explicitly opted in).
185
+ */
186
+ export function isRegisteredEscrow(
187
+ network: MetrikNetwork,
188
+ escrow: string,
189
+ ): boolean {
190
+ return registeredDeployment(network, escrow) !== undefined;
191
+ }
192
+
193
+ /**
194
+ * The viem chain for a chain id: the registered network's chain when there is
195
+ * one, otherwise a minimal chain definition around the given RPC (so a custom,
196
+ * explicitly configured deployment still signs with the right chain id).
197
+ */
198
+ export function chainForChainId(chainId: number, rpcUrl: string): Chain {
199
+ const registered = networkForChainId(chainId);
200
+ if (registered !== undefined) return registered.chain;
201
+ return defineChain({
202
+ id: chainId,
203
+ name: `eip155:${String(chainId)}`,
204
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
205
+ rpcUrls: { default: { http: [rpcUrl] } },
206
+ });
207
+ }
208
+
209
+ /**
210
+ * A read-only `MetrikClient` for one escrow on a REGISTERED network (default:
211
+ * the registry's default network). The chain, the default USDC and oracle, and
212
+ * opener-factory detection all come from the registry; the escrow and RPC are
213
+ * the caller's. A chain id the registry does not know is refused — register the
214
+ * network with the SDK's `registerNetwork()` first.
215
+ */
216
+ export function readOnlyMetrikClient(options: {
217
+ readonly escrowAddress: `0x${string}`;
218
+ readonly rpcUrl: string;
219
+ readonly chainId?: number;
220
+ /**
221
+ * Only for an escrow the registry does NOT record (a deliberate private
222
+ * deployment): its declared generation. The SDK then skips its code-hash
223
+ * pin. Ignored for a registered escrow, whose generation is the registry's.
224
+ */
225
+ readonly unregisteredEscrowGeneration?: "v2" | "v3";
226
+ }): MetrikClient {
227
+ const network =
228
+ options.chainId === undefined
229
+ ? defaultNetwork()
230
+ : requireNetworkForChainId(options.chainId);
231
+ const registered = registeredDeployment(network, options.escrowAddress);
232
+ return MetrikClient.forNetwork(network, {
233
+ escrow: options.escrowAddress,
234
+ rpcUrl: options.rpcUrl,
235
+ ...(registered === undefined &&
236
+ options.unregisteredEscrowGeneration !== undefined
237
+ ? {
238
+ allowUnregisteredEscrow: true,
239
+ generation: options.unregisteredEscrowGeneration,
240
+ }
241
+ : {}),
242
+ });
243
+ }
244
+
245
+ // ── Funding hints ────────────────────────────────────────────────────────────
246
+
247
+ /**
248
+ * Where a test wallet on a network gets its gas and its USDC. Off-chain
249
+ * courtesy data the registry does not carry; keyed by registry id, never by
250
+ * chain id.
251
+ */
252
+ export interface NetworkFunding {
253
+ /** A faucet for the network's GAS token, or `null` if none is known. */
254
+ readonly gasFaucetUrl: string | null;
255
+ /** A faucet for the network's settlement USDC, or `null` if none is known. */
256
+ readonly usdcFaucetUrl: string | null;
257
+ /** The Coinbase CDP faucet's name for this network, or `null` if CDP has none. */
258
+ readonly cdpNetwork: string | null;
259
+ }
260
+
261
+ const NETWORK_FUNDING: Readonly<Record<string, NetworkFunding>> = {
262
+ baseSepolia: {
263
+ gasFaucetUrl: "https://www.alchemy.com/faucets/base-sepolia",
264
+ usdcFaucetUrl: "https://faucet.circle.com",
265
+ cdpNetwork: "base-sepolia",
266
+ },
267
+ };
268
+
269
+ /** Funding hints for a network; all `null` for a network with none known. */
270
+ export function networkFunding(network: MetrikNetwork): NetworkFunding {
271
+ return (
272
+ NETWORK_FUNDING[network.id] ?? {
273
+ gasFaucetUrl: null,
274
+ usdcFaucetUrl: null,
275
+ cdpNetwork: null,
276
+ }
277
+ );
278
+ }
279
+
280
+ /**
281
+ * One sentence telling a user how to fund GAS on this network, read from the
282
+ * network's gas-token metadata. Where gas is the settlement token (USDC), the
283
+ * USDC faucet is the gas faucet.
284
+ */
285
+ export function gasFundingHint(network: MetrikNetwork): string {
286
+ const funding = networkFunding(network);
287
+ const symbol = network.gasToken.symbol;
288
+ const url = network.gasToken.isSettlementToken
289
+ ? funding.usdcFaucetUrl
290
+ : funding.gasFaucetUrl;
291
+ return url === null
292
+ ? `acquire ${symbol} on ${network.name}`
293
+ : `fund it with ${symbol} at ${url}`;
294
+ }
295
+
296
+ /** One sentence telling a user how to fund the settlement USDC on this network. */
297
+ export function usdcFundingHint(network: MetrikNetwork): string {
298
+ const url = networkFunding(network).usdcFaucetUrl;
299
+ return url === null
300
+ ? `acquire USDC on ${network.name}`
301
+ : `fund it with USDC at ${url} (${network.name})`;
302
+ }
package/src/sdk/client.ts CHANGED
@@ -87,6 +87,11 @@ export interface AgentSdkClient {
87
87
  claimable(streamId: `0x${string}`): Promise<bigint>;
88
88
  reclaimable(streamId: `0x${string}`): Promise<bigint>;
89
89
  claim(streamId: `0x${string}`): Promise<StreamProofTransactionResult>;
90
+ /**
91
+ * StreamEscrowV3 only: redeem the on-chain proven high-water without a proof.
92
+ * Optional so an existing custom SDK client keeps compiling.
93
+ */
94
+ claimProven?(streamId: `0x${string}`): Promise<StreamProofTransactionResult>;
90
95
  close(streamId: `0x${string}`): Promise<StreamProofTransactionResult>;
91
96
  reclaim(streamId: `0x${string}`): Promise<StreamProofTransactionResult>;
92
97
  /**
@@ -192,6 +197,26 @@ export class VerifiedStreamAgentClient implements VerifiedStreamAgentOpener {
192
197
  return await this.sdkClient.claim(input.streamId);
193
198
  }
194
199
 
200
+ /**
201
+ * Operator-only, StreamEscrowV3 only: redeem the stream's on-chain proven
202
+ * high-water (`claimProven`) without a fresh proof. Authorized exactly like
203
+ * {@link claimStream} — it pays the same party from the same escrow, only an
204
+ * amount already proven against a signed checkpoint root and recorded
205
+ * on-chain, so it can never pay more than a proof claim could have.
206
+ */
207
+ async claimProvenStream(
208
+ input: MandateAuthorizedStreamActionInput,
209
+ ): Promise<StreamProofTransactionResult> {
210
+ const claimProven = this.sdkClient.claimProven?.bind(this.sdkClient);
211
+ if (claimProven === undefined) {
212
+ throw new Error(
213
+ "this SDK client cannot send claimProven (StreamEscrowV3 only)",
214
+ );
215
+ }
216
+ await this.authorizeExistingStreamAction(input);
217
+ return await claimProven(input.streamId);
218
+ }
219
+
195
220
  async closeStream(
196
221
  input: MandateAuthorizedStreamActionInput,
197
222
  ): Promise<StreamProofTransactionResult> {
package/src/sdk/invoke.ts CHANGED
@@ -6,7 +6,6 @@ import {
6
6
  signedServiceDescriptorSchema,
7
7
  type DeliveryReceiptDomainInput,
8
8
  } from "@absol-labs/shared";
9
- import { MetrikClient } from "@absol-labs/sdk";
10
9
  import type { Address, Hex, LocalAccount } from "viem";
11
10
 
12
11
  import type { ServiceListing } from "../discovery/registry.js";
@@ -30,6 +29,7 @@ import {
30
29
  type SignedInvocationCapability,
31
30
  DEFAULT_CAPABILITY_TTL_SECONDS,
32
31
  } from "../capability/invocation-capability.js";
32
+ import { readOnlyMetrikClient } from "../network.js";
33
33
 
34
34
  /**
35
35
  * Buyer half of the pay -> use loop (metrik-agent#64, impl of #62 part 2/2).
@@ -57,11 +57,12 @@ export interface InvokeStreamReader {
57
57
  export function createSdkInvokeStreamReader(options: {
58
58
  readonly escrowAddress: Address;
59
59
  readonly rpcUrl: string;
60
+ /** Chain of the escrow; must be a registered network. Default: the registry default. */
61
+ readonly chainId?: number;
62
+ /** See `readOnlyMetrikClient`: only for an escrow the registry does not record. */
63
+ readonly unregisteredEscrowGeneration?: "v2" | "v3";
60
64
  }): InvokeStreamReader {
61
- const metrik = MetrikClient.baseSepolia({
62
- escrow: options.escrowAddress,
63
- rpcUrl: options.rpcUrl,
64
- });
65
+ const metrik = readOnlyMetrikClient(options);
65
66
  return {
66
67
  async getStreamV2(streamId) {
67
68
  const stream = await metrik.getStreamV2(streamId);
@@ -4,7 +4,6 @@ import {
4
4
  formatRequestForAuthorizationSignature,
5
5
  type PrivyClient,
6
6
  } from "@privy-io/node";
7
- import { streamEscrowV2Abi } from "@absol-labs/shared";
8
7
  import {
9
8
  decodeFunctionData,
10
9
  getAddress,
@@ -16,6 +15,7 @@ import { z } from "zod";
16
15
 
17
16
  import {
18
17
  autonomousProofBytes,
18
+ AUTONOMOUS_WALLET_CAIP2,
19
19
  AUTONOMOUS_WALLET_CHAIN_ID,
20
20
  AUTONOMOUS_WALLET_VERSION,
21
21
  type AutonomousWalletBroker as AutonomousWalletClientBroker,
@@ -35,6 +35,14 @@ import {
35
35
  PRIVY_BROKER_USDC,
36
36
  type BrokerStreamReader,
37
37
  } from "./privy-session-broker.js";
38
+ import {
39
+ BROKER_EXIT_METHODS,
40
+ brokerEscrowPolicy,
41
+ decodeEscrowCall,
42
+ escrowRole,
43
+ type BrokerEscrowPolicy,
44
+ } from "./broker-escrows.js";
45
+ import { defaultNetwork } from "../network.js";
38
46
 
39
47
  const transactionSchema = z.object({
40
48
  from: z.string().refine(isAddress),
@@ -137,6 +145,8 @@ export interface AutonomousWalletBrokerOptions {
137
145
  readonly requestTtlSeconds?: number;
138
146
  /** Must match the base URL used by the Privy client, without a trailing slash. */
139
147
  readonly privyApiBaseUrl?: string;
148
+ /** Current + legacy escrows. Default: from the registries (see `./broker-escrows.ts`). */
149
+ readonly escrows?: BrokerEscrowPolicy;
140
150
  }
141
151
 
142
152
  /**
@@ -288,6 +298,7 @@ export class AutonomousWalletBroker implements AutonomousWalletClientBroker {
288
298
  provision.address,
289
299
  this.options.streamReader,
290
300
  this.nowSeconds(),
301
+ this.options.escrows ?? brokerEscrowPolicy(defaultNetwork()),
291
302
  );
292
303
  const requestExpiryMs = (this.nowSeconds() + this.requestTtl) * 1_000;
293
304
  const idempotencyKey = randomUUID();
@@ -558,6 +569,7 @@ async function buildRpcBody(
558
569
  address: Address,
559
570
  streamReader: BrokerStreamReader,
560
571
  now: number,
572
+ escrows: BrokerEscrowPolicy,
561
573
  ): Promise<Record<string, unknown>> {
562
574
  if (method === "eth_sendTransaction") {
563
575
  const tx = transactionSchema.parse(params[0]);
@@ -568,11 +580,19 @@ async function buildRpcBody(
568
580
  );
569
581
  assertChain(tx.chainId);
570
582
  assertZeroValue(tx.value);
571
- const target = getAddress(tx.to).toLowerCase();
572
- if (target === PRIVY_BROKER_USDC.toLowerCase()) {
573
- assertUsdcApproval(tx.data as Hex);
574
- } else if (target === PRIVY_BROKER_ESCROW.toLowerCase()) {
575
- await assertEscrowMethod(tx.data as Hex, address, streamReader);
583
+ const target = getAddress(tx.to);
584
+ const role = escrowRole(escrows, target);
585
+ if (target.toLowerCase() === PRIVY_BROKER_USDC.toLowerCase()) {
586
+ // The approval spender must be the CURRENT escrow, never a legacy one.
587
+ assertUsdcApproval(tx.data as Hex, escrows.current);
588
+ } else if (role !== null) {
589
+ await assertEscrowMethod(
590
+ tx.data as Hex,
591
+ address,
592
+ streamReader,
593
+ target,
594
+ role,
595
+ );
576
596
  } else {
577
597
  throw new AutonomousWalletBrokerError(
578
598
  "policy-denied",
@@ -583,7 +603,7 @@ async function buildRpcBody(
583
603
  return {
584
604
  method,
585
605
  chain_type: "ethereum",
586
- caip2: "eip155:84532",
606
+ caip2: AUTONOMOUS_WALLET_CAIP2,
587
607
  params: { transaction: normalizeJson(transaction) },
588
608
  };
589
609
  }
@@ -613,7 +633,7 @@ async function buildRpcBody(
613
633
  parsed.domain.name !== invocationCapabilityDomainName ||
614
634
  parsed.domain.version !== invocationCapabilityDomainVersion ||
615
635
  parsed.domain.verifyingContract.toLowerCase() !==
616
- PRIVY_BROKER_ESCROW.toLowerCase()
636
+ escrows.current.toLowerCase()
617
637
  )
618
638
  throw new AutonomousWalletBrokerError(
619
639
  "policy-denied",
@@ -655,7 +675,7 @@ async function buildRpcBody(
655
675
  return {
656
676
  method,
657
677
  chain_type: "ethereum",
658
- caip2: "eip155:84532",
678
+ caip2: AUTONOMOUS_WALLET_CAIP2,
659
679
  params: {
660
680
  typed_data: normalizeJson({
661
681
  ...wireTypedData,
@@ -704,7 +724,7 @@ function assertZeroValue(value: string | number | bigint | undefined): void {
704
724
  }
705
725
  }
706
726
 
707
- function assertUsdcApproval(data: Hex): void {
727
+ function assertUsdcApproval(data: Hex, currentEscrow: Address): void {
708
728
  try {
709
729
  const decoded = decodeFunctionData({
710
730
  abi: [
@@ -723,7 +743,7 @@ function assertUsdcApproval(data: Hex): void {
723
743
  });
724
744
  const [spender, amount] = decoded.args;
725
745
  if (
726
- spender.toLowerCase() !== PRIVY_BROKER_ESCROW.toLowerCase() ||
746
+ spender.toLowerCase() !== currentEscrow.toLowerCase() ||
727
747
  amount > 1_000_000n
728
748
  )
729
749
  throw new Error("approval outside Metrik policy");
@@ -740,10 +760,13 @@ async function assertEscrowMethod(
740
760
  data: Hex,
741
761
  address: Address,
742
762
  streamReader: BrokerStreamReader,
763
+ escrow: Address,
764
+ role: "current" | "legacy",
743
765
  ): Promise<void> {
744
766
  try {
745
- const decoded = decodeFunctionData({ abi: streamEscrowV2Abi, data });
746
- if (decoded.functionName === "openStream") {
767
+ const decoded = decodeEscrowCall(data);
768
+ // A legacy escrow is exit-only: openStream there falls through and fails.
769
+ if (decoded.functionName === "openStream" && role === "current") {
747
770
  const [, , deposit, rate, duration] = decoded.args;
748
771
  if (
749
772
  deposit > PRIVY_POLICY_MAX_TOTAL_USDC ||
@@ -754,14 +777,17 @@ async function assertEscrowMethod(
754
777
  }
755
778
  return;
756
779
  }
757
- if (
758
- decoded.functionName !== "close" &&
759
- decoded.functionName !== "reclaim" &&
760
- decoded.functionName !== "reclaimUnverified"
761
- ) {
762
- throw new Error("escrow method is not allowlisted");
780
+ if (!BROKER_EXIT_METHODS.has(decoded.functionName)) {
781
+ throw new Error(
782
+ role === "legacy"
783
+ ? "only close, reclaim and reclaimUnverified are allowed on a legacy escrow"
784
+ : "escrow method is not allowlisted",
785
+ );
763
786
  }
764
- const stream = await streamReader.getStream(decoded.args[0]);
787
+ const stream = await streamReader.getStream(
788
+ (decoded.args as readonly unknown[])[0] as Hex,
789
+ escrow,
790
+ );
765
791
  if (stream.buyer.toLowerCase() !== address.toLowerCase())
766
792
  throw new Error("autonomous wallet is not the stream buyer");
767
793
  } catch (error) {
@@ -1,8 +1,17 @@
1
1
  import type { Address, Hex } from "viem";
2
2
 
3
+ import { defaultNetwork } from "../network.js";
4
+
3
5
  export const AUTONOMOUS_WALLET_VERSION = 1 as const;
4
- export const AUTONOMOUS_WALLET_CHAIN_ID = 84532 as const;
5
- export const AUTONOMOUS_WALLET_CAIP2 = "eip155:84532" as const;
6
+ /**
7
+ * The network an agent-owned Privy wallet is provisioned and policed on: the
8
+ * registry's default network. A broker's Privy policy allowlists ONE escrow and
9
+ * ONE USDC, so the wallet is single-network by construction; the values come
10
+ * from the `@absol-labs/sdk` registry rather than literals.
11
+ */
12
+ export const AUTONOMOUS_WALLET_CHAIN_ID: number = defaultNetwork().chain.id;
13
+ export const AUTONOMOUS_WALLET_CAIP2: `eip155:${number}` =
14
+ defaultNetwork().caip2;
6
15
 
7
16
  export interface PreparedPrivyRequest {
8
17
  readonly requestId: string;
@@ -27,6 +27,7 @@ import {
27
27
  type AutonomousWalletCredentialStore,
28
28
  type AutonomousWalletRecord,
29
29
  } from "./autonomous-wallet-store.js";
30
+ import { defaultNetwork } from "../network.js";
30
31
 
31
32
  export {
32
33
  AUTONOMOUS_WALLET_CAIP2,
@@ -366,7 +367,8 @@ export function createAutonomousWalletProvider(
366
367
  let rpcId = 0;
367
368
  return {
368
369
  async request({ method, params = [] }) {
369
- if (method === "eth_chainId") return "0x14a34";
370
+ if (method === "eth_chainId")
371
+ return `0x${AUTONOMOUS_WALLET_CHAIN_ID.toString(16)}`;
370
372
  if (method === "eth_accounts" || method === "eth_requestAccounts")
371
373
  return [address];
372
374
  if (
@@ -410,7 +412,7 @@ export function createAutonomousWalletProvider(
410
412
  }
411
413
  const response = await (
412
414
  options.fetchImpl ?? globalThis.fetch.bind(globalThis)
413
- )(options.rpcUrl ?? "https://base-sepolia-rpc.publicnode.com", {
415
+ )(options.rpcUrl ?? defaultNetwork().rpcUrls[0], {
414
416
  method: "POST",
415
417
  headers: { "content-type": "application/json" },
416
418
  body: JSON.stringify(
@@ -0,0 +1,66 @@
1
+ import type { MetrikNetwork } from "@absol-labs/sdk";
2
+ import { streamEscrowV2Abi, streamEscrowV3Abi } from "@absol-labs/shared";
3
+ import {
4
+ decodeFunctionData,
5
+ getAddress,
6
+ isAddressEqual,
7
+ type Address,
8
+ type Hex,
9
+ } from "viem";
10
+
11
+ /**
12
+ * Which escrows a Privy broker will send a transaction to, and for what
13
+ * (the V3 cutover, metrik-agent#121). Read from the SDK network registry —
14
+ * data, never addresses in code:
15
+ *
16
+ * - the CURRENT escrow (`network.escrow`) for every method the broker
17
+ * allowlists: `openStream`, `close`, `reclaim`, `reclaimUnverified`, and the
18
+ * bounded USDC `approve` to it;
19
+ * - each LEGACY escrow (`network.legacy`) for EXITS only: `close`, `reclaim`,
20
+ * `reclaimUnverified`. Never `openStream` and never an approval: a legacy
21
+ * escrow can only give an agent its own money back.
22
+ */
23
+ export interface BrokerEscrowPolicy {
24
+ readonly current: Address;
25
+ readonly legacy: readonly Address[];
26
+ }
27
+
28
+ export function brokerEscrowPolicy(network: MetrikNetwork): BrokerEscrowPolicy {
29
+ const current = getAddress(network.escrow.address);
30
+ const legacy = network.legacy
31
+ .map((deployment) => getAddress(deployment.escrow.address))
32
+ .filter((escrow) => !isAddressEqual(escrow, current));
33
+ return Object.freeze({
34
+ current,
35
+ legacy: Object.freeze([...new Set(legacy)]),
36
+ });
37
+ }
38
+
39
+ /** The exit methods a legacy escrow is allowed for. */
40
+ export const BROKER_EXIT_METHODS: ReadonlySet<string> = new Set([
41
+ "close",
42
+ "reclaim",
43
+ "reclaimUnverified",
44
+ ]);
45
+
46
+ /** `"current"`, `"legacy"`, or `null` for an escrow the broker never calls. */
47
+ export function escrowRole(
48
+ policy: BrokerEscrowPolicy,
49
+ target: Address,
50
+ ): "current" | "legacy" | null {
51
+ if (isAddressEqual(target, policy.current)) return "current";
52
+ return policy.legacy.some((escrow) => isAddressEqual(escrow, target))
53
+ ? "legacy"
54
+ : null;
55
+ }
56
+
57
+ /**
58
+ * V2 and V3 share the selectors and argument layouts of every method the
59
+ * broker allowlists, so one decoder serves both: V3 first, V2 for anything
60
+ * only V2 knows.
61
+ */
62
+ const escrowCallAbi = [...streamEscrowV3Abi, ...streamEscrowV2Abi];
63
+
64
+ export function decodeEscrowCall(data: Hex) {
65
+ return decodeFunctionData({ abi: escrowCallAbi, data });
66
+ }