mppx 0.8.17 → 0.8.19

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 (914) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +15 -0
  3. package/dist/Challenge.js +21 -4
  4. package/dist/bin.js +3 -3
  5. package/dist/cli/THIRD-PARTY-LICENSES.txt +328 -0
  6. package/dist/cli/cli.js +253 -1505
  7. package/dist/cli/plugins/index.js +19 -5
  8. package/dist/cli/plugins/tempo.js +7 -3
  9. package/dist/cli/sessions/Manager.js +7 -4
  10. package/dist/cli/sessions/request.d.ts +2 -0
  11. package/dist/cli/sessions/request.js +18 -0
  12. package/dist/cli/sessions/store.js +28 -14
  13. package/dist/discovery/Discovery.js +2 -1
  14. package/dist/evm/client/Charge.js +8 -0
  15. package/dist/server/core.d.ts +9 -0
  16. package/dist/server/core.js +9 -0
  17. package/dist/stripe/server/Charge.js +2 -4
  18. package/dist/stripe/server/Methods.d.ts +2 -2
  19. package/dist/stripe/server/Methods.js +17 -11
  20. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  21. package/dist/stripe/server/internal/html.gen.js +1 -1
  22. package/dist/stripe/server/spt.d.ts +8 -0
  23. package/dist/stripe/server/spt.js +8 -0
  24. package/dist/tempo/Methods.d.ts +13 -0
  25. package/dist/tempo/Methods.js +14 -3
  26. package/dist/tempo/client/Charge.d.ts +3 -0
  27. package/dist/tempo/client/Charge.js +31 -9
  28. package/dist/tempo/client/Methods.d.ts +13 -0
  29. package/dist/tempo/internal/defaults.d.ts +11 -0
  30. package/dist/tempo/internal/defaults.js +11 -0
  31. package/dist/tempo/internal/machine-token-charge.d.ts +51 -0
  32. package/dist/tempo/internal/machine-token-charge.js +113 -0
  33. package/dist/tempo/internal/machine-token-session.d.ts +88 -0
  34. package/dist/tempo/internal/machine-token-session.js +173 -0
  35. package/dist/tempo/internal/signature-envelope.d.ts +14 -0
  36. package/dist/tempo/internal/signature-envelope.js +28 -0
  37. package/dist/tempo/legacy/client/ChannelOps.d.ts +2 -2
  38. package/dist/tempo/legacy/client/ChannelOps.js +11 -5
  39. package/dist/tempo/legacy/client/Session.d.ts +13 -1
  40. package/dist/tempo/legacy/client/Session.js +3 -3
  41. package/dist/tempo/legacy/client/SessionManager.d.ts +3 -1
  42. package/dist/tempo/legacy/client/SessionManager.js +2 -0
  43. package/dist/tempo/server/Charge.d.ts +3 -0
  44. package/dist/tempo/server/Charge.js +58 -17
  45. package/dist/tempo/server/Methods.d.ts +21 -4
  46. package/dist/tempo/server/Methods.js +8 -4
  47. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  48. package/dist/tempo/server/internal/html.gen.js +1 -1
  49. package/dist/tempo/session/client/ChannelOps.d.ts +18 -3
  50. package/dist/tempo/session/client/ChannelOps.js +35 -6
  51. package/dist/tempo/session/client/ChannelStore.d.ts +0 -5
  52. package/dist/tempo/session/client/ChannelStore.js +2 -2
  53. package/dist/tempo/session/client/CredentialState.d.ts +17 -2
  54. package/dist/tempo/session/client/CredentialState.js +77 -76
  55. package/dist/tempo/session/client/Runtime.d.ts +4 -2
  56. package/dist/tempo/session/client/Runtime.js +21 -5
  57. package/dist/tempo/session/client/Session.d.ts +15 -3
  58. package/dist/tempo/session/client/Session.js +186 -63
  59. package/dist/tempo/session/client/SessionManager.d.ts +3 -1
  60. package/dist/tempo/session/client/SessionManager.js +35 -11
  61. package/dist/tempo/session/client/Transports.d.ts +2 -0
  62. package/dist/tempo/session/client/Transports.js +12 -2
  63. package/dist/tempo/session/precompile/Chain.d.ts +10 -2
  64. package/dist/tempo/session/precompile/Chain.js +51 -10
  65. package/dist/tempo/session/precompile/Protocol.d.ts +15 -0
  66. package/dist/tempo/session/precompile/Protocol.js +7 -0
  67. package/dist/tempo/session/precompile/Voucher.d.ts +3 -1
  68. package/dist/tempo/session/precompile/Voucher.js +6 -12
  69. package/dist/tempo/session/server/ChannelStore.d.ts +6 -0
  70. package/dist/tempo/session/server/ChannelStore.js +11 -4
  71. package/dist/tempo/session/server/CredentialVerification.d.ts +11 -9
  72. package/dist/tempo/session/server/CredentialVerification.js +185 -109
  73. package/dist/tempo/session/server/MeteredStream.d.ts +1 -1
  74. package/dist/tempo/session/server/MeteredStream.js +5 -4
  75. package/dist/tempo/session/server/RequestState.d.ts +19 -0
  76. package/dist/tempo/session/server/RequestState.js +61 -15
  77. package/dist/tempo/session/server/Session.d.ts +14 -2
  78. package/dist/tempo/session/server/Session.js +37 -6
  79. package/dist/tempo/session/server/Settlement.d.ts +11 -4
  80. package/dist/tempo/session/server/Settlement.js +53 -21
  81. package/dist/x402/client/Exact.d.ts +8 -0
  82. package/dist/x402/client/Exact.js +40 -10
  83. package/dist/x402/server/EvmCharge.d.ts +22 -0
  84. package/dist/x402/server/EvmCharge.js +23 -1
  85. package/package.json +15 -37
  86. package/dist/BodyDigest.d.ts.map +0 -1
  87. package/dist/BodyDigest.js.map +0 -1
  88. package/dist/Challenge.d.ts.map +0 -1
  89. package/dist/Challenge.js.map +0 -1
  90. package/dist/Constants.d.ts.map +0 -1
  91. package/dist/Constants.js.map +0 -1
  92. package/dist/Credential.d.ts.map +0 -1
  93. package/dist/Credential.js.map +0 -1
  94. package/dist/Errors.d.ts.map +0 -1
  95. package/dist/Errors.js.map +0 -1
  96. package/dist/Expires.d.ts.map +0 -1
  97. package/dist/Expires.js.map +0 -1
  98. package/dist/Html.d.ts.map +0 -1
  99. package/dist/Html.js.map +0 -1
  100. package/dist/Mcp.d.ts.map +0 -1
  101. package/dist/Mcp.js.map +0 -1
  102. package/dist/Method.d.ts.map +0 -1
  103. package/dist/Method.js.map +0 -1
  104. package/dist/PaymentRequest.d.ts.map +0 -1
  105. package/dist/PaymentRequest.js.map +0 -1
  106. package/dist/Receipt.d.ts.map +0 -1
  107. package/dist/Receipt.js.map +0 -1
  108. package/dist/Store.d.ts.map +0 -1
  109. package/dist/Store.js.map +0 -1
  110. package/dist/attestation/Client.d.ts.map +0 -1
  111. package/dist/attestation/Client.js.map +0 -1
  112. package/dist/attestation/Constants.d.ts.map +0 -1
  113. package/dist/attestation/Constants.js.map +0 -1
  114. package/dist/attestation/Server.d.ts.map +0 -1
  115. package/dist/attestation/Server.js.map +0 -1
  116. package/dist/attestation/Types.d.ts.map +0 -1
  117. package/dist/attestation/Types.js.map +0 -1
  118. package/dist/attestation/index.d.ts.map +0 -1
  119. package/dist/attestation/index.js.map +0 -1
  120. package/dist/attestation/internal/HttpMessageSignature.d.ts.map +0 -1
  121. package/dist/attestation/internal/HttpMessageSignature.js.map +0 -1
  122. package/dist/attestation/internal/SigningContext.d.ts.map +0 -1
  123. package/dist/attestation/internal/SigningContext.js.map +0 -1
  124. package/dist/bin.d.ts.map +0 -1
  125. package/dist/bin.js.map +0 -1
  126. package/dist/cli/account.d.ts.map +0 -1
  127. package/dist/cli/account.js.map +0 -1
  128. package/dist/cli/cli.d.ts.map +0 -1
  129. package/dist/cli/cli.js.map +0 -1
  130. package/dist/cli/config.d.ts.map +0 -1
  131. package/dist/cli/config.js.map +0 -1
  132. package/dist/cli/internal.d.ts.map +0 -1
  133. package/dist/cli/internal.js.map +0 -1
  134. package/dist/cli/plugins/evm.d.ts.map +0 -1
  135. package/dist/cli/plugins/evm.js.map +0 -1
  136. package/dist/cli/plugins/index.d.ts.map +0 -1
  137. package/dist/cli/plugins/index.js.map +0 -1
  138. package/dist/cli/plugins/plugin.d.ts.map +0 -1
  139. package/dist/cli/plugins/plugin.js.map +0 -1
  140. package/dist/cli/plugins/stripe.d.ts.map +0 -1
  141. package/dist/cli/plugins/stripe.js.map +0 -1
  142. package/dist/cli/plugins/tempo.d.ts.map +0 -1
  143. package/dist/cli/plugins/tempo.js.map +0 -1
  144. package/dist/cli/sessions/Manager.d.ts.map +0 -1
  145. package/dist/cli/sessions/Manager.js.map +0 -1
  146. package/dist/cli/sessions/commands.d.ts.map +0 -1
  147. package/dist/cli/sessions/commands.js.map +0 -1
  148. package/dist/cli/sessions/request.d.ts.map +0 -1
  149. package/dist/cli/sessions/request.js.map +0 -1
  150. package/dist/cli/sessions/store.d.ts.map +0 -1
  151. package/dist/cli/sessions/store.js.map +0 -1
  152. package/dist/cli/utils.d.ts.map +0 -1
  153. package/dist/cli/utils.js.map +0 -1
  154. package/dist/cli/validate/challenge.d.ts.map +0 -1
  155. package/dist/cli/validate/challenge.js.map +0 -1
  156. package/dist/cli/validate/discovery.d.ts.map +0 -1
  157. package/dist/cli/validate/discovery.js.map +0 -1
  158. package/dist/cli/validate/helpers.d.ts.map +0 -1
  159. package/dist/cli/validate/helpers.js.map +0 -1
  160. package/dist/cli/validate/index.d.ts.map +0 -1
  161. package/dist/cli/validate/index.js.map +0 -1
  162. package/dist/cli/validate/messages.d.ts.map +0 -1
  163. package/dist/cli/validate/messages.js.map +0 -1
  164. package/dist/cli/validate/payment.d.ts.map +0 -1
  165. package/dist/cli/validate/payment.js.map +0 -1
  166. package/dist/client/Methods.d.ts.map +0 -1
  167. package/dist/client/Methods.js.map +0 -1
  168. package/dist/client/Mppx.d.ts.map +0 -1
  169. package/dist/client/Mppx.js.map +0 -1
  170. package/dist/client/Transport.d.ts.map +0 -1
  171. package/dist/client/Transport.js.map +0 -1
  172. package/dist/client/index.d.ts.map +0 -1
  173. package/dist/client/index.js.map +0 -1
  174. package/dist/client/internal/Fetch.d.ts.map +0 -1
  175. package/dist/client/internal/Fetch.js.map +0 -1
  176. package/dist/client/internal/MethodChallenge.d.ts.map +0 -1
  177. package/dist/client/internal/MethodChallenge.js.map +0 -1
  178. package/dist/client/internal/MethodResponse.d.ts.map +0 -1
  179. package/dist/client/internal/MethodResponse.js.map +0 -1
  180. package/dist/client/internal/protocols/Mcp.d.ts.map +0 -1
  181. package/dist/client/internal/protocols/Mcp.js.map +0 -1
  182. package/dist/client/internal/protocols/Mpp.d.ts.map +0 -1
  183. package/dist/client/internal/protocols/Mpp.js.map +0 -1
  184. package/dist/client/internal/protocols/Protocol.d.ts.map +0 -1
  185. package/dist/client/internal/protocols/Protocol.js.map +0 -1
  186. package/dist/client/internal/protocols/Shared.d.ts.map +0 -1
  187. package/dist/client/internal/protocols/Shared.js.map +0 -1
  188. package/dist/client/internal/protocols/X402.d.ts.map +0 -1
  189. package/dist/client/internal/protocols/X402.js.map +0 -1
  190. package/dist/client/node.d.ts.map +0 -1
  191. package/dist/client/node.js.map +0 -1
  192. package/dist/discovery/Discovery.d.ts.map +0 -1
  193. package/dist/discovery/Discovery.js.map +0 -1
  194. package/dist/discovery/OpenApi.d.ts.map +0 -1
  195. package/dist/discovery/OpenApi.js.map +0 -1
  196. package/dist/discovery/Validate.d.ts.map +0 -1
  197. package/dist/discovery/Validate.js.map +0 -1
  198. package/dist/discovery/index.d.ts.map +0 -1
  199. package/dist/discovery/index.js.map +0 -1
  200. package/dist/discovery/internal/Metadata.d.ts.map +0 -1
  201. package/dist/discovery/internal/Metadata.js.map +0 -1
  202. package/dist/evm/Assets.d.ts.map +0 -1
  203. package/dist/evm/Assets.js.map +0 -1
  204. package/dist/evm/Chains.d.ts.map +0 -1
  205. package/dist/evm/Chains.js.map +0 -1
  206. package/dist/evm/Methods.d.ts.map +0 -1
  207. package/dist/evm/Methods.js.map +0 -1
  208. package/dist/evm/Types.d.ts.map +0 -1
  209. package/dist/evm/Types.js.map +0 -1
  210. package/dist/evm/client/Charge.d.ts.map +0 -1
  211. package/dist/evm/client/Charge.js.map +0 -1
  212. package/dist/evm/client/Methods.d.ts.map +0 -1
  213. package/dist/evm/client/Methods.js.map +0 -1
  214. package/dist/evm/client/index.d.ts.map +0 -1
  215. package/dist/evm/client/index.js.map +0 -1
  216. package/dist/evm/index.d.ts.map +0 -1
  217. package/dist/evm/index.js.map +0 -1
  218. package/dist/evm/server/Charge.d.ts.map +0 -1
  219. package/dist/evm/server/Charge.js.map +0 -1
  220. package/dist/evm/server/Methods.d.ts.map +0 -1
  221. package/dist/evm/server/Methods.js.map +0 -1
  222. package/dist/evm/server/index.d.ts.map +0 -1
  223. package/dist/evm/server/index.js.map +0 -1
  224. package/dist/index.d.ts.map +0 -1
  225. package/dist/index.js.map +0 -1
  226. package/dist/internal/AcceptPayment.d.ts.map +0 -1
  227. package/dist/internal/AcceptPayment.js.map +0 -1
  228. package/dist/internal/HeaderCodec.d.ts.map +0 -1
  229. package/dist/internal/HeaderCodec.js.map +0 -1
  230. package/dist/internal/constantTimeEqual.d.ts.map +0 -1
  231. package/dist/internal/constantTimeEqual.js.map +0 -1
  232. package/dist/internal/env.d.ts.map +0 -1
  233. package/dist/internal/env.js.map +0 -1
  234. package/dist/internal/types.d.ts.map +0 -1
  235. package/dist/internal/types.js.map +0 -1
  236. package/dist/mcp/client/McpClient.d.ts.map +0 -1
  237. package/dist/mcp/client/McpClient.js.map +0 -1
  238. package/dist/mcp/client/index.d.ts.map +0 -1
  239. package/dist/mcp/client/index.js.map +0 -1
  240. package/dist/mcp/server/Transport.d.ts.map +0 -1
  241. package/dist/mcp/server/Transport.js.map +0 -1
  242. package/dist/mcp/server/index.d.ts.map +0 -1
  243. package/dist/mcp/server/index.js.map +0 -1
  244. package/dist/middlewares/elysia.d.ts.map +0 -1
  245. package/dist/middlewares/elysia.js.map +0 -1
  246. package/dist/middlewares/express.d.ts.map +0 -1
  247. package/dist/middlewares/express.js.map +0 -1
  248. package/dist/middlewares/hono.d.ts.map +0 -1
  249. package/dist/middlewares/hono.js.map +0 -1
  250. package/dist/middlewares/internal/mppx.d.ts.map +0 -1
  251. package/dist/middlewares/internal/mppx.js.map +0 -1
  252. package/dist/middlewares/nextjs.d.ts.map +0 -1
  253. package/dist/middlewares/nextjs.js.map +0 -1
  254. package/dist/proxy/Proxy.d.ts.map +0 -1
  255. package/dist/proxy/Proxy.js.map +0 -1
  256. package/dist/proxy/Service.d.ts.map +0 -1
  257. package/dist/proxy/Service.js.map +0 -1
  258. package/dist/proxy/index.d.ts.map +0 -1
  259. package/dist/proxy/index.js.map +0 -1
  260. package/dist/proxy/internal/Headers.d.ts.map +0 -1
  261. package/dist/proxy/internal/Headers.js.map +0 -1
  262. package/dist/proxy/internal/Route.d.ts.map +0 -1
  263. package/dist/proxy/internal/Route.js.map +0 -1
  264. package/dist/proxy/services/anthropic.d.ts.map +0 -1
  265. package/dist/proxy/services/anthropic.js.map +0 -1
  266. package/dist/proxy/services/openai.d.ts.map +0 -1
  267. package/dist/proxy/services/openai.js.map +0 -1
  268. package/dist/proxy/services/stripe.d.ts.map +0 -1
  269. package/dist/proxy/services/stripe.js.map +0 -1
  270. package/dist/server/Methods.d.ts.map +0 -1
  271. package/dist/server/Methods.js.map +0 -1
  272. package/dist/server/Mppx.d.ts.map +0 -1
  273. package/dist/server/Mppx.js.map +0 -1
  274. package/dist/server/NodeListener.d.ts.map +0 -1
  275. package/dist/server/NodeListener.js.map +0 -1
  276. package/dist/server/Request.d.ts.map +0 -1
  277. package/dist/server/Request.js.map +0 -1
  278. package/dist/server/Response.d.ts.map +0 -1
  279. package/dist/server/Response.js.map +0 -1
  280. package/dist/server/Transport.d.ts.map +0 -1
  281. package/dist/server/Transport.js.map +0 -1
  282. package/dist/server/index.d.ts.map +0 -1
  283. package/dist/server/index.js.map +0 -1
  284. package/dist/server/internal/html/compose.main.gen.d.ts.map +0 -1
  285. package/dist/server/internal/html/compose.main.gen.js.map +0 -1
  286. package/dist/server/internal/html/config.d.ts.map +0 -1
  287. package/dist/server/internal/html/config.js.map +0 -1
  288. package/dist/server/internal/html/constants.d.ts.map +0 -1
  289. package/dist/server/internal/html/constants.js.map +0 -1
  290. package/dist/server/internal/html/serviceWorker.client.d.ts.map +0 -1
  291. package/dist/server/internal/html/serviceWorker.client.js.map +0 -1
  292. package/dist/server/internal/html/serviceWorker.gen.d.ts.map +0 -1
  293. package/dist/server/internal/html/serviceWorker.gen.js.map +0 -1
  294. package/dist/server/internal/scope.d.ts.map +0 -1
  295. package/dist/server/internal/scope.js.map +0 -1
  296. package/dist/stripe/Methods.d.ts.map +0 -1
  297. package/dist/stripe/Methods.js.map +0 -1
  298. package/dist/stripe/client/Charge.d.ts.map +0 -1
  299. package/dist/stripe/client/Charge.js.map +0 -1
  300. package/dist/stripe/client/Methods.d.ts.map +0 -1
  301. package/dist/stripe/client/Methods.js.map +0 -1
  302. package/dist/stripe/client/index.d.ts.map +0 -1
  303. package/dist/stripe/client/index.js.map +0 -1
  304. package/dist/stripe/index.d.ts.map +0 -1
  305. package/dist/stripe/index.js.map +0 -1
  306. package/dist/stripe/internal/constants.d.ts.map +0 -1
  307. package/dist/stripe/internal/constants.js.map +0 -1
  308. package/dist/stripe/internal/types.d.ts.map +0 -1
  309. package/dist/stripe/internal/types.js.map +0 -1
  310. package/dist/stripe/server/Charge.d.ts.map +0 -1
  311. package/dist/stripe/server/Charge.js.map +0 -1
  312. package/dist/stripe/server/Methods.d.ts.map +0 -1
  313. package/dist/stripe/server/Methods.js.map +0 -1
  314. package/dist/stripe/server/index.d.ts.map +0 -1
  315. package/dist/stripe/server/index.js.map +0 -1
  316. package/dist/stripe/server/internal/deposit-address.d.ts.map +0 -1
  317. package/dist/stripe/server/internal/deposit-address.js.map +0 -1
  318. package/dist/stripe/server/internal/html/types.d.ts.map +0 -1
  319. package/dist/stripe/server/internal/html/types.js.map +0 -1
  320. package/dist/stripe/server/internal/html.gen.d.ts.map +0 -1
  321. package/dist/stripe/server/internal/html.gen.js.map +0 -1
  322. package/dist/stripe/server/internal/record-payment.d.ts.map +0 -1
  323. package/dist/stripe/server/internal/record-payment.js.map +0 -1
  324. package/dist/stripe/server/internal/request.d.ts.map +0 -1
  325. package/dist/stripe/server/internal/request.js.map +0 -1
  326. package/dist/tap/Constants.d.ts.map +0 -1
  327. package/dist/tap/Constants.js.map +0 -1
  328. package/dist/tap/Types.d.ts.map +0 -1
  329. package/dist/tap/Types.js.map +0 -1
  330. package/dist/tap/client/index.d.ts.map +0 -1
  331. package/dist/tap/client/index.js.map +0 -1
  332. package/dist/tap/index.d.ts.map +0 -1
  333. package/dist/tap/index.js.map +0 -1
  334. package/dist/tap/server/index.d.ts.map +0 -1
  335. package/dist/tap/server/index.js.map +0 -1
  336. package/dist/tempo/Attribution.d.ts.map +0 -1
  337. package/dist/tempo/Attribution.js.map +0 -1
  338. package/dist/tempo/Methods.d.ts.map +0 -1
  339. package/dist/tempo/Methods.js.map +0 -1
  340. package/dist/tempo/Proof.d.ts.map +0 -1
  341. package/dist/tempo/Proof.js.map +0 -1
  342. package/dist/tempo/client/Charge.d.ts.map +0 -1
  343. package/dist/tempo/client/Charge.js.map +0 -1
  344. package/dist/tempo/client/Methods.d.ts.map +0 -1
  345. package/dist/tempo/client/Methods.js.map +0 -1
  346. package/dist/tempo/client/ResolveAccount.d.ts.map +0 -1
  347. package/dist/tempo/client/ResolveAccount.js.map +0 -1
  348. package/dist/tempo/client/Subscription.d.ts.map +0 -1
  349. package/dist/tempo/client/Subscription.js.map +0 -1
  350. package/dist/tempo/client/index.d.ts.map +0 -1
  351. package/dist/tempo/client/index.js.map +0 -1
  352. package/dist/tempo/index.d.ts.map +0 -1
  353. package/dist/tempo/index.js.map +0 -1
  354. package/dist/tempo/internal/account.d.ts.map +0 -1
  355. package/dist/tempo/internal/account.js.map +0 -1
  356. package/dist/tempo/internal/address.d.ts.map +0 -1
  357. package/dist/tempo/internal/address.js.map +0 -1
  358. package/dist/tempo/internal/auto-swap.d.ts.map +0 -1
  359. package/dist/tempo/internal/auto-swap.js.map +0 -1
  360. package/dist/tempo/internal/charge.d.ts.map +0 -1
  361. package/dist/tempo/internal/charge.js.map +0 -1
  362. package/dist/tempo/internal/defaults.d.ts.map +0 -1
  363. package/dist/tempo/internal/defaults.js.map +0 -1
  364. package/dist/tempo/internal/fee-payer.d.ts.map +0 -1
  365. package/dist/tempo/internal/fee-payer.js.map +0 -1
  366. package/dist/tempo/internal/fee-token.d.ts.map +0 -1
  367. package/dist/tempo/internal/fee-token.js.map +0 -1
  368. package/dist/tempo/internal/proof.d.ts.map +0 -1
  369. package/dist/tempo/internal/proof.js.map +0 -1
  370. package/dist/tempo/internal/selectors.d.ts.map +0 -1
  371. package/dist/tempo/internal/selectors.js.map +0 -1
  372. package/dist/tempo/internal/types.d.ts.map +0 -1
  373. package/dist/tempo/internal/types.js.map +0 -1
  374. package/dist/tempo/legacy/client/ChannelOps.d.ts.map +0 -1
  375. package/dist/tempo/legacy/client/ChannelOps.js.map +0 -1
  376. package/dist/tempo/legacy/client/Session.d.ts.map +0 -1
  377. package/dist/tempo/legacy/client/Session.js.map +0 -1
  378. package/dist/tempo/legacy/client/SessionManager.d.ts.map +0 -1
  379. package/dist/tempo/legacy/client/SessionManager.js.map +0 -1
  380. package/dist/tempo/legacy/client/index.d.ts.map +0 -1
  381. package/dist/tempo/legacy/client/index.js.map +0 -1
  382. package/dist/tempo/legacy/index.d.ts.map +0 -1
  383. package/dist/tempo/legacy/index.js.map +0 -1
  384. package/dist/tempo/legacy/session/Chain.d.ts.map +0 -1
  385. package/dist/tempo/legacy/session/Chain.js.map +0 -1
  386. package/dist/tempo/legacy/session/Channel.d.ts.map +0 -1
  387. package/dist/tempo/legacy/session/Channel.js.map +0 -1
  388. package/dist/tempo/legacy/session/Types.d.ts.map +0 -1
  389. package/dist/tempo/legacy/session/Types.js.map +0 -1
  390. package/dist/tempo/legacy/session/Voucher.d.ts.map +0 -1
  391. package/dist/tempo/legacy/session/Voucher.js.map +0 -1
  392. package/dist/tempo/legacy/session/escrow.abi.d.ts.map +0 -1
  393. package/dist/tempo/legacy/session/escrow.abi.js.map +0 -1
  394. package/dist/tempo/legacy/session/index.d.ts.map +0 -1
  395. package/dist/tempo/legacy/session/index.js.map +0 -1
  396. package/dist/tempo/server/Charge.d.ts.map +0 -1
  397. package/dist/tempo/server/Charge.js.map +0 -1
  398. package/dist/tempo/server/Methods.d.ts.map +0 -1
  399. package/dist/tempo/server/Methods.js.map +0 -1
  400. package/dist/tempo/server/Relay.d.ts.map +0 -1
  401. package/dist/tempo/server/Relay.js.map +0 -1
  402. package/dist/tempo/server/SponsorBudget.d.ts.map +0 -1
  403. package/dist/tempo/server/SponsorBudget.js.map +0 -1
  404. package/dist/tempo/server/Subscription.d.ts.map +0 -1
  405. package/dist/tempo/server/Subscription.js.map +0 -1
  406. package/dist/tempo/server/index.d.ts.map +0 -1
  407. package/dist/tempo/server/index.js.map +0 -1
  408. package/dist/tempo/server/internal/html.gen.d.ts.map +0 -1
  409. package/dist/tempo/server/internal/html.gen.js.map +0 -1
  410. package/dist/tempo/server/internal/request-body.d.ts.map +0 -1
  411. package/dist/tempo/server/internal/request-body.js.map +0 -1
  412. package/dist/tempo/server/internal/transport.d.ts.map +0 -1
  413. package/dist/tempo/server/internal/transport.js.map +0 -1
  414. package/dist/tempo/session/Snapshot.d.ts.map +0 -1
  415. package/dist/tempo/session/Snapshot.js.map +0 -1
  416. package/dist/tempo/session/client/ChannelOps.d.ts.map +0 -1
  417. package/dist/tempo/session/client/ChannelOps.js.map +0 -1
  418. package/dist/tempo/session/client/ChannelStore.d.ts.map +0 -1
  419. package/dist/tempo/session/client/ChannelStore.js.map +0 -1
  420. package/dist/tempo/session/client/CredentialState.d.ts.map +0 -1
  421. package/dist/tempo/session/client/CredentialState.js.map +0 -1
  422. package/dist/tempo/session/client/ReceiptCoordinator.d.ts.map +0 -1
  423. package/dist/tempo/session/client/ReceiptCoordinator.js.map +0 -1
  424. package/dist/tempo/session/client/Runtime.d.ts.map +0 -1
  425. package/dist/tempo/session/client/Runtime.js.map +0 -1
  426. package/dist/tempo/session/client/Session.d.ts.map +0 -1
  427. package/dist/tempo/session/client/Session.js.map +0 -1
  428. package/dist/tempo/session/client/SessionManager.d.ts.map +0 -1
  429. package/dist/tempo/session/client/SessionManager.js.map +0 -1
  430. package/dist/tempo/session/client/Transports.d.ts.map +0 -1
  431. package/dist/tempo/session/client/Transports.js.map +0 -1
  432. package/dist/tempo/session/client/index.d.ts.map +0 -1
  433. package/dist/tempo/session/client/index.js.map +0 -1
  434. package/dist/tempo/session/client/internal/SessionManager.d.ts.map +0 -1
  435. package/dist/tempo/session/client/internal/SessionManager.js.map +0 -1
  436. package/dist/tempo/session/index.d.ts.map +0 -1
  437. package/dist/tempo/session/index.js.map +0 -1
  438. package/dist/tempo/session/precompile/Chain.d.ts.map +0 -1
  439. package/dist/tempo/session/precompile/Chain.js.map +0 -1
  440. package/dist/tempo/session/precompile/Channel.d.ts.map +0 -1
  441. package/dist/tempo/session/precompile/Channel.js.map +0 -1
  442. package/dist/tempo/session/precompile/Protocol.d.ts.map +0 -1
  443. package/dist/tempo/session/precompile/Protocol.js.map +0 -1
  444. package/dist/tempo/session/precompile/Voucher.d.ts.map +0 -1
  445. package/dist/tempo/session/precompile/Voucher.js.map +0 -1
  446. package/dist/tempo/session/precompile/escrow.abi.d.ts.map +0 -1
  447. package/dist/tempo/session/precompile/escrow.abi.js.map +0 -1
  448. package/dist/tempo/session/precompile/index.d.ts.map +0 -1
  449. package/dist/tempo/session/precompile/index.js.map +0 -1
  450. package/dist/tempo/session/server/ChannelOps.d.ts.map +0 -1
  451. package/dist/tempo/session/server/ChannelOps.js.map +0 -1
  452. package/dist/tempo/session/server/ChannelStore.d.ts.map +0 -1
  453. package/dist/tempo/session/server/ChannelStore.js.map +0 -1
  454. package/dist/tempo/session/server/CredentialVerification.d.ts.map +0 -1
  455. package/dist/tempo/session/server/CredentialVerification.js.map +0 -1
  456. package/dist/tempo/session/server/MeteredStream.d.ts.map +0 -1
  457. package/dist/tempo/session/server/MeteredStream.js.map +0 -1
  458. package/dist/tempo/session/server/RequestState.d.ts.map +0 -1
  459. package/dist/tempo/session/server/RequestState.js.map +0 -1
  460. package/dist/tempo/session/server/Session.d.ts.map +0 -1
  461. package/dist/tempo/session/server/Session.js.map +0 -1
  462. package/dist/tempo/session/server/Settlement.d.ts.map +0 -1
  463. package/dist/tempo/session/server/Settlement.js.map +0 -1
  464. package/dist/tempo/session/server/Sse.d.ts.map +0 -1
  465. package/dist/tempo/session/server/Sse.js.map +0 -1
  466. package/dist/tempo/session/server/Transports.d.ts.map +0 -1
  467. package/dist/tempo/session/server/Transports.js.map +0 -1
  468. package/dist/tempo/session/server/Ws.d.ts.map +0 -1
  469. package/dist/tempo/session/server/Ws.js.map +0 -1
  470. package/dist/tempo/session/server/index.d.ts.map +0 -1
  471. package/dist/tempo/session/server/index.js.map +0 -1
  472. package/dist/tempo/subscription/KeyAuthorization.d.ts.map +0 -1
  473. package/dist/tempo/subscription/KeyAuthorization.js.map +0 -1
  474. package/dist/tempo/subscription/Receipt.d.ts.map +0 -1
  475. package/dist/tempo/subscription/Receipt.js.map +0 -1
  476. package/dist/tempo/subscription/Store.d.ts.map +0 -1
  477. package/dist/tempo/subscription/Store.js.map +0 -1
  478. package/dist/tempo/subscription/Types.d.ts.map +0 -1
  479. package/dist/tempo/subscription/Types.js.map +0 -1
  480. package/dist/tempo/subscription/index.d.ts.map +0 -1
  481. package/dist/tempo/subscription/index.js.map +0 -1
  482. package/dist/validation/core.d.ts.map +0 -1
  483. package/dist/validation/core.js.map +0 -1
  484. package/dist/validation/index.d.ts.map +0 -1
  485. package/dist/validation/index.js.map +0 -1
  486. package/dist/viem/Account.d.ts.map +0 -1
  487. package/dist/viem/Account.js.map +0 -1
  488. package/dist/viem/Client.d.ts.map +0 -1
  489. package/dist/viem/Client.js.map +0 -1
  490. package/dist/web-bot-auth/Constants.d.ts.map +0 -1
  491. package/dist/web-bot-auth/Constants.js.map +0 -1
  492. package/dist/web-bot-auth/Types.d.ts.map +0 -1
  493. package/dist/web-bot-auth/Types.js.map +0 -1
  494. package/dist/web-bot-auth/client/index.d.ts.map +0 -1
  495. package/dist/web-bot-auth/client/index.js.map +0 -1
  496. package/dist/web-bot-auth/index.d.ts.map +0 -1
  497. package/dist/web-bot-auth/index.js.map +0 -1
  498. package/dist/web-bot-auth/internal/JwkThumbprint.d.ts.map +0 -1
  499. package/dist/web-bot-auth/internal/JwkThumbprint.js.map +0 -1
  500. package/dist/web-bot-auth/internal/SignatureAgent.d.ts.map +0 -1
  501. package/dist/web-bot-auth/internal/SignatureAgent.js.map +0 -1
  502. package/dist/web-bot-auth/server/index.d.ts.map +0 -1
  503. package/dist/web-bot-auth/server/index.js.map +0 -1
  504. package/dist/x402/Assets.d.ts.map +0 -1
  505. package/dist/x402/Assets.js.map +0 -1
  506. package/dist/x402/Header.d.ts.map +0 -1
  507. package/dist/x402/Header.js.map +0 -1
  508. package/dist/x402/Types.d.ts.map +0 -1
  509. package/dist/x402/Types.js.map +0 -1
  510. package/dist/x402/client/Exact.d.ts.map +0 -1
  511. package/dist/x402/client/Exact.js.map +0 -1
  512. package/dist/x402/index.d.ts.map +0 -1
  513. package/dist/x402/index.js.map +0 -1
  514. package/dist/x402/internal/ChallengeBrand.d.ts.map +0 -1
  515. package/dist/x402/internal/ChallengeBrand.js.map +0 -1
  516. package/dist/x402/internal/RouteBinding.d.ts.map +0 -1
  517. package/dist/x402/internal/RouteBinding.js.map +0 -1
  518. package/dist/x402/server/EvmCharge.d.ts.map +0 -1
  519. package/dist/x402/server/EvmCharge.js.map +0 -1
  520. package/dist/x402/server/Facilitator.d.ts.map +0 -1
  521. package/dist/x402/server/Facilitator.js.map +0 -1
  522. package/dist/zod.d.ts.map +0 -1
  523. package/dist/zod.js.map +0 -1
  524. package/src/BodyDigest.test.ts +0 -43
  525. package/src/BodyDigest.ts +0 -55
  526. package/src/Challenge.fuzz.test.ts +0 -154
  527. package/src/Challenge.test-d.ts +0 -82
  528. package/src/Challenge.test.ts +0 -1060
  529. package/src/Challenge.ts +0 -687
  530. package/src/Constants.ts +0 -58
  531. package/src/Credential.fuzz.test.ts +0 -62
  532. package/src/Credential.test.ts +0 -378
  533. package/src/Credential.ts +0 -217
  534. package/src/Errors.test.ts +0 -520
  535. package/src/Errors.ts +0 -448
  536. package/src/Expires.test.ts +0 -112
  537. package/src/Expires.ts +0 -59
  538. package/src/Html.ts +0 -67
  539. package/src/Mcp.ts +0 -85
  540. package/src/Method.test.ts +0 -177
  541. package/src/Method.ts +0 -631
  542. package/src/PaymentRequest.test.ts +0 -147
  543. package/src/PaymentRequest.ts +0 -108
  544. package/src/Receipt.test.ts +0 -151
  545. package/src/Receipt.ts +0 -146
  546. package/src/Store.test-d.ts +0 -211
  547. package/src/Store.test.ts +0 -407
  548. package/src/Store.ts +0 -397
  549. package/src/attestation/Attestation.integration.test.ts +0 -208
  550. package/src/attestation/Client.test.ts +0 -83
  551. package/src/attestation/Client.ts +0 -34
  552. package/src/attestation/Constants.ts +0 -15
  553. package/src/attestation/Server.test.ts +0 -60
  554. package/src/attestation/Server.ts +0 -12
  555. package/src/attestation/Types.test-d.ts +0 -54
  556. package/src/attestation/Types.ts +0 -77
  557. package/src/attestation/index.ts +0 -5
  558. package/src/attestation/internal/HttpMessageSignature.test.ts +0 -101
  559. package/src/attestation/internal/HttpMessageSignature.ts +0 -429
  560. package/src/attestation/internal/SigningContext.ts +0 -13
  561. package/src/bin.js +0 -2
  562. package/src/bin.ts +0 -4
  563. package/src/cli/account.ts +0 -269
  564. package/src/cli/cli.test.ts +0 -2221
  565. package/src/cli/cli.ts +0 -1650
  566. package/src/cli/config.test.ts +0 -89
  567. package/src/cli/config.ts +0 -50
  568. package/src/cli/internal.ts +0 -114
  569. package/src/cli/mcp.test.ts +0 -262
  570. package/src/cli/plugins/evm.ts +0 -55
  571. package/src/cli/plugins/index.ts +0 -4
  572. package/src/cli/plugins/plugin.ts +0 -84
  573. package/src/cli/plugins/stripe.ts +0 -174
  574. package/src/cli/plugins/tempo.ts +0 -1102
  575. package/src/cli/sessions/Manager.test.ts +0 -249
  576. package/src/cli/sessions/Manager.ts +0 -93
  577. package/src/cli/sessions/commands.ts +0 -444
  578. package/src/cli/sessions/request.test.ts +0 -51
  579. package/src/cli/sessions/request.ts +0 -353
  580. package/src/cli/sessions/store.test.ts +0 -581
  581. package/src/cli/sessions/store.ts +0 -940
  582. package/src/cli/utils.test.ts +0 -156
  583. package/src/cli/utils.ts +0 -394
  584. package/src/cli/validate/challenge.ts +0 -565
  585. package/src/cli/validate/discovery.test.ts +0 -435
  586. package/src/cli/validate/discovery.ts +0 -221
  587. package/src/cli/validate/helpers.ts +0 -166
  588. package/src/cli/validate/index.ts +0 -229
  589. package/src/cli/validate/messages.ts +0 -7
  590. package/src/cli/validate/payment.ts +0 -774
  591. package/src/cli/validate.test.ts +0 -843
  592. package/src/client/Methods.ts +0 -8
  593. package/src/client/Mppx.test-d.ts +0 -287
  594. package/src/client/Mppx.test.ts +0 -1065
  595. package/src/client/Mppx.ts +0 -487
  596. package/src/client/Transport.test.ts +0 -586
  597. package/src/client/Transport.ts +0 -170
  598. package/src/client/index.ts +0 -29
  599. package/src/client/internal/Fetch.browser.test.ts +0 -197
  600. package/src/client/internal/Fetch.test-d.ts +0 -109
  601. package/src/client/internal/Fetch.test.ts +0 -2336
  602. package/src/client/internal/Fetch.ts +0 -1075
  603. package/src/client/internal/MethodChallenge.ts +0 -35
  604. package/src/client/internal/MethodResponse.ts +0 -67
  605. package/src/client/internal/protocols/Mcp.test.ts +0 -220
  606. package/src/client/internal/protocols/Mcp.ts +0 -186
  607. package/src/client/internal/protocols/Mpp.ts +0 -21
  608. package/src/client/internal/protocols/Protocol.ts +0 -10
  609. package/src/client/internal/protocols/Shared.ts +0 -25
  610. package/src/client/internal/protocols/X402.ts +0 -46
  611. package/src/client/node.test.ts +0 -115
  612. package/src/client/node.ts +0 -247
  613. package/src/discovery/Discovery.test.ts +0 -214
  614. package/src/discovery/Discovery.ts +0 -105
  615. package/src/discovery/OpenApi.test.ts +0 -623
  616. package/src/discovery/OpenApi.ts +0 -192
  617. package/src/discovery/Validate.test.ts +0 -305
  618. package/src/discovery/Validate.ts +0 -77
  619. package/src/discovery/index.ts +0 -3
  620. package/src/discovery/internal/Metadata.ts +0 -51
  621. package/src/env.d.ts +0 -12
  622. package/src/evm/Assets.ts +0 -1
  623. package/src/evm/Chains.ts +0 -11
  624. package/src/evm/Methods.ts +0 -44
  625. package/src/evm/PublicInterface.test-d.ts +0 -134
  626. package/src/evm/Types.ts +0 -140
  627. package/src/evm/client/Charge.test.ts +0 -347
  628. package/src/evm/client/Charge.ts +0 -187
  629. package/src/evm/client/Methods.ts +0 -19
  630. package/src/evm/client/index.ts +0 -6
  631. package/src/evm/index.ts +0 -16
  632. package/src/evm/server/Charge.test.ts +0 -339
  633. package/src/evm/server/Charge.ts +0 -295
  634. package/src/evm/server/Methods.ts +0 -22
  635. package/src/evm/server/index.ts +0 -6
  636. package/src/index.ts +0 -14
  637. package/src/internal/AcceptPayment.test.ts +0 -347
  638. package/src/internal/AcceptPayment.ts +0 -366
  639. package/src/internal/HeaderCodec.ts +0 -36
  640. package/src/internal/changeset.test.ts +0 -106
  641. package/src/internal/constantTimeEqual.test.ts +0 -47
  642. package/src/internal/constantTimeEqual.ts +0 -10
  643. package/src/internal/env.test.ts +0 -42
  644. package/src/internal/env.ts +0 -49
  645. package/src/internal/types.test-d.ts +0 -21
  646. package/src/internal/types.ts +0 -479
  647. package/src/mcp/client/McpClient.integration.test.ts +0 -639
  648. package/src/mcp/client/McpClient.test-d.ts +0 -144
  649. package/src/mcp/client/McpClient.test.ts +0 -463
  650. package/src/mcp/client/McpClient.ts +0 -307
  651. package/src/mcp/client/McpClient.unit.test.ts +0 -135
  652. package/src/mcp/client/index.ts +0 -2
  653. package/src/mcp/server/Transport.test.ts +0 -191
  654. package/src/mcp/server/Transport.ts +0 -111
  655. package/src/mcp/server/index.ts +0 -1
  656. package/src/middlewares/elysia.test.ts +0 -285
  657. package/src/middlewares/elysia.ts +0 -116
  658. package/src/middlewares/express.test.ts +0 -361
  659. package/src/middlewares/express.ts +0 -140
  660. package/src/middlewares/hono.test.ts +0 -473
  661. package/src/middlewares/hono.ts +0 -153
  662. package/src/middlewares/internal/mppx.test.ts +0 -177
  663. package/src/middlewares/internal/mppx.ts +0 -67
  664. package/src/middlewares/nextjs.test.ts +0 -359
  665. package/src/middlewares/nextjs.ts +0 -107
  666. package/src/proxy/Proxy.test.ts +0 -1038
  667. package/src/proxy/Proxy.ts +0 -483
  668. package/src/proxy/Proxy.upstreamError.test.ts +0 -364
  669. package/src/proxy/Service.test.ts +0 -252
  670. package/src/proxy/Service.ts +0 -280
  671. package/src/proxy/index.ts +0 -6
  672. package/src/proxy/internal/Headers.test.ts +0 -139
  673. package/src/proxy/internal/Headers.ts +0 -66
  674. package/src/proxy/internal/Route.test.ts +0 -217
  675. package/src/proxy/internal/Route.ts +0 -64
  676. package/src/proxy/services/anthropic.test.ts +0 -132
  677. package/src/proxy/services/anthropic.ts +0 -53
  678. package/src/proxy/services/hooks.test-d.ts +0 -14
  679. package/src/proxy/services/hooks.test.ts +0 -44
  680. package/src/proxy/services/openai.test.ts +0 -157
  681. package/src/proxy/services/openai.ts +0 -60
  682. package/src/proxy/services/stripe.test.ts +0 -175
  683. package/src/proxy/services/stripe.ts +0 -59
  684. package/src/server/Methods.test-d.ts +0 -88
  685. package/src/server/Methods.test.ts +0 -69
  686. package/src/server/Methods.ts +0 -3
  687. package/src/server/Mppx.authorize.test.ts +0 -210
  688. package/src/server/Mppx.test-d.ts +0 -494
  689. package/src/server/Mppx.test.ts +0 -6711
  690. package/src/server/Mppx.ts +0 -2919
  691. package/src/server/NodeListener.test.ts +0 -293
  692. package/src/server/NodeListener.ts +0 -45
  693. package/src/server/Request.test.ts +0 -255
  694. package/src/server/Request.ts +0 -155
  695. package/src/server/Response.test.ts +0 -32
  696. package/src/server/Response.ts +0 -45
  697. package/src/server/Transport.test.ts +0 -598
  698. package/src/server/Transport.ts +0 -320
  699. package/src/server/index.ts +0 -9
  700. package/src/server/internal/html/compose.main.gen.ts +0 -2
  701. package/src/server/internal/html/compose.main.ts +0 -88
  702. package/src/server/internal/html/config.ts +0 -672
  703. package/src/server/internal/html/constants.ts +0 -28
  704. package/src/server/internal/html/serviceWorker.client.ts +0 -28
  705. package/src/server/internal/html/serviceWorker.gen.ts +0 -2
  706. package/src/server/internal/html/serviceWorker.ts +0 -27
  707. package/src/server/internal/html/tsconfig.compose.json +0 -8
  708. package/src/server/internal/html/tsconfig.worker.client.json +0 -8
  709. package/src/server/internal/html/tsconfig.worker.json +0 -8
  710. package/src/server/internal/scope.ts +0 -43
  711. package/src/stripe/Charge.integration.test.ts +0 -329
  712. package/src/stripe/Methods.test.ts +0 -62
  713. package/src/stripe/Methods.ts +0 -44
  714. package/src/stripe/client/Charge.test.ts +0 -205
  715. package/src/stripe/client/Charge.ts +0 -132
  716. package/src/stripe/client/Methods.ts +0 -37
  717. package/src/stripe/client/index.ts +0 -2
  718. package/src/stripe/index.ts +0 -1
  719. package/src/stripe/internal/constants.ts +0 -7
  720. package/src/stripe/internal/types.ts +0 -47
  721. package/src/stripe/server/Charge.test-d.ts +0 -81
  722. package/src/stripe/server/Charge.test.ts +0 -700
  723. package/src/stripe/server/Charge.ts +0 -487
  724. package/src/stripe/server/Methods.test-d.ts +0 -157
  725. package/src/stripe/server/Methods.test.ts +0 -403
  726. package/src/stripe/server/Methods.ts +0 -441
  727. package/src/stripe/server/index.ts +0 -2
  728. package/src/stripe/server/internal/deposit-address.ts +0 -57
  729. package/src/stripe/server/internal/html/main.ts +0 -165
  730. package/src/stripe/server/internal/html/node_modules/.bin/mppx +0 -22
  731. package/src/stripe/server/internal/html/node_modules/.bin/mppx.src +0 -22
  732. package/src/stripe/server/internal/html/package.json +0 -9
  733. package/src/stripe/server/internal/html/stripe-js-pure.d.ts +0 -7
  734. package/src/stripe/server/internal/html/tsconfig.json +0 -8
  735. package/src/stripe/server/internal/html/types.ts +0 -5
  736. package/src/stripe/server/internal/html.gen.ts +0 -2
  737. package/src/stripe/server/internal/record-payment.ts +0 -66
  738. package/src/stripe/server/internal/request.ts +0 -49
  739. package/src/tap/Constants.ts +0 -32
  740. package/src/tap/Tap.test.ts +0 -125
  741. package/src/tap/Types.ts +0 -11
  742. package/src/tap/client/index.ts +0 -54
  743. package/src/tap/index.ts +0 -4
  744. package/src/tap/server/index.ts +0 -48
  745. package/src/tempo/AccessKeyAuthorization.test.ts +0 -141
  746. package/src/tempo/Attribution.test.ts +0 -294
  747. package/src/tempo/Attribution.ts +0 -185
  748. package/src/tempo/Methods.test.ts +0 -425
  749. package/src/tempo/Methods.ts +0 -367
  750. package/src/tempo/Proof.conformance.test.ts +0 -146
  751. package/src/tempo/Proof.test-d.ts +0 -32
  752. package/src/tempo/Proof.test.ts +0 -40
  753. package/src/tempo/Proof.ts +0 -69
  754. package/src/tempo/PublicExports.test-d.ts +0 -130
  755. package/src/tempo/Subscription.integration.test.ts +0 -591
  756. package/src/tempo/client/Charge.test.ts +0 -501
  757. package/src/tempo/client/Charge.ts +0 -271
  758. package/src/tempo/client/Methods.ts +0 -45
  759. package/src/tempo/client/ResolveAccount.ts +0 -46
  760. package/src/tempo/client/Subscription.test.ts +0 -180
  761. package/src/tempo/client/Subscription.ts +0 -156
  762. package/src/tempo/client/index.ts +0 -17
  763. package/src/tempo/index.ts +0 -5
  764. package/src/tempo/internal/account.ts +0 -56
  765. package/src/tempo/internal/address.test.ts +0 -42
  766. package/src/tempo/internal/address.ts +0 -6
  767. package/src/tempo/internal/auto-swap.test.ts +0 -198
  768. package/src/tempo/internal/auto-swap.ts +0 -145
  769. package/src/tempo/internal/charge.test.ts +0 -66
  770. package/src/tempo/internal/charge.ts +0 -43
  771. package/src/tempo/internal/defaults.test.ts +0 -95
  772. package/src/tempo/internal/defaults.ts +0 -53
  773. package/src/tempo/internal/fee-payer.test.ts +0 -1177
  774. package/src/tempo/internal/fee-payer.ts +0 -808
  775. package/src/tempo/internal/fee-token.test.ts +0 -165
  776. package/src/tempo/internal/fee-token.ts +0 -72
  777. package/src/tempo/internal/proof.test.ts +0 -97
  778. package/src/tempo/internal/proof.ts +0 -87
  779. package/src/tempo/internal/selectors.ts +0 -10
  780. package/src/tempo/internal/types.ts +0 -19
  781. package/src/tempo/legacy/AccessKeyAuthorization.test.ts +0 -162
  782. package/src/tempo/legacy/README.md +0 -9
  783. package/src/tempo/legacy/client/ChannelOps.test.ts +0 -379
  784. package/src/tempo/legacy/client/ChannelOps.ts +0 -271
  785. package/src/tempo/legacy/client/Session.test.ts +0 -800
  786. package/src/tempo/legacy/client/Session.ts +0 -397
  787. package/src/tempo/legacy/client/SessionManager.test.ts +0 -468
  788. package/src/tempo/legacy/client/SessionManager.ts +0 -909
  789. package/src/tempo/legacy/client/index.ts +0 -6
  790. package/src/tempo/legacy/index.ts +0 -4
  791. package/src/tempo/legacy/session/Chain.test.ts +0 -1349
  792. package/src/tempo/legacy/session/Chain.ts +0 -830
  793. package/src/tempo/legacy/session/Channel.test.ts +0 -109
  794. package/src/tempo/legacy/session/Channel.ts +0 -51
  795. package/src/tempo/legacy/session/Types.ts +0 -91
  796. package/src/tempo/legacy/session/Voucher.test.ts +0 -410
  797. package/src/tempo/legacy/session/Voucher.ts +0 -183
  798. package/src/tempo/legacy/session/escrow.abi.ts +0 -760
  799. package/src/tempo/legacy/session/index.ts +0 -8
  800. package/src/tempo/server/AtomicStore.test-d.ts +0 -63
  801. package/src/tempo/server/Charge.test.ts +0 -6056
  802. package/src/tempo/server/Charge.ts +0 -1379
  803. package/src/tempo/server/Methods.ts +0 -86
  804. package/src/tempo/server/Relay.test.ts +0 -677
  805. package/src/tempo/server/Relay.ts +0 -297
  806. package/src/tempo/server/SponsorBudget.test.ts +0 -154
  807. package/src/tempo/server/SponsorBudget.ts +0 -219
  808. package/src/tempo/server/Sse.test.ts +0 -321
  809. package/src/tempo/server/Subscription.test.ts +0 -1944
  810. package/src/tempo/server/Subscription.ts +0 -1336
  811. package/src/tempo/server/index.ts +0 -12
  812. package/src/tempo/server/internal/html/main.ts +0 -115
  813. package/src/tempo/server/internal/html/node_modules/.bin/mppx +0 -22
  814. package/src/tempo/server/internal/html/node_modules/.bin/mppx.src +0 -22
  815. package/src/tempo/server/internal/html/package.json +0 -10
  816. package/src/tempo/server/internal/html/tsconfig.json +0 -8
  817. package/src/tempo/server/internal/html.gen.ts +0 -2
  818. package/src/tempo/server/internal/request-body.test.ts +0 -210
  819. package/src/tempo/server/internal/request-body.ts +0 -61
  820. package/src/tempo/server/internal/transport.test.ts +0 -922
  821. package/src/tempo/server/internal/transport.ts +0 -322
  822. package/src/tempo/session/README.md +0 -320
  823. package/src/tempo/session/Snapshot.test.ts +0 -41
  824. package/src/tempo/session/Snapshot.ts +0 -95
  825. package/src/tempo/session/client/ChannelOps.test.ts +0 -218
  826. package/src/tempo/session/client/ChannelOps.ts +0 -348
  827. package/src/tempo/session/client/ChannelStore.ts +0 -111
  828. package/src/tempo/session/client/CredentialState.test.ts +0 -789
  829. package/src/tempo/session/client/CredentialState.ts +0 -942
  830. package/src/tempo/session/client/ReceiptCoordinator.ts +0 -95
  831. package/src/tempo/session/client/Runtime.test.ts +0 -1104
  832. package/src/tempo/session/client/Runtime.ts +0 -1008
  833. package/src/tempo/session/client/Session.test.ts +0 -1355
  834. package/src/tempo/session/client/Session.ts +0 -420
  835. package/src/tempo/session/client/SessionManager.test.ts +0 -1899
  836. package/src/tempo/session/client/SessionManager.ts +0 -996
  837. package/src/tempo/session/client/Transports.test.ts +0 -1141
  838. package/src/tempo/session/client/Transports.ts +0 -1534
  839. package/src/tempo/session/client/index.ts +0 -40
  840. package/src/tempo/session/client/internal/SessionManager.ts +0 -36
  841. package/src/tempo/session/index.ts +0 -7
  842. package/src/tempo/session/precompile/Chain.integration.test.ts +0 -339
  843. package/src/tempo/session/precompile/Chain.test.ts +0 -1641
  844. package/src/tempo/session/precompile/Chain.ts +0 -1269
  845. package/src/tempo/session/precompile/Channel.test.ts +0 -147
  846. package/src/tempo/session/precompile/Channel.ts +0 -108
  847. package/src/tempo/session/precompile/Protocol.test.ts +0 -358
  848. package/src/tempo/session/precompile/Protocol.ts +0 -520
  849. package/src/tempo/session/precompile/Voucher.test.ts +0 -354
  850. package/src/tempo/session/precompile/Voucher.ts +0 -162
  851. package/src/tempo/session/precompile/escrow.abi.ts +0 -226
  852. package/src/tempo/session/precompile/index.ts +0 -33
  853. package/src/tempo/session/server/ChannelOps.test.ts +0 -129
  854. package/src/tempo/session/server/ChannelOps.ts +0 -157
  855. package/src/tempo/session/server/ChannelStore.test.ts +0 -1093
  856. package/src/tempo/session/server/ChannelStore.ts +0 -856
  857. package/src/tempo/session/server/CredentialVerification.test.ts +0 -299
  858. package/src/tempo/session/server/CredentialVerification.ts +0 -1087
  859. package/src/tempo/session/server/MeteredStream.ts +0 -99
  860. package/src/tempo/session/server/RequestState.test.ts +0 -574
  861. package/src/tempo/session/server/RequestState.ts +0 -507
  862. package/src/tempo/session/server/Session.integration.test.ts +0 -449
  863. package/src/tempo/session/server/Session.test.ts +0 -4247
  864. package/src/tempo/session/server/Session.ts +0 -669
  865. package/src/tempo/session/server/Settlement.test.ts +0 -345
  866. package/src/tempo/session/server/Settlement.ts +0 -527
  867. package/src/tempo/session/server/Sse.fuzz.test.ts +0 -138
  868. package/src/tempo/session/server/Sse.test.ts +0 -634
  869. package/src/tempo/session/server/Sse.ts +0 -261
  870. package/src/tempo/session/server/Transports.test.ts +0 -346
  871. package/src/tempo/session/server/Transports.ts +0 -256
  872. package/src/tempo/session/server/Ws.test.ts +0 -765
  873. package/src/tempo/session/server/Ws.ts +0 -391
  874. package/src/tempo/session/server/index.ts +0 -12
  875. package/src/tempo/subscription/KeyAuthorization.test.ts +0 -282
  876. package/src/tempo/subscription/KeyAuthorization.ts +0 -396
  877. package/src/tempo/subscription/Receipt.ts +0 -28
  878. package/src/tempo/subscription/Store.test.ts +0 -609
  879. package/src/tempo/subscription/Store.ts +0 -449
  880. package/src/tempo/subscription/Types.ts +0 -68
  881. package/src/tempo/subscription/index.ts +0 -23
  882. package/src/tsconfig.json +0 -10
  883. package/src/validation/core.ts +0 -386
  884. package/src/validation/index.ts +0 -11
  885. package/src/viem/Account.test.ts +0 -72
  886. package/src/viem/Account.ts +0 -30
  887. package/src/viem/Client.test.ts +0 -366
  888. package/src/viem/Client.ts +0 -93
  889. package/src/web-bot-auth/Constants.ts +0 -24
  890. package/src/web-bot-auth/Types.ts +0 -9
  891. package/src/web-bot-auth/WebBotAuth.test.ts +0 -182
  892. package/src/web-bot-auth/client/index.ts +0 -84
  893. package/src/web-bot-auth/index.ts +0 -6
  894. package/src/web-bot-auth/internal/JwkThumbprint.ts +0 -21
  895. package/src/web-bot-auth/internal/SignatureAgent.ts +0 -18
  896. package/src/web-bot-auth/server/index.ts +0 -113
  897. package/src/x402/Assets.test.ts +0 -253
  898. package/src/x402/Assets.ts +0 -221
  899. package/src/x402/Exact.e2e.test.ts +0 -488
  900. package/src/x402/Exact.localnet.test.ts +0 -475
  901. package/src/x402/Header.test.ts +0 -73
  902. package/src/x402/Header.ts +0 -79
  903. package/src/x402/PublicInterface.test-d.ts +0 -39
  904. package/src/x402/Types.ts +0 -248
  905. package/src/x402/client/Exact.test.ts +0 -309
  906. package/src/x402/client/Exact.ts +0 -186
  907. package/src/x402/index.ts +0 -6
  908. package/src/x402/internal/ChallengeBrand.ts +0 -14
  909. package/src/x402/internal/RouteBinding.ts +0 -18
  910. package/src/x402/server/EvmCharge.ts +0 -410
  911. package/src/x402/server/Facilitator.test.ts +0 -111
  912. package/src/x402/server/Facilitator.ts +0 -56
  913. package/src/zod.test.ts +0 -169
  914. package/src/zod.ts +0 -71
