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

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 (350) hide show
  1. package/README.md +42 -50
  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.js +1 -1
  12. package/dist/cli/commands/claim.js.map +1 -1
  13. package/dist/cli/commands/close.d.ts.map +1 -1
  14. package/dist/cli/commands/close.js +35 -3
  15. package/dist/cli/commands/close.js.map +1 -1
  16. package/dist/cli/commands/invoke.d.ts +2 -0
  17. package/dist/cli/commands/invoke.d.ts.map +1 -1
  18. package/dist/cli/commands/invoke.js +2 -2
  19. package/dist/cli/commands/invoke.js.map +1 -1
  20. package/dist/cli/commands/mcp.d.ts.map +1 -1
  21. package/dist/cli/commands/mcp.js +15 -2
  22. package/dist/cli/commands/mcp.js.map +1 -1
  23. package/dist/cli/commands/open.d.ts.map +1 -1
  24. package/dist/cli/commands/open.js +58 -4
  25. package/dist/cli/commands/open.js.map +1 -1
  26. package/dist/cli/commands/pay.d.ts +19 -0
  27. package/dist/cli/commands/pay.d.ts.map +1 -0
  28. package/dist/cli/commands/pay.js +355 -0
  29. package/dist/cli/commands/pay.js.map +1 -0
  30. package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -1
  31. package/dist/cli/commands/reclaim-unverified.js +3 -2
  32. package/dist/cli/commands/reclaim-unverified.js.map +1 -1
  33. package/dist/cli/commands/reclaim.d.ts +23 -2
  34. package/dist/cli/commands/reclaim.d.ts.map +1 -1
  35. package/dist/cli/commands/reclaim.js +184 -16
  36. package/dist/cli/commands/reclaim.js.map +1 -1
  37. package/dist/cli/commands/refund.d.ts +13 -0
  38. package/dist/cli/commands/refund.d.ts.map +1 -0
  39. package/dist/cli/commands/refund.js +224 -0
  40. package/dist/cli/commands/refund.js.map +1 -0
  41. package/dist/cli/commands/status.d.ts.map +1 -1
  42. package/dist/cli/commands/status.js +10 -1
  43. package/dist/cli/commands/status.js.map +1 -1
  44. package/dist/cli/commands/streams.js +8 -12
  45. package/dist/cli/commands/streams.js.map +1 -1
  46. package/dist/cli/commands/watch.d.ts.map +1 -1
  47. package/dist/cli/commands/watch.js +2 -1
  48. package/dist/cli/commands/watch.js.map +1 -1
  49. package/dist/cli/config.d.ts +44 -26
  50. package/dist/cli/config.d.ts.map +1 -1
  51. package/dist/cli/config.js +88 -38
  52. package/dist/cli/config.js.map +1 -1
  53. package/dist/cli/deps.d.ts +33 -0
  54. package/dist/cli/deps.d.ts.map +1 -1
  55. package/dist/cli/deps.js +37 -1
  56. package/dist/cli/deps.js.map +1 -1
  57. package/dist/cli/errors.d.ts.map +1 -1
  58. package/dist/cli/errors.js +21 -1
  59. package/dist/cli/errors.js.map +1 -1
  60. package/dist/cli/escape-hatch.d.ts +6 -4
  61. package/dist/cli/escape-hatch.d.ts.map +1 -1
  62. package/dist/cli/escape-hatch.js +6 -2
  63. package/dist/cli/escape-hatch.js.map +1 -1
  64. package/dist/cli/listings.d.ts +18 -0
  65. package/dist/cli/listings.d.ts.map +1 -1
  66. package/dist/cli/listings.js +22 -12
  67. package/dist/cli/listings.js.map +1 -1
  68. package/dist/cli/preflight.d.ts +20 -14
  69. package/dist/cli/preflight.d.ts.map +1 -1
  70. package/dist/cli/preflight.js +34 -20
  71. package/dist/cli/preflight.js.map +1 -1
  72. package/dist/cli/privy.d.ts.map +1 -1
  73. package/dist/cli/privy.js +4 -2
  74. package/dist/cli/privy.js.map +1 -1
  75. package/dist/cli/reclaimability.d.ts +82 -0
  76. package/dist/cli/reclaimability.d.ts.map +1 -0
  77. package/dist/cli/reclaimability.js +80 -0
  78. package/dist/cli/reclaimability.js.map +1 -0
  79. package/dist/cli/run.d.ts +2 -1
  80. package/dist/cli/run.d.ts.map +1 -1
  81. package/dist/cli/run.js +40 -11
  82. package/dist/cli/run.js.map +1 -1
  83. package/dist/cli/scan-range.d.ts +2 -2
  84. package/dist/cli/scan-range.js +2 -2
  85. package/dist/cli/status.d.ts +3 -1
  86. package/dist/cli/status.d.ts.map +1 -1
  87. package/dist/cli/status.js +15 -3
  88. package/dist/cli/status.js.map +1 -1
  89. package/dist/cli/wallet.d.ts +1 -1
  90. package/dist/cli/wallet.js +2 -2
  91. package/dist/cli/wallet.js.map +1 -1
  92. package/dist/discovery/rate-band.d.ts +74 -0
  93. package/dist/discovery/rate-band.d.ts.map +1 -0
  94. package/dist/discovery/rate-band.js +114 -0
  95. package/dist/discovery/rate-band.js.map +1 -0
  96. package/dist/escrow-generation.d.ts +81 -0
  97. package/dist/escrow-generation.d.ts.map +1 -0
  98. package/dist/escrow-generation.js +76 -0
  99. package/dist/escrow-generation.js.map +1 -0
  100. package/dist/frameworks/agentkit.d.ts +8 -4
  101. package/dist/frameworks/agentkit.d.ts.map +1 -1
  102. package/dist/frameworks/agentkit.js +27 -10
  103. package/dist/frameworks/agentkit.js.map +1 -1
  104. package/dist/frameworks/eliza.d.ts +3 -3
  105. package/dist/frameworks/eliza.d.ts.map +1 -1
  106. package/dist/frameworks/eliza.js +15 -6
  107. package/dist/frameworks/eliza.js.map +1 -1
  108. package/dist/frameworks/langchain.d.ts.map +1 -1
  109. package/dist/frameworks/langchain.js +8 -0
  110. package/dist/frameworks/langchain.js.map +1 -1
  111. package/dist/gateway/caller-auth-gateway.d.ts +83 -31
  112. package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
  113. package/dist/gateway/caller-auth-gateway.js +180 -27
  114. package/dist/gateway/caller-auth-gateway.js.map +1 -1
  115. package/dist/gateway/http-server.d.ts +111 -44
  116. package/dist/gateway/http-server.d.ts.map +1 -1
  117. package/dist/gateway/http-server.js +439 -155
  118. package/dist/gateway/http-server.js.map +1 -1
  119. package/dist/gateway/probe-auth.d.ts +112 -0
  120. package/dist/gateway/probe-auth.d.ts.map +1 -0
  121. package/dist/gateway/probe-auth.js +127 -0
  122. package/dist/gateway/probe-auth.js.map +1 -0
  123. package/dist/gateway/signed-rate-bounds.d.ts +51 -0
  124. package/dist/gateway/signed-rate-bounds.d.ts.map +1 -0
  125. package/dist/gateway/signed-rate-bounds.js +94 -0
  126. package/dist/gateway/signed-rate-bounds.js.map +1 -0
  127. package/dist/gateway/x402-opener-mode.d.ts +215 -0
  128. package/dist/gateway/x402-opener-mode.d.ts.map +1 -0
  129. package/dist/gateway/x402-opener-mode.js +639 -0
  130. package/dist/gateway/x402-opener-mode.js.map +1 -0
  131. package/dist/index.d.ts +6 -2
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +10 -5
  134. package/dist/index.js.map +1 -1
  135. package/dist/mcp/server.d.ts +52 -1
  136. package/dist/mcp/server.d.ts.map +1 -1
  137. package/dist/mcp/server.js +228 -37
  138. package/dist/mcp/server.js.map +1 -1
  139. package/dist/mcp/x402-tools.d.ts +104 -0
  140. package/dist/mcp/x402-tools.d.ts.map +1 -0
  141. package/dist/mcp/x402-tools.js +434 -0
  142. package/dist/mcp/x402-tools.js.map +1 -0
  143. package/dist/network.d.ts +119 -0
  144. package/dist/network.d.ts.map +1 -0
  145. package/dist/network.js +199 -0
  146. package/dist/network.js.map +1 -0
  147. package/dist/sdk/invoke.d.ts +4 -0
  148. package/dist/sdk/invoke.d.ts.map +1 -1
  149. package/dist/sdk/invoke.js +2 -5
  150. package/dist/sdk/invoke.js.map +1 -1
  151. package/dist/wallet/autonomous-wallet-broker.d.ts +3 -0
  152. package/dist/wallet/autonomous-wallet-broker.d.ts.map +1 -1
  153. package/dist/wallet/autonomous-wallet-broker.js +27 -23
  154. package/dist/wallet/autonomous-wallet-broker.js.map +1 -1
  155. package/dist/wallet/autonomous-wallet-protocol.d.ts +8 -2
  156. package/dist/wallet/autonomous-wallet-protocol.d.ts.map +1 -1
  157. package/dist/wallet/autonomous-wallet-protocol.js +9 -2
  158. package/dist/wallet/autonomous-wallet-protocol.js.map +1 -1
  159. package/dist/wallet/autonomous-wallet.d.ts.map +1 -1
  160. package/dist/wallet/autonomous-wallet.js +3 -2
  161. package/dist/wallet/autonomous-wallet.js.map +1 -1
  162. package/dist/wallet/broker-escrows.d.ts +222 -0
  163. package/dist/wallet/broker-escrows.d.ts.map +1 -0
  164. package/dist/wallet/broker-escrows.js +36 -0
  165. package/dist/wallet/broker-escrows.js.map +1 -0
  166. package/dist/wallet/lifecycle.d.ts +21 -5
  167. package/dist/wallet/lifecycle.d.ts.map +1 -1
  168. package/dist/wallet/lifecycle.js +32 -12
  169. package/dist/wallet/lifecycle.js.map +1 -1
  170. package/dist/wallet/privy-broker-server.d.ts.map +1 -1
  171. package/dist/wallet/privy-broker-server.js +31 -26
  172. package/dist/wallet/privy-broker-server.js.map +1 -1
  173. package/dist/wallet/privy-session-broker.d.ts +14 -5
  174. package/dist/wallet/privy-session-broker.d.ts.map +1 -1
  175. package/dist/wallet/privy-session-broker.js +29 -17
  176. package/dist/wallet/privy-session-broker.js.map +1 -1
  177. package/dist/wallet/privy-session-provider.d.ts +3 -1
  178. package/dist/wallet/privy-session-provider.d.ts.map +1 -1
  179. package/dist/wallet/privy-session-provider.js +5 -3
  180. package/dist/wallet/privy-session-provider.js.map +1 -1
  181. package/dist/wallet/provider.d.ts.map +1 -1
  182. package/dist/wallet/provider.js +15 -8
  183. package/dist/wallet/provider.js.map +1 -1
  184. package/dist/x402/facilitator.d.ts +3 -30
  185. package/dist/x402/facilitator.d.ts.map +1 -1
  186. package/dist/x402/facilitator.js +0 -27
  187. package/dist/x402/facilitator.js.map +1 -1
  188. package/dist/x402-buyer/guarded-fetch.d.ts +51 -0
  189. package/dist/x402-buyer/guarded-fetch.d.ts.map +1 -0
  190. package/dist/x402-buyer/guarded-fetch.js +147 -0
  191. package/dist/x402-buyer/guarded-fetch.js.map +1 -0
  192. package/dist/x402-buyer/index.d.ts +10 -0
  193. package/dist/x402-buyer/index.d.ts.map +1 -0
  194. package/dist/x402-buyer/index.js +10 -0
  195. package/dist/x402-buyer/index.js.map +1 -0
  196. package/dist/x402-buyer/pay.d.ts +135 -0
  197. package/dist/x402-buyer/pay.d.ts.map +1 -0
  198. package/dist/x402-buyer/pay.js +336 -0
  199. package/dist/x402-buyer/pay.js.map +1 -0
  200. package/dist/x402-opener/abi.d.ts +684 -0
  201. package/dist/x402-opener/abi.d.ts.map +1 -0
  202. package/dist/x402-opener/abi.js +880 -0
  203. package/dist/x402-opener/abi.js.map +1 -0
  204. package/dist/x402-opener/facilitator-entry.d.ts +3 -0
  205. package/dist/x402-opener/facilitator-entry.d.ts.map +1 -0
  206. package/dist/x402-opener/facilitator-entry.js +37 -0
  207. package/dist/x402-opener/facilitator-entry.js.map +1 -0
  208. package/dist/x402-opener/facilitator-server.d.ts +180 -0
  209. package/dist/x402-opener/facilitator-server.d.ts.map +1 -0
  210. package/dist/x402-opener/facilitator-server.js +696 -0
  211. package/dist/x402-opener/facilitator-server.js.map +1 -0
  212. package/dist/x402-opener/index.d.ts +14 -0
  213. package/dist/x402-opener/index.d.ts.map +1 -0
  214. package/dist/x402-opener/index.js +14 -0
  215. package/dist/x402-opener/index.js.map +1 -0
  216. package/dist/x402-opener/listing-resolver.d.ts +55 -0
  217. package/dist/x402-opener/listing-resolver.d.ts.map +1 -0
  218. package/dist/x402-opener/listing-resolver.js +125 -0
  219. package/dist/x402-opener/listing-resolver.js.map +1 -0
  220. package/dist/x402-opener/refund-relay.d.ts +240 -0
  221. package/dist/x402-opener/refund-relay.d.ts.map +1 -0
  222. package/dist/x402-opener/refund-relay.js +1240 -0
  223. package/dist/x402-opener/refund-relay.js.map +1 -0
  224. package/dist/x402-opener/relayer-queue.d.ts +14 -0
  225. package/dist/x402-opener/relayer-queue.d.ts.map +1 -0
  226. package/dist/x402-opener/relayer-queue.js +18 -0
  227. package/dist/x402-opener/relayer-queue.js.map +1 -0
  228. package/dist/x402-opener/scheme.d.ts +217 -0
  229. package/dist/x402-opener/scheme.d.ts.map +1 -0
  230. package/dist/x402-opener/scheme.js +749 -0
  231. package/dist/x402-opener/scheme.js.map +1 -0
  232. package/dist/x402-opener/terms.d.ts +105 -0
  233. package/dist/x402-opener/terms.d.ts.map +1 -0
  234. package/dist/x402-opener/terms.js +212 -0
  235. package/dist/x402-opener/terms.js.map +1 -0
  236. package/dist/zktls/reclaim.d.ts +2 -2
  237. package/dist/zktls/t2-delivery-proof.d.ts +6 -6
  238. package/docs/agent-layer.md +3 -2
  239. package/docs/autonomous-privy-wallet.md +188 -0
  240. package/docs/cli.md +184 -31
  241. package/docs/langchain.md +5 -0
  242. package/docs/mcp-reference.md +75 -5
  243. package/docs/probe-capability.md +191 -0
  244. package/docs/quickstart.md +36 -1
  245. package/docs/threat-model.md +20 -0
  246. package/docs/x402.md +628 -595
  247. package/package.json +19 -17
  248. package/src/capability/probe-capability.ts +355 -0
  249. package/src/cli/args.ts +29 -0
  250. package/src/cli/commands/claim.ts +1 -1
  251. package/src/cli/commands/close.ts +36 -3
  252. package/src/cli/commands/invoke.ts +5 -2
  253. package/src/cli/commands/mcp.ts +18 -2
  254. package/src/cli/commands/open.ts +75 -4
  255. package/src/cli/commands/pay.ts +442 -0
  256. package/src/cli/commands/reclaim-unverified.ts +8 -2
  257. package/src/cli/commands/reclaim.ts +252 -14
  258. package/src/cli/commands/refund.ts +277 -0
  259. package/src/cli/commands/status.ts +17 -1
  260. package/src/cli/commands/streams.ts +10 -14
  261. package/src/cli/commands/watch.ts +7 -1
  262. package/src/cli/config.ts +139 -52
  263. package/src/cli/deps.ts +74 -1
  264. package/src/cli/errors.ts +24 -1
  265. package/src/cli/escape-hatch.ts +19 -5
  266. package/src/cli/listings.ts +43 -10
  267. package/src/cli/preflight.ts +36 -21
  268. package/src/cli/privy.ts +4 -2
  269. package/src/cli/reclaimability.ts +154 -0
  270. package/src/cli/run.ts +54 -11
  271. package/src/cli/scan-range.ts +2 -2
  272. package/src/cli/status.ts +14 -1
  273. package/src/cli/wallet.ts +2 -2
  274. package/src/discovery/rate-band.ts +172 -0
  275. package/src/escrow-generation.ts +135 -0
  276. package/src/frameworks/agentkit.ts +45 -11
  277. package/src/frameworks/eliza.ts +27 -5
  278. package/src/frameworks/langchain.ts +14 -0
  279. package/src/gateway/caller-auth-gateway.ts +320 -68
  280. package/src/gateway/http-server.ts +629 -220
  281. package/src/gateway/probe-auth.ts +191 -0
  282. package/src/gateway/signed-rate-bounds.ts +164 -0
  283. package/src/gateway/x402-opener-mode.ts +974 -0
  284. package/src/index.ts +82 -19
  285. package/src/mcp/server.ts +319 -42
  286. package/src/mcp/x402-tools.ts +621 -0
  287. package/src/network.ts +302 -0
  288. package/src/sdk/invoke.ts +6 -5
  289. package/src/wallet/autonomous-wallet-broker.ts +46 -20
  290. package/src/wallet/autonomous-wallet-protocol.ts +11 -2
  291. package/src/wallet/autonomous-wallet.ts +4 -2
  292. package/src/wallet/broker-escrows.ts +66 -0
  293. package/src/wallet/lifecycle.ts +53 -18
  294. package/src/wallet/privy-broker-server.ts +35 -25
  295. package/src/wallet/privy-session-broker.ts +58 -25
  296. package/src/wallet/privy-session-provider.ts +7 -3
  297. package/src/wallet/provider.ts +20 -15
  298. package/src/x402/facilitator.ts +3 -43
  299. package/src/x402-buyer/guarded-fetch.ts +213 -0
  300. package/src/x402-buyer/index.ts +9 -0
  301. package/src/x402-buyer/pay.ts +517 -0
  302. package/src/x402-opener/abi.ts +881 -0
  303. package/src/x402-opener/facilitator-entry.ts +45 -0
  304. package/src/x402-opener/facilitator-server.ts +1014 -0
  305. package/src/x402-opener/index.ts +13 -0
  306. package/src/x402-opener/listing-resolver.ts +202 -0
  307. package/src/x402-opener/refund-relay.ts +1743 -0
  308. package/src/x402-opener/relayer-queue.ts +18 -0
  309. package/src/x402-opener/scheme.ts +1133 -0
  310. package/src/x402-opener/terms.ts +300 -0
  311. package/dist/gateway/x402-mode.d.ts +0 -123
  312. package/dist/gateway/x402-mode.d.ts.map +0 -1
  313. package/dist/gateway/x402-mode.js +0 -212
  314. package/dist/gateway/x402-mode.js.map +0 -1
  315. package/dist/x402/delivery-oracle.d.ts +0 -108
  316. package/dist/x402/delivery-oracle.d.ts.map +0 -1
  317. package/dist/x402/delivery-oracle.js +0 -174
  318. package/dist/x402/delivery-oracle.js.map +0 -1
  319. package/dist/x402/facilitator-server-entry.d.ts +0 -3
  320. package/dist/x402/facilitator-server-entry.d.ts.map +0 -1
  321. package/dist/x402/facilitator-server-entry.js +0 -27
  322. package/dist/x402/facilitator-server-entry.js.map +0 -1
  323. package/dist/x402/facilitator-server.d.ts +0 -73
  324. package/dist/x402/facilitator-server.d.ts.map +0 -1
  325. package/dist/x402/facilitator-server.js +0 -305
  326. package/dist/x402/facilitator-server.js.map +0 -1
  327. package/dist/x402/payment-requirements.d.ts +0 -106
  328. package/dist/x402/payment-requirements.d.ts.map +0 -1
  329. package/dist/x402/payment-requirements.js +0 -138
  330. package/dist/x402/payment-requirements.js.map +0 -1
  331. package/dist/x402/relayer.d.ts +0 -41
  332. package/dist/x402/relayer.d.ts.map +0 -1
  333. package/dist/x402/relayer.js +0 -64
  334. package/dist/x402/relayer.js.map +0 -1
  335. package/dist/x402/resource-index.d.ts +0 -75
  336. package/dist/x402/resource-index.d.ts.map +0 -1
  337. package/dist/x402/resource-index.js +0 -126
  338. package/dist/x402/resource-index.js.map +0 -1
  339. package/dist/x402/verified-delivery-facilitator.d.ts +0 -285
  340. package/dist/x402/verified-delivery-facilitator.d.ts.map +0 -1
  341. package/dist/x402/verified-delivery-facilitator.js +0 -423
  342. package/dist/x402/verified-delivery-facilitator.js.map +0 -1
  343. package/src/gateway/x402-mode.ts +0 -350
  344. package/src/x402/delivery-oracle.ts +0 -285
  345. package/src/x402/facilitator-server-entry.ts +0 -35
  346. package/src/x402/facilitator-server.ts +0 -445
  347. package/src/x402/payment-requirements.ts +0 -231
  348. package/src/x402/relayer.ts +0 -122
  349. package/src/x402/resource-index.ts +0 -228
  350. package/src/x402/verified-delivery-facilitator.ts +0 -744
