@absol-labs/agent 0.9.1 → 0.11.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 (293) hide show
  1. package/README.md +184 -26
  2. package/dist/capability/invocation-capability.d.ts +18 -6
  3. package/dist/capability/invocation-capability.d.ts.map +1 -1
  4. package/dist/capability/invocation-capability.js.map +1 -1
  5. package/dist/cli/amounts.d.ts +26 -0
  6. package/dist/cli/amounts.d.ts.map +1 -0
  7. package/dist/cli/amounts.js +71 -0
  8. package/dist/cli/amounts.js.map +1 -0
  9. package/dist/cli/args.d.ts +32 -0
  10. package/dist/cli/args.d.ts.map +1 -0
  11. package/dist/cli/args.js +119 -0
  12. package/dist/cli/args.js.map +1 -0
  13. package/dist/cli/attesters.d.ts +51 -0
  14. package/dist/cli/attesters.d.ts.map +1 -0
  15. package/dist/cli/attesters.js +58 -0
  16. package/dist/cli/attesters.js.map +1 -0
  17. package/dist/cli/bin.d.ts +3 -0
  18. package/dist/cli/bin.d.ts.map +1 -0
  19. package/dist/cli/bin.js +5 -0
  20. package/dist/cli/bin.js.map +1 -0
  21. package/dist/cli/commands/claim.d.ts +13 -0
  22. package/dist/cli/commands/claim.d.ts.map +1 -0
  23. package/dist/cli/commands/claim.js +102 -0
  24. package/dist/cli/commands/claim.js.map +1 -0
  25. package/dist/cli/commands/close.d.ts +3 -0
  26. package/dist/cli/commands/close.d.ts.map +1 -0
  27. package/dist/cli/commands/close.js +55 -0
  28. package/dist/cli/commands/close.js.map +1 -0
  29. package/dist/cli/commands/discover.d.ts +3 -0
  30. package/dist/cli/commands/discover.d.ts.map +1 -0
  31. package/dist/cli/commands/discover.js +183 -0
  32. package/dist/cli/commands/discover.js.map +1 -0
  33. package/dist/cli/commands/invoke.d.ts +3 -0
  34. package/dist/cli/commands/invoke.d.ts.map +1 -0
  35. package/dist/cli/commands/invoke.js +142 -0
  36. package/dist/cli/commands/invoke.js.map +1 -0
  37. package/dist/cli/commands/mcp.d.ts +3 -0
  38. package/dist/cli/commands/mcp.d.ts.map +1 -0
  39. package/dist/cli/commands/mcp.js +113 -0
  40. package/dist/cli/commands/mcp.js.map +1 -0
  41. package/dist/cli/commands/open.d.ts +3 -0
  42. package/dist/cli/commands/open.d.ts.map +1 -0
  43. package/dist/cli/commands/open.js +331 -0
  44. package/dist/cli/commands/open.js.map +1 -0
  45. package/dist/cli/commands/reclaim-unverified.d.ts +3 -0
  46. package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -0
  47. package/dist/cli/commands/reclaim-unverified.js +172 -0
  48. package/dist/cli/commands/reclaim-unverified.js.map +1 -0
  49. package/dist/cli/commands/reclaim.d.ts +33 -0
  50. package/dist/cli/commands/reclaim.d.ts.map +1 -0
  51. package/dist/cli/commands/reclaim.js +308 -0
  52. package/dist/cli/commands/reclaim.js.map +1 -0
  53. package/dist/cli/commands/status.d.ts +3 -0
  54. package/dist/cli/commands/status.d.ts.map +1 -0
  55. package/dist/cli/commands/status.js +43 -0
  56. package/dist/cli/commands/status.js.map +1 -0
  57. package/dist/cli/commands/streams.d.ts +3 -0
  58. package/dist/cli/commands/streams.d.ts.map +1 -0
  59. package/dist/cli/commands/streams.js +257 -0
  60. package/dist/cli/commands/streams.js.map +1 -0
  61. package/dist/cli/commands/watch.d.ts +3 -0
  62. package/dist/cli/commands/watch.d.ts.map +1 -0
  63. package/dist/cli/commands/watch.js +55 -0
  64. package/dist/cli/commands/watch.js.map +1 -0
  65. package/dist/cli/config.d.ts +61 -0
  66. package/dist/cli/config.d.ts.map +1 -0
  67. package/dist/cli/config.js +140 -0
  68. package/dist/cli/config.js.map +1 -0
  69. package/dist/cli/context.d.ts +29 -0
  70. package/dist/cli/context.d.ts.map +1 -0
  71. package/dist/cli/context.js +2 -0
  72. package/dist/cli/context.js.map +1 -0
  73. package/dist/cli/deps.d.ts +191 -0
  74. package/dist/cli/deps.d.ts.map +1 -0
  75. package/dist/cli/deps.js +277 -0
  76. package/dist/cli/deps.js.map +1 -0
  77. package/dist/cli/descriptor.d.ts +61 -0
  78. package/dist/cli/descriptor.d.ts.map +1 -0
  79. package/dist/cli/descriptor.js +78 -0
  80. package/dist/cli/descriptor.js.map +1 -0
  81. package/dist/cli/errors.d.ts +48 -0
  82. package/dist/cli/errors.d.ts.map +1 -0
  83. package/dist/cli/errors.js +129 -0
  84. package/dist/cli/errors.js.map +1 -0
  85. package/dist/cli/escape-hatch.d.ts +50 -0
  86. package/dist/cli/escape-hatch.d.ts.map +1 -0
  87. package/dist/cli/escape-hatch.js +45 -0
  88. package/dist/cli/escape-hatch.js.map +1 -0
  89. package/dist/cli/index.d.ts +8 -0
  90. package/dist/cli/index.d.ts.map +1 -0
  91. package/dist/cli/index.js +7 -0
  92. package/dist/cli/index.js.map +1 -0
  93. package/dist/cli/listings.d.ts +15 -0
  94. package/dist/cli/listings.d.ts.map +1 -0
  95. package/dist/cli/listings.js +56 -0
  96. package/dist/cli/listings.js.map +1 -0
  97. package/dist/cli/mandate.d.ts +66 -0
  98. package/dist/cli/mandate.d.ts.map +1 -0
  99. package/dist/cli/mandate.js +61 -0
  100. package/dist/cli/mandate.js.map +1 -0
  101. package/dist/cli/output.d.ts +33 -0
  102. package/dist/cli/output.d.ts.map +1 -0
  103. package/dist/cli/output.js +34 -0
  104. package/dist/cli/output.js.map +1 -0
  105. package/dist/cli/preflight.d.ts +38 -0
  106. package/dist/cli/preflight.d.ts.map +1 -0
  107. package/dist/cli/preflight.js +72 -0
  108. package/dist/cli/preflight.js.map +1 -0
  109. package/dist/cli/privy.d.ts +83 -0
  110. package/dist/cli/privy.d.ts.map +1 -0
  111. package/dist/cli/privy.js +230 -0
  112. package/dist/cli/privy.js.map +1 -0
  113. package/dist/cli/progress.d.ts +36 -0
  114. package/dist/cli/progress.d.ts.map +1 -0
  115. package/dist/cli/progress.js +40 -0
  116. package/dist/cli/progress.js.map +1 -0
  117. package/dist/cli/run.d.ts +25 -0
  118. package/dist/cli/run.d.ts.map +1 -0
  119. package/dist/cli/run.js +173 -0
  120. package/dist/cli/run.js.map +1 -0
  121. package/dist/cli/scan-range.d.ts +55 -0
  122. package/dist/cli/scan-range.d.ts.map +1 -0
  123. package/dist/cli/scan-range.js +57 -0
  124. package/dist/cli/scan-range.js.map +1 -0
  125. package/dist/cli/spend-policy.d.ts +60 -0
  126. package/dist/cli/spend-policy.d.ts.map +1 -0
  127. package/dist/cli/spend-policy.js +65 -0
  128. package/dist/cli/spend-policy.js.map +1 -0
  129. package/dist/cli/status.d.ts +90 -0
  130. package/dist/cli/status.d.ts.map +1 -0
  131. package/dist/cli/status.js +252 -0
  132. package/dist/cli/status.js.map +1 -0
  133. package/dist/cli/timeout.d.ts +30 -0
  134. package/dist/cli/timeout.d.ts.map +1 -0
  135. package/dist/cli/timeout.js +55 -0
  136. package/dist/cli/timeout.js.map +1 -0
  137. package/dist/cli/version.d.ts +12 -0
  138. package/dist/cli/version.d.ts.map +1 -0
  139. package/dist/cli/version.js +22 -0
  140. package/dist/cli/version.js.map +1 -0
  141. package/dist/cli/wallet.d.ts +164 -0
  142. package/dist/cli/wallet.d.ts.map +1 -0
  143. package/dist/cli/wallet.js +234 -0
  144. package/dist/cli/wallet.js.map +1 -0
  145. package/dist/frameworks/crewai.d.ts +10 -0
  146. package/dist/frameworks/crewai.d.ts.map +1 -1
  147. package/dist/frameworks/crewai.js +12 -2
  148. package/dist/frameworks/crewai.js.map +1 -1
  149. package/dist/gateway/caller-auth-gateway.d.ts +38 -3
  150. package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
  151. package/dist/gateway/caller-auth-gateway.js +25 -1
  152. package/dist/gateway/caller-auth-gateway.js.map +1 -1
  153. package/dist/gateway/http-server.d.ts +53 -0
  154. package/dist/gateway/http-server.d.ts.map +1 -1
  155. package/dist/gateway/http-server.js +189 -4
  156. package/dist/gateway/http-server.js.map +1 -1
  157. package/dist/gateway/server-entry.d.ts +1 -0
  158. package/dist/gateway/server-entry.js +1 -0
  159. package/dist/gateway/server-entry.js.map +1 -1
  160. package/dist/gateway/x402-mode.d.ts +123 -0
  161. package/dist/gateway/x402-mode.d.ts.map +1 -0
  162. package/dist/gateway/x402-mode.js +212 -0
  163. package/dist/gateway/x402-mode.js.map +1 -0
  164. package/dist/index.d.ts +6 -4
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +8 -3
  167. package/dist/index.js.map +1 -1
  168. package/dist/mandates/env.d.ts +3 -2
  169. package/dist/mandates/env.d.ts.map +1 -1
  170. package/dist/mandates/env.js +3 -2
  171. package/dist/mandates/env.js.map +1 -1
  172. package/dist/mcp/http-server.d.ts +1 -0
  173. package/dist/mcp/http-server.js +1 -0
  174. package/dist/mcp/http-server.js.map +1 -1
  175. package/dist/mcp/server.d.ts +49 -0
  176. package/dist/mcp/server.d.ts.map +1 -1
  177. package/dist/mcp/server.js +533 -25
  178. package/dist/mcp/server.js.map +1 -1
  179. package/dist/mcp/service-invoker.d.ts +97 -0
  180. package/dist/mcp/service-invoker.d.ts.map +1 -0
  181. package/dist/mcp/service-invoker.js +167 -0
  182. package/dist/mcp/service-invoker.js.map +1 -0
  183. package/dist/mcp/stdio.d.ts +1 -0
  184. package/dist/mcp/stdio.js +1 -0
  185. package/dist/mcp/stdio.js.map +1 -1
  186. package/dist/sdk/client.d.ts +25 -1
  187. package/dist/sdk/client.d.ts.map +1 -1
  188. package/dist/sdk/client.js +20 -1
  189. package/dist/sdk/client.js.map +1 -1
  190. package/dist/sdk/invoke.d.ts +19 -4
  191. package/dist/sdk/invoke.d.ts.map +1 -1
  192. package/dist/sdk/invoke.js +69 -5
  193. package/dist/sdk/invoke.js.map +1 -1
  194. package/dist/x402/delivery-oracle.d.ts +108 -0
  195. package/dist/x402/delivery-oracle.d.ts.map +1 -0
  196. package/dist/x402/delivery-oracle.js +174 -0
  197. package/dist/x402/delivery-oracle.js.map +1 -0
  198. package/dist/x402/facilitator-server-entry.d.ts +3 -0
  199. package/dist/x402/facilitator-server-entry.d.ts.map +1 -0
  200. package/dist/x402/facilitator-server-entry.js +27 -0
  201. package/dist/x402/facilitator-server-entry.js.map +1 -0
  202. package/dist/x402/facilitator-server.d.ts +73 -0
  203. package/dist/x402/facilitator-server.d.ts.map +1 -0
  204. package/dist/x402/facilitator-server.js +305 -0
  205. package/dist/x402/facilitator-server.js.map +1 -0
  206. package/dist/x402/facilitator.d.ts +69 -17
  207. package/dist/x402/facilitator.d.ts.map +1 -1
  208. package/dist/x402/facilitator.js +76 -33
  209. package/dist/x402/facilitator.js.map +1 -1
  210. package/dist/x402/payment-requirements.d.ts +106 -0
  211. package/dist/x402/payment-requirements.d.ts.map +1 -0
  212. package/dist/x402/payment-requirements.js +138 -0
  213. package/dist/x402/payment-requirements.js.map +1 -0
  214. package/dist/x402/relayer.d.ts +41 -0
  215. package/dist/x402/relayer.d.ts.map +1 -0
  216. package/dist/x402/relayer.js +64 -0
  217. package/dist/x402/relayer.js.map +1 -0
  218. package/dist/x402/resource-index.d.ts +75 -0
  219. package/dist/x402/resource-index.d.ts.map +1 -0
  220. package/dist/x402/resource-index.js +126 -0
  221. package/dist/x402/resource-index.js.map +1 -0
  222. package/dist/x402/verified-delivery-facilitator.d.ts +285 -0
  223. package/dist/x402/verified-delivery-facilitator.d.ts.map +1 -0
  224. package/dist/x402/verified-delivery-facilitator.js +423 -0
  225. package/dist/x402/verified-delivery-facilitator.js.map +1 -0
  226. package/dist/zktls/t2-delivery-proof.d.ts +6 -6
  227. package/docs/agent-layer.md +14 -9
  228. package/docs/cli.md +705 -0
  229. package/docs/crewai.md +6 -2
  230. package/docs/eliza.md +6 -1
  231. package/docs/mcp-hosted.md +7 -5
  232. package/docs/mcp-reference.md +175 -0
  233. package/docs/quickstart.md +36 -9
  234. package/docs/threat-model.md +4 -3
  235. package/docs/x402.md +648 -0
  236. package/package.json +33 -10
  237. package/src/capability/invocation-capability.ts +17 -1
  238. package/src/cli/amounts.ts +102 -0
  239. package/src/cli/args.ts +150 -0
  240. package/src/cli/attesters.ts +86 -0
  241. package/src/cli/bin.ts +5 -0
  242. package/src/cli/commands/claim.ts +126 -0
  243. package/src/cli/commands/close.ts +69 -0
  244. package/src/cli/commands/discover.ts +228 -0
  245. package/src/cli/commands/invoke.ts +178 -0
  246. package/src/cli/commands/mcp.ts +135 -0
  247. package/src/cli/commands/open.ts +397 -0
  248. package/src/cli/commands/reclaim-unverified.ts +218 -0
  249. package/src/cli/commands/reclaim.ts +377 -0
  250. package/src/cli/commands/status.ts +56 -0
  251. package/src/cli/commands/streams.ts +344 -0
  252. package/src/cli/commands/watch.ts +70 -0
  253. package/src/cli/config.ts +208 -0
  254. package/src/cli/context.ts +30 -0
  255. package/src/cli/deps.ts +528 -0
  256. package/src/cli/descriptor.ts +133 -0
  257. package/src/cli/errors.ts +162 -0
  258. package/src/cli/escape-hatch.ts +92 -0
  259. package/src/cli/index.ts +27 -0
  260. package/src/cli/listings.ts +77 -0
  261. package/src/cli/mandate.ts +126 -0
  262. package/src/cli/output.ts +63 -0
  263. package/src/cli/preflight.ts +88 -0
  264. package/src/cli/privy.ts +396 -0
  265. package/src/cli/progress.ts +75 -0
  266. package/src/cli/run.ts +209 -0
  267. package/src/cli/scan-range.ts +76 -0
  268. package/src/cli/spend-policy.ts +139 -0
  269. package/src/cli/status.ts +381 -0
  270. package/src/cli/timeout.ts +64 -0
  271. package/src/cli/version.ts +21 -0
  272. package/src/cli/wallet.ts +372 -0
  273. package/src/frameworks/crewai.ts +13 -2
  274. package/src/gateway/caller-auth-gateway.ts +77 -6
  275. package/src/gateway/http-server.ts +280 -6
  276. package/src/gateway/server-entry.ts +1 -0
  277. package/src/gateway/x402-mode.ts +350 -0
  278. package/src/index.ts +40 -5
  279. package/src/mandates/env.ts +3 -2
  280. package/src/mcp/http-server.ts +1 -0
  281. package/src/mcp/server.ts +706 -30
  282. package/src/mcp/service-invoker.ts +285 -0
  283. package/src/mcp/stdio.ts +1 -0
  284. package/src/sdk/client.ts +33 -1
  285. package/src/sdk/invoke.ts +90 -12
  286. package/src/x402/delivery-oracle.ts +285 -0
  287. package/src/x402/facilitator-server-entry.ts +35 -0
  288. package/src/x402/facilitator-server.ts +445 -0
  289. package/src/x402/facilitator.ts +125 -46
  290. package/src/x402/payment-requirements.ts +231 -0
  291. package/src/x402/relayer.ts +122 -0
  292. package/src/x402/resource-index.ts +228 -0
  293. package/src/x402/verified-delivery-facilitator.ts +744 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relayer.js","sourceRoot":"","sources":["../../src/x402/relayer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,IAAI,EACJ,aAAa,GAGd,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAa9E;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAoC,MAAM,CAAC,MAAM,CAAC;IACxE,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,WAAW;CACnB,CAAC,CAAC;AASH,SAAS,QAAQ,CAAC,OAAe;IAC/B,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,sCAAsC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAyB;IAEzB,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,kBAAkB,CAAC;QAChC,KAAK;QACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;KAChC,CAAC,CAAC;IACH,OAAO;QACL,MAAM,CACJ,OAAuB,EACvB,YAAiC;YAEjC,OAAO,UAAU,CACf,MAA0C,EAC1C,OAAO,EACP,YAAY,CACb,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAYD;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAA2B;IAE3B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,kBAAkB,CAAC;QAChC,OAAO;QACP,KAAK;QACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;KAChC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACzB,OAAO;QACL,MAAM,CACJ,OAAuB,EACvB,YAAiC;YAEjC,OAAO,UAAU,CACf,MAA0C,EAC1C,OAAO,EACP,YAAY,CACb,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,UAAe;IAC5C,OAAO,mBAAmB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;AACjD,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { type DiscoverServicesOptions, type ServiceListing } from "../discovery/registry.js";