@@ -1,2336 +0,0 @@
1
- import { Challenge, Credential, Errors, Mcp, Receipt } from 'mppx'
2
- import { tempo } from 'mppx/client'
3
- import { Mppx as Mppx_server, tempo as tempo_server } from 'mppx/server'
4
- import { Header as x402_Header, Types as x402_Types, type PaymentRequired } from 'mppx/x402'
5
- import { Base64 } from 'ox'
6
- import { createClient, defineChain } from 'viem'
7
- import { describe, expect, test, vi } from 'vp/test'
8
- import * as Http from '~test/Http.js'
9
- import { rpcUrl } from '~test/tempo/rpc.js'
10
- import { accounts, asset, chain, client, http } from '~test/tempo/viem.js'
11
-
12
- import * as Fetch from './Fetch.js'
13
- import * as MethodChallenge from './MethodChallenge.js'
14
- import * as MethodResponse from './MethodResponse.js'
15
-
16
- const realm = 'api.example.com'
17
- const secretKey = 'test-secret-key-test-secret-key-32'
18
-
19
- const server = Mppx_server.create({
20
- methods: [
21
- tempo_server({
22
- getClient: () => client,
23
- account: accounts[0],
24
- }),
25
- ],
26
- realm,
27
- secretKey,
28
- })
29
-
30
- describe('Fetch.from', () => {
31
- test('default: account at creation', async () => {
32
- const fetch = Fetch.from({
33
- methods: [
34
- tempo.charge({
35
- account: accounts[1],
36
- getClient: () => client,
37
- }),
38
- ],
39
- })
40
-
41
- const httpServer = await Http.createServer(async (req, res) => {
42
- const result = await Mppx_server.toNodeListener(
43
- server.charge({
44
- amount: '1',
45
- currency: asset,
46
- expires: new Date(Date.now() + 60_000).toISOString(),
47
- recipient: accounts[0].address,
48
- }),
49
- )(req, res)
50
- if (result.status === 402) return
51
- res.end('OK')
52
- })
53
-
54
- const response = await fetch(httpServer.url)
55
- expect(response.status).toBe(200)
56
-
57
- const receipt = Receipt.fromResponse(response)
58
- expect({
59
- ...receipt,
60
- reference: '[reference]',
61
- timestamp: '[timestamp]',
62
- }).toMatchInlineSnapshot(`
63
- {
64
- "method": "tempo",
65
- "reference": "[reference]",
66
- "status": "success",
67
- "timestamp": "[timestamp]",
68
- }
69
- `)
70
-
71
- httpServer.close()
72
- })
73
-
74
- test('default: account via context', async () => {
75
- const fetch = Fetch.from({
76
- methods: [
77
- tempo.charge({
78
- getClient: () => client,
79
- }),
80
- ],
81
- })
82
-
83
- const httpServer = await Http.createServer(async (req, res) => {
84
- const result = await Mppx_server.toNodeListener(
85
- server.charge({
86
- amount: '1',
87
- currency: asset,
88
- expires: new Date(Date.now() + 60_000).toISOString(),
89
- recipient: accounts[0].address,
90
- }),
91
- )(req, res)
92
- if (result.status === 402) return
93
- res.end('OK')
94
- })
95
-
96
- const response = await fetch(httpServer.url, {
97
- context: { account: accounts[1] },
98
- })
99
- expect(response.status).toBe(200)
100
-
101
- const receipt = Receipt.fromResponse(response)
102
- expect(receipt.status).toBe('success')
103
-
104
- httpServer.close()
105
- })
106
-
107
- test('behavior: context overrides account at creation', async () => {
108
- const fetch = Fetch.from({
109
- methods: [
110
- tempo.charge({
111
- account: accounts[0],
112
- getClient: () => client,
113
- }),
114
- ],
115
- })
116
-
117
- const httpServer = await Http.createServer(async (req, res) => {
118
- const result = await Mppx_server.toNodeListener(
119
- server.charge({
120
- amount: '1',
121
- currency: asset,
122
- expires: new Date(Date.now() + 60_000).toISOString(),
123
- recipient: accounts[0].address,
124
- }),
125
- )(req, res)
126
- if (result.status === 402) return
127
- res.end('OK')
128
- })
129
-
130
- const response = await fetch(httpServer.url, {
131
- context: { account: accounts[1] },
132
- })
133
- expect(response.status).toBe(200)
134
-
135
- httpServer.close()
136
- })
137
-
138
- test('behavior: throws when no account provided', async () => {
139
- const fetch = Fetch.from({
140
- methods: [
141
- tempo.charge({
142
- getClient: () => createClient({ chain, transport: http() }),
143
- }),
144
- ],
145
- })
146
-
147
- const httpServer = await Http.createServer(async (req, res) => {
148
- const result = await Mppx_server.toNodeListener(
149
- server.charge({
150
- amount: '1',
151
- currency: asset,
152
- expires: new Date(Date.now() + 60_000).toISOString(),
153
- recipient: accounts[0].address,
154
- }),
155
- )(req, res)
156
- if (result.status === 402) return
157
- res.end('OK')
158
- })
159
-
160
- await expect(fetch(httpServer.url)).rejects.toThrow(
161
- 'No `account` provided. Pass `account` to parameters or context.',
162
- )
163
-
164
- httpServer.close()
165
- })
166
-
167
- test('behavior: passes through non-402 responses', async () => {
168
- const fetch = Fetch.from({
169
- methods: [
170
- tempo.charge({
171
- account: accounts[1],
172
- getClient: () => client,
173
- }),
174
- ],
175
- })
176
-
177
- const httpServer = await Http.createServer(async (_req, res) => {
178
- res.writeHead(200)
179
- res.end('OK')
180
- })
181
-
182
- const response = await fetch(httpServer.url)
183
- expect(response.status).toBe(200)
184
- expect(await response.text()).toBe('OK')
185
-
186
- httpServer.close()
187
- })
188
-
189
- test('behavior: fee payer', async () => {
190
- const serverWithFeePayer = Mppx_server.create({
191
- methods: [
192
- tempo_server.charge({
193
- feePayer: accounts[0],
194
- getClient: () => client,
195
- }),
196
- ],
197
- realm,
198
- secretKey,
199
- })
200
-
201
- const fetch = Fetch.from({
202
- methods: [
203
- tempo.charge({
204
- account: accounts[1],
205
- getClient: () => client,
206
- }),
207
- ],
208
- })
209
-
210
- const httpServer = await Http.createServer(async (req, res) => {
211
- const result = await Mppx_server.toNodeListener(
212
- serverWithFeePayer.charge({
213
- amount: '1',
214
- currency: asset,
215
- expires: new Date(Date.now() + 60_000).toISOString(),
216
- recipient: accounts[0].address,
217
- }),
218
- )(req, res)
219
- if (result.status === 402) return
220
- res.end('OK')
221
- })
222
-
223
- const response = await fetch(httpServer.url)
224
- expect(response.status).toBe(200)
225
-
226
- const receipt = Receipt.fromResponse(response)
227
- expect({
228
- ...receipt,
229
- reference: '[reference]',
230
- timestamp: '[timestamp]',
231
- }).toMatchInlineSnapshot(`
232
- {
233
- "method": "tempo",
234
- "reference": "[reference]",
235
- "status": "success",
236
- "timestamp": "[timestamp]",
237
- }
238
- `)
239
-
240
- httpServer.close()
241
- })
242
-
243
- test('behavior: fee payer with plain chain client (no Tempo serializers)', async () => {
244
- const plainChain = defineChain({
245
- id: chain.id,
246
- name: chain.name,
247
- nativeCurrency: chain.nativeCurrency,
248
- rpcUrls: chain.rpcUrls,
249
- })
250
- const plainClient = createClient({
251
- account: accounts[1],
252
- chain: plainChain,
253
- transport: http(rpcUrl),
254
- })
255
-
256
- const serverWithFeePayer = Mppx_server.create({
257
- methods: [
258
- tempo_server.charge({
259
- feePayer: accounts[0],
260
- getClient: () => client,
261
- }),
262
- ],
263
- realm,
264
- secretKey,
265
- })
266
-
267
- const fetch = Fetch.from({
268
- methods: [
269
- tempo.charge({
270
- account: accounts[1],
271
- getClient: () => plainClient,
272
- }),
273
- ],
274
- })
275
-
276
- const httpServer = await Http.createServer(async (req, res) => {
277
- const result = await Mppx_server.toNodeListener(
278
- serverWithFeePayer.charge({
279
- amount: '1',
280
- currency: asset,
281
- expires: new Date(Date.now() + 60_000).toISOString(),
282
- recipient: accounts[0].address,
283
- }),
284
- )(req, res)
285
- if (result.status === 402) return
286
- res.end('OK')
287
- })
288
-
289
- const response = await fetch(httpServer.url)
290
- expect(response.status).toBe(200)
291
-
292
- const receipt = Receipt.fromResponse(response)
293
- expect(receipt.status).toBe('success')
294
-
295
- httpServer.close()
296
- })
297
-
298
- test('behavior: onChallenge can create credential', async () => {
299
- const onChallenge = vi.fn(async (_challenge, { createCredential }) =>
300
- createCredential({ account: accounts[1] }),
301
- )
302
-
303
- const fetch = Fetch.from({
304
- methods: [
305
- tempo.charge({
306
- getClient: () => client,
307
- }),
308
- ],
309
- onChallenge,
310
- })
311
-
312
- const httpServer = await Http.createServer(async (req, res) => {
313
- const result = await Mppx_server.toNodeListener(
314
- server.charge({
315
- amount: '1',
316
- currency: asset,
317
- expires: new Date(Date.now() + 60_000).toISOString(),
318
- recipient: accounts[0].address,
319
- }),
320
- )(req, res)
321
- if (result.status === 402) return
322
- res.end('OK')
323
- })
324
-
325
- const response = await fetch(httpServer.url)
326
- expect(response.status).toBe(200)
327
- expect(onChallenge).toHaveBeenCalledTimes(1)
328
-
329
- httpServer.close()
330
- })
331
- })
332
-
333
- // Minimal mock method — createCredential is only invoked on the 402 retry path.
334
- const noopMethod = {
335
- name: 'test',
336
- intent: 'test',
337
- context: undefined,
338
- createCredential: async () => 'credential',
339
- } as any
340
-
341
- function trackedMethod(settlements: MethodResponse.AttemptOutcome['status'][]) {
342
- const method = {
343
- ...noopMethod,
344
- async createCredential(parameters: object) {
345
- const attempt = MethodResponse.getAttempt(parameters)
346
- if (attempt)
347
- attempt.settle = (outcome) => {
348
- settlements.push(outcome.status)
349
- return outcome.status !== 'pending'
350
- }
351
- return 'credential'
352
- },
353
- }
354
- MethodChallenge.register(method, () => undefined)
355
- return MethodResponse.register(method, ({ response }) => response)
356
- }
357
-
358
- const x402PaymentRequired = {
359
- accepts: [
360
- {
361
- amount: '10000',
362
- asset: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
363
- maxTimeoutSeconds: 60,
364
- network: 'eip155:84532',
365
- payTo: '0x209693Bc6afc0C5328bA36FaF03C514EF312287C',
366
- scheme: x402_Types.schemes[0],
367
- },
368
- ],
369
- resource: { url: 'https://example.com/api' },
370
- x402Version: 2,
371
- } satisfies PaymentRequired
372
-
373
- /** Builds a valid 402 response with a WWW-Authenticate header. */
374
- function make402(overrides?: { expires?: string; id?: string; intent?: string; method?: string }) {
375
- const id = overrides?.id ?? 'abc'
376
- const method = overrides?.method ?? 'test'
377
- const intent = overrides?.intent ?? 'test'
378
- const expires = overrides?.expires ? `, expires="${overrides.expires}"` : ''
379
- const request = btoa(JSON.stringify({ amount: '1' }))
380
- .replace(/\+/g, '-')
381
- .replace(/\//g, '_')
382
- .replace(/=+$/, '')
383
- const header = `Payment id="${id}", realm="test", method="${method}", intent="${intent}", request="${request}"${expires}`
384
- return new Response(null, {
385
- status: 402,
386
- headers: { 'WWW-Authenticate': header },
387
- })
388
- }
389
-
390
- function makeCombined402(overrides?: {
391
- expires?: string
392
- id?: string
393
- intent?: string
394
- method?: string
395
- }) {
396
- const response = make402(overrides)
397
- const headers = new Headers(response.headers)
398
- headers.set(
399
- x402_Types.paymentRequiredHeader,
400
- x402_Header.encodePaymentRequired(x402PaymentRequired),
401
- )
402
- return new Response(null, {
403
- status: 402,
404
- headers,
405
- })
406
- }
407
-
408
- // Strict x402 encoding rejects unsupported accepts before the transport can filter them.
409
- function encodeRawPaymentRequiredHeader(value: unknown): string {
410
- return Base64.fromString(JSON.stringify(value))
411
- }
412
-
413
- describe('Fetch.from: method responses', () => {
414
- test('handles successful paid responses without touching free responses', async () => {
415
- const method = { ...noopMethod }
416
- const handle = vi.fn(
417
- async ({ response }: MethodResponse.HandlerParameters) =>
418
- new Response(`handled:${await response.text()}`, response),
419
- )
420
- MethodResponse.register(method, handle)
421
-
422
- let paidResponse: Response | undefined
423
- const mockFetch: typeof globalThis.fetch = async (input, init) => {
424
- if (input.toString().endsWith('/free')) return new Response('free')
425
- if (!new Headers(init?.headers).has('Authorization')) return make402()
426
- paidResponse = new Response('paid')
427
- vi.spyOn(paidResponse, 'clone')
428
- return paidResponse
429
- }
430
- const fetch = Fetch.from({ fetch: mockFetch, methods: [method] })
431
-
432
- expect(await (await fetch('https://example.com/free')).text()).toBe('free')
433
- expect(handle).not.toHaveBeenCalled()
434
- expect(await (await fetch('https://example.com/paid')).text()).toBe('handled:paid')
435
- expect(handle).toHaveBeenCalledOnce()
436
- expect(handle).toHaveBeenCalledWith(expect.objectContaining({ credential: 'credential' }))
437
- expect(paidResponse?.clone).not.toHaveBeenCalled()
438
- })
439
-
440
- test.each([
441
- ['a rejected paid response', () => new Response('rejected', { status: 500 }), 500, undefined],
442
- ['the final payment retry', () => make402(), 402, 1],
443
- [
444
- 'the paid request throwing',
445
- () => Promise.reject(new Error('paid request failed')),
446
- undefined,
447
- undefined,
448
- ],
449
- ])('settles credential state after %s', async (_name, paidRequest, status, maxPaymentRetries) => {
450
- const settlements: MethodResponse.AttemptOutcome['status'][] = []
451
- let calls = 0
452
- const fetch = Fetch.from({
453
- fetch: async () => (++calls === 1 ? make402() : paidRequest()),
454
- maxPaymentRetries,
455
- methods: [trackedMethod(settlements)],
456
- })
457
-
458
- const result = fetch('https://example.com/paid')
459
- if (status) expect((await result).status).toBe(status)
460
- else await expect(result).rejects.toThrow('paid request failed')
461
- expect(settlements).toEqual(['rejected'])
462
- })
463
- })
464
-
465
- describe('Fetch.from: init passthrough (non-402)', () => {
466
- test('preserves init object identity while adding Accept-Payment', async () => {
467
- const receivedInits: (RequestInit | undefined)[] = []
468
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
469
- receivedInits.push(init)
470
- return new Response('OK', { status: 200 })
471
- }
472
-
473
- const fetch = Fetch.from({
474
- fetch: mockFetch,
475
- methods: [noopMethod],
476
- })
477
-
478
- const customInit = {
479
- method: 'POST',
480
- headers: { 'X-Custom': 'value' },
481
- body: JSON.stringify({ data: 'test' }),
482
- }
483
-
484
- await fetch('https://example.com/ws-upgrade', customInit)
485
-
486
- expect(receivedInits[0]).toBe(customInit)
487
- const headers = new Headers(receivedInits[0]?.headers)
488
- expect(headers.get('X-Custom')).toBe('value')
489
- expect(headers.get('Accept-Payment')).toBe('test/test')
490
- })
491
-
492
- test('preserves extra properties on init for non-402 responses', async () => {
493
- const receivedInits: (RequestInit | undefined)[] = []
494
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
495
- receivedInits.push(init)
496
- return new Response('OK', { status: 200 })
497
- }
498
-
499
- const fetch = Fetch.from({
500
- fetch: mockFetch,
501
- methods: [noopMethod],
502
- })
503
-
504
- const customInit = {
505
- method: 'GET',
506
- headers: { Authorization: 'Bearer token123' },
507
- signal: AbortSignal.timeout(5000),
508
- }
509
-
510
- await fetch('https://example.com/api', customInit)
511
-
512
- const received = receivedInits[0]!
513
- expect(received.method).toBe('GET')
514
- expect(new Headers(received.headers).get('Authorization')).toBe('Bearer token123')
515
- expect(new Headers(received.headers).get('Accept-Payment')).toBe('test/test')
516
- expect(received.signal).toBe(customInit.signal)
517
- })
518
-
519
- test('passes through undefined init', async () => {
520
- const receivedInits: (RequestInit | undefined)[] = []
521
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
522
- receivedInits.push(init)
523
- return new Response('OK', { status: 200 })
524
- }
525
-
526
- const fetch = Fetch.from({
527
- fetch: mockFetch,
528
- methods: [noopMethod],
529
- })
530
-
531
- await fetch('https://example.com/api')
532
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('test/test')
533
- })
534
-
535
- test('passes init with context through untouched', async () => {
536
- const receivedInits: (RequestInit | undefined)[] = []
537
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
538
- receivedInits.push(init)
539
- return new Response('OK', { status: 200 })
540
- }
541
-
542
- const fetch = Fetch.from({
543
- fetch: mockFetch,
544
- methods: [noopMethod],
545
- })
546
-
547
- const customInit = { method: 'POST', context: { account: '0xabc' } }
548
- await fetch('https://example.com/api', customInit as any)
549
-
550
- expect(receivedInits[0]).toBe(customInit)
551
- expect((receivedInits[0] as Record<string, unknown>).context).toEqual({ account: '0xabc' })
552
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('test/test')
553
- })
554
-
555
- test('preserves Request-carried headers when injecting Accept-Payment', async () => {
556
- const receivedInputs: (RequestInfo | URL)[] = []
557
- const receivedInits: (RequestInit | undefined)[] = []
558
- const mockFetch: typeof globalThis.fetch = async (input, init) => {
559
- receivedInputs.push(input)
560
- receivedInits.push(init)
561
- return new Response('OK', { status: 200 })
562
- }
563
-
564
- const fetch = Fetch.from({
565
- fetch: mockFetch,
566
- methods: [noopMethod],
567
- })
568
-
569
- const request = new Request('https://example.com/api', {
570
- headers: { Authorization: 'Bearer token123', 'X-Custom': 'value' },
571
- })
572
-
573
- await fetch(request)
574
-
575
- expect(receivedInputs[0]).toBe(request)
576
- const headers = new Headers(receivedInits[0]?.headers)
577
- expect(headers.get('Authorization')).toBe('Bearer token123')
578
- expect(headers.get('X-Custom')).toBe('value')
579
- expect(headers.get('Accept-Payment')).toBe('test/test')
580
- })
581
-
582
- test('does not overwrite an explicit Accept-Payment header', async () => {
583
- const receivedInits: (RequestInit | undefined)[] = []
584
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
585
- receivedInits.push(init)
586
- return new Response('OK', { status: 200 })
587
- }
588
-
589
- const fetch = Fetch.from({
590
- fetch: mockFetch,
591
- methods: [noopMethod],
592
- })
593
-
594
- await fetch('https://example.com/api', {
595
- headers: { 'Accept-Payment': 'custom/charge;q=0.5' },
596
- })
597
-
598
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('custom/charge;q=0.5')
599
- })
600
-
601
- test('uses an explicit Accept-Payment header to reprioritize challenge selection', async () => {
602
- let callCount = 0
603
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
604
- callCount++
605
- if (callCount === 1) {
606
- expect(new Headers(init?.headers).get('Accept-Payment')).toBe(
607
- 'stripe/charge, tempo/charge;q=0.1',
608
- )
609
-
610
- return new Response(null, {
611
- status: 402,
612
- headers: {
613
- 'WWW-Authenticate': [
614
- 'Payment id="tempo", realm="test", method="tempo", intent="charge", request="eyJhbW91bnQiOiIxIn0"',
615
- 'Payment id="stripe", realm="test", method="stripe", intent="charge", request="eyJhbW91bnQiOiIxIn0"',
616
- ].join(', '),
617
- },
618
- })
619
- }
620
-
621
- expect(new Headers(init?.headers).get('Authorization')).toBe('stripe-credential')
622
- return new Response('OK', { status: 200 })
623
- }
624
-
625
- const fetch = Fetch.from({
626
- fetch: mockFetch,
627
- methods: [
628
- {
629
- name: 'tempo',
630
- intent: 'charge',
631
- context: undefined,
632
- createCredential: async () => 'tempo-credential',
633
- },
634
- {
635
- name: 'stripe',
636
- intent: 'charge',
637
- context: undefined,
638
- createCredential: async () => 'stripe-credential',
639
- },
640
- ] as const,
641
- })
642
-
643
- const response = await fetch('https://example.com/api', {
644
- headers: { 'Accept-Payment': 'stripe/charge, tempo/charge;q=0.1' },
645
- })
646
- expect(response.status).toBe(200)
647
- })
648
-
649
- test('applies an explicit method opt-out before broader wildcard preferences', async () => {
650
- let callCount = 0
651
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
652
- callCount++
653
- if (callCount === 1) {
654
- expect(new Headers(init?.headers).get('Accept-Payment')).toBe(
655
- 'tempo/*;q=1, tempo/charge;q=0, stripe/*;q=0.5',
656
- )
657
-
658
- return new Response(null, {
659
- status: 402,
660
- headers: {
661
- 'WWW-Authenticate': [
662
- 'Payment id="tempo", realm="test", method="tempo", intent="charge", request="eyJhbW91bnQiOiIxIn0"',
663
- 'Payment id="stripe", realm="test", method="stripe", intent="charge", request="eyJhbW91bnQiOiIxIn0"',
664
- ].join(', '),
665
- },
666
- })
667
- }
668
-
669
- expect(new Headers(init?.headers).get('Authorization')).toBe('stripe-credential')
670
- return new Response('OK', { status: 200 })
671
- }
672
-
673
- const fetch = Fetch.from({
674
- fetch: mockFetch,
675
- methods: [
676
- {
677
- name: 'tempo',
678
- intent: 'charge',
679
- context: undefined,
680
- createCredential: async () => 'tempo-credential',
681
- },
682
- {
683
- name: 'stripe',
684
- intent: 'charge',
685
- context: undefined,
686
- createCredential: async () => 'stripe-credential',
687
- },
688
- ] as const,
689
- })
690
-
691
- const response = await fetch('https://example.com/api', {
692
- headers: { 'Accept-Payment': 'tempo/*;q=1, tempo/charge;q=0, stripe/*;q=0.5' },
693
- })
694
- expect(response.status).toBe(200)
695
- })
696
-
697
- test('preserves non-header init fields across all non-402 status codes', async () => {
698
- for (const status of [200, 201, 204, 301, 400, 401, 403, 404, 500, 503]) {
699
- const receivedInits: (RequestInit | undefined)[] = []
700
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
701
- receivedInits.push(init)
702
- return new Response(null, { status })
703
- }
704
-
705
- const fetch = Fetch.from({
706
- fetch: mockFetch,
707
- methods: [noopMethod],
708
- })
709
-
710
- const customInit = { method: 'GET' }
711
- await fetch('https://example.com/api', customInit)
712
- expect(receivedInits[0]?.method).toBe(customInit.method)
713
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('test/test')
714
- }
715
- })
716
- })
717
-
718
- describe('Fetch.from: 402 retry path', () => {
719
- test('rejects expired challenges before hooks or credential creation', async () => {
720
- const createCredential = vi.fn(async () => 'credential')
721
- const onChallenge = vi.fn(async () => undefined)
722
- const mockFetch = vi.fn(async () =>
723
- make402({ expires: new Date(Date.now() - 60_000).toISOString() }),
724
- )
725
- const fetch = Fetch.from({
726
- fetch: mockFetch as typeof globalThis.fetch,
727
- methods: [{ ...noopMethod, createCredential }],
728
- onChallenge,
729
- })
730
-
731
- await expect(fetch('https://example.com/api')).rejects.toThrow(Errors.PaymentExpiredError)
732
- expect(onChallenge).not.toHaveBeenCalled()
733
- expect(createCredential).not.toHaveBeenCalled()
734
- expect(mockFetch).toHaveBeenCalledTimes(1)
735
- })
736
-
737
- test('strips context from init on retry', async () => {
738
- const calls: { init: RequestInit | undefined }[] = []
739
- let callCount = 0
740
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
741
- calls.push({ init })
742
- callCount++
743
- if (callCount === 1) return make402()
744
- return new Response('OK', { status: 200 })
745
- }
746
-
747
- const fetch = Fetch.from({
748
- fetch: mockFetch,
749
- methods: [noopMethod],
750
- })
751
-
752
- await fetch('https://example.com/api', {
753
- method: 'POST',
754
- context: { account: '0xabc' },
755
- } as any)
756
-
757
- expect(calls).toHaveLength(2)
758
- const retryInit = calls[1]!.init as Record<string, unknown>
759
- expect(retryInit).not.toHaveProperty('context')
760
- })
761
-
762
- test('adds Authorization header on retry', async () => {
763
- let callCount = 0
764
- const calls: { init: RequestInit | undefined }[] = []
765
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
766
- calls.push({ init })
767
- callCount++
768
- if (callCount === 1) return make402()
769
- return new Response('OK', { status: 200 })
770
- }
771
-
772
- const fetch = Fetch.from({
773
- fetch: mockFetch,
774
- methods: [noopMethod],
775
- })
776
-
777
- await fetch('https://example.com/api')
778
-
779
- const retryInit = calls[1]!.init as Record<string, unknown>
780
- const headers = new Headers(retryInit.headers as HeadersInit)
781
- expect(headers.get('Authorization')).toBe('credential')
782
- })
783
-
784
- test('chooses native Payment-auth from combined MPP and x402 HTTP 402 offers', async () => {
785
- let callCount = 0
786
- const calls: { init: RequestInit | undefined }[] = []
787
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
788
- calls.push({ init })
789
- callCount++
790
- if (callCount === 1) return makeCombined402()
791
- return new Response('OK', { status: 200 })
792
- }
793
-
794
- const fetch = Fetch.from({
795
- fetch: mockFetch,
796
- methods: [noopMethod],
797
- })
798
-
799
- const response = await fetch('https://example.com/api')
800
-
801
- expect(response.status).toBe(200)
802
- expect(calls).toHaveLength(2)
803
- const retryHeaders = new Headers(calls[1]!.init?.headers)
804
- expect(retryHeaders.get('Authorization')).toBe('credential')
805
- expect(retryHeaders.get(x402_Types.paymentSignatureHeader)).toBeNull()
806
- })
807
-
808
- test('prefers mpp Payment-auth over x402 when both are signable', async () => {
809
- let callCount = 0
810
- const calls: { init: RequestInit | undefined }[] = []
811
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
812
- calls.push({ init })
813
- callCount++
814
- if (callCount === 1) return makeCombined402({ method: 'tempo', intent: 'charge' })
815
- return new Response('OK', { status: 200 })
816
- }
817
-
818
- const fetch = Fetch.from({
819
- fetch: mockFetch,
820
- methods: [
821
- {
822
- name: 'tempo',
823
- intent: 'charge',
824
- context: undefined,
825
- createCredential: async () => 'tempo-credential',
826
- },
827
- {
828
- name: 'evm',
829
- intent: 'charge',
830
- context: undefined,
831
- createCredential: async () => 'evm-credential',
832
- },
833
- ] as const,
834
- })
835
-
836
- const response = await fetch('https://example.com/api')
837
-
838
- expect(response.status).toBe(200)
839
- const retryHeaders = new Headers(calls[1]!.init?.headers)
840
- expect(retryHeaders.get('Authorization')).toBe('tempo-credential')
841
- expect(retryHeaders.get(x402_Types.paymentSignatureHeader)).toBeNull()
842
- })
843
-
844
- test('prefers native EVM Payment-auth over x402 for EVM-only clients', async () => {
845
- let callCount = 0
846
- const calls: { init: RequestInit | undefined }[] = []
847
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
848
- calls.push({ init })
849
- callCount++
850
- if (callCount === 1) return makeCombined402({ method: 'evm', intent: 'charge' })
851
- return new Response('OK', { status: 200 })
852
- }
853
-
854
- const fetch = Fetch.from({
855
- fetch: mockFetch,
856
- methods: [
857
- {
858
- name: 'evm',
859
- intent: 'charge',
860
- context: undefined,
861
- createCredential: async () => 'evm-credential',
862
- },
863
- ] as const,
864
- })
865
-
866
- const response = await fetch('https://example.com/api')
867
-
868
- expect(response.status).toBe(200)
869
- const retryHeaders = new Headers(calls[1]!.init?.headers)
870
- expect(retryHeaders.get('Authorization')).toBe('evm-credential')
871
- expect(retryHeaders.get(x402_Types.paymentSignatureHeader)).toBeNull()
872
- })
873
-
874
- test('uses x402 when no signable Payment-auth challenge is available', async () => {
875
- let callCount = 0
876
- const calls: { init: RequestInit | undefined }[] = []
877
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
878
- calls.push({ init })
879
- callCount++
880
- if (callCount === 1)
881
- return new Response(null, {
882
- status: 402,
883
- headers: {
884
- [x402_Types.paymentRequiredHeader]:
885
- x402_Header.encodePaymentRequired(x402PaymentRequired),
886
- },
887
- })
888
- return new Response('OK', { status: 200 })
889
- }
890
-
891
- const fetch = Fetch.from({
892
- fetch: mockFetch,
893
- methods: [
894
- {
895
- name: 'evm',
896
- intent: 'charge',
897
- context: undefined,
898
- createCredential: async () => 'x402-credential',
899
- },
900
- ] as const,
901
- })
902
-
903
- const response = await fetch('https://example.com/api')
904
-
905
- expect(response.status).toBe(200)
906
- const retryHeaders = new Headers(calls[1]!.init?.headers)
907
- expect(retryHeaders.get('Authorization')).toBeNull()
908
- expect(retryHeaders.get(x402_Types.paymentSignatureHeader)).toBe('x402-credential')
909
- })
910
-
911
- test('lets orderChallenges force x402 before native Payment-auth', async () => {
912
- let callCount = 0
913
- const calls: { init: RequestInit | undefined }[] = []
914
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
915
- calls.push({ init })
916
- callCount++
917
- if (callCount === 1) return makeCombined402({ method: 'evm', intent: 'charge' })
918
- return new Response('OK', { status: 200 })
919
- }
920
-
921
- const fetch = Fetch.from({
922
- fetch: mockFetch,
923
- methods: [
924
- {
925
- name: 'evm',
926
- intent: 'charge',
927
- context: undefined,
928
- createCredential: async () => 'x402-credential',
929
- },
930
- ] as const,
931
- orderChallenges: (candidates) =>
932
- [...candidates].sort((left, right) => right.challenge.id.localeCompare(left.challenge.id)),
933
- })
934
-
935
- const response = await fetch('https://example.com/api')
936
-
937
- expect(response.status).toBe(200)
938
- const retryHeaders = new Headers(calls[1]!.init?.headers)
939
- expect(retryHeaders.get('Authorization')).toBeNull()
940
- expect(retryHeaders.get(x402_Types.paymentSignatureHeader)).toBe('x402-credential')
941
- })
942
-
943
- test('settles MCP-over-HTTP JSON-RPC payment challenges at the fetch boundary', async () => {
944
- const mcpChallenge = Challenge.from({
945
- id: 'mcp-challenge',
946
- intent: 'test',
947
- method: 'test',
948
- realm: 'test',
949
- request: { amount: '1' },
950
- })
951
- const method = {
952
- ...noopMethod,
953
- createCredential: async ({ challenge }: { challenge: Challenge.Challenge }) =>
954
- Credential.serialize({ challenge, payload: { source: 'mcp' } }),
955
- }
956
- const initialBody = JSON.stringify({
957
- jsonrpc: '2.0',
958
- id: 1,
959
- method: 'tools/call',
960
- params: { name: 'paid-tool' },
961
- })
962
- let callCount = 0
963
- const calls: { init: RequestInit | undefined }[] = []
964
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
965
- calls.push({ init })
966
- callCount++
967
- if (callCount === 1)
968
- return Response.json({
969
- jsonrpc: '2.0',
970
- id: 1,
971
- error: {
972
- code: Mcp.paymentRequiredCode,
973
- message: 'Payment Required',
974
- data: { challenges: [mcpChallenge] },
975
- },
976
- })
977
-
978
- const body = JSON.parse(init?.body as string)
979
- expect(new Headers(init?.headers).get('Authorization')).toBeNull()
980
- expect(body.params['_meta'][Mcp.credentialMetaKey]).toMatchObject({
981
- payload: { source: 'mcp' },
982
- })
983
- return Response.json({ ok: true })
984
- }
985
-
986
- const fetch = Fetch.from({
987
- fetch: mockFetch,
988
- methods: [method],
989
- })
990
-
991
- const response = await fetch('https://example.com/mcp', {
992
- method: 'POST',
993
- headers: { accept: 'application/json, text/event-stream' },
994
- body: initialBody,
995
- })
996
-
997
- expect(response.status).toBe(200)
998
- expect(calls).toHaveLength(2)
999
- })
1000
-
1001
- test('settles MCP-over-HTTP result metadata payment challenges at the fetch boundary', async () => {
1002
- const mcpChallenge = Challenge.from({
1003
- id: 'mcp-result-challenge',
1004
- intent: 'test',
1005
- method: 'test',
1006
- realm: 'test',
1007
- request: { amount: '1' },
1008
- })
1009
- const method = {
1010
- ...noopMethod,
1011
- createCredential: async ({ challenge }: { challenge: Challenge.Challenge }) =>
1012
- Credential.serialize({ challenge, payload: { source: 'mcp-result' } }),
1013
- }
1014
- const initialBody = JSON.stringify({
1015
- jsonrpc: '2.0',
1016
- id: 1,
1017
- method: 'tools/call',
1018
- params: { name: 'paid-tool' },
1019
- })
1020
- let callCount = 0
1021
- const calls: { init: RequestInit | undefined }[] = []
1022
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1023
- calls.push({ init })
1024
- callCount++
1025
- if (callCount === 1)
1026
- return Response.json({
1027
- jsonrpc: '2.0',
1028
- id: 1,
1029
- result: {
1030
- content: [{ type: 'text', text: 'Payment Required' }],
1031
- isError: true,
1032
- _meta: {
1033
- [Mcp.paymentRequiredMetaKey]: {
1034
- httpStatus: 402,
1035
- challenges: [mcpChallenge],
1036
- },
1037
- },
1038
- },
1039
- })
1040
-
1041
- const body = JSON.parse(init?.body as string)
1042
- expect(new Headers(init?.headers).get('Authorization')).toBeNull()
1043
- expect(body.params['_meta'][Mcp.credentialMetaKey]).toMatchObject({
1044
- payload: { source: 'mcp-result' },
1045
- })
1046
- return Response.json({ ok: true })
1047
- }
1048
-
1049
- const fetch = Fetch.from({
1050
- fetch: mockFetch,
1051
- methods: [method],
1052
- })
1053
-
1054
- const response = await fetch('https://example.com/mcp', {
1055
- method: 'POST',
1056
- headers: { accept: 'application/json, text/event-stream' },
1057
- body: initialBody,
1058
- })
1059
-
1060
- expect(response.status).toBe(200)
1061
- expect(calls).toHaveLength(2)
1062
- })
1063
-
1064
- test('settles MCP-over-HTTP when the JSON-RPC request body is carried by Request input', async () => {
1065
- const mcpChallenge = Challenge.from({
1066
- id: 'mcp-request-input-challenge',
1067
- intent: 'test',
1068
- method: 'test',
1069
- realm: 'test',
1070
- request: { amount: '1' },
1071
- })
1072
- const method = {
1073
- ...noopMethod,
1074
- createCredential: async ({ challenge }: { challenge: Challenge.Challenge }) =>
1075
- Credential.serialize({ challenge, payload: { source: 'request-input' } }),
1076
- }
1077
- const initialBody = JSON.stringify({
1078
- jsonrpc: '2.0',
1079
- id: 1,
1080
- method: 'tools/call',
1081
- params: { name: 'paid-tool' },
1082
- })
1083
- let callCount = 0
1084
- const calls: { init: RequestInit | undefined; input: RequestInfo | URL }[] = []
1085
- const mockFetch: typeof globalThis.fetch = async (input, init) => {
1086
- calls.push({ input, init })
1087
- callCount++
1088
- if (callCount === 1) {
1089
- expect(input).toBeInstanceOf(Request)
1090
- expect(await (input as Request).text()).toBe(initialBody)
1091
- return Response.json({
1092
- jsonrpc: '2.0',
1093
- id: 1,
1094
- error: {
1095
- code: Mcp.paymentRequiredCode,
1096
- message: 'Payment Required',
1097
- data: { challenges: [mcpChallenge] },
1098
- },
1099
- })
1100
- }
1101
-
1102
- const body = JSON.parse(init?.body as string)
1103
- expect(body.params['_meta'][Mcp.credentialMetaKey]).toMatchObject({
1104
- payload: { source: 'request-input' },
1105
- })
1106
- return Response.json({ ok: true })
1107
- }
1108
-
1109
- const fetch = Fetch.from({
1110
- fetch: mockFetch,
1111
- methods: [method],
1112
- })
1113
- const request = new Request('https://example.com/mcp', {
1114
- method: 'POST',
1115
- headers: { accept: 'application/json, text/event-stream' },
1116
- body: initialBody,
1117
- })
1118
-
1119
- const response = await fetch(request)
1120
-
1121
- expect(response.status).toBe(200)
1122
- expect(calls).toHaveLength(2)
1123
- expect(calls[1]?.input).toBe(request)
1124
- })
1125
-
1126
- test('settles native HTTP 402 when a POST body is carried by Request input', async () => {
1127
- const initialBody = JSON.stringify({ ok: true })
1128
- let callCount = 0
1129
- const calls: { init: RequestInit | undefined; input: RequestInfo | URL }[] = []
1130
- const mockFetch: typeof globalThis.fetch = async (input, init) => {
1131
- calls.push({ input, init })
1132
- callCount++
1133
- const request = input instanceof Request && !init ? input : new Request(input, init)
1134
- expect(await request.text()).toBe(initialBody)
1135
- if (callCount === 1) return make402()
1136
-
1137
- expect(request.headers.get('Authorization')).toBe('credential')
1138
- return new Response('OK', { status: 200 })
1139
- }
1140
-
1141
- const fetch = Fetch.from({
1142
- fetch: mockFetch,
1143
- methods: [noopMethod],
1144
- })
1145
- const request = new Request('https://example.com/api', {
1146
- method: 'POST',
1147
- headers: { 'Content-Type': 'application/json' },
1148
- body: initialBody,
1149
- })
1150
-
1151
- const response = await fetch(request)
1152
-
1153
- expect(response.status).toBe(200)
1154
- expect(calls).toHaveLength(2)
1155
- expect(calls[1]?.input).toBe(request)
1156
- })
1157
-
1158
- test('sends credential retry to the final same-origin 402 response URL', async () => {
1159
- let callCount = 0
1160
- const calls: { input: RequestInfo | URL; init: RequestInit | undefined }[] = []
1161
- const mockFetch: typeof globalThis.fetch = async (input, init) => {
1162
- calls.push({ input, init })
1163
- callCount++
1164
- if (callCount === 1) {
1165
- const response = make402()
1166
- Object.defineProperty(response, 'url', {
1167
- value: 'https://api.example.com/redirected-protected',
1168
- })
1169
- return response
1170
- }
1171
- return new Response('OK', { status: 200 })
1172
- }
1173
-
1174
- const fetch = Fetch.from({
1175
- fetch: mockFetch,
1176
- methods: [noopMethod],
1177
- })
1178
-
1179
- const response = await fetch('https://api.example.com/protected')
1180
-
1181
- expect(response.status).toBe(200)
1182
- expect(calls[0]!.input).toBe('https://api.example.com/protected')
1183
- expect(calls[1]!.input).toBe('https://api.example.com/redirected-protected')
1184
- expect(new Headers(calls[1]!.init?.headers).get('Authorization')).toBe('credential')
1185
- })
1186
-
1187
- test('rejects credential retry to a cross-origin 402 response URL', async () => {
1188
- const calls: { input: RequestInfo | URL; init: RequestInit | undefined }[] = []
1189
- const mockFetch: typeof globalThis.fetch = async (input, init) => {
1190
- calls.push({ input, init })
1191
- const response = make402()
1192
- Object.defineProperty(response, 'url', {
1193
- value: 'https://payments.example.com/protected',
1194
- })
1195
- return response
1196
- }
1197
-
1198
- const fetch = Fetch.from({
1199
- fetch: mockFetch,
1200
- methods: [noopMethod],
1201
- })
1202
-
1203
- await expect(fetch('https://api.example.com/protected')).rejects.toThrow(
1204
- 'Refusing to send payment credential across redirect from https://api.example.com to https://payments.example.com',
1205
- )
1206
-
1207
- expect(calls).toHaveLength(1)
1208
- expect(calls[0]!.input).toBe('https://api.example.com/protected')
1209
- expect(new Headers(calls[0]!.init?.headers).get('Authorization')).toBeNull()
1210
- })
1211
-
1212
- test('emits client events and allows challenge handler to provide credential', async () => {
1213
- const events: string[] = []
1214
- const createCredential = vi.fn(async () => 'method-credential')
1215
- let callCount = 0
1216
- const calls: { init: RequestInit | undefined }[] = []
1217
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1218
- calls.push({ init })
1219
- callCount++
1220
- if (callCount === 1) return make402()
1221
- return new Response('OK', { status: 200 })
1222
- }
1223
-
1224
- const method = { ...noopMethod, createCredential }
1225
- const eventDispatcher = Fetch.createEventDispatcher<[typeof method]>()
1226
- eventDispatcher.on('*', (event) => {
1227
- events.push(`*:${event.name}`)
1228
- })
1229
- eventDispatcher.on('challenge.received', async (payload) => {
1230
- events.push(`challenge:${payload.challenge.id}`)
1231
- return 'event-credential'
1232
- })
1233
- eventDispatcher.on('credential.created', (payload) => {
1234
- events.push(`credential:${payload.credential}`)
1235
- throw new Error('observer failed')
1236
- })
1237
- eventDispatcher.on('payment.response', (payload) => {
1238
- events.push(`response:${payload.response.status}`)
1239
- throw new Error('observer failed')
1240
- })
1241
-
1242
- const fetch = Fetch.from({
1243
- eventDispatcher,
1244
- fetch: mockFetch,
1245
- methods: [method],
1246
- })
1247
-
1248
- const response = await fetch('https://example.com/api')
1249
-
1250
- expect(response.status).toBe(200)
1251
- expect(createCredential).not.toHaveBeenCalled()
1252
- const retryHeaders = new Headers((calls[1]!.init as RequestInit).headers)
1253
- expect(retryHeaders.get('Authorization')).toBe('event-credential')
1254
- expect(events).toEqual([
1255
- 'challenge:abc',
1256
- '*:challenge.received',
1257
- 'credential:event-credential',
1258
- '*:credential.created',
1259
- 'response:200',
1260
- '*:payment.response',
1261
- ])
1262
- })
1263
-
1264
- test('uses the first challenge event credential', async () => {
1265
- const events: string[] = []
1266
- const createCredential = vi.fn(async () => 'method-credential')
1267
- const method = { ...noopMethod, createCredential }
1268
- let callCount = 0
1269
- const calls: { init: RequestInit | undefined }[] = []
1270
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1271
- calls.push({ init })
1272
- callCount++
1273
- if (callCount === 1) return make402()
1274
- return new Response('OK', { status: 200 })
1275
- }
1276
- const eventDispatcher = Fetch.createEventDispatcher<[typeof method]>()
1277
- eventDispatcher.on('challenge.received', () => {
1278
- events.push('first')
1279
- return 'first-credential'
1280
- })
1281
- eventDispatcher.on('challenge.received', () => {
1282
- events.push('second')
1283
- return 'second-credential'
1284
- })
1285
-
1286
- const fetch = Fetch.from({
1287
- eventDispatcher,
1288
- fetch: mockFetch,
1289
- methods: [method],
1290
- })
1291
-
1292
- await fetch('https://example.com/api')
1293
-
1294
- expect(createCredential).not.toHaveBeenCalled()
1295
- const retryHeaders = new Headers((calls[1]!.init as RequestInit).headers)
1296
- expect(retryHeaders.get('Authorization')).toBe('first-credential')
1297
- expect(events).toEqual(['first'])
1298
- })
1299
-
1300
- test('does not emit payment.response for non-ok retry responses', async () => {
1301
- const events: string[] = []
1302
- const createCredential = vi.fn(async () => 'method-credential')
1303
- const method = { ...noopMethod, createCredential }
1304
- let callCount = 0
1305
- const mockFetch: typeof globalThis.fetch = async () => {
1306
- callCount++
1307
- if (callCount === 1) return make402()
1308
- return new Response('Internal Server Error', { status: 500 })
1309
- }
1310
- const eventDispatcher = Fetch.createEventDispatcher<[typeof method]>()
1311
- eventDispatcher.on('payment.response', (payload) => {
1312
- events.push(`response:${payload.response.status}`)
1313
- })
1314
-
1315
- const fetch = Fetch.from({
1316
- eventDispatcher,
1317
- fetch: mockFetch,
1318
- methods: [method],
1319
- })
1320
-
1321
- const response = await fetch('https://example.com/api')
1322
-
1323
- expect(response.status).toBe(500)
1324
- expect(events).toEqual([])
1325
- })
1326
-
1327
- test('ignores empty challenge event credentials and continues handlers', async () => {
1328
- const createCredential = vi.fn(async () => 'method-credential')
1329
- const method = { ...noopMethod, createCredential }
1330
- let callCount = 0
1331
- const calls: { init: RequestInit | undefined }[] = []
1332
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1333
- calls.push({ init })
1334
- callCount++
1335
- if (callCount === 1) return make402()
1336
- return new Response('OK', { status: 200 })
1337
- }
1338
- const eventDispatcher = Fetch.createEventDispatcher<[typeof method]>()
1339
- eventDispatcher.on('challenge.received', () => '')
1340
- eventDispatcher.on('challenge.received', () => 'second-credential')
1341
-
1342
- const fetch = Fetch.from({
1343
- eventDispatcher,
1344
- fetch: mockFetch,
1345
- methods: [method],
1346
- })
1347
-
1348
- await fetch('https://example.com/api')
1349
-
1350
- expect(createCredential).not.toHaveBeenCalled()
1351
- const retryHeaders = new Headers((calls[1]!.init as RequestInit).headers)
1352
- expect(retryHeaders.get('Authorization')).toBe('second-credential')
1353
- })
1354
-
1355
- test('memoizes createCredential across wildcard observers and fallback', async () => {
1356
- const createCredential = vi.fn(async () => 'method-credential')
1357
- const method = { ...noopMethod, createCredential }
1358
- let callCount = 0
1359
- const mockFetch: typeof globalThis.fetch = async () => {
1360
- callCount++
1361
- if (callCount === 1) return make402()
1362
- return new Response('OK', { status: 200 })
1363
- }
1364
- const eventDispatcher = Fetch.createEventDispatcher<[typeof method]>()
1365
- eventDispatcher.on('*', async (event) => {
1366
- if (event.name === 'challenge.received') await event.payload.createCredential()
1367
- })
1368
-
1369
- const fetch = Fetch.from({
1370
- eventDispatcher,
1371
- fetch: mockFetch,
1372
- methods: [method],
1373
- })
1374
-
1375
- await fetch('https://example.com/api')
1376
-
1377
- expect(createCredential).toHaveBeenCalledTimes(1)
1378
- })
1379
-
1380
- test('does not expose live challenges or init headers to observers', async () => {
1381
- const createCredential = vi.fn(async ({ challenge }) => `amount:${challenge.request.amount}`)
1382
- const method = { ...noopMethod, createCredential }
1383
- let callCount = 0
1384
- const calls: { init: RequestInit | undefined }[] = []
1385
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1386
- calls.push({ init })
1387
- callCount++
1388
- if (callCount === 1) return make402()
1389
- return new Response('OK', { status: 200 })
1390
- }
1391
- const eventDispatcher = Fetch.createEventDispatcher<[typeof method]>()
1392
- eventDispatcher.on('*', (event) => {
1393
- if (event.name !== 'challenge.received') return
1394
- try {
1395
- ;(event.payload.challenge.request as { amount: string }).amount = '999'
1396
- } catch {}
1397
- const headers = new Headers(event.payload.init?.headers)
1398
- headers.set('Authorization', 'attacker')
1399
- if (event.payload.init) event.payload.init.headers = headers
1400
- })
1401
-
1402
- const fetch = Fetch.from({
1403
- eventDispatcher,
1404
- fetch: mockFetch,
1405
- methods: [method],
1406
- })
1407
-
1408
- await fetch('https://example.com/api', {
1409
- headers: { 'X-Test': '1' },
1410
- })
1411
-
1412
- const retryHeaders = new Headers((calls[1]!.init as RequestInit).headers)
1413
- expect(retryHeaders.get('Authorization')).toBe('amount:1')
1414
- })
1415
-
1416
- test('continues dispatching observer listeners after one throws', async () => {
1417
- const events: string[] = []
1418
- const method = { ...noopMethod, createCredential: vi.fn(async () => 'credential') }
1419
- let callCount = 0
1420
- const mockFetch: typeof globalThis.fetch = async () => {
1421
- callCount++
1422
- if (callCount === 1) return make402()
1423
- return new Response('OK', { status: 200 })
1424
- }
1425
- const eventDispatcher = Fetch.createEventDispatcher<[typeof method]>()
1426
- eventDispatcher.on('credential.created', () => {
1427
- events.push('first')
1428
- throw new Error('observer failed')
1429
- })
1430
- eventDispatcher.on('credential.created', () => {
1431
- events.push('second')
1432
- })
1433
-
1434
- const fetch = Fetch.from({
1435
- eventDispatcher,
1436
- fetch: mockFetch,
1437
- methods: [method],
1438
- })
1439
-
1440
- await fetch('https://example.com/api')
1441
-
1442
- expect(events).toEqual(['first', 'second'])
1443
- })
1444
-
1445
- test('emits payment.failed when automatic payment handling rejects', async () => {
1446
- const events: string[] = []
1447
- const createCredential = vi.fn(async () => 'credential')
1448
- const mockFetch = vi.fn(async () =>
1449
- make402({ expires: new Date(Date.now() - 60_000).toISOString() }),
1450
- )
1451
- const method = { ...noopMethod, createCredential }
1452
- const eventDispatcher = Fetch.createEventDispatcher<[typeof method]>()
1453
- eventDispatcher.on('*', (event) => {
1454
- events.push(`*:${event.name}`)
1455
- })
1456
- eventDispatcher.on('payment.failed', (payload) => {
1457
- events.push(
1458
- `failed:${payload.error instanceof Errors.PaymentExpiredError}:${payload.challenge?.id}`,
1459
- )
1460
- throw new Error('observer failed')
1461
- })
1462
- const fetch = Fetch.from({
1463
- eventDispatcher,
1464
- fetch: mockFetch as typeof globalThis.fetch,
1465
- methods: [method],
1466
- })
1467
-
1468
- await expect(fetch('https://example.com/api')).rejects.toThrow(Errors.PaymentExpiredError)
1469
- expect(createCredential).not.toHaveBeenCalled()
1470
- expect(events).toEqual(['failed:true:abc', '*:payment.failed'])
1471
- })
1472
-
1473
- test('preserves existing headers on retry', async () => {
1474
- let callCount = 0
1475
- const calls: { init: RequestInit | undefined }[] = []
1476
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1477
- calls.push({ init })
1478
- callCount++
1479
- if (callCount === 1) return make402()
1480
- return new Response('OK', { status: 200 })
1481
- }
1482
-
1483
- const fetch = Fetch.from({
1484
- fetch: mockFetch,
1485
- methods: [noopMethod],
1486
- })
1487
-
1488
- await fetch('https://example.com/api', {
1489
- headers: { 'X-Custom': 'value', 'Content-Type': 'application/json' },
1490
- })
1491
-
1492
- const retryInit = calls[1]!.init as Record<string, unknown>
1493
- const headers = new Headers(retryInit.headers as HeadersInit)
1494
- expect(headers.get('X-Custom')).toBe('value')
1495
- expect(headers.get('Content-Type')).toBe('application/json')
1496
- expect(headers.get('Accept-Payment')).toBe('test/test')
1497
- expect(headers.get('Authorization')).toBe('credential')
1498
- })
1499
-
1500
- test('preserves method and other init properties on retry', async () => {
1501
- let callCount = 0
1502
- const calls: { init: RequestInit | undefined }[] = []
1503
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1504
- calls.push({ init })
1505
- callCount++
1506
- if (callCount === 1) return make402()
1507
- return new Response('OK', { status: 200 })
1508
- }
1509
-
1510
- const fetch = Fetch.from({
1511
- fetch: mockFetch,
1512
- methods: [noopMethod],
1513
- })
1514
-
1515
- await fetch('https://example.com/api', {
1516
- method: 'PUT',
1517
- body: JSON.stringify({ data: 'test' }),
1518
- credentials: 'include',
1519
- mode: 'cors',
1520
- })
1521
-
1522
- const retryInit = calls[1]!.init as Record<string, unknown>
1523
- expect(retryInit.method).toBe('PUT')
1524
- expect(retryInit.body).toBe(JSON.stringify({ data: 'test' }))
1525
- expect(retryInit.credentials).toBe('include')
1526
- expect(retryInit.mode).toBe('cors')
1527
- })
1528
-
1529
- test('handles undefined init on 402 retry', async () => {
1530
- let callCount = 0
1531
- const calls: { init: RequestInit | undefined }[] = []
1532
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1533
- calls.push({ init })
1534
- callCount++
1535
- if (callCount === 1) return make402()
1536
- return new Response('OK', { status: 200 })
1537
- }
1538
-
1539
- const fetch = Fetch.from({
1540
- fetch: mockFetch,
1541
- methods: [noopMethod],
1542
- })
1543
-
1544
- await fetch('https://example.com/api')
1545
-
1546
- expect(calls).toHaveLength(2)
1547
- const retryInit = calls[1]!.init as Record<string, unknown>
1548
- const headers = new Headers(retryInit.headers as HeadersInit)
1549
- expect(headers.get('Accept-Payment')).toBe('test/test')
1550
- expect(headers.get('Authorization')).toBe('credential')
1551
- })
1552
-
1553
- test('preserves Request-carried headers on retry after injecting Accept-Payment', async () => {
1554
- let callCount = 0
1555
- const calls: { init: RequestInit | undefined; input: RequestInfo | URL }[] = []
1556
- const mockFetch: typeof globalThis.fetch = async (input, init) => {
1557
- calls.push({ init, input })
1558
- callCount++
1559
- if (callCount === 1) return make402()
1560
- return new Response('OK', { status: 200 })
1561
- }
1562
-
1563
- const fetch = Fetch.from({
1564
- fetch: mockFetch,
1565
- methods: [noopMethod],
1566
- })
1567
-
1568
- const request = new Request('https://example.com/api', {
1569
- headers: { Authorization: 'Bearer token123', 'X-Custom': 'value' },
1570
- })
1571
-
1572
- await fetch(request)
1573
-
1574
- expect(calls[0]?.input).toBe(request)
1575
- expect(calls[1]?.input).toBe(request)
1576
- const headers = new Headers(calls[1]?.init?.headers)
1577
- expect(headers.get('X-Custom')).toBe('value')
1578
- expect(headers.get('Accept-Payment')).toBe('test/test')
1579
- expect(headers.get('Authorization')).toBe('credential')
1580
- })
1581
-
1582
- test('selects the highest-ranked supported challenge', async () => {
1583
- let callCount = 0
1584
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1585
- callCount++
1586
- if (callCount === 1) {
1587
- expect(new Headers(init?.headers).get('Accept-Payment')).toBe(
1588
- 'tempo/charge, stripe/charge;q=0.5',
1589
- )
1590
-
1591
- return new Response(null, {
1592
- status: 402,
1593
- headers: {
1594
- 'WWW-Authenticate': [
1595
- 'Payment id="stripe", realm="test", method="stripe", intent="charge", request="eyJhbW91bnQiOiIxIn0"',
1596
- 'Payment id="tempo", realm="test", method="tempo", intent="charge", request="eyJhbW91bnQiOiIxIn0"',
1597
- ].join(', '),
1598
- },
1599
- })
1600
- }
1601
-
1602
- expect(new Headers(init?.headers).get('Authorization')).toBe('tempo-credential')
1603
- return new Response('OK', { status: 200 })
1604
- }
1605
-
1606
- const fetch = Fetch.from({
1607
- fetch: mockFetch,
1608
- methods: [
1609
- {
1610
- name: 'tempo',
1611
- intent: 'charge',
1612
- context: undefined,
1613
- createCredential: async () => 'tempo-credential',
1614
- },
1615
- {
1616
- name: 'stripe',
1617
- intent: 'charge',
1618
- context: undefined,
1619
- createCredential: async () => 'stripe-credential',
1620
- },
1621
- ] as const,
1622
- acceptPayment: {
1623
- definition: { 'stripe/charge': 0.5 },
1624
- entries: [
1625
- { intent: 'charge', method: 'tempo', q: 1, index: 0 },
1626
- { intent: 'charge', method: 'stripe', q: 0.5, index: 1 },
1627
- ],
1628
- header: 'tempo/charge, stripe/charge;q=0.5',
1629
- keys: {
1630
- stripe: { charge: 'stripe/charge' },
1631
- tempo: { charge: 'tempo/charge' },
1632
- },
1633
- },
1634
- })
1635
-
1636
- const response = await fetch('https://example.com/api')
1637
- expect(response.status).toBe(200)
1638
- })
1639
-
1640
- test('ignores unsupported x402 accepts when selecting a Payment auth challenge', async () => {
1641
- let callCount = 0
1642
- const createCredential = vi.fn(async () => 'tempo-credential')
1643
- const tempoChallenge = Challenge.from({
1644
- id: 'tempo',
1645
- realm: 'test',
1646
- method: 'tempo',
1647
- intent: 'charge',
1648
- request: { amount: '1' },
1649
- })
1650
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1651
- callCount++
1652
- if (callCount === 1) {
1653
- return new Response(null, {
1654
- status: 402,
1655
- headers: {
1656
- [x402_Types.paymentRequiredHeader]: encodeRawPaymentRequiredHeader({
1657
- accepts: [
1658
- {
1659
- amount: '10000',
1660
- asset: 'USDC',
1661
- maxTimeoutSeconds: 60,
1662
- network: 'solana:mainnet',
1663
- payTo: '9xQeWvG816bUx9EPjHmaT23yvVM2ZWdYqPxfowV5n2kg',
1664
- scheme: 'exact',
1665
- },
1666
- ],
1667
- resource: { url: 'https://example.com/api' },
1668
- x402Version: 2,
1669
- }),
1670
- 'WWW-Authenticate': Challenge.serialize(tempoChallenge),
1671
- },
1672
- })
1673
- }
1674
-
1675
- expect(new Headers(init?.headers).get('Authorization')).toBe('tempo-credential')
1676
- return new Response('OK', { status: 200 })
1677
- }
1678
-
1679
- const fetch = Fetch.from({
1680
- fetch: mockFetch,
1681
- methods: [
1682
- {
1683
- name: 'tempo',
1684
- intent: 'charge',
1685
- context: undefined,
1686
- createCredential,
1687
- },
1688
- ] as const,
1689
- })
1690
-
1691
- const response = await fetch('https://example.com/api')
1692
-
1693
- expect(response.status).toBe(200)
1694
- expect(createCredential).toHaveBeenCalledOnce()
1695
- })
1696
-
1697
- test('orderChallenges filters and sorts supported challenges before signing', async () => {
1698
- let callCount = 0
1699
- const pathUsd = Challenge.from({
1700
- id: 'pathusd',
1701
- realm: 'test',
1702
- method: 'test',
1703
- intent: 'test',
1704
- request: { chainId: 11155111, currency: 'pathusd' },
1705
- })
1706
- const usdc = Challenge.from({
1707
- id: 'usdc',
1708
- realm: 'test',
1709
- method: 'test',
1710
- intent: 'test',
1711
- request: { chainId: 8453, currency: 'usdc' },
1712
- })
1713
- const createCredential = vi.fn(
1714
- async ({ challenge }: { challenge: Challenge.Challenge }) => `credential-${challenge.id}`,
1715
- )
1716
-
1717
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1718
- callCount++
1719
- if (callCount === 1) {
1720
- return new Response(null, {
1721
- status: 402,
1722
- headers: {
1723
- 'WWW-Authenticate': `${Challenge.serialize(pathUsd)}, ${Challenge.serialize(usdc)}`,
1724
- },
1725
- })
1726
- }
1727
-
1728
- expect(new Headers(init?.headers).get('Authorization')).toBe('credential-usdc')
1729
- return new Response('OK', { status: 200 })
1730
- }
1731
-
1732
- const fetch = Fetch.from({
1733
- fetch: mockFetch,
1734
- methods: [{ ...noopMethod, createCredential }],
1735
- orderChallenges: (candidates) =>
1736
- candidates.filter(({ challenge }) => challenge.request.currency === 'usdc'),
1737
- })
1738
-
1739
- const response = await fetch('https://example.com/api')
1740
-
1741
- expect(response.status).toBe(200)
1742
- expect(createCredential).toHaveBeenCalledOnce()
1743
- expect(createCredential.mock.calls[0]?.[0].challenge.id).toBe('usdc')
1744
- })
1745
-
1746
- test('request-local orderChallenges overrides configured ordering', async () => {
1747
- let callCount = 0
1748
- const first = Challenge.from({
1749
- id: 'first',
1750
- realm: 'test',
1751
- method: 'test',
1752
- intent: 'test',
1753
- request: { currency: 'first' },
1754
- })
1755
- const second = Challenge.from({
1756
- id: 'second',
1757
- realm: 'test',
1758
- method: 'test',
1759
- intent: 'test',
1760
- request: { currency: 'second' },
1761
- })
1762
- const createCredential = vi.fn(
1763
- async ({ challenge }: { challenge: Challenge.Challenge }) => `credential-${challenge.id}`,
1764
- )
1765
-
1766
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1767
- callCount++
1768
- if (callCount === 1) {
1769
- return new Response(null, {
1770
- status: 402,
1771
- headers: {
1772
- 'WWW-Authenticate': `${Challenge.serialize(first)}, ${Challenge.serialize(second)}`,
1773
- },
1774
- })
1775
- }
1776
-
1777
- expect(new Headers(init?.headers).get('Authorization')).toBe('credential-second')
1778
- return new Response('OK', { status: 200 })
1779
- }
1780
-
1781
- const fetch = Fetch.from({
1782
- fetch: mockFetch,
1783
- methods: [{ ...noopMethod, createCredential }],
1784
- orderChallenges: (candidates) =>
1785
- candidates.filter(({ challenge }) => challenge.id === 'first'),
1786
- })
1787
-
1788
- const response = await fetch('https://example.com/api', {
1789
- orderChallenges: (candidates) =>
1790
- candidates.filter(({ challenge }) => challenge.id === 'second'),
1791
- })
1792
-
1793
- expect(response.status).toBe(200)
1794
- expect(createCredential.mock.calls[0]?.[0].challenge.id).toBe('second')
1795
- })
1796
-
1797
- test('throws when orderChallenges rejects every supported challenge', async () => {
1798
- const mockFetch: typeof globalThis.fetch = async () => make402()
1799
- const createCredential = vi.fn(async () => 'credential')
1800
-
1801
- const fetch = Fetch.from({
1802
- fetch: mockFetch,
1803
- methods: [{ ...noopMethod, createCredential }],
1804
- orderChallenges: () => [],
1805
- })
1806
-
1807
- await expect(fetch('https://example.com/api')).rejects.toThrow(
1808
- 'No method found for challenges: test.test',
1809
- )
1810
- expect(createCredential).not.toHaveBeenCalled()
1811
- })
1812
-
1813
- test('falls back to configured preferences when explicit Accept-Payment is invalid', async () => {
1814
- let callCount = 0
1815
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1816
- callCount++
1817
- if (callCount === 1) {
1818
- expect(new Headers(init?.headers).get('Accept-Payment')).toBe('not a valid header')
1819
-
1820
- return new Response(null, {
1821
- status: 402,
1822
- headers: {
1823
- 'WWW-Authenticate': [
1824
- 'Payment id="stripe", realm="test", method="stripe", intent="charge", request="eyJhbW91bnQiOiIxIn0"',
1825
- 'Payment id="tempo", realm="test", method="tempo", intent="charge", request="eyJhbW91bnQiOiIxIn0"',
1826
- ].join(', '),
1827
- },
1828
- })
1829
- }
1830
-
1831
- expect(new Headers(init?.headers).get('Authorization')).toBe('tempo-credential')
1832
- return new Response('OK', { status: 200 })
1833
- }
1834
-
1835
- const fetch = Fetch.from({
1836
- fetch: mockFetch,
1837
- methods: [
1838
- {
1839
- name: 'tempo',
1840
- intent: 'charge',
1841
- context: undefined,
1842
- createCredential: async () => 'tempo-credential',
1843
- },
1844
- {
1845
- name: 'stripe',
1846
- intent: 'charge',
1847
- context: undefined,
1848
- createCredential: async () => 'stripe-credential',
1849
- },
1850
- ] as const,
1851
- acceptPayment: {
1852
- definition: { 'stripe/charge': 0.5 },
1853
- entries: [
1854
- { intent: 'charge', method: 'tempo', q: 1, index: 0 },
1855
- { intent: 'charge', method: 'stripe', q: 0.5, index: 1 },
1856
- ],
1857
- header: 'tempo/charge, stripe/charge;q=0.5',
1858
- keys: {
1859
- stripe: { charge: 'stripe/charge' },
1860
- tempo: { charge: 'tempo/charge' },
1861
- },
1862
- },
1863
- })
1864
-
1865
- const response = await fetch('https://example.com/api', {
1866
- headers: { 'Accept-Payment': 'not a valid header' },
1867
- })
1868
- expect(response.status).toBe(200)
1869
- })
1870
-
1871
- test('throws when no matching method for 402 challenge', async () => {
1872
- const mockFetch: typeof globalThis.fetch = async () =>
1873
- make402({ method: 'stripe', intent: 'charge' })
1874
-
1875
- const fetch = Fetch.from({
1876
- fetch: mockFetch,
1877
- methods: [noopMethod],
1878
- })
1879
-
1880
- await expect(fetch('https://example.com/api')).rejects.toThrow(
1881
- 'No method found for challenges: stripe.charge',
1882
- )
1883
- })
1884
-
1885
- test('creates a fresh credential for each incremental 402 challenge', async () => {
1886
- const createCredential = vi.fn(
1887
- async ({ challenge }: { challenge: Challenge.Challenge }) => `credential-${challenge.id}`,
1888
- )
1889
- const calls: { init: RequestInit | undefined }[] = []
1890
- let callCount = 0
1891
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
1892
- calls.push({ init })
1893
- callCount++
1894
- if (callCount === 1) return make402({ id: 'first' })
1895
- if (callCount === 2) return make402({ id: 'second' })
1896
- if (callCount === 3) return make402({ id: 'third' })
1897
- return new Response('OK', { status: 200 })
1898
- }
1899
-
1900
- const fetch = Fetch.from({
1901
- fetch: mockFetch,
1902
- methods: [{ ...noopMethod, createCredential }],
1903
- })
1904
-
1905
- const response = await fetch('https://example.com/api')
1906
-
1907
- expect(response.status).toBe(200)
1908
- expect(createCredential.mock.calls.map((call) => call[0].challenge.id)).toEqual([
1909
- 'first',
1910
- 'second',
1911
- 'third',
1912
- ])
1913
- expect(
1914
- calls.slice(1).map((call) => new Headers(call.init?.headers).get('Authorization')),
1915
- ).toEqual(['credential-first', 'credential-second', 'credential-third'])
1916
- })
1917
-
1918
- test('invalidates a prepared credential across a generic challenge', async () => {
1919
- const firstCredential = vi.fn(async () => 'first')
1920
- const first = { ...noopMethod, name: 'first', createCredential: firstCredential }
1921
- const second = { ...noopMethod, name: 'second', createCredential: async () => 'second' }
1922
- MethodChallenge.register(first, () => undefined)
1923
- const responses = [
1924
- make402({ id: 'first', method: 'first' }),
1925
- make402({ id: 'second', method: 'second' }),
1926
- make402({ id: 'first', method: 'first' }),
1927
- new Response('OK'),
1928
- ]
1929
- const mockFetch = vi.fn(async () => responses.shift()!)
1930
- const fetch = Fetch.from({ fetch: mockFetch, methods: [first, second] })
1931
-
1932
- expect((await fetch('https://example.com/api')).status).toBe(200)
1933
- expect(firstCredential).toHaveBeenCalledTimes(2)
1934
- })
1935
-
1936
- test('invalidates a prepared credential after an explicit context', async () => {
1937
- const createCredential = vi.fn(async () => 'credential')
1938
- const method = { ...noopMethod, createCredential }
1939
- MethodChallenge.register(method, () => undefined)
1940
- let challenges = 0
1941
- const mockFetch = vi.fn(async () => (++challenges <= 3 ? make402() : new Response('OK')))
1942
- const fetch = Fetch.from({
1943
- fetch: mockFetch as typeof globalThis.fetch,
1944
- methods: [method],
1945
- onChallenge: async (_challenge, { createCredential: create }) =>
1946
- challenges === 2 ? create({ override: true } as never) : undefined,
1947
- })
1948
-
1949
- expect((await fetch('https://example.com/api')).status).toBe(200)
1950
- expect(createCredential).toHaveBeenCalledTimes(3)
1951
- })
1952
-
1953
- test('caps repeated 402 retries at three', async () => {
1954
- let callCount = 0
1955
- const createCredential = vi.fn(async () => 'credential')
1956
- const mockFetch: typeof globalThis.fetch = async () => {
1957
- callCount++
1958
- return make402()
1959
- }
1960
-
1961
- const fetch = Fetch.from({
1962
- fetch: mockFetch,
1963
- methods: [{ ...noopMethod, createCredential }],
1964
- })
1965
-
1966
- const response = await fetch('https://example.com/api')
1967
- expect(callCount).toBe(4)
1968
- expect(createCredential).toHaveBeenCalledTimes(3)
1969
- expect(response.status).toBe(402)
1970
- })
1971
-
1972
- test('respects configured retry cap', async () => {
1973
- let callCount = 0
1974
- const createCredential = vi.fn(async () => 'credential')
1975
- const mockFetch: typeof globalThis.fetch = async () => {
1976
- callCount++
1977
- return make402()
1978
- }
1979
-
1980
- const fetch = Fetch.from({
1981
- fetch: mockFetch,
1982
- maxPaymentRetries: 1,
1983
- methods: [{ ...noopMethod, createCredential }],
1984
- })
1985
-
1986
- const response = await fetch('https://example.com/api')
1987
- expect(callCount).toBe(2)
1988
- expect(createCredential).toHaveBeenCalledOnce()
1989
- expect(response.status).toBe(402)
1990
- })
1991
-
1992
- test('returns a challenge-less 402 after a rejected payment', async () => {
1993
- let callCount = 0
1994
- const createCredential = vi.fn(async () => 'credential')
1995
- const mockFetch: typeof globalThis.fetch = async () => {
1996
- callCount++
1997
- if (callCount === 1) return make402()
1998
- return new Response(JSON.stringify({ title: 'Verification Failed' }), {
1999
- status: 402,
2000
- headers: { 'Content-Type': 'application/json' },
2001
- })
2002
- }
2003
-
2004
- const fetch = Fetch.from({
2005
- fetch: mockFetch,
2006
- methods: [{ ...noopMethod, createCredential }],
2007
- })
2008
-
2009
- const response = await fetch('https://example.com/api')
2010
- expect(callCount).toBe(2)
2011
- expect(createCredential).toHaveBeenCalledOnce()
2012
- expect(response.status).toBe(402)
2013
- await expect(response.json()).resolves.toEqual({ title: 'Verification Failed' })
2014
- })
2015
-
2016
- test('returns a post-payment 402 with only unsupported challenges', async () => {
2017
- let callCount = 0
2018
- const createCredential = vi.fn(async () => 'credential')
2019
- const mockFetch: typeof globalThis.fetch = async () => {
2020
- callCount++
2021
- if (callCount === 1) return make402()
2022
- return make402({ method: 'stripe', intent: 'charge' })
2023
- }
2024
-
2025
- const fetch = Fetch.from({
2026
- fetch: mockFetch,
2027
- methods: [{ ...noopMethod, createCredential }],
2028
- })
2029
-
2030
- const response = await fetch('https://example.com/api')
2031
- expect(callCount).toBe(2)
2032
- expect(createCredential).toHaveBeenCalledOnce()
2033
- expect(response.status).toBe(402)
2034
- })
2035
- })
2036
-
2037
- describe('Fetch.from: acceptPaymentPolicy', () => {
2038
- test('policy: "always" injects Accept-Payment on all requests', async () => {
2039
- const receivedInits: (RequestInit | undefined)[] = []
2040
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
2041
- receivedInits.push(init)
2042
- return new Response('OK', { status: 200 })
2043
- }
2044
-
2045
- const fetch = Fetch.from({
2046
- fetch: mockFetch,
2047
- methods: [noopMethod],
2048
- acceptPaymentPolicy: 'always',
2049
- })
2050
-
2051
- await fetch('https://cross-origin.com/api')
2052
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('test/test')
2053
- })
2054
-
2055
- test('policy: "never" skips Accept-Payment on all requests', async () => {
2056
- const receivedInits: (RequestInit | undefined)[] = []
2057
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
2058
- receivedInits.push(init)
2059
- return new Response('OK', { status: 200 })
2060
- }
2061
-
2062
- const fetch = Fetch.from({
2063
- fetch: mockFetch,
2064
- methods: [noopMethod],
2065
- acceptPaymentPolicy: 'never',
2066
- })
2067
-
2068
- await fetch('https://example.com/api')
2069
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBeNull()
2070
- })
2071
-
2072
- test('policy: "same-origin" injects when no globalThis.location (server-side)', async () => {
2073
- const receivedInits: (RequestInit | undefined)[] = []
2074
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
2075
- receivedInits.push(init)
2076
- return new Response('OK', { status: 200 })
2077
- }
2078
-
2079
- const fetch = Fetch.from({
2080
- fetch: mockFetch,
2081
- methods: [noopMethod],
2082
- acceptPaymentPolicy: 'same-origin',
2083
- })
2084
-
2085
- await fetch('https://example.com/api')
2086
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('test/test')
2087
- })
2088
-
2089
- test('policy: { origins } injects only for matching origins', async () => {
2090
- const receivedInits: (RequestInit | undefined)[] = []
2091
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
2092
- receivedInits.push(init)
2093
- return new Response('OK', { status: 200 })
2094
- }
2095
-
2096
- const fetch = Fetch.from({
2097
- fetch: mockFetch,
2098
- methods: [noopMethod],
2099
- acceptPaymentPolicy: { origins: ['https://pay.example.com'] },
2100
- })
2101
-
2102
- await fetch('https://pay.example.com/resource')
2103
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('test/test')
2104
-
2105
- await fetch('https://other.example.com/resource')
2106
- expect(new Headers(receivedInits[1]?.headers).get('Accept-Payment')).toBeNull()
2107
- })
2108
-
2109
- test('policy: { origins } matches origin regardless of path', async () => {
2110
- const receivedInits: (RequestInit | undefined)[] = []
2111
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
2112
- receivedInits.push(init)
2113
- return new Response('OK', { status: 200 })
2114
- }
2115
-
2116
- const fetch = Fetch.from({
2117
- fetch: mockFetch,
2118
- methods: [noopMethod],
2119
- acceptPaymentPolicy: { origins: ['https://pay.example.com/some/path'] },
2120
- })
2121
-
2122
- await fetch('https://pay.example.com/different/path')
2123
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('test/test')
2124
- })
2125
-
2126
- test('policy: { origins } supports wildcard subdomains', async () => {
2127
- const receivedInits: (RequestInit | undefined)[] = []
2128
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
2129
- receivedInits.push(init)
2130
- return new Response('OK', { status: 200 })
2131
- }
2132
-
2133
- const fetch = Fetch.from({
2134
- fetch: mockFetch,
2135
- methods: [noopMethod],
2136
- acceptPaymentPolicy: { origins: ['*.example.com'] },
2137
- })
2138
-
2139
- await fetch('https://pay.example.com/resource')
2140
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('test/test')
2141
-
2142
- await fetch('https://api.pay.example.com/resource')
2143
- expect(new Headers(receivedInits[1]?.headers).get('Accept-Payment')).toBe('test/test')
2144
-
2145
- await fetch('https://example.com/resource')
2146
- expect(new Headers(receivedInits[2]?.headers).get('Accept-Payment')).toBe('test/test')
2147
-
2148
- await fetch('https://notexample.com/resource')
2149
- expect(new Headers(receivedInits[3]?.headers).get('Accept-Payment')).toBeNull()
2150
- })
2151
-
2152
- test('policy: "never" still handles 402 responses', async () => {
2153
- let callCount = 0
2154
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
2155
- callCount++
2156
- if (callCount === 1) {
2157
- expect(new Headers(init?.headers).get('Accept-Payment')).toBeNull()
2158
- return make402()
2159
- }
2160
- expect(new Headers(init?.headers).get('Authorization')).toBe('credential')
2161
- return new Response('OK', { status: 200 })
2162
- }
2163
-
2164
- const fetch = Fetch.from({
2165
- fetch: mockFetch,
2166
- methods: [noopMethod],
2167
- acceptPaymentPolicy: 'never',
2168
- })
2169
-
2170
- const response = await fetch('https://example.com/api')
2171
- expect(response.status).toBe(200)
2172
- })
2173
-
2174
- test('policy: explicit Accept-Payment header always takes precedence over "never"', async () => {
2175
- const receivedInits: (RequestInit | undefined)[] = []
2176
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
2177
- receivedInits.push(init)
2178
- return new Response('OK', { status: 200 })
2179
- }
2180
-
2181
- const fetch = Fetch.from({
2182
- fetch: mockFetch,
2183
- methods: [noopMethod],
2184
- acceptPaymentPolicy: 'never',
2185
- })
2186
-
2187
- await fetch('https://example.com/api', {
2188
- headers: { 'Accept-Payment': 'custom/charge' },
2189
- })
2190
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('custom/charge')
2191
- })
2192
-
2193
- test('defaults to "always" for Fetch.from', async () => {
2194
- const receivedInits: (RequestInit | undefined)[] = []
2195
- const mockFetch: typeof globalThis.fetch = async (_input, init) => {
2196
- receivedInits.push(init)
2197
- return new Response('OK', { status: 200 })
2198
- }
2199
-
2200
- const fetch = Fetch.from({
2201
- fetch: mockFetch,
2202
- methods: [noopMethod],
2203
- })
2204
-
2205
- await fetch('https://cross-origin.com/api')
2206
- expect(new Headers(receivedInits[0]?.headers).get('Accept-Payment')).toBe('test/test')
2207
- })
2208
- })
2209
-
2210
- describe('Fetch.from: input passthrough', () => {
2211
- test('passes URL input through on both initial and retry calls', async () => {
2212
- let callCount = 0
2213
- const receivedInputs: (RequestInfo | URL)[] = []
2214
- const mockFetch: typeof globalThis.fetch = async (input, _init) => {
2215
- receivedInputs.push(input)
2216
- callCount++
2217
- if (callCount === 1) return make402()
2218
- return new Response('OK', { status: 200 })
2219
- }
2220
-
2221
- const fetch = Fetch.from({
2222
- fetch: mockFetch,
2223
- methods: [noopMethod],
2224
- })
2225
-
2226
- const url = new URL('https://example.com/resource')
2227
- await fetch(url)
2228
-
2229
- expect(receivedInputs[0]).toBe(url)
2230
- expect(receivedInputs[1]).toBe(url)
2231
- })
2232
- })
2233
-
2234
- describe('Fetch.polyfill', () => {
2235
- test('default', async () => {
2236
- Fetch.polyfill({
2237
- methods: [
2238
- tempo.charge({
2239
- account: accounts[1],
2240
- getClient: () => client,
2241
- }),
2242
- ],
2243
- })
2244
-
2245
- const httpServer = await Http.createServer(async (req, res) => {
2246
- const result = await Mppx_server.toNodeListener(
2247
- server.charge({
2248
- amount: '1',
2249
- currency: asset,
2250
- expires: new Date(Date.now() + 60_000).toISOString(),
2251
- recipient: accounts[0].address,
2252
- }),
2253
- )(req, res)
2254
- if (result.status === 402) return
2255
- res.end('OK')
2256
- })
2257
-
2258
- const response = await fetch(httpServer.url)
2259
- expect(response.status).toBe(200)
2260
-
2261
- const receipt = Receipt.fromResponse(response)
2262
- expect({
2263
- ...receipt,
2264
- reference: '[reference]',
2265
- timestamp: '[timestamp]',
2266
- }).toMatchInlineSnapshot(`
2267
- {
2268
- "method": "tempo",
2269
- "reference": "[reference]",
2270
- "status": "success",
2271
- "timestamp": "[timestamp]",
2272
- }
2273
- `)
2274
-
2275
- httpServer.close()
2276
- Fetch.restore()
2277
- })
2278
- })
2279
-
2280
- describe('Fetch.polyfill / restore', () => {
2281
- test('restore is a no-op when polyfill was never called', () => {
2282
- const before = globalThis.fetch
2283
- Fetch.restore()
2284
- expect(globalThis.fetch).toBe(before)
2285
- })
2286
-
2287
- test('restore reverts to original fetch', () => {
2288
- const originalFetch = globalThis.fetch
2289
-
2290
- Fetch.polyfill({ methods: [noopMethod] })
2291
- expect(globalThis.fetch).not.toBe(originalFetch)
2292
-
2293
- Fetch.restore()
2294
- expect(globalThis.fetch).toBe(originalFetch)
2295
- })
2296
-
2297
- test('stacked polyfill calls preserve the true original fetch', () => {
2298
- const originalFetch = globalThis.fetch
2299
-
2300
- Fetch.polyfill({ methods: [noopMethod] })
2301
- const firstPolyfill = globalThis.fetch
2302
-
2303
- Fetch.polyfill({ methods: [noopMethod] })
2304
- expect(globalThis.fetch).not.toBe(firstPolyfill)
2305
-
2306
- Fetch.restore()
2307
- expect(globalThis.fetch).toBe(originalFetch)
2308
- })
2309
-
2310
- test('double restore does not clobber fetch', () => {
2311
- const originalFetch = globalThis.fetch
2312
-
2313
- Fetch.polyfill({ methods: [noopMethod] })
2314
- Fetch.restore()
2315
- expect(globalThis.fetch).toBe(originalFetch)
2316
-
2317
- Fetch.restore()
2318
- expect(globalThis.fetch).toBe(originalFetch)
2319
- })
2320
-
2321
- test('restore is a no-op when fetch was replaced externally after polyfill', () => {
2322
- const originalFetch = globalThis.fetch
2323
- const externalFetch = vi.fn(
2324
- async (_input: RequestInfo | URL, _init?: RequestInit) =>
2325
- new Response('external', { status: 200 }),
2326
- ) as unknown as typeof globalThis.fetch
2327
-
2328
- Fetch.polyfill({ methods: [noopMethod] })
2329
- globalThis.fetch = externalFetch
2330
-
2331
- Fetch.restore()
2332
- expect(globalThis.fetch).toBe(externalFetch)
2333
-
2334
- globalThis.fetch = originalFetch
2335
- })
2336
- })