@@ -0,0 +1,300 @@
1
+ import { getAddress, isAddress, isHex, type Address, type Hex } from "viem";
2
+
3
+ /**
4
+ * Shared vocabulary of the x402 v2 escrow-opener path (metrik-agent#116).
5
+ *
6
+ * A standard x402 v2 `exact` payment (an EIP-3009 `transferWithAuthorization`)
7
+ * is settled through the ownerless `X402StreamOpenerFactory`
8
+ * (metrik-contracts#48): the x402 `payTo` is the CREATE2 address of the opener
9
+ * for one immutable set of stream {@link OpenerTerms}, so the payer's signature
10
+ * (which binds `to`) commits to those terms, and the opener turns the payment
11
+ * into an ordinary `StreamEscrowV2` stream with `deposit = amount`.
12
+ *
13
+ * This module has no network or package side effects: it is the pure,
14
+ * dependency-free part shared by the facilitator and the gateway.
15
+ */
16
+
17
+ /** Scheme name. The standard x402 `exact` scheme, nothing Metrik-specific. */
18
+ export const OPENER_SCHEME = "exact" as const;
19
+
20
+ /*
21
+ * Network, USDC, escrow, factory and oracle defaults are NOT constants here:
22
+ * they come from the `@absol-labs/sdk` network registry (see `../network.ts`),
23
+ * so a new deployment is a registry change, never an edit to this module.
24
+ */
25
+
26
+ /** Public docs for the x402 opener path, linked from the 402. */
27
+ export const DEFAULT_OPENER_DOCS_URL =
28
+ "https://github.com/Absol-Labs/metrik-agent/blob/main/docs/x402.md";
29
+
30
+ /** Longest informational link accepted in `extra.metrikStreamOpener`. */
31
+ const MAX_LINK_LENGTH = 2048;
32
+
33
+ /**
34
+ * Key under `PaymentRequirements.extra` that carries the opener terms. The
35
+ * facilitator reads the terms ONLY from here, recomputes the opener address
36
+ * on-chain and requires it to equal `payTo`, so a tampered value can never
37
+ * redirect funds: it just fails verification.
38
+ */
39
+ export const OPENER_EXTRA_KEY = "metrikStreamOpener" as const;
40
+
41
+ /** `uint64` ceiling for `maxDuration`. */
42
+ const MAX_UINT64 = (1n << 64n) - 1n;
43
+
44
+ /** Immutable per-listing stream terms, mirroring the Solidity `Terms` struct. */
45
+ export interface OpenerTerms {
46
+ readonly operator: Address;
47
+ readonly serviceRef: Hex;
48
+ /** USDC base units per second. */
49
+ readonly ratePerSecond: bigint;
50
+ /** Seconds. */
51
+ readonly maxDuration: bigint;
52
+ }
53
+
54
+ /** JSON-safe projection of {@link OpenerTerms} plus the factory that prices them. */
55
+ export interface OpenerTermsExtra {
56
+ readonly factory: Address;
57
+ readonly operator: Address;
58
+ readonly serviceRef: Hex;
59
+ readonly ratePerSecond: string;
60
+ readonly maxDuration: string;
61
+ /**
62
+ * Informational only (metrik-agent#119): where the payer gets unearned money
63
+ * back without ETH, as a template containing `{streamId}`. Never used for
64
+ * settlement; the facilitator validates it is an http(s) link and ignores it.
65
+ */
66
+ readonly refundUrl?: string;
67
+ /** Informational only: docs for this payment path. */
68
+ readonly docsUrl?: string;
69
+ }
70
+
71
+ /** True for an absolute http(s) URL of sane length. */
72
+ export function isHttpLink(value: unknown): value is string {
73
+ if (typeof value !== "string" || value.length > MAX_LINK_LENGTH) return false;
74
+ try {
75
+ const url = new URL(value);
76
+ return url.protocol === "https:" || url.protocol === "http:";
77
+ } catch {
78
+ return false;
79
+ }
80
+ }
81
+
82
+ export class InvalidOpenerTermsError extends Error {
83
+ constructor(message: string) {
84
+ super(message);
85
+ this.name = "InvalidOpenerTermsError";
86
+ }
87
+ }
88
+
89
+ /** Parses a non-negative base-10 integer string. Throws on anything else. */
90
+ export function parseUintString(value: unknown, field: string): bigint {
91
+ if (typeof value !== "string" || !/^(0|[1-9]\d*)$/.test(value)) {
92
+ throw new InvalidOpenerTermsError(
93
+ `${field} must be a base-10 integer string without sign or leading zeros`,
94
+ );
95
+ }
96
+ return BigInt(value);
97
+ }
98
+
99
+ /**
100
+ * Validates terms the way the factory's `deploy` does (non-zero operator, rate
101
+ * and duration, `maxDuration` within `uint64`) plus the shape checks the
102
+ * contract cannot do for us (32-byte serviceRef).
103
+ */
104
+ export function assertValidTerms(terms: OpenerTerms): void {
105
+ if (!isAddress(terms.operator, { strict: false })) {
106
+ throw new InvalidOpenerTermsError("operator must be an EVM address");
107
+ }
108
+ if (/^0x0{40}$/i.test(terms.operator)) {
109
+ throw new InvalidOpenerTermsError("operator must not be the zero address");
110
+ }
111
+ if (
112
+ !isHex(terms.serviceRef, { strict: true }) ||
113
+ terms.serviceRef.length !== 66
114
+ ) {
115
+ throw new InvalidOpenerTermsError("serviceRef must be a 32-byte hex value");
116
+ }
117
+ if (terms.ratePerSecond <= 0n) {
118
+ throw new InvalidOpenerTermsError("ratePerSecond must be > 0");
119
+ }
120
+ if (terms.maxDuration <= 0n || terms.maxDuration > MAX_UINT64) {
121
+ throw new InvalidOpenerTermsError(
122
+ "maxDuration must be > 0 and fit in uint64",
123
+ );
124
+ }
125
+ }
126
+
127
+ /** The largest deposit a stream on these terms can ever earn out: `rate * maxDuration`. */
128
+ export function maxEarnable(terms: OpenerTerms): bigint {
129
+ return terms.ratePerSecond * terms.maxDuration;
130
+ }
131
+
132
+ /**
133
+ * The price (= stream deposit) must be positive and must not exceed what the
134
+ * stream can ever accrue. A deposit above `rate * maxDuration` would lock money
135
+ * the seller can never earn, reclaimable only by a second buyer action.
136
+ */
137
+ export function assertValidPrice(price: bigint, terms: OpenerTerms): void {
138
+ if (price <= 0n) {
139
+ throw new InvalidOpenerTermsError("price must be > 0");
140
+ }
141
+ if (price > maxEarnable(terms)) {
142
+ throw new InvalidOpenerTermsError(
143
+ `price ${price} exceeds ratePerSecond * maxDuration (${maxEarnable(terms)})`,
144
+ );
145
+ }
146
+ }
147
+
148
+ export function termsToExtra(
149
+ factory: Address,
150
+ terms: OpenerTerms,
151
+ ): OpenerTermsExtra {
152
+ return {
153
+ factory: getAddress(factory),
154
+ operator: getAddress(terms.operator),
155
+ serviceRef: terms.serviceRef.toLowerCase() as Hex,
156
+ ratePerSecond: terms.ratePerSecond.toString(),
157
+ maxDuration: terms.maxDuration.toString(),
158
+ };
159
+ }
160
+
161
+ /**
162
+ * Reads opener terms from an untrusted `PaymentRequirements.extra`. Every field
163
+ * is re-validated; unknown keys under the opener object are rejected so the
164
+ * wire shape cannot drift silently.
165
+ */
166
+ export function termsFromExtra(extra: unknown): {
167
+ readonly factory: Address;
168
+ readonly terms: OpenerTerms;
169
+ } {
170
+ if (typeof extra !== "object" || extra === null) {
171
+ throw new InvalidOpenerTermsError("requirements.extra is missing");
172
+ }
173
+ const raw = (extra as Record<string, unknown>)[OPENER_EXTRA_KEY];
174
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
175
+ throw new InvalidOpenerTermsError(
176
+ `requirements.extra.${OPENER_EXTRA_KEY} is missing`,
177
+ );
178
+ }
179
+ const record = raw as Record<string, unknown>;
180
+ const allowed = new Set([
181
+ "factory",
182
+ "operator",
183
+ "serviceRef",
184
+ "ratePerSecond",
185
+ "maxDuration",
186
+ "refundUrl",
187
+ "docsUrl",
188
+ ]);
189
+ for (const key of Object.keys(record)) {
190
+ if (!allowed.has(key)) {
191
+ throw new InvalidOpenerTermsError(
192
+ `unknown key ${key} in requirements.extra.${OPENER_EXTRA_KEY}`,
193
+ );
194
+ }
195
+ }
196
+ for (const link of ["refundUrl", "docsUrl"] as const) {
197
+ if (record[link] !== undefined && !isHttpLink(record[link])) {
198
+ throw new InvalidOpenerTermsError(
199
+ `${link} in requirements.extra.${OPENER_EXTRA_KEY} must be an http(s) URL`,
200
+ );
201
+ }
202
+ }
203
+ const { factory, operator, serviceRef } = record;
204
+ if (typeof factory !== "string" || !isAddress(factory, { strict: false })) {
205
+ throw new InvalidOpenerTermsError("factory must be an EVM address");
206
+ }
207
+ if (typeof operator !== "string" || !isAddress(operator, { strict: false })) {
208
+ throw new InvalidOpenerTermsError("operator must be an EVM address");
209
+ }
210
+ if (typeof serviceRef !== "string") {
211
+ throw new InvalidOpenerTermsError("serviceRef must be a string");
212
+ }
213
+ const terms: OpenerTerms = {
214
+ operator: getAddress(operator),
215
+ serviceRef: serviceRef as Hex,
216
+ ratePerSecond: parseUintString(record.ratePerSecond, "ratePerSecond"),
217
+ maxDuration: parseUintString(record.maxDuration, "maxDuration"),
218
+ };
219
+ assertValidTerms(terms);
220
+ return { factory: getAddress(factory), terms };
221
+ }
222
+
223
+ /** Chain id encoded in an `eip155:<id>` CAIP-2 identifier. Throws otherwise. */
224
+ export function chainIdFromNetwork(network: string): number {
225
+ const match = /^eip155:([1-9]\d*)$/.exec(network);
226
+ if (match === null) {
227
+ throw new InvalidOpenerTermsError(
228
+ `network must be an eip155 CAIP-2 identifier, got ${network}`,
229
+ );
230
+ }
231
+ const chainId = Number(match[1]);
232
+ if (!Number.isSafeInteger(chainId)) {
233
+ throw new InvalidOpenerTermsError(`unsupported chain id in ${network}`);
234
+ }
235
+ return chainId;
236
+ }
237
+
238
+ /** Solidity-tuple view of terms for viem contract calls. */
239
+ export function termsTuple(terms: OpenerTerms): {
240
+ readonly operator: Address;
241
+ readonly serviceRef: Hex;
242
+ readonly ratePerSecond: bigint;
243
+ readonly maxDuration: bigint;
244
+ } {
245
+ return {
246
+ operator: getAddress(terms.operator),
247
+ serviceRef: terms.serviceRef,
248
+ ratePerSecond: terms.ratePerSecond,
249
+ maxDuration: terms.maxDuration,
250
+ };
251
+ }
252
+
253
+ /** A bazaar-shaped `{info: {input, output?}, schema?}` declaration. */
254
+ export interface X402SchemaDeclaration {
255
+ readonly info: {
256
+ readonly input: { readonly type: "http" } & Record<string, unknown>;
257
+ readonly output?: Record<string, unknown>;
258
+ };
259
+ readonly schema?: Record<string, unknown>;
260
+ }
261
+
262
+ /** Largest accepted schema declaration, serialized bytes. */
263
+ export const MAX_SCHEMA_DECLARATION_BYTES = 16 * 1024;
264
+
265
+ /** Validates a bazaar-shaped schema declaration. Throws on anything else. */
266
+ export function assertSchemaDeclaration(
267
+ value: unknown,
268
+ ): asserts value is X402SchemaDeclaration {
269
+ if (JSON.stringify(value ?? null).length > MAX_SCHEMA_DECLARATION_BYTES) {
270
+ throw new Error(
271
+ `the schema declaration exceeds ${MAX_SCHEMA_DECLARATION_BYTES} bytes`,
272
+ );
273
+ }
274
+ const record = value as Record<string, unknown> | null;
275
+ const info = record?.info as Record<string, unknown> | undefined;
276
+ const input = info?.input as Record<string, unknown> | undefined;
277
+ if (
278
+ typeof record !== "object" ||
279
+ record === null ||
280
+ Array.isArray(record) ||
281
+ typeof info !== "object" ||
282
+ info === null ||
283
+ typeof input !== "object" ||
284
+ input === null ||
285
+ input.type !== "http" ||
286
+ (info.output !== undefined &&
287
+ (typeof info.output !== "object" || info.output === null)) ||
288
+ (record.schema !== undefined &&
289
+ (typeof record.schema !== "object" || record.schema === null))
290
+ ) {
291
+ throw new Error(
292
+ 'the schema declaration must be {info: {input: {type: "http", ...}, output?}, schema?}',
293
+ );
294
+ }
295
+ for (const key of Object.keys(record)) {
296
+ if (key !== "info" && key !== "schema") {
297
+ throw new Error(`unknown key ${key} in the schema declaration`);
298
+ }
299
+ }
300
+ }
@@ -1,123 +0,0 @@
1
- import type { PaymentRequirements, SettleResponse, VerifyResponse } from "x402/types";
2
- import { type SignedListingPayee, type X402AssetConfig, type X402PaymentRequiredBody } from "../x402/payment-requirements.js";
3
- /**
4
- * Standard x402 mode for the seller-side gateway (Tier 1).
5
- *
6
- * The gateway already authorizes requests that carry a Metrik
7
- * `InvocationCapability` — a buyer with an open, funded, verified stream. That
8
- * path is untouched. This module adds a SECOND, independent way in: a request
9
- * with no capability gets an ordinary HTTP `402` carrying real x402
10
- * `PaymentRequirements`, so an agent holding nothing but `x402-fetch` can pay
11
- * per call without knowing Metrik exists.
12
- *
13
- * ## The two paths never overlap
14
- *
15
- * - capability header present -> stream path, exactly as before;
16
- * - capability header absent, x402 mode on -> `402` + `PaymentRequirements`;
17
- * - BOTH present -> rejected. A request that looks like both is ambiguous about
18
- * which one is paying for it, and the failure mode of guessing is charging the
19
- * caller twice for one call. Better a loud `400` than a silent double charge.
20
- *
21
- * ## The per-call price is the seller's, and is not signed
22
- *
23
- * `payTo` comes from the operator-signed descriptor (see
24
- * `../x402/payment-requirements.ts`). The price does not — the descriptor has no
25
- * per-call price field. It is the seller's own number on the seller's own
26
- * gateway, which is legitimate, but a buyer cannot cross-check it against the
27
- * registry the way they can cross-check the payee.
28
- */
29
- /** Request header carrying the x402 payment payload (x402 v1). */
30
- export declare const X402_PAYMENT_HEADER: "x-payment";
31
- /** Response header carrying the settlement result (x402 v1). */
32
- export declare const X402_PAYMENT_RESPONSE_HEADER: "x-payment-response";
33
- /** The facilitator the gateway delegates verify/settle to. */
34
- export interface X402FacilitatorClient {
35
- verify(payload: unknown, requirements: PaymentRequirements): Promise<VerifyResponse>;
36
- settle(payload: unknown, requirements: PaymentRequirements): Promise<SettleResponse>;
37
- }
38
- export interface HttpFacilitatorClientOptions {
39
- /** Base URL of a facilitator exposing `/verify` and `/settle`. */
40
- readonly url: string;
41
- /**
42
- * Shared secret for the facilitator's `/settle`. Sent as
43
- * `Authorization: Bearer`. Metrik's own facilitator refuses to start a
44
- * settling deployment without one, because `/settle` spends its gas.
45
- */
46
- readonly token?: string;
47
- readonly headers?: Readonly<Record<string, string>>;
48
- readonly timeoutMs?: number;
49
- readonly fetch?: typeof globalThis.fetch;
50
- }
51
- /**
52
- * Talks to any x402 facilitator over HTTP — including Metrik's own
53
- * (`../x402/facilitator-server.ts`), which is the point: a seller who wires this
54
- * gateway to the Metrik facilitator gets a paywall whose payments stop when
55
- * their own delivery stops being verifiable.
56
- */
57
- export declare function createHttpFacilitatorClient(options: HttpFacilitatorClientOptions): X402FacilitatorClient;
58
- /** Builds the `PaymentRequirements` quoted for a given request. */
59
- export type X402Quoter = (request: {
60
- readonly method: string;
61
- readonly path: string;
62
- }) => readonly PaymentRequirements[] | Promise<readonly PaymentRequirements[]>;
63
- export interface ListingPriceQuoterOptions {
64
- /** Projected from the OPERATOR-SIGNED descriptor. `payTo` comes from here. */
65
- readonly listing: SignedListingPayee;
66
- /** Public origin buyers reach this gateway on, e.g. `https://svc.example.com`. */
67
- readonly resourceBaseUrl: string;
68
- /** Per-call price in the asset's base units (micro-USDC). Seller-set, unsigned. */
69
- readonly pricePerCallBaseUnits: bigint;
70
- readonly chainId: number;
71
- readonly description?: string;
72
- readonly mimeType?: string;
73
- readonly maxTimeoutSeconds?: number;
74
- readonly asset?: X402AssetConfig;
75
- }
76
- /** One flat price per call, quoted against the request's own path. */
77
- export declare function createListingPriceQuoter(options: ListingPriceQuoterOptions): X402Quoter;
78
- export interface GatewayX402Mode {
79
- readonly quote: X402Quoter;
80
- readonly facilitator: X402FacilitatorClient;
81
- }
82
- /** Decoded, still-untrusted `X-PAYMENT` payload plus the quote it answers. */
83
- export interface AcceptedX402Payment {
84
- readonly payload: unknown;
85
- readonly requirements: PaymentRequirements;
86
- readonly payer?: string;
87
- /**
88
- * Unix seconds after which the signed authorization is no longer settleable
89
- * (`validBefore`), when the payload carried one.
90
- *
91
- * The upstream runs BEFORE settlement, so an upstream slower than this window
92
- * would produce its side effects and then fail to be paid for. The server
93
- * bounds the upstream call by this instead of letting that happen.
94
- */
95
- readonly validBefore?: number;
96
- }
97
- export type X402EvaluationOutcome = {
98
- readonly outcome: "payment-required";
99
- readonly body: X402PaymentRequiredBody;
100
- } | {
101
- readonly outcome: "accepted";
102
- readonly payment: AcceptedX402Payment;
103
- };
104
- /**
105
- * Evaluates the x402 half of a request. Returns either the `402` body to send or
106
- * an accepted payment to settle after the upstream has been called.
107
- */
108
- export declare function evaluateX402Request(request: {
109
- readonly method: string;
110
- readonly path: string;
111
- }, paymentHeader: string | undefined, mode: GatewayX402Mode): Promise<X402EvaluationOutcome>;
112
- /**
113
- * Seconds of headroom the settlement leg needs after the upstream returns.
114
- *
115
- * The x402 `exact` verifier rejects an authorization whose `validBefore` is less
116
- * than 6 s away, so an upstream allowed to run right up to the deadline would
117
- * hand back a response that can never be settled. This leaves room for that
118
- * check plus the settle round trip.
119
- */
120
- export declare const X402_SETTLEMENT_HEADROOM_SECONDS = 10;
121
- export declare function decodePaymentHeader(header: string): unknown;
122
- export declare function encodeSettleResponseHeader(response: SettleResponse): string;
123
- //# sourceMappingURL=x402-mode.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"x402-mode.d.ts","sourceRoot":"","sources":["../../src/gateway/x402-mode.ts"],"names":[],"mappings":"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"}
@@ -1,212 +0,0 @@
1
- import { buildMetrikPaymentRequirements, buildX402PaymentRequiredBody, } from "../x402/payment-requirements.js";
2
- /**
3
- * Standard x402 mode for the seller-side gateway (Tier 1).
4
- *
5
- * The gateway already authorizes requests that carry a Metrik
6
- * `InvocationCapability` — a buyer with an open, funded, verified stream. That
7
- * path is untouched. This module adds a SECOND, independent way in: a request
8
- * with no capability gets an ordinary HTTP `402` carrying real x402
9
- * `PaymentRequirements`, so an agent holding nothing but `x402-fetch` can pay
10
- * per call without knowing Metrik exists.
11
- *
12
- * ## The two paths never overlap
13
- *
14
- * - capability header present -> stream path, exactly as before;
15
- * - capability header absent, x402 mode on -> `402` + `PaymentRequirements`;
16
- * - BOTH present -> rejected. A request that looks like both is ambiguous about
17
- * which one is paying for it, and the failure mode of guessing is charging the
18
- * caller twice for one call. Better a loud `400` than a silent double charge.
19
- *
20
- * ## The per-call price is the seller's, and is not signed
21
- *
22
- * `payTo` comes from the operator-signed descriptor (see
23
- * `../x402/payment-requirements.ts`). The price does not — the descriptor has no
24
- * per-call price field. It is the seller's own number on the seller's own
25
- * gateway, which is legitimate, but a buyer cannot cross-check it against the
26
- * registry the way they can cross-check the payee.
27
- */
28
- /** Request header carrying the x402 payment payload (x402 v1). */
29
- export const X402_PAYMENT_HEADER = "x-payment";
30
- /** Response header carrying the settlement result (x402 v1). */
31
- export const X402_PAYMENT_RESPONSE_HEADER = "x-payment-response";
32
- /**
33
- * Talks to any x402 facilitator over HTTP — including Metrik's own
34
- * (`../x402/facilitator-server.ts`), which is the point: a seller who wires this
35
- * gateway to the Metrik facilitator gets a paywall whose payments stop when
36
- * their own delivery stops being verifiable.
37
- */
38
- export function createHttpFacilitatorClient(options) {
39
- const base = options.url.replace(/\/+$/, "");
40
- const timeoutMs = options.timeoutMs ?? 10_000;
41
- const doFetch = options.fetch ?? globalThis.fetch;
42
- async function post(path, body) {
43
- const controller = new AbortController();
44
- const timer = setTimeout(() => controller.abort(), timeoutMs);
45
- try {
46
- const response = await doFetch(`${base}${path}`, {
47
- method: "POST",
48
- headers: {
49
- "content-type": "application/json",
50
- ...(options.token === undefined
51
- ? {}
52
- : { authorization: `Bearer ${options.token}` }),
53
- ...(options.headers ?? {}),
54
- },
55
- body: JSON.stringify(body),
56
- signal: controller.signal,
57
- });
58
- return await response.json();
59
- }
60
- finally {
61
- clearTimeout(timer);
62
- }
63
- }
64
- return {
65
- async verify(payload, requirements) {
66
- const result = (await post("/verify", {
67
- x402Version: 1,
68
- paymentPayload: payload,
69
- paymentRequirements: requirements,
70
- }));
71
- // Fail closed: an unreadable facilitator answer is not a pass.
72
- if (typeof result !== "object" || result === null) {
73
- return { isValid: false, invalidReason: "unexpected_verify_error" };
74
- }
75
- return result;
76
- },
77
- async settle(payload, requirements) {
78
- return (await post("/settle", {
79
- x402Version: 1,
80
- paymentPayload: payload,
81
- paymentRequirements: requirements,
82
- }));
83
- },
84
- };
85
- }
86
- /** One flat price per call, quoted against the request's own path. */
87
- export function createListingPriceQuoter(options) {
88
- const base = new URL(options.resourceBaseUrl);
89
- return (request) => [
90
- buildMetrikPaymentRequirements({
91
- listing: options.listing,
92
- resource: new URL(request.path, base).toString(),
93
- priceBaseUnits: options.pricePerCallBaseUnits,
94
- chainId: options.chainId,
95
- ...(options.description === undefined
96
- ? {}
97
- : { description: options.description }),
98
- ...(options.mimeType === undefined ? {} : { mimeType: options.mimeType }),
99
- ...(options.maxTimeoutSeconds === undefined
100
- ? {}
101
- : { maxTimeoutSeconds: options.maxTimeoutSeconds }),
102
- ...(options.asset === undefined ? {} : { asset: options.asset }),
103
- }),
104
- ];
105
- }
106
- /**
107
- * Evaluates the x402 half of a request. Returns either the `402` body to send or
108
- * an accepted payment to settle after the upstream has been called.
109
- */
110
- export async function evaluateX402Request(request, paymentHeader, mode) {
111
- const accepts = await mode.quote(request);
112
- if (paymentHeader === undefined || paymentHeader.trim().length === 0) {
113
- return {
114
- outcome: "payment-required",
115
- body: buildX402PaymentRequiredBody(accepts),
116
- };
117
- }
118
- const payload = decodePaymentHeader(paymentHeader);
119
- if (payload === undefined) {
120
- return {
121
- outcome: "payment-required",
122
- body: buildX402PaymentRequiredBody(accepts, "X-PAYMENT header is not base64-encoded JSON"),
123
- };
124
- }
125
- const requirements = selectRequirements(accepts, payload);
126
- if (requirements === undefined) {
127
- return {
128
- outcome: "payment-required",
129
- body: buildX402PaymentRequiredBody(accepts, "X-PAYMENT does not match any offered payment requirements"),
130
- };
131
- }
132
- let verified;
133
- try {
134
- verified = await mode.facilitator.verify(payload, requirements);
135
- }
136
- catch (error) {
137
- // An unreachable facilitator is a refusal, never a free call.
138
- return {
139
- outcome: "payment-required",
140
- body: buildX402PaymentRequiredBody(accepts, `payment could not be verified: ${error instanceof Error ? error.message : "facilitator unreachable"}`),
141
- };
142
- }
143
- if (!verified.isValid) {
144
- return {
145
- outcome: "payment-required",
146
- body: buildX402PaymentRequiredBody(accepts, verified.invalidReason ?? "payment rejected by facilitator"),
147
- };
148
- }
149
- // A Metrik facilitator reports up front whether it would actually broadcast
150
- // this payment (asset allowlist, settlement scope, ...). Refusing HERE — before
151
- // the upstream runs — is the difference between "the caller gets nothing" and
152
- // "the caller gets the upstream's side effects for free and we cannot charge
153
- // for them". A non-Metrik facilitator omits the field and nothing changes.
154
- const annotation = verified.metrik;
155
- if (annotation?.settleable === false) {
156
- return {
157
- outcome: "payment-required",
158
- body: buildX402PaymentRequiredBody(accepts, `facilitator will not settle this payment: ${annotation.detail ?? "refused"}`),
159
- };
160
- }
161
- const validBefore = readValidBefore(payload);
162
- return {
163
- outcome: "accepted",
164
- payment: {
165
- payload,
166
- requirements,
167
- ...(verified.payer === undefined ? {} : { payer: verified.payer }),
168
- ...(validBefore === undefined ? {} : { validBefore }),
169
- },
170
- };
171
- }
172
- /** Reads the exact-EVM authorization deadline, if the payload has one. */
173
- function readValidBefore(payload) {
174
- const authorization = payload?.payload?.authorization;
175
- const raw = authorization?.validBefore;
176
- if (typeof raw !== "string" && typeof raw !== "number") {
177
- return undefined;
178
- }
179
- const parsed = Number(raw);
180
- return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
181
- }
182
- /**
183
- * Seconds of headroom the settlement leg needs after the upstream returns.
184
- *
185
- * The x402 `exact` verifier rejects an authorization whose `validBefore` is less
186
- * than 6 s away, so an upstream allowed to run right up to the deadline would
187
- * hand back a response that can never be settled. This leaves room for that
188
- * check plus the settle round trip.
189
- */
190
- export const X402_SETTLEMENT_HEADROOM_SECONDS = 10;
191
- /** Matches the payload's scheme+network against the quotes actually offered. */
192
- function selectRequirements(accepts, payload) {
193
- if (typeof payload !== "object" || payload === null) {
194
- return undefined;
195
- }
196
- const { scheme, network } = payload;
197
- return accepts.find((candidate) => candidate.scheme === scheme && candidate.network === network);
198
- }
199
- export function decodePaymentHeader(header) {
200
- try {
201
- const decoded = Buffer.from(header.trim(), "base64").toString("utf8");
202
- const parsed = JSON.parse(decoded);
203
- return typeof parsed === "object" && parsed !== null ? parsed : undefined;
204
- }
205
- catch {
206
- return undefined;
207
- }
208
- }
209
- export function encodeSettleResponseHeader(response) {
210
- return Buffer.from(JSON.stringify(response), "utf8").toString("base64");
211
- }
212
- //# sourceMappingURL=x402-mode.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"x402-mode.js","sourceRoot":"","sources":["../../src/gateway/x402-mode.ts"],"names":[],"mappings":"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"}