2
+ import type { SignedListingPayee } from "./payment-requirements.js";
3
+ /**
4
+ * Maps an x402 `PaymentRequirements.resource` URL onto the Metrik listing that
5
+ * serves it — the step that decides whether Metrik has any business having an
6
+ * opinion about a payment at all.
7
+ *
8
+ * ## Derived, never supplied
9
+ *
10
+ * The only thing taken from the request is the `resource` URL itself, because
11
+ * the x402 wire format gives the facilitator nothing else to key on. Everything
12
+ * the verdict is actually computed from — which listing that URL belongs to, the
13
+ * operator address on it, and the delivery record for it — is resolved HERE,
14
+ * from Metrik's own verified view of the registry. In particular the
15
+ * `extra.metrikServiceRef` hint that `buildMetrikPaymentRequirements` publishes
16
+ * is deliberately ignored: it rides inside a caller-supplied body, and reading
17
+ * it would let a caller choose which service's delivery record gets checked.
18
+ *
19
+ * ## Origin matching, and why not path matching
20
+ *
21
+ * A listing owns an ORIGIN (scheme + host + port). Matching on origin means a
22
+ * seller does not have to re-register every route, and it cannot over-reach: two
23
+ * listings never share an origin, because the origin is what the oracle probes
24
+ * and what `serviceRef` is derived from. A resource whose origin matches no
25
+ * listing is simply not ours.
26
+ */
27
+ export interface ResolvedMetrikResource extends SignedListingPayee {
28
+ /** The listing, as verified by `discoverServices` (EIP-712 signer recovered). */
29
+ readonly listing: ServiceListing;
30
+ /** Which of the listing's signed origins the resource matched. */
31
+ readonly matchedOrigin: string;
32
+ }
33
+ export type ResourceIndexStatus = "resolved" | "not-listed"
34
+ /**
35
+ * Two or more signed listings claim this origin, so there is no single right
36
+ * answer about whose delivery record applies.
37
+ *
38
+ * Picking one — which "first claimant wins" did — is the origin-squatting
39
+ * primitive: a second listing claiming a victim's origin could take over the
40
+ * victim's gate and permanently refuse their payments. Not exploitable while
41
+ * listing insertion requires an operator-held key, but "unresolvable" costs
42
+ * nothing and removes the primitive before registration ever opens.
43
+ */
44
+ | "ambiguous" | "registry-unavailable";
45
+ export interface ResourceLookup {
46
+ readonly status: ResourceIndexStatus;
47
+ readonly resource?: ResolvedMetrikResource;
48
+ }
49
+ export interface MetrikResourceIndex {
50
+ /** Never throws: an unreachable registry is a status, not an exception. */
51
+ lookup(resourceUrl: string): Promise<ResourceLookup>;
52
+ }
53
+ /** How long a registry snapshot is reused before a refresh is attempted. */
54
+ export declare const DEFAULT_RESOURCE_INDEX_REFRESH_MS = 60000;
55
+ /**
56
+ * How long a stale snapshot keeps being served after refreshes start failing.
57
+ * Serving a stale listing is safe in a way that serving a stale DELIVERY verdict
58
+ * is not: listings change on a human timescale (a new signed descriptor), and
59
+ * the fields used from them — `operator`, `serviceRef` — are the stable ones. The
60
+ * live verdict is always fetched fresh by the delivery oracle.
61
+ */
62
+ export declare const DEFAULT_RESOURCE_INDEX_MAX_STALE_MS: number;
63
+ export interface RegistryResourceIndexOptions {
64
+ readonly discover?: () => Promise<readonly ServiceListing[]>;
65
+ readonly discoverOptions?: DiscoverServicesOptions;
66
+ readonly refreshMs?: number;
67
+ readonly maxStaleMs?: number;
68
+ readonly now?: () => number;
69
+ }
70
+ export declare function createRegistryResourceIndex(options?: RegistryResourceIndexOptions): MetrikResourceIndex;
71
+ /** Every origin the SIGNED record claims for a listing. */
72
+ export declare function signedOriginsOf(listing: ServiceListing): readonly string[];
73
+ /** Normalized `scheme://host[:port]`, or `undefined` if not a usable URL. */
74
+ export declare function originOf(url: string): string | undefined;
75
+ //# sourceMappingURL=resource-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-index.d.ts","sourceRoot":"","sources":["../../src/x402/resource-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,sBAAuB,SAAQ,kBAAkB;IAChE,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,mBAAmB,GAC3B,UAAU,GACV,YAAY;AACd;;;;;;;;;GASG;GACD,WAAW,GACX,sBAAsB,CAAC;AAE3B,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;CAC5C;AAED,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACtD;AAED,4EAA4E;AAC5E,eAAO,MAAM,iCAAiC,QAAS,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,QAAc,CAAC;AAE/D,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;IAC7D,QAAQ,CAAC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,wBAAgB,2BAA2B,CACzC,OAAO,GAAE,4BAAiC,GACzC,mBAAmB,CA+FrB;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,MAAM,EAAE,CA6B1E;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUxD"}
@@ -0,0 +1,126 @@
1
+ import { discoverServices, } from "../discovery/registry.js";
2
+ /** How long a registry snapshot is reused before a refresh is attempted. */
3
+ export const DEFAULT_RESOURCE_INDEX_REFRESH_MS = 60_000;
4
+ /**
5
+ * How long a stale snapshot keeps being served after refreshes start failing.
6
+ * Serving a stale listing is safe in a way that serving a stale DELIVERY verdict
7
+ * is not: listings change on a human timescale (a new signed descriptor), and
8
+ * the fields used from them — `operator`, `serviceRef` — are the stable ones. The
9
+ * live verdict is always fetched fresh by the delivery oracle.
10
+ */
11
+ export const DEFAULT_RESOURCE_INDEX_MAX_STALE_MS = 15 * 60_000;
12
+ export function createRegistryResourceIndex(options = {}) {
13
+ const refreshMs = options.refreshMs ?? DEFAULT_RESOURCE_INDEX_REFRESH_MS;
14
+ const maxStaleMs = options.maxStaleMs ?? DEFAULT_RESOURCE_INDEX_MAX_STALE_MS;
15
+ const now = options.now ?? (() => Date.now());
16
+ const discover = options.discover ??
17
+ (() => discoverServices(options.discoverOptions ?? {}));
18
+ let snapshot;
19
+ let inFlight;
20
+ async function refresh() {
21
+ try {
22
+ const listings = await discover();
23
+ const byOrigin = new Map();
24
+ const ambiguous = new Set();
25
+ for (const listing of listings) {
26
+ for (const origin of signedOriginsOf(listing)) {
27
+ const claimed = byOrigin.get(origin);
28
+ if (claimed === undefined) {
29
+ byOrigin.set(origin, {
30
+ serviceRef: listing.serviceRef,
31
+ operator: listing.operator,
32
+ listing,
33
+ matchedOrigin: origin,
34
+ });
35
+ continue;
36
+ }
37
+ // A DIFFERENT service claiming an origin another already claims makes
38
+ // the origin unresolvable, not first-come-first-served. See the
39
+ // `ambiguous` doc on `ResourceIndexStatus`. A listing re-claiming its
40
+ // OWN origin (e.g. publicUrl and baseUrl agreeing) is not a conflict.
41
+ if (claimed.serviceRef.toLowerCase() !==
42
+ listing.serviceRef.toLowerCase()) {
43
+ ambiguous.add(origin);
44
+ }
45
+ }
46
+ }
47
+ for (const origin of ambiguous) {
48
+ byOrigin.delete(origin);
49
+ }
50
+ return { loadedAtMs: now(), byOrigin, ambiguous };
51
+ }
52
+ catch {
53
+ return undefined;
54
+ }
55
+ }
56
+ async function currentSnapshot() {
57
+ const cached = snapshot;
58
+ if (cached !== undefined && now() - cached.loadedAtMs < refreshMs) {
59
+ return cached;
60
+ }
61
+ inFlight ??= refresh().finally(() => {
62
+ inFlight = undefined;
63
+ });
64
+ const loaded = await inFlight;
65
+ if (loaded !== undefined) {
66
+ snapshot = loaded;
67
+ return loaded;
68
+ }
69
+ if (cached !== undefined && now() - cached.loadedAtMs <= maxStaleMs) {
70
+ return cached;
71
+ }
72
+ return undefined;
73
+ }
74
+ return {
75
+ async lookup(resourceUrl) {
76
+ const origin = originOf(resourceUrl);
77
+ if (origin === undefined) {
78
+ return { status: "not-listed" };
79
+ }
80
+ const loaded = await currentSnapshot();
81
+ if (loaded === undefined) {
82
+ return { status: "registry-unavailable" };
83
+ }
84
+ if (loaded.ambiguous.has(origin)) {
85
+ return { status: "ambiguous" };
86
+ }
87
+ const resource = loaded.byOrigin.get(origin);
88
+ return resource === undefined
89
+ ? { status: "not-listed" }
90
+ : { status: "resolved", resource };
91
+ },
92
+ };
93
+ }
94
+ /** Every origin the SIGNED record claims for a listing. */
95
+ export function signedOriginsOf(listing) {
96
+ const candidates = [
97
+ listing.publicUrl,
98
+ listing.accessUrl,
99
+ ];
100
+ const descriptor = listing.signed.descriptor;
101
+ if (descriptor !== undefined) {
102
+ candidates.push(descriptor.publicUrl, descriptor.interface?.baseUrl, descriptor.callerAuth?.accessUrl);
103
+ }
104
+ const origins = new Set();
105
+ for (const candidate of candidates) {
106
+ const origin = candidate === undefined ? undefined : originOf(candidate);
107
+ if (origin !== undefined) {
108
+ origins.add(origin);
109
+ }
110
+ }
111
+ return [...origins];
112
+ }
113
+ /** Normalized `scheme://host[:port]`, or `undefined` if not a usable URL. */
114
+ export function originOf(url) {
115
+ try {
116
+ const parsed = new URL(url);
117
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
118
+ return undefined;
119
+ }
120
+ return `${parsed.protocol}//${parsed.host.toLowerCase()}`;
121
+ }
122
+ catch {
123
+ return undefined;
124
+ }
125
+ }
126
+ //# sourceMappingURL=resource-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-index.js","sourceRoot":"","sources":["../../src/x402/resource-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,285 @@
1
+ import { type PaymentPayload, type PaymentRequirements, type SettleResponse, type VerifyResponse } from "x402/types";
2
+ import type { DeliveryVerdict, DeliveryVerdictReason, MetrikDeliveryOracle } from "./delivery-oracle.js";
3
+ import type { MetrikResourceIndex } from "./resource-index.js";
4
+ /**
5
+ * Metrik's x402 facilitator: a fully conformant `exact` facilitator that ALSO
6
+ * refuses to settle payment for a service its own oracle says is not delivering.
7
+ *
8
+ * ## Why this is spec-legal
9
+ *
10
+ * `VerifyResponse` is `{ isValid: boolean, invalidReason?, payer? }`. Nothing in
11
+ * the x402 specification constrains WHY a facilitator answers `false`. A
12
+ * facilitator is the party a resource server delegates its "should this payment
13
+ * go through" decision to; Metrik simply knows one more thing than every other
14
+ * facilitator, because it runs a prober.
15
+ *
16
+ * ## What this is NOT
17
+ *
18
+ * **This is strictly weaker buyer protection than a Metrik escrow stream.** A
19
+ * stream holds the buyer's money and releases it only for intervals that
20
+ * verified, so money already spent on a service that stopped delivering is
21
+ * recoverable. This gate holds nothing. It can only prevent a payment that has
22
+ * not happened yet; it can never recover one that has. An `exact` payment that
23
+ * Metrik lets through is gone, exactly as it would be through any other
24
+ * facilitator.
25
+ *
26
+ * And `isValid: true` from this facilitator is NOT an endorsement. It means only
27
+ * "the payment is well-formed and Metrik has no fresh evidence that this service
28
+ * is failing". The gate subtracts; it never adds.
29
+ *
30
+ * ## Scope: only services Metrik actually tracks
31
+ *
32
+ * A resource that maps to no Metrik listing gets the ordinary facilitator
33
+ * answer, unchanged. Refusing payments for services Metrik has no opinion about
34
+ * would not be caution, it would be a broken facilitator.
35
+ */
36
+ /** What the delivery gate did to a payment. */
37
+ export type MetrikGateOutcome =
38
+ /** The resource is not a Metrik listing — ordinary facilitator behaviour. */
39
+ "not-applicable"
40
+ /** Fresh evidence the service is delivering; payment allowed to proceed. */
41
+ | "passed"
42
+ /** Fresh evidence the service is failing; payment refused. */
43
+ | "refused"
44
+ /** No fresh evidence; `indeterminatePolicy` decided. */
45
+ | "indeterminate"
46
+ /** The resource's payee is not the operator who signed the listing. */
47
+ | "payee-mismatch"
48
+ /** Metrik could not tell whether the resource is one of its listings. */
49
+ | "registry-unavailable";
50
+ /** The delivery gate's own verdict, before settlement policy is applied. */
51
+ export interface MetrikGateVerdict {
52
+ readonly gate: MetrikGateOutcome;
53
+ /** Human-readable explanation. See "Where the explanation goes" below. */
54
+ readonly detail: string;
55
+ readonly serviceRef?: string;
56
+ readonly deliveryVerdict?: DeliveryVerdict;
57
+ readonly deliveryReason?: DeliveryVerdictReason;
58
+ readonly lastCheckedAt?: number | null;
59
+ readonly verdictAgeSeconds?: number | null;
60
+ readonly freshnessWindowSeconds?: number;
61
+ }
62
+ export interface MetrikGateAnnotation extends MetrikGateVerdict {
63
+ /**
64
+ * Whether THIS facilitator would broadcast this payment if asked.
65
+ *
66
+ * Distinct from `isValid`, and deliberately reported on `/verify`: a payment
67
+ * can be perfectly valid and still be one this relayer will not spend its own
68
+ * gas on (see {@link SettlementRefusalReason}). Reporting it up front lets a
69
+ * resource server refuse BEFORE it executes the request, instead of doing the
70
+ * work and then failing to get paid for it.
71
+ */
72
+ readonly settleable: boolean;
73
+ /** Why `settleable` is false. Absent when it is true. */
74
+ readonly settlementRefusal?: SettlementRefusalReason;
75
+ }
76
+ export declare const SETTLEMENT_REFUSAL_DETAIL: Readonly<Record<SettlementRefusalReason, string>>;
77
+ /**
78
+ * A `VerifyResponse` with Metrik's reasoning attached.
79
+ *
80
+ * ### Where the explanation goes
81
+ *
82
+ * `invalidReason` is a CLOSED enum in the x402 spec and there is no member for
83
+ * "this service is not delivering". Inventing one would break every conformant
84
+ * client that parses the field. So the enum carries the closest honest member
85
+ * (see {@link DELIVERY_REFUSAL_REASON}) and the real explanation travels in a
86
+ * `metrik` object alongside it.
87
+ *
88
+ * `VerifyResponseSchema` is a `strip` (not `strict`) Zod object, so this extra
89
+ * key is spec-tolerated: a conformant client parses the response successfully
90
+ * and simply drops `metrik`. A client that wants the reason can read it off the
91
+ * raw body. Nothing about the standard fields changes.
92
+ */
93
+ export type MetrikVerifyResponse = VerifyResponse & {
94
+ readonly metrik: MetrikGateAnnotation;
95
+ };
96
+ export type MetrikSettleResponse = SettleResponse & {
97
+ readonly metrik: MetrikGateAnnotation;
98
+ };
99
+ /**
100
+ * Why this facilitator will not BROADCAST a payment, independent of whether the
101
+ * payment is valid.
102
+ *
103
+ * `/settle` makes the operator's relayer sign and broadcast a call to
104
+ * `paymentRequirements.asset` and pay the gas for it. Every field of
105
+ * `PaymentRequirements` arrives in the request body, and `PaymentRequirementsSchema`
106
+ * accepts ANY `asset` address, ANY `payTo`, `maxAmountRequired: "0"`, and any
107
+ * valid-URL `resource`. The library's `verify` only checks the payload against
108
+ * those same caller-supplied requirements — signature recovers to
109
+ * `authorization.from`, `to === payTo`, window valid, and
110
+ * `balanceOf(from) >= maxAmountRequired` **on the caller-supplied asset**. An
111
+ * attacker signing from their own key to their own address satisfies all of it.
112
+ *
113
+ * Without the checks below, `/settle` is a permissionless "make the relayer
114
+ * broadcast a call to a contract of my choosing" endpoint: deploy something
115
+ * whose `balanceOf` returns a huge number and whose `transferWithAuthorization`
116
+ * burns gas, and drain the relayer until legitimate settlement stops. No funds
117
+ * are stolen — but it is the operator's money, and it induces the operator's key
118
+ * to sign transactions to contracts they never chose.
119
+ *
120
+ * The asset allowlist is the one that removes the arbitrary-contract-call
121
+ * primitive outright; the rest are defence in depth.
122
+ */
123
+ export type SettlementRefusalReason =
124
+ /** `asset` is not an operator-approved settlement token. */
125
+ "asset-not-allowed"
126
+ /** The payload or the requirements name a chain this facilitator does not settle. */
127
+ | "network-mismatch"
128
+ /** A zero-value settlement moves nothing and only burns the relayer's gas. */
129
+ | "zero-amount"
130
+ /** The relayer only pays gas for resources Metrik actually tracks. */
131
+ | "resource-not-tracked";
132
+ /**
133
+ * Which resources this facilitator will spend the relayer's gas on.
134
+ *
135
+ * `tracked-resources` (default) is a deliberate ASYMMETRY with the delivery
136
+ * gate's allow-by-default policy, and the asymmetry is the point: an OPINION
137
+ * about a service costs nothing and should be given freely, so `/verify` stays
138
+ * universal and fails open. BROADCASTING costs the operator real gas, so
139
+ * `/settle` fails closed and is scoped to Metrik's own marketplace.
140
+ *
141
+ * This is not a censorship lever. Metrik declining to spend its own gas does
142
+ * not stop anyone being paid — any other facilitator (or the payer's own
143
+ * relayer) can settle the same payment.
144
+ *
145
+ * `any-resource` is for an operator deliberately running a general-purpose
146
+ * facilitator on a relayer they are content to fund for anyone's traffic. The
147
+ * asset allowlist still applies.
148
+ */
149
+ export type SettlementScope = "tracked-resources" | "any-resource";
150
+ export declare const DEFAULT_SETTLEMENT_SCOPE: SettlementScope;
151
+ /**
152
+ * The `invalidReason` used when the delivery gate refuses.
153
+ *
154
+ * The enum has no member for "the resource is not delivering", so the choice is
155
+ * between members that are all imperfect. Every payer-side member
156
+ * (`invalid_payload`, `invalid_exact_evm_payload_signature`,
157
+ * `insufficient_funds`) would be an active lie: it sends the developer to debug
158
+ * a wallet that is working correctly. `unexpected_verify_error` is also false —
159
+ * this refusal is deliberate and expected, not an error.
160
+ *
161
+ * `invalid_payment_requirements` is the only member that points at the
162
+ * REQUIREMENTS side of the exchange, which is exactly where the problem is:
163
+ * Metrik will not settle a payment quoted for THIS resource to THIS payee right
164
+ * now. It is the honest member, and the `metrik.detail` string carries the rest.
165
+ */
166
+ export declare const DELIVERY_REFUSAL_REASON: "invalid_payment_requirements";
167
+ /** What to do when Metrik has no fresh delivery evidence. */
168
+ export type IndeterminatePolicy = "allow" | "deny";
169
+ /**
170
+ * Default: `allow`.
171
+ *
172
+ * The standing Metrik rule is buyer-favouring, and it still is — but it applies
173
+ * where Metrik HOLDS the buyer's money and must decide whether to release it.
174
+ * Here Metrik holds nothing, so refusing does not protect a buyer's funds; it
175
+ * only denies them a service they asked to buy, on a rail that works fine
176
+ * without Metrik. Four things make `allow` the right default:
177
+ *
178
+ * 1. **Absent evidence is the normal case, not the exception.** The oracle's
179
+ * `/services` projection is built from ACTIVE STREAMS. A service with no live
180
+ * Metrik stream has no row at all — on the live oracle today that is every
181
+ * service. Failing closed would refuse 100% of payments, which is a broken
182
+ * facilitator rather than a careful one.
183
+ * 2. **Fail-closed is a censorship lever.** If "oracle down" meant "no payments",
184
+ * anyone who could degrade Metrik's oracle could block payments to a
185
+ * competitor listed on it. `allow` removes that lever entirely.
186
+ * 3. **The harms are asymmetric.** A wrong refusal denies a service outright. A
187
+ * wrong allowance passes one `exact` payment, at a price the buyer already
188
+ * agreed to, which by construction is one call's worth.
189
+ * 4. **A pass never claims anything.** `isValid: true` with
190
+ * `gate: "indeterminate"` says "no fresh evidence", and the annotation says
191
+ * so in the response. Nobody has to infer an endorsement that was not made.
192
+ *
193
+ * Set `indeterminatePolicy: "deny"` for a deployment that would rather refuse
194
+ * than proceed without positive fresh evidence. That is a real, supported
195
+ * choice — it is just not a safe default.
196
+ */
197
+ export declare const DEFAULT_INDETERMINATE_POLICY: IndeterminatePolicy;
198
+ /** The payment-validity half of the facilitator (signature, amount, funds, window). */
199
+ export interface PaymentVerifier {
200
+ verify(payload: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;
201
+ }
202
+ /** The broadcast half. Requires a funded relayer wallet. */
203
+ export interface PaymentSettler {
204
+ settle(payload: PaymentPayload, requirements: PaymentRequirements): Promise<SettleResponse>;
205
+ }
206
+ export declare class RelayerNotConfiguredError extends Error {
207
+ constructor();
208
+ }
209
+ export interface MetrikVerifiedDeliveryFacilitatorOptions {
210
+ readonly paymentVerifier: PaymentVerifier;
211
+ /** Omit to run a verify-only facilitator: `/settle` then fails loudly. */
212
+ readonly paymentSettler?: PaymentSettler;
213
+ readonly resourceIndex: MetrikResourceIndex;
214
+ readonly deliveryOracle: MetrikDeliveryOracle;
215
+ /** Default {@link DEFAULT_INDETERMINATE_POLICY}. */
216
+ readonly indeterminatePolicy?: IndeterminatePolicy;
217
+ /** Chain this facilitator settles on. Default `84532` (Base Sepolia). */
218
+ readonly chainId?: number;
219
+ /**
220
+ * Token contracts the relayer may be asked to call. Defaults to the single
221
+ * canonical USDC for `chainId`. An empty array is rejected: a settling
222
+ * facilitator with no allowed asset can never settle anything, and silently
223
+ * accepting that would hide a misconfiguration.
224
+ *
225
+ * THIS IS THE CONTROL that stops `/settle` being an arbitrary-contract-call
226
+ * primitive. See {@link SettlementRefusalReason}.
227
+ */
228
+ readonly settlementAssetAllowlist?: readonly string[];
229
+ /** Default {@link DEFAULT_SETTLEMENT_SCOPE}. */
230
+ readonly settlementScope?: SettlementScope;
231
+ }
232
+ export interface FacilitatorSupported {
233
+ readonly x402Version: number;
234
+ readonly kind: readonly {
235
+ readonly scheme: string;
236
+ readonly networkId: string;
237
+ readonly extra: object;
238
+ }[];
239
+ }
240
+ export declare class MetrikVerifiedDeliveryFacilitator {
241
+ private readonly paymentVerifier;
242
+ private readonly paymentSettler;
243
+ private readonly resourceIndex;
244
+ private readonly deliveryOracle;
245
+ private readonly indeterminatePolicy;
246
+ private readonly network;
247
+ private readonly settlementAssets;
248
+ private readonly settlementScope;
249
+ constructor(options: MetrikVerifiedDeliveryFacilitatorOptions);
250
+ /** The assets this relayer may be asked to call, for logging at startup. */
251
+ get allowedSettlementAssets(): readonly string[];
252
+ supported(): FacilitatorSupported;
253
+ /** `POST /verify`. Takes an unvalidated body; never throws on bad input. */
254
+ verify(body: unknown): Promise<MetrikVerifyResponse>;
255
+ /**
256
+ * `POST /settle`. Re-runs the full gate before broadcasting: a facilitator
257
+ * must never settle something it would not verify, and `/settle` is reachable
258
+ * without `/verify` ever having been called.
259
+ */
260
+ settle(body: unknown): Promise<MetrikSettleResponse>;
261
+ /**
262
+ * Settlement constraints checkable from the request alone — no RPC, no
263
+ * registry, no oracle. Returns the refusal, or `undefined` if the request
264
+ * clears them.
265
+ */
266
+ private settlementPreflight;
267
+ /** Builds the standard-shaped refusal for a settlement the relayer declines. */
268
+ private refuseSettlement;
269
+ private evaluate;
270
+ /** Does this gate outcome name a resource the relayer will pay gas for? */
271
+ private scopeRefusal;
272
+ private evaluateGate;
273
+ private applyIndeterminate;
274
+ }
275
+ interface ParsedFacilitatorRequest {
276
+ readonly paymentPayload: PaymentPayload;
277
+ readonly paymentRequirements: PaymentRequirements;
278
+ }
279
+ /**
280
+ * Parses the facilitator wire body with the REAL x402 schemas. Both `/verify`
281
+ * and `/settle` take the same `{paymentPayload, paymentRequirements}` pair.
282
+ */
283
+ export declare function parseFacilitatorRequest(body: unknown): ParsedFacilitatorRequest | undefined;
284
+ export {};
285
+ //# sourceMappingURL=verified-delivery-facilitator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verified-delivery-facilitator.d.ts","sourceRoot":"","sources":["../../src/x402/verified-delivery-facilitator.ts"],"names":[],"mappings":"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"}