mppx 0.8.14 → 0.8.17

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 (507) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/Challenge.d.ts.map +1 -1
  3. package/dist/Challenge.js +40 -35
  4. package/dist/Challenge.js.map +1 -1
  5. package/dist/Constants.d.ts +17 -17
  6. package/dist/Constants.d.ts.map +1 -1
  7. package/dist/Credential.d.ts.map +1 -1
  8. package/dist/Errors.d.ts +3 -3
  9. package/dist/Errors.d.ts.map +1 -1
  10. package/dist/Errors.js.map +1 -1
  11. package/dist/Method.d.ts +35 -5
  12. package/dist/Method.d.ts.map +1 -1
  13. package/dist/Method.js +7 -22
  14. package/dist/Method.js.map +1 -1
  15. package/dist/Store.d.ts +19 -0
  16. package/dist/Store.d.ts.map +1 -1
  17. package/dist/Store.js +43 -0
  18. package/dist/Store.js.map +1 -1
  19. package/dist/attestation/Client.d.ts +17 -0
  20. package/dist/attestation/Client.d.ts.map +1 -0
  21. package/dist/attestation/Client.js +28 -0
  22. package/dist/attestation/Client.js.map +1 -0
  23. package/dist/attestation/Constants.d.ts +15 -0
  24. package/dist/attestation/Constants.d.ts.map +1 -0
  25. package/dist/attestation/Constants.js +15 -0
  26. package/dist/attestation/Constants.js.map +1 -0
  27. package/dist/attestation/Server.d.ts +4 -0
  28. package/dist/attestation/Server.d.ts.map +1 -0
  29. package/dist/attestation/Server.js +8 -0
  30. package/dist/attestation/Server.js.map +1 -0
  31. package/dist/attestation/Types.d.ts +76 -0
  32. package/dist/attestation/Types.d.ts.map +1 -0
  33. package/dist/attestation/Types.js +2 -0
  34. package/dist/attestation/Types.js.map +1 -0
  35. package/dist/attestation/index.d.ts +6 -0
  36. package/dist/attestation/index.d.ts.map +1 -0
  37. package/dist/attestation/index.js +6 -0
  38. package/dist/attestation/index.js.map +1 -0
  39. package/dist/attestation/internal/HttpMessageSignature.d.ts +73 -0
  40. package/dist/attestation/internal/HttpMessageSignature.d.ts.map +1 -0
  41. package/dist/attestation/internal/HttpMessageSignature.js +320 -0
  42. package/dist/attestation/internal/HttpMessageSignature.js.map +1 -0
  43. package/dist/attestation/internal/SigningContext.d.ts +4 -0
  44. package/dist/attestation/internal/SigningContext.d.ts.map +1 -0
  45. package/dist/attestation/internal/SigningContext.js +11 -0
  46. package/dist/attestation/internal/SigningContext.js.map +1 -0
  47. package/dist/cli/account.d.ts +14 -14
  48. package/dist/cli/account.d.ts.map +1 -1
  49. package/dist/cli/cli.d.ts +6 -6
  50. package/dist/cli/cli.d.ts.map +1 -1
  51. package/dist/cli/cli.js +1 -0
  52. package/dist/cli/cli.js.map +1 -1
  53. package/dist/cli/plugins/tempo.js.map +1 -1
  54. package/dist/cli/sessions/commands.d.ts +4 -4
  55. package/dist/cli/sessions/commands.d.ts.map +1 -1
  56. package/dist/cli/sessions/commands.js.map +1 -1
  57. package/dist/cli/sessions/store.d.ts.map +1 -1
  58. package/dist/cli/sessions/store.js.map +1 -1
  59. package/dist/cli/utils.d.ts +1 -1
  60. package/dist/cli/utils.d.ts.map +1 -1
  61. package/dist/cli/utils.js.map +1 -1
  62. package/dist/cli/validate/discovery.js.map +1 -1
  63. package/dist/cli/validate/index.d.ts +3 -3
  64. package/dist/cli/validate/index.d.ts.map +1 -1
  65. package/dist/cli/validate/payment.d.ts.map +1 -1
  66. package/dist/cli/validate/payment.js +18 -4
  67. package/dist/cli/validate/payment.js.map +1 -1
  68. package/dist/client/Mppx.d.ts +3 -0
  69. package/dist/client/Mppx.d.ts.map +1 -1
  70. package/dist/client/Mppx.js +13 -5
  71. package/dist/client/Mppx.js.map +1 -1
  72. package/dist/client/Transport.d.ts +3 -5
  73. package/dist/client/Transport.d.ts.map +1 -1
  74. package/dist/client/Transport.js +1 -17
  75. package/dist/client/Transport.js.map +1 -1
  76. package/dist/client/internal/Fetch.d.ts.map +1 -1
  77. package/dist/client/internal/Fetch.js +92 -13
  78. package/dist/client/internal/Fetch.js.map +1 -1
  79. package/dist/client/internal/MethodChallenge.d.ts +2 -0
  80. package/dist/client/internal/MethodChallenge.d.ts.map +1 -1
  81. package/dist/client/internal/MethodChallenge.js +4 -0
  82. package/dist/client/internal/MethodChallenge.js.map +1 -1
  83. package/dist/client/internal/MethodResponse.d.ts +15 -0
  84. package/dist/client/internal/MethodResponse.d.ts.map +1 -1
  85. package/dist/client/internal/MethodResponse.js +10 -0
  86. package/dist/client/internal/MethodResponse.js.map +1 -1
  87. package/dist/client/node.js.map +1 -1
  88. package/dist/discovery/OpenApi.d.ts +3 -5
  89. package/dist/discovery/OpenApi.d.ts.map +1 -1
  90. package/dist/discovery/OpenApi.js +13 -34
  91. package/dist/discovery/OpenApi.js.map +1 -1
  92. package/dist/discovery/internal/Metadata.d.ts +20 -0
  93. package/dist/discovery/internal/Metadata.d.ts.map +1 -0
  94. package/dist/discovery/internal/Metadata.js +36 -0
  95. package/dist/discovery/internal/Metadata.js.map +1 -0
  96. package/dist/evm/Methods.d.ts +11 -11
  97. package/dist/evm/Methods.d.ts.map +1 -1
  98. package/dist/evm/Types.d.ts +17 -17
  99. package/dist/evm/Types.d.ts.map +1 -1
  100. package/dist/evm/client/Charge.d.ts +11 -11
  101. package/dist/evm/client/Methods.d.ts +11 -11
  102. package/dist/evm/server/Charge.d.ts +1 -1
  103. package/dist/evm/server/Charge.d.ts.map +1 -1
  104. package/dist/evm/server/Charge.js +2 -0
  105. package/dist/evm/server/Charge.js.map +1 -1
  106. package/dist/evm/server/Methods.d.ts +11 -11
  107. package/dist/internal/HeaderCodec.d.ts +2 -2
  108. package/dist/internal/HeaderCodec.d.ts.map +1 -1
  109. package/dist/internal/types.d.ts +6 -0
  110. package/dist/internal/types.d.ts.map +1 -1
  111. package/dist/middlewares/elysia.js.map +1 -1
  112. package/dist/middlewares/express.js.map +1 -1
  113. package/dist/middlewares/hono.js.map +1 -1
  114. package/dist/middlewares/nextjs.js.map +1 -1
  115. package/dist/proxy/Proxy.d.ts +2 -0
  116. package/dist/proxy/Proxy.d.ts.map +1 -1
  117. package/dist/proxy/Proxy.js +117 -9
  118. package/dist/proxy/Proxy.js.map +1 -1
  119. package/dist/proxy/Service.d.ts +36 -1
  120. package/dist/proxy/Service.d.ts.map +1 -1
  121. package/dist/proxy/Service.js +9 -8
  122. package/dist/proxy/Service.js.map +1 -1
  123. package/dist/proxy/services/anthropic.d.ts.map +1 -1
  124. package/dist/proxy/services/anthropic.js +1 -0
  125. package/dist/proxy/services/anthropic.js.map +1 -1
  126. package/dist/proxy/services/openai.d.ts.map +1 -1
  127. package/dist/proxy/services/openai.js +1 -0
  128. package/dist/proxy/services/openai.js.map +1 -1
  129. package/dist/proxy/services/stripe.d.ts.map +1 -1
  130. package/dist/proxy/services/stripe.js +1 -0
  131. package/dist/proxy/services/stripe.js.map +1 -1
  132. package/dist/server/Mppx.d.ts +75 -13
  133. package/dist/server/Mppx.d.ts.map +1 -1
  134. package/dist/server/Mppx.js +201 -23
  135. package/dist/server/Mppx.js.map +1 -1
  136. package/dist/server/internal/html/config.d.ts +9 -9
  137. package/dist/server/internal/html/config.d.ts.map +1 -1
  138. package/dist/server/internal/html/constants.d.ts +17 -17
  139. package/dist/server/internal/html/constants.d.ts.map +1 -1
  140. package/dist/stripe/Methods.d.ts +10 -10
  141. package/dist/stripe/Methods.d.ts.map +1 -1
  142. package/dist/stripe/client/Charge.d.ts +10 -10
  143. package/dist/stripe/client/Methods.d.ts +10 -10
  144. package/dist/stripe/internal/constants.d.ts +1 -1
  145. package/dist/stripe/internal/constants.js +1 -1
  146. package/dist/stripe/internal/types.d.ts +1 -0
  147. package/dist/stripe/internal/types.d.ts.map +1 -1
  148. package/dist/stripe/server/Charge.d.ts +11 -11
  149. package/dist/stripe/server/Charge.d.ts.map +1 -1
  150. package/dist/stripe/server/Charge.js +49 -1
  151. package/dist/stripe/server/Charge.js.map +1 -1
  152. package/dist/stripe/server/Methods.d.ts +137 -48
  153. package/dist/stripe/server/Methods.d.ts.map +1 -1
  154. package/dist/stripe/server/Methods.js +259 -4
  155. package/dist/stripe/server/Methods.js.map +1 -1
  156. package/dist/stripe/server/internal/deposit-address.d.ts +13 -0
  157. package/dist/stripe/server/internal/deposit-address.d.ts.map +1 -0
  158. package/dist/stripe/server/internal/deposit-address.js +28 -0
  159. package/dist/stripe/server/internal/deposit-address.js.map +1 -0
  160. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  161. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
  162. package/dist/stripe/server/internal/html.gen.js +1 -1
  163. package/dist/stripe/server/internal/html.gen.js.map +1 -1
  164. package/dist/stripe/server/internal/record-payment.d.ts +15 -0
  165. package/dist/stripe/server/internal/record-payment.d.ts.map +1 -0
  166. package/dist/stripe/server/internal/record-payment.js +42 -0
  167. package/dist/stripe/server/internal/record-payment.js.map +1 -0
  168. package/dist/stripe/server/internal/request.d.ts +25 -0
  169. package/dist/stripe/server/internal/request.d.ts.map +1 -0
  170. package/dist/stripe/server/internal/request.js +29 -0
  171. package/dist/stripe/server/internal/request.js.map +1 -0
  172. package/dist/tap/Constants.d.ts +28 -0
  173. package/dist/tap/Constants.d.ts.map +1 -0
  174. package/dist/tap/Constants.js +32 -0
  175. package/dist/tap/Constants.js.map +1 -0
  176. package/dist/tap/Types.d.ts +11 -0
  177. package/dist/tap/Types.d.ts.map +1 -0
  178. package/dist/tap/Types.js +2 -0
  179. package/dist/tap/Types.js.map +1 -0
  180. package/dist/tap/client/index.d.ts +26 -0
  181. package/dist/tap/client/index.d.ts.map +1 -0
  182. package/dist/tap/client/index.js +33 -0
  183. package/dist/tap/client/index.js.map +1 -0
  184. package/dist/tap/index.d.ts +5 -0
  185. package/dist/tap/index.d.ts.map +1 -0
  186. package/dist/tap/index.js +5 -0
  187. package/dist/tap/index.js.map +1 -0
  188. package/dist/tap/server/index.d.ts +20 -0
  189. package/dist/tap/server/index.d.ts.map +1 -0
  190. package/dist/tap/server/index.js +36 -0
  191. package/dist/tap/server/index.js.map +1 -0
  192. package/dist/tempo/Attribution.d.ts +1 -1
  193. package/dist/tempo/Methods.d.ts +60 -60
  194. package/dist/tempo/Methods.d.ts.map +1 -1
  195. package/dist/tempo/Proof.d.ts +16 -16
  196. package/dist/tempo/client/Charge.d.ts +19 -19
  197. package/dist/tempo/client/Charge.d.ts.map +1 -1
  198. package/dist/tempo/client/Charge.js +1 -7
  199. package/dist/tempo/client/Charge.js.map +1 -1
  200. package/dist/tempo/client/Methods.d.ts +38 -38
  201. package/dist/tempo/client/Methods.js.map +1 -1
  202. package/dist/tempo/client/Subscription.d.ts +23 -23
  203. package/dist/tempo/client/Subscription.js.map +1 -1
  204. package/dist/tempo/internal/address.d.ts +2 -1
  205. package/dist/tempo/internal/address.d.ts.map +1 -1
  206. package/dist/tempo/internal/address.js +3 -1
  207. package/dist/tempo/internal/address.js.map +1 -1
  208. package/dist/tempo/internal/auto-swap.d.ts.map +1 -1
  209. package/dist/tempo/internal/auto-swap.js +4 -19
  210. package/dist/tempo/internal/auto-swap.js.map +1 -1
  211. package/dist/tempo/internal/defaults.d.ts +6 -6
  212. package/dist/tempo/internal/defaults.d.ts.map +1 -1
  213. package/dist/tempo/internal/fee-payer.d.ts +12 -12
  214. package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
  215. package/dist/tempo/internal/fee-payer.js.map +1 -1
  216. package/dist/tempo/internal/proof.d.ts +17 -17
  217. package/dist/tempo/internal/proof.d.ts.map +1 -1
  218. package/dist/tempo/legacy/client/Session.d.ts +20 -20
  219. package/dist/tempo/legacy/client/Session.js.map +1 -1
  220. package/dist/tempo/legacy/client/SessionManager.js.map +1 -1
  221. package/dist/tempo/legacy/index.d.ts +1 -3
  222. package/dist/tempo/legacy/index.d.ts.map +1 -1
  223. package/dist/tempo/legacy/index.js +1 -3
  224. package/dist/tempo/legacy/index.js.map +1 -1
  225. package/dist/tempo/legacy/session/escrow.abi.d.ts +374 -374
  226. package/dist/tempo/legacy/session/escrow.abi.d.ts.map +1 -1
  227. package/dist/tempo/server/Charge.d.ts +34 -12
  228. package/dist/tempo/server/Charge.d.ts.map +1 -1
  229. package/dist/tempo/server/Charge.js +44 -39
  230. package/dist/tempo/server/Charge.js.map +1 -1
  231. package/dist/tempo/server/Methods.d.ts +37 -52
  232. package/dist/tempo/server/Methods.d.ts.map +1 -1
  233. package/dist/tempo/server/Methods.js +0 -14
  234. package/dist/tempo/server/Methods.js.map +1 -1
  235. package/dist/tempo/server/Relay.d.ts +14 -5
  236. package/dist/tempo/server/Relay.d.ts.map +1 -1
  237. package/dist/tempo/server/Relay.js +6 -4
  238. package/dist/tempo/server/Relay.js.map +1 -1
  239. package/dist/tempo/server/SponsorBudget.d.ts.map +1 -1
  240. package/dist/tempo/server/SponsorBudget.js +7 -1
  241. package/dist/tempo/server/SponsorBudget.js.map +1 -1
  242. package/dist/tempo/server/Subscription.d.ts +25 -25
  243. package/dist/tempo/server/Subscription.d.ts.map +1 -1
  244. package/dist/tempo/server/Subscription.js +2 -0
  245. package/dist/tempo/server/Subscription.js.map +1 -1
  246. package/dist/tempo/server/index.d.ts +1 -1
  247. package/dist/tempo/server/index.d.ts.map +1 -1
  248. package/dist/tempo/server/index.js +1 -1
  249. package/dist/tempo/server/index.js.map +1 -1
  250. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  251. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  252. package/dist/tempo/server/internal/html.gen.js +1 -1
  253. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  254. package/dist/tempo/server/internal/transport.d.ts +2 -0
  255. package/dist/tempo/server/internal/transport.d.ts.map +1 -1
  256. package/dist/tempo/server/internal/transport.js +9 -2
  257. package/dist/tempo/server/internal/transport.js.map +1 -1
  258. package/dist/tempo/session/client/ChannelOps.js.map +1 -1
  259. package/dist/tempo/session/client/CredentialState.d.ts +1 -1
  260. package/dist/tempo/session/client/CredentialState.js.map +1 -1
  261. package/dist/tempo/session/client/ReceiptCoordinator.js.map +1 -1
  262. package/dist/tempo/session/client/Runtime.js.map +1 -1
  263. package/dist/tempo/session/client/Session.d.ts +19 -19
  264. package/dist/tempo/session/client/Session.d.ts.map +1 -1
  265. package/dist/tempo/session/client/Session.js +128 -14
  266. package/dist/tempo/session/client/Session.js.map +1 -1
  267. package/dist/tempo/session/client/SessionManager.d.ts.map +1 -1
  268. package/dist/tempo/session/client/SessionManager.js +62 -20
  269. package/dist/tempo/session/client/SessionManager.js.map +1 -1
  270. package/dist/tempo/session/client/Transports.d.ts +9 -1
  271. package/dist/tempo/session/client/Transports.d.ts.map +1 -1
  272. package/dist/tempo/session/client/Transports.js +36 -13
  273. package/dist/tempo/session/client/Transports.js.map +1 -1
  274. package/dist/tempo/session/precompile/Chain.d.ts +27 -0
  275. package/dist/tempo/session/precompile/Chain.d.ts.map +1 -1
  276. package/dist/tempo/session/precompile/Chain.js +68 -7
  277. package/dist/tempo/session/precompile/Chain.js.map +1 -1
  278. package/dist/tempo/session/precompile/Protocol.js.map +1 -1
  279. package/dist/tempo/session/precompile/Voucher.d.ts +4 -4
  280. package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -1
  281. package/dist/tempo/session/precompile/escrow.abi.d.ts +306 -306
  282. package/dist/tempo/session/precompile/escrow.abi.d.ts.map +1 -1
  283. package/dist/tempo/session/server/ChannelStore.d.ts +9 -0
  284. package/dist/tempo/session/server/ChannelStore.d.ts.map +1 -1
  285. package/dist/tempo/session/server/ChannelStore.js +16 -8
  286. package/dist/tempo/session/server/ChannelStore.js.map +1 -1
  287. package/dist/tempo/session/server/CredentialVerification.d.ts +30 -13
  288. package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -1
  289. package/dist/tempo/session/server/CredentialVerification.js +207 -13
  290. package/dist/tempo/session/server/CredentialVerification.js.map +1 -1
  291. package/dist/tempo/session/server/MeteredStream.d.ts +3 -0
  292. package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -1
  293. package/dist/tempo/session/server/MeteredStream.js +3 -1
  294. package/dist/tempo/session/server/MeteredStream.js.map +1 -1
  295. package/dist/tempo/session/server/Session.d.ts +32 -21
  296. package/dist/tempo/session/server/Session.d.ts.map +1 -1
  297. package/dist/tempo/session/server/Session.js +116 -53
  298. package/dist/tempo/session/server/Session.js.map +1 -1
  299. package/dist/tempo/session/server/Sse.d.ts +3 -1
  300. package/dist/tempo/session/server/Sse.d.ts.map +1 -1
  301. package/dist/tempo/session/server/Sse.js +2 -1
  302. package/dist/tempo/session/server/Sse.js.map +1 -1
  303. package/dist/tempo/session/server/Transports.d.ts +1 -1
  304. package/dist/tempo/session/server/Transports.d.ts.map +1 -1
  305. package/dist/tempo/session/server/Transports.js +1 -0
  306. package/dist/tempo/session/server/Transports.js.map +1 -1
  307. package/dist/tempo/session/server/Ws.d.ts +6 -1
  308. package/dist/tempo/session/server/Ws.d.ts.map +1 -1
  309. package/dist/tempo/session/server/Ws.js +4 -0
  310. package/dist/tempo/session/server/Ws.js.map +1 -1
  311. package/dist/tempo/subscription/KeyAuthorization.d.ts +38 -866
  312. package/dist/tempo/subscription/KeyAuthorization.d.ts.map +1 -1
  313. package/dist/tempo/subscription/KeyAuthorization.js +14 -3
  314. package/dist/tempo/subscription/KeyAuthorization.js.map +1 -1
  315. package/dist/viem/Account.d.ts.map +1 -1
  316. package/dist/viem/Account.js.map +1 -1
  317. package/dist/viem/Client.d.ts.map +1 -1
  318. package/dist/viem/Client.js +6 -1
  319. package/dist/viem/Client.js.map +1 -1
  320. package/dist/web-bot-auth/Constants.d.ts +20 -0
  321. package/dist/web-bot-auth/Constants.d.ts.map +1 -0
  322. package/dist/web-bot-auth/Constants.js +24 -0
  323. package/dist/web-bot-auth/Constants.js.map +1 -0
  324. package/dist/web-bot-auth/Types.d.ts +10 -0
  325. package/dist/web-bot-auth/Types.d.ts.map +1 -0
  326. package/dist/web-bot-auth/Types.js +2 -0
  327. package/dist/web-bot-auth/Types.js.map +1 -0
  328. package/dist/web-bot-auth/client/index.d.ts +29 -0
  329. package/dist/web-bot-auth/client/index.d.ts.map +1 -0
  330. package/dist/web-bot-auth/client/index.js +64 -0
  331. package/dist/web-bot-auth/client/index.js.map +1 -0
  332. package/dist/web-bot-auth/index.d.ts +7 -0
  333. package/dist/web-bot-auth/index.d.ts.map +1 -0
  334. package/dist/web-bot-auth/index.js +7 -0
  335. package/dist/web-bot-auth/index.js.map +1 -0
  336. package/dist/web-bot-auth/internal/JwkThumbprint.d.ts +5 -0
  337. package/dist/web-bot-auth/internal/JwkThumbprint.d.ts.map +1 -0
  338. package/dist/web-bot-auth/internal/JwkThumbprint.js +20 -0
  339. package/dist/web-bot-auth/internal/JwkThumbprint.js.map +1 -0
  340. package/dist/web-bot-auth/internal/SignatureAgent.d.ts +3 -0
  341. package/dist/web-bot-auth/internal/SignatureAgent.d.ts.map +1 -0
  342. package/dist/web-bot-auth/internal/SignatureAgent.js +18 -0
  343. package/dist/web-bot-auth/internal/SignatureAgent.js.map +1 -0
  344. package/dist/web-bot-auth/server/index.d.ts +35 -0
  345. package/dist/web-bot-auth/server/index.d.ts.map +1 -0
  346. package/dist/web-bot-auth/server/index.js +88 -0
  347. package/dist/web-bot-auth/server/index.js.map +1 -0
  348. package/dist/x402/Assets.d.ts.map +1 -1
  349. package/dist/x402/Types.d.ts +6 -6
  350. package/dist/x402/Types.d.ts.map +1 -1
  351. package/dist/x402/server/EvmCharge.d.ts.map +1 -1
  352. package/dist/x402/server/EvmCharge.js +32 -20
  353. package/dist/x402/server/EvmCharge.js.map +1 -1
  354. package/package.json +20 -4
  355. package/src/Challenge.fuzz.test.ts +80 -47
  356. package/src/Challenge.test.ts +65 -0
  357. package/src/Challenge.ts +39 -35
  358. package/src/Method.ts +82 -68
  359. package/src/Store.test-d.ts +16 -0
  360. package/src/Store.test.ts +50 -0
  361. package/src/Store.ts +68 -0
  362. package/src/attestation/Attestation.integration.test.ts +208 -0
  363. package/src/attestation/Client.test.ts +83 -0
  364. package/src/attestation/Client.ts +34 -0
  365. package/src/attestation/Constants.ts +15 -0
  366. package/src/attestation/Server.test.ts +60 -0
  367. package/src/attestation/Server.ts +12 -0
  368. package/src/attestation/Types.test-d.ts +54 -0
  369. package/src/attestation/Types.ts +77 -0
  370. package/src/attestation/index.ts +5 -0
  371. package/src/attestation/internal/HttpMessageSignature.test.ts +101 -0
  372. package/src/attestation/internal/HttpMessageSignature.ts +429 -0
  373. package/src/attestation/internal/SigningContext.ts +13 -0
  374. package/src/bin.js +2 -0
  375. package/src/cli/cli.ts +1 -0
  376. package/src/cli/validate/payment.ts +18 -4
  377. package/src/cli/validate.test.ts +16 -0
  378. package/src/client/Mppx.test-d.ts +17 -0
  379. package/src/client/Mppx.test.ts +14 -14
  380. package/src/client/Mppx.ts +25 -4
  381. package/src/client/Transport.test.ts +12 -45
  382. package/src/client/Transport.ts +3 -24
  383. package/src/client/internal/Fetch.test.ts +77 -0
  384. package/src/client/internal/Fetch.ts +112 -14
  385. package/src/client/internal/MethodChallenge.ts +5 -0
  386. package/src/client/internal/MethodResponse.ts +28 -0
  387. package/src/discovery/OpenApi.test.ts +170 -0
  388. package/src/discovery/OpenApi.ts +16 -48
  389. package/src/discovery/internal/Metadata.ts +51 -0
  390. package/src/evm/server/Charge.ts +6 -1
  391. package/src/internal/AcceptPayment.test.ts +12 -8
  392. package/src/internal/types.ts +9 -0
  393. package/src/mcp/client/McpClient.integration.test.ts +19 -32
  394. package/src/middlewares/elysia.test.ts +2 -12
  395. package/src/middlewares/express.test.ts +2 -12
  396. package/src/middlewares/hono.test.ts +6 -9
  397. package/src/middlewares/nextjs.test.ts +2 -12
  398. package/src/proxy/Proxy.test.ts +26 -19
  399. package/src/proxy/Proxy.ts +147 -9
  400. package/src/proxy/Proxy.upstreamError.test.ts +364 -0
  401. package/src/proxy/Service.test.ts +73 -3
  402. package/src/proxy/Service.ts +50 -23
  403. package/src/proxy/services/anthropic.ts +1 -0
  404. package/src/proxy/services/hooks.test-d.ts +14 -0
  405. package/src/proxy/services/hooks.test.ts +44 -0
  406. package/src/proxy/services/openai.ts +1 -0
  407. package/src/proxy/services/stripe.ts +1 -0
  408. package/src/server/Methods.test-d.ts +88 -0
  409. package/src/server/Methods.test.ts +69 -0
  410. package/src/server/Mppx.test-d.ts +141 -7
  411. package/src/server/Mppx.test.ts +1017 -119
  412. package/src/server/Mppx.ts +350 -54
  413. package/src/stripe/internal/constants.ts +1 -1
  414. package/src/stripe/internal/types.ts +1 -0
  415. package/src/stripe/server/Charge.test-d.ts +16 -1
  416. package/src/stripe/server/Charge.test.ts +79 -0
  417. package/src/stripe/server/Charge.ts +54 -1
  418. package/src/stripe/server/Methods.test-d.ts +157 -0
  419. package/src/stripe/server/Methods.test.ts +403 -0
  420. package/src/stripe/server/Methods.ts +423 -6
  421. package/src/stripe/server/internal/deposit-address.ts +57 -0
  422. package/src/stripe/server/internal/html/node_modules/.bin/mppx +3 -3
  423. package/src/stripe/server/internal/html/package.json +1 -1
  424. package/src/stripe/server/internal/html.gen.ts +1 -1
  425. package/src/stripe/server/internal/record-payment.ts +66 -0
  426. package/src/stripe/server/internal/request.ts +49 -0
  427. package/src/tap/Constants.ts +32 -0
  428. package/src/tap/Tap.test.ts +125 -0
  429. package/src/tap/Types.ts +11 -0
  430. package/src/tap/client/index.ts +54 -0
  431. package/src/tap/index.ts +4 -0
  432. package/src/tap/server/index.ts +48 -0
  433. package/src/tempo/PublicExports.test-d.ts +3 -3
  434. package/src/tempo/client/Charge.ts +1 -19
  435. package/src/tempo/internal/address.test.ts +42 -0
  436. package/src/tempo/internal/address.ts +3 -3
  437. package/src/tempo/internal/auto-swap.test.ts +4 -4
  438. package/src/tempo/internal/auto-swap.ts +7 -50
  439. package/src/tempo/legacy/README.md +5 -5
  440. package/src/tempo/legacy/index.ts +1 -3
  441. package/src/tempo/server/AtomicStore.test-d.ts +13 -0
  442. package/src/tempo/server/Charge.test.ts +19 -84
  443. package/src/tempo/server/Charge.ts +92 -56
  444. package/src/tempo/server/Methods.ts +0 -20
  445. package/src/tempo/server/Relay.test.ts +161 -7
  446. package/src/tempo/server/Relay.ts +15 -6
  447. package/src/tempo/server/SponsorBudget.test.ts +29 -0
  448. package/src/tempo/server/SponsorBudget.ts +7 -1
  449. package/src/tempo/server/Subscription.ts +4 -1
  450. package/src/tempo/server/index.ts +1 -1
  451. package/src/tempo/server/internal/html/node_modules/.bin/mppx +3 -3
  452. package/src/tempo/server/internal/html/package.json +1 -1
  453. package/src/tempo/server/internal/html.gen.ts +1 -1
  454. package/src/tempo/server/internal/transport.test.ts +22 -3
  455. package/src/tempo/server/internal/transport.ts +15 -3
  456. package/src/tempo/session/README.md +119 -0
  457. package/src/tempo/session/client/Session.test.ts +299 -33
  458. package/src/tempo/session/client/Session.ts +152 -16
  459. package/src/tempo/session/client/SessionManager.test.ts +216 -9
  460. package/src/tempo/session/client/SessionManager.ts +63 -17
  461. package/src/tempo/session/client/Transports.test.ts +22 -0
  462. package/src/tempo/session/client/Transports.ts +58 -22
  463. package/src/tempo/session/precompile/Chain.ts +131 -11
  464. package/src/tempo/session/server/ChannelStore.ts +33 -12
  465. package/src/tempo/session/server/CredentialVerification.test.ts +4 -4
  466. package/src/tempo/session/server/CredentialVerification.ts +340 -28
  467. package/src/tempo/session/server/MeteredStream.ts +5 -1
  468. package/src/tempo/session/server/Session.test.ts +483 -36
  469. package/src/tempo/session/server/Session.ts +159 -60
  470. package/src/tempo/session/server/Sse.test.ts +77 -0
  471. package/src/tempo/session/server/Sse.ts +8 -1
  472. package/src/tempo/session/server/Transports.ts +2 -1
  473. package/src/tempo/session/server/Ws.test.ts +171 -0
  474. package/src/tempo/session/server/Ws.ts +10 -1
  475. package/src/tempo/subscription/KeyAuthorization.test.ts +70 -1
  476. package/src/tempo/subscription/KeyAuthorization.ts +14 -3
  477. package/src/viem/Client.test.ts +18 -1
  478. package/src/viem/Client.ts +7 -1
  479. package/src/web-bot-auth/Constants.ts +24 -0
  480. package/src/web-bot-auth/Types.ts +9 -0
  481. package/src/web-bot-auth/WebBotAuth.test.ts +182 -0
  482. package/src/web-bot-auth/client/index.ts +84 -0
  483. package/src/web-bot-auth/index.ts +6 -0
  484. package/src/web-bot-auth/internal/JwkThumbprint.ts +21 -0
  485. package/src/web-bot-auth/internal/SignatureAgent.ts +18 -0
  486. package/src/web-bot-auth/server/index.ts +113 -0
  487. package/src/x402/Exact.e2e.test.ts +121 -81
  488. package/src/x402/Exact.localnet.test.ts +1 -1
  489. package/src/x402/server/EvmCharge.ts +35 -19
  490. package/dist/tempo/legacy/server/Session.d.ts +0 -208
  491. package/dist/tempo/legacy/server/Session.d.ts.map +0 -1
  492. package/dist/tempo/legacy/server/Session.js +0 -698
  493. package/dist/tempo/legacy/server/Session.js.map +0 -1
  494. package/dist/tempo/legacy/server/index.d.ts +0 -5
  495. package/dist/tempo/legacy/server/index.d.ts.map +0 -1
  496. package/dist/tempo/legacy/server/index.js +0 -5
  497. package/dist/tempo/legacy/server/index.js.map +0 -1
  498. package/dist/tempo/legacy/session/ChannelStore.d.ts +0 -22
  499. package/dist/tempo/legacy/session/ChannelStore.d.ts.map +0 -1
  500. package/dist/tempo/legacy/session/ChannelStore.js +0 -6
  501. package/dist/tempo/legacy/session/ChannelStore.js.map +0 -1
  502. package/src/tempo/legacy/server/Defaults.test-d.ts +0 -9
  503. package/src/tempo/legacy/server/Session.test.ts +0 -6370
  504. package/src/tempo/legacy/server/Session.ts +0 -1024
  505. package/src/tempo/legacy/server/index.ts +0 -4
  506. package/src/tempo/legacy/session/ChannelStore.test.ts +0 -58
  507. package/src/tempo/legacy/session/ChannelStore.ts +0 -39
@@ -0,0 +1,429 @@
1
+ import {
2
+ isInnerList,
3
+ parseDictionary,
4
+ serializeItem,
5
+ serializeDictionary,
6
+ serializeInnerList,
7
+ serializeParameters,
8
+ } from 'structured-headers'
9
+ import type { BareItem, Dictionary, InnerList, Item } from 'structured-headers'
10
+
11
+ import type { MaybePromise } from '../../internal/types.js'
12
+ import * as Store from '../../Store.js'
13
+ import { Algorithms, Headers as AttestationHeaders } from '../Constants.js'
14
+ import type { KeyResolver, SignatureAlgorithm, SigningContext } from '../Types.js'
15
+ import * as SigningContextInternal from './SigningContext.js'
16
+
17
+ /** RFC 9421 constants used by request-attestation signature profiles. */
18
+ export const Constants = {
19
+ /** Derived request components supported by this narrow request profile. */
20
+ components: {
21
+ /** The target host and non-default port. */
22
+ authority: '@authority',
23
+ /** The request URL path without its query string. */
24
+ path: '@path',
25
+ /** The lowercased `Signature-Agent` request header. */
26
+ signatureAgent: 'signature-agent',
27
+ /** The signature's canonicalized covered-components and parameters. */
28
+ signatureParams: '@signature-params',
29
+ },
30
+ } as const
31
+
32
+ const algorithmDescriptors = {
33
+ [Algorithms.ed25519]: {
34
+ hash: undefined,
35
+ keyAlgorithm: 'Ed25519',
36
+ webCryptoAlgorithm: 'Ed25519',
37
+ },
38
+ [Algorithms.rsaPssSha512]: {
39
+ hash: 'SHA-512',
40
+ keyAlgorithm: 'RSA-PSS',
41
+ webCryptoAlgorithm: { name: 'RSA-PSS', saltLength: 64 },
42
+ },
43
+ } as const satisfies Record<
44
+ SignatureAlgorithm,
45
+ {
46
+ hash: string | undefined
47
+ keyAlgorithm: string
48
+ webCryptoAlgorithm: AlgorithmIdentifier | RsaPssParams
49
+ }
50
+ >
51
+
52
+ /** A covered HTTP message component and its RFC 9421 component parameters. */
53
+ export type Component = {
54
+ /** Derived component identifier or lowercased HTTP field name. */
55
+ id: string
56
+ /** Parameters that qualify the component, such as `;key="agent"`. */
57
+ parameters?: ReadonlyMap<string, BareItem> | undefined
58
+ }
59
+
60
+ /** Input accepted by signers; bare strings denote unparameterized components. */
61
+ export type ComponentInput = string | Component
62
+
63
+ export type SignatureInput = {
64
+ algorithm: SignatureAlgorithm
65
+ components: readonly Component[]
66
+ created: number
67
+ expires: number
68
+ keyId: string
69
+ label: string
70
+ nonce: string
71
+ parameters: ReadonlyMap<string, BareItem>
72
+ tag: string
73
+ }
74
+
75
+ /** Result of validating one supported RFC 9421 signature. */
76
+ export type VerificationResult =
77
+ | { status: 'absent' }
78
+ | { status: 'invalid'; reason: string }
79
+ | { status: 'unverified'; reason: string }
80
+ | { status: 'verified'; input: SignatureInput }
81
+
82
+ /** Signs a request using the configured RFC 9421-derived component list. */
83
+ export async function sign(
84
+ request: Request,
85
+ options: {
86
+ components: readonly ComponentInput[]
87
+ expiresIn?: number | undefined
88
+ keyId: string
89
+ key: CryptoKey
90
+ label: string
91
+ context?: SigningContext | undefined
92
+ tag: string
93
+ },
94
+ ): Promise<Request> {
95
+ const context = options.context ?? SigningContextInternal.create()
96
+ const created = context.created
97
+ const expires = created + (options.expiresIn ?? 60)
98
+ const algorithm = algorithmFromKey(options.key)
99
+ const parameters = new Map<string, BareItem>([
100
+ ['created', created],
101
+ ['expires', expires],
102
+ ['keyid', options.keyId],
103
+ ['alg', algorithm],
104
+ ['nonce', context.nonce],
105
+ ['tag', options.tag],
106
+ ])
107
+ const input: SignatureInput = {
108
+ algorithm,
109
+ components: options.components.map(toComponent),
110
+ created,
111
+ expires,
112
+ keyId: options.keyId,
113
+ label: options.label,
114
+ nonce: context.nonce,
115
+ parameters,
116
+ tag: options.tag,
117
+ }
118
+ const signature = await crypto.subtle.sign(
119
+ webCryptoAlgorithm(algorithm),
120
+ options.key,
121
+ toArrayBuffer(encode(signatureBase(request, input))),
122
+ )
123
+ const headers = new Headers(request.headers)
124
+ const inputs = parseHeaderDictionary(headers, AttestationHeaders.signatureInput)
125
+ const signatures = parseHeaderDictionary(headers, AttestationHeaders.signature)
126
+ if (!haveSameKeys(inputs, signatures))
127
+ throw new Error('Signature-Input and Signature must contain the same labels.')
128
+ if (inputs.has(input.label) || signatures.has(input.label))
129
+ throw new Error(`HTTP message signature label "${input.label}" already exists.`)
130
+ inputs.set(input.label, toInnerList(input))
131
+ signatures.set(input.label, [signature, new Map()])
132
+ headers.set(AttestationHeaders.signatureInput, serializeDictionary(inputs))
133
+ headers.set(AttestationHeaders.signature, serializeDictionary(signatures))
134
+ return new Request(request, { headers })
135
+ }
136
+
137
+ /** Verifies a request signature, its lifetime, and optionally its nonce. */
138
+ export async function verify(
139
+ request: Request,
140
+ options: {
141
+ keyResolver: KeyResolver
142
+ maxAge: number
143
+ nonceNamespace: string
144
+ nonceStore: Store.AtomicStore
145
+ requiredComponents: readonly string[]
146
+ tag: string | readonly string[]
147
+ validate?: ((input: SignatureInput, request: Request) => string | undefined) | undefined
148
+ validateKey?:
149
+ | ((
150
+ key: CryptoKey,
151
+ input: SignatureInput,
152
+ request: Request,
153
+ ) => MaybePromise<string | undefined>)
154
+ | undefined
155
+ },
156
+ ): Promise<VerificationResult> {
157
+ const parsed = parse(request, options.tag)
158
+ if (!parsed) return { status: 'absent' }
159
+ if (parsed.reason) return { status: 'invalid', reason: parsed.reason }
160
+ if (!parsed.input || !parsed.signature)
161
+ return { status: 'invalid', reason: 'The HTTP message signature is malformed.' }
162
+ const { input, signature } = parsed
163
+
164
+ if (!options.requiredComponents.every((component) => hasComponent(input.components, component)))
165
+ return {
166
+ status: 'invalid',
167
+ reason: 'The signature does not cover the required request components.',
168
+ }
169
+ const now = Math.floor(Date.now() / 1000)
170
+ if (input.created > now || input.expires <= now || input.expires - input.created > options.maxAge)
171
+ return { status: 'invalid', reason: 'The signature is expired or has an invalid lifetime.' }
172
+ if (options.validate) {
173
+ const reason = options.validate(input, request)
174
+ if (reason) return { status: 'invalid', reason }
175
+ }
176
+ let key: CryptoKey | undefined
177
+ try {
178
+ key = await options.keyResolver({
179
+ algorithm: input.algorithm,
180
+ keyId: input.keyId,
181
+ request,
182
+ })
183
+ } catch {
184
+ return { status: 'unverified', reason: 'The public key could not be resolved.' }
185
+ }
186
+ if (!key)
187
+ return {
188
+ status: 'unverified',
189
+ reason: 'No public key is available for the signature key ID.',
190
+ }
191
+ if (!keySupportsAlgorithm(key, input.algorithm))
192
+ return {
193
+ status: 'invalid',
194
+ reason: 'The public key does not support the signature algorithm.',
195
+ }
196
+ if (options.validateKey) {
197
+ const reason = await options.validateKey(key, input, request)
198
+ if (reason) return { status: 'invalid', reason }
199
+ }
200
+ let valid: boolean
201
+ try {
202
+ valid = await crypto.subtle.verify(
203
+ webCryptoAlgorithm(input.algorithm),
204
+ key,
205
+ toArrayBuffer(signature),
206
+ toArrayBuffer(encode(signatureBase(request, input))),
207
+ )
208
+ } catch {
209
+ valid = false
210
+ }
211
+ if (!valid) return { status: 'invalid', reason: 'The HTTP message signature is invalid.' }
212
+ try {
213
+ if (
214
+ !(await Store.tryClaim(
215
+ options.nonceStore,
216
+ `${options.nonceNamespace}:${input.keyId}:${input.nonce}`,
217
+ input.expires * 1000,
218
+ ))
219
+ )
220
+ return { status: 'invalid', reason: 'The signature nonce has already been used.' }
221
+ } catch {
222
+ return { status: 'unverified', reason: 'Replay protection is unavailable.' }
223
+ }
224
+ return { status: 'verified', input }
225
+ }
226
+
227
+ function parse(
228
+ request: Request,
229
+ expectedTag: string | readonly string[],
230
+ ): { input?: SignatureInput; reason?: string; signature?: Uint8Array } | undefined {
231
+ const inputHeader = request.headers.get(AttestationHeaders.signatureInput)
232
+ const signatureHeader = request.headers.get(AttestationHeaders.signature)
233
+ if (!inputHeader && !signatureHeader) return undefined
234
+ if (!inputHeader || !signatureHeader)
235
+ return { reason: 'Signature-Input and Signature must both be provided.' }
236
+ let inputs: Dictionary
237
+ let signatures: Dictionary
238
+ try {
239
+ inputs = parseDictionary(inputHeader)
240
+ signatures = parseDictionary(signatureHeader)
241
+ } catch {
242
+ return { reason: 'The HTTP message signature is malformed.' }
243
+ }
244
+ if (!haveSameKeys(inputs, signatures))
245
+ return { reason: 'Signature-Input and Signature do not contain the same labels.' }
246
+ const tags = new Set(typeof expectedTag === 'string' ? [expectedTag] : expectedTag)
247
+ for (const [label, entry] of inputs) {
248
+ if (!hasExpectedTag(entry, tags)) continue
249
+ const input = toSignatureInput(label, entry)
250
+ if (!input) return { reason: 'The HTTP message signature is malformed.' }
251
+ const signature = signatures.get(label)
252
+ if (!signature || isInnerList(signature) || !(signature[0] instanceof ArrayBuffer))
253
+ return { reason: 'No matching HTTP message signature was provided.' }
254
+ return { input, signature: new Uint8Array(signature[0]) }
255
+ }
256
+ return undefined
257
+ }
258
+
259
+ function serializeInput(input: SignatureInput): string {
260
+ return serializeInnerList(toInnerList(input))
261
+ }
262
+
263
+ function toInnerList(input: SignatureInput): InnerList {
264
+ const components: InnerList[0] = input.components.map((component) => [
265
+ component.id,
266
+ new Map(component.parameters),
267
+ ])
268
+ return [components, new Map(input.parameters)]
269
+ }
270
+
271
+ function toSignatureInput(label: string, entry: unknown): SignatureInput | undefined {
272
+ const innerList = entry as InnerList
273
+ if (!isInnerList(innerList)) return undefined
274
+ const [componentEntries, parameters] = innerList
275
+ if (
276
+ !componentEntries.length ||
277
+ !componentEntries.every(([component]) => typeof component === 'string')
278
+ )
279
+ return undefined
280
+ const components = componentEntries.map(([id, parameters]) => ({
281
+ id: id as string,
282
+ parameters,
283
+ }))
284
+ const created = parameters.get('created')
285
+ const expires = parameters.get('expires')
286
+ const algorithm = parameters.get('alg')
287
+ const keyId = parameters.get('keyid')
288
+ const nonce = parameters.get('nonce')
289
+ const tag = parameters.get('tag')
290
+ if (
291
+ !isInteger(created) ||
292
+ !isInteger(expires) ||
293
+ !isSignatureAlgorithm(algorithm) ||
294
+ typeof keyId !== 'string' ||
295
+ typeof nonce !== 'string' ||
296
+ typeof tag !== 'string'
297
+ )
298
+ return undefined
299
+ return {
300
+ algorithm,
301
+ components,
302
+ created,
303
+ expires,
304
+ keyId,
305
+ label,
306
+ nonce,
307
+ parameters,
308
+ tag,
309
+ }
310
+ }
311
+
312
+ function algorithmFromKey(key: CryptoKey): SignatureAlgorithm {
313
+ for (const algorithm of Object.values(Algorithms))
314
+ if (keySupportsAlgorithm(key, algorithm)) return algorithm
315
+ throw new TypeError('Request attestation requires an Ed25519 or RSA-PSS SHA-512 signing key.')
316
+ }
317
+
318
+ function isInteger(value: unknown): value is number {
319
+ return typeof value === 'number' && Number.isInteger(value)
320
+ }
321
+
322
+ function isSignatureAlgorithm(value: unknown): value is SignatureAlgorithm {
323
+ return typeof value === 'string' && Object.hasOwn(algorithmDescriptors, value)
324
+ }
325
+
326
+ function keySupportsAlgorithm(key: CryptoKey, algorithm: SignatureAlgorithm): boolean {
327
+ const { hash, keyAlgorithm } = algorithmDescriptors[algorithm]
328
+ return (
329
+ key.algorithm.name === keyAlgorithm &&
330
+ (!hash || (key.algorithm as RsaHashedKeyAlgorithm).hash.name === hash)
331
+ )
332
+ }
333
+
334
+ function webCryptoAlgorithm(algorithm: SignatureAlgorithm): AlgorithmIdentifier | RsaPssParams {
335
+ return algorithmDescriptors[algorithm].webCryptoAlgorithm
336
+ }
337
+
338
+ function signatureBase(request: Request, input: SignatureInput): string {
339
+ const lines = input.components.map(
340
+ (component) => `${serializeComponent(component)}: ${componentValue(request, component)}`,
341
+ )
342
+ lines.push(`"${Constants.components.signatureParams}": ${serializeInput(input)}`)
343
+ return lines.join('\n')
344
+ }
345
+
346
+ function componentValue(request: Request, component: Component): string {
347
+ const url = new URL(request.url)
348
+ if (component.id === Constants.components.authority) {
349
+ if (component.parameters?.size) throw new Error('Unsupported parameters for "@authority".')
350
+ return url.host
351
+ }
352
+ if (component.id === Constants.components.path) {
353
+ if (component.parameters?.size) throw new Error('Unsupported parameters for "@path".')
354
+ return url.pathname
355
+ }
356
+ if (component.parameters?.size)
357
+ return componentDictionaryValue(request, component.id, component.parameters)
358
+ const value = request.headers.get(component.id)
359
+ if (value === null) throw new Error(`Missing signed HTTP header "${component.id}".`)
360
+ // RFC 9421 signs the serialized field value, not a Unicode-normalized string.
361
+ if (!/^[\x20-\x7e]*$/.test(value))
362
+ throw new Error(`Signed HTTP header "${component.id}" is not ASCII.`)
363
+ return value
364
+ }
365
+
366
+ function componentDictionaryValue(
367
+ request: Request,
368
+ component: string,
369
+ parameters: ReadonlyMap<string, BareItem>,
370
+ ): string {
371
+ const key = parameters.get('key')
372
+ if (typeof key !== 'string' || parameters.size !== 1)
373
+ throw new Error(`Unsupported parameters for signed HTTP header "${component}".`)
374
+ const value = request.headers.get(component)
375
+ if (value === null) throw new Error(`Missing signed HTTP header "${component}".`)
376
+ let dictionary: Dictionary
377
+ try {
378
+ dictionary = parseDictionary(value)
379
+ } catch {
380
+ throw new Error(`Signed HTTP header "${component}" is not a structured dictionary.`)
381
+ }
382
+ const member = dictionary.get(key)
383
+ if (!member || isInnerList(member))
384
+ throw new Error(`Signed HTTP header "${component}" has no member "${key}".`)
385
+ return serializeItem(member)
386
+ }
387
+
388
+ function hasComponent(components: readonly Component[], expected: string): boolean {
389
+ return components.some((component) => component.id === expected)
390
+ }
391
+
392
+ function haveSameKeys(left: Dictionary, right: Dictionary): boolean {
393
+ return left.size === right.size && [...left.keys()].every((key) => right.has(key))
394
+ }
395
+
396
+ function hasExpectedTag(entry: unknown, tags: ReadonlySet<string>): boolean {
397
+ const value = entry as Item | InnerList
398
+ if (!isInnerList(value)) return false
399
+ const tag = value[1].get('tag')
400
+ return typeof tag === 'string' && tags.has(tag)
401
+ }
402
+
403
+ function serializeComponent(component: Component): string {
404
+ return `"${component.id}"${component.parameters?.size ? serializeParameters(new Map(component.parameters)) : ''}`
405
+ }
406
+
407
+ function toComponent(component: ComponentInput): Component {
408
+ return typeof component === 'string'
409
+ ? { id: component }
410
+ : { id: component.id, parameters: component.parameters && new Map(component.parameters) }
411
+ }
412
+
413
+ function parseHeaderDictionary(headers: Headers, name: string): Dictionary {
414
+ const value = headers.get(name)
415
+ if (!value) return new Map()
416
+ try {
417
+ return parseDictionary(value)
418
+ } catch {
419
+ throw new Error(`HTTP header "${name}" is not a structured dictionary.`)
420
+ }
421
+ }
422
+
423
+ function encode(value: string): Uint8Array {
424
+ return new TextEncoder().encode(value)
425
+ }
426
+
427
+ function toArrayBuffer(value: Uint8Array): ArrayBuffer {
428
+ return value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength) as ArrayBuffer
429
+ }
@@ -0,0 +1,13 @@
1
+ import { Base64 } from 'ox'
2
+
3
+ import type * as Types from '../Types.js'
4
+
5
+ /** Creates the signing context for one outbound HTTP request attempt. */
6
+ export function create(): Types.SigningContext {
7
+ const bytes = new Uint8Array(64)
8
+ crypto.getRandomValues(bytes)
9
+ return Object.freeze({
10
+ created: Math.floor(Date.now() / 1_000),
11
+ nonce: Base64.fromBytes(bytes, { pad: false, url: true }),
12
+ })
13
+ }
package/src/bin.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/bin.js'
package/src/cli/cli.ts CHANGED
@@ -212,6 +212,7 @@ function findService(
212
212
  }
213
213
 
214
214
  const cli = Cli.create('mppx', {
215
+ mcp: { tools: { discovery: 'direct' } },
215
216
  version: packageJson.version,
216
217
  description: 'Make HTTP requests with automatic payment handling',
217
218
  usage: [{ suffix: '<url> [options]' }],
@@ -46,6 +46,20 @@ async function provisionAndPayTestnet(
46
46
  await Promise.all(hashes.map((hash) => waitForTransactionReceipt(client, { hash })))
47
47
  if (!silent) console.log(pc.dim(` Using wallet: ${account.address}`))
48
48
 
49
+ // The faucet tx receipt can land before the RPC's balance reads are
50
+ // consistent with it, so poll briefly for the funded balance to appear
51
+ // rather than racing straight into the charge.
52
+ const currency = (challenge.request as Record<string, unknown>).currency
53
+ if (typeof currency === 'string') {
54
+ for (let attempt = 0; attempt < 10; attempt++) {
55
+ const balance = await Actions.token
56
+ .getBalance(client, { account: account.address, token: currency as Address })
57
+ .catch(() => undefined)
58
+ if (balance && balance.amount > 0n) break
59
+ await new Promise((resolve) => setTimeout(resolve, 500))
60
+ }
61
+ }
62
+
49
63
  const methods = [...tempoMethods({ account })]
50
64
  return { methods }
51
65
  } catch (error) {
@@ -198,7 +212,7 @@ export async function validatePaymentFlow(
198
212
  const mppx = Mppx.create({ methods: provisioned.methods, polyfill: false })
199
213
  const cred = await mppx.createCredential(fakeResp)
200
214
  results.push(check('Payment: submitted', 'ephemeral testnet wallet'))
201
- return await sendAndValidateResponse(
215
+ await sendAndValidateResponse(
202
216
  results,
203
217
  url,
204
218
  endpoint,
@@ -210,17 +224,17 @@ export async function validatePaymentFlow(
210
224
  )
211
225
  } catch (error) {
212
226
  results.push(fail('Payment: create credential', (error as Error).message))
213
- return results
214
227
  }
215
228
  } else {
216
229
  results.push(
217
230
  fail('Payment: auto-provision wallet', 'Failed to create and fund testnet wallet'),
218
231
  )
219
- return results
220
232
  }
233
+ options.onResults?.(results)
221
234
  }
222
235
 
223
- // Try each challenge method (skip testnet challenge already handled above)
236
+ // Try each remaining challenge method (tempo testnet already handled above),
237
+ // so validate exercises every payment method the server offers, same as mainnet.
224
238
  const loaded = await loadConfig().catch(() => undefined)
225
239
  const isInteractive = options.interactive
226
240
  const stripeKey = process.env.MPPX_STRIPE_SECRET_KEY ?? resolveStripeKey(verbose)
@@ -707,6 +707,22 @@ describe('validate: multi-challenge', () => {
707
707
  const { output } = await serve(['validate', server.url])
708
708
  expect(output).toContain('Amount is valid integer string (Got: 1.50)')
709
709
  })
710
+
711
+ test("tempo doesn't block other testnet methods", { timeout: 15_000 }, async () => {
712
+ // makeChallenge() defaults to a tempo testnet challenge (chainId 42431),
713
+ // which takes the ephemeral-wallet fast path. That path used to return
714
+ // immediately, so a server offering evm/stripe alongside tempo would
715
+ // never have those methods exercised. It should now fall through and
716
+ // try them too, same as it does for tempo mainnet challenges.
717
+ const server = await multiChallengeServer([makeChallenge(), makeEvmChallenge()])
718
+ const { output } = await serve(['validate', server.url, '--outputJson', '--yes'])
719
+ const jsonStart = output.indexOf('{')
720
+ const jsonEnd = output.lastIndexOf('}')
721
+ const result = JSON.parse(output.slice(jsonStart, jsonEnd + 1))
722
+ const paymentLabels = result.endpoints[0].payment.map((r: { label: string }) => r.label)
723
+ expect(paymentLabels).toContain('Payment: submitted')
724
+ expect(paymentLabels.some((l: string) => l.includes('[evm]'))).toBe(true)
725
+ })
710
726
  })
711
727
 
712
728
  describe('validate: payment methods coverage', () => {
@@ -1,6 +1,7 @@
1
1
  import type { Account, Address } from 'viem'
2
2
  import { describe, expectTypeOf, test } from 'vp/test'
3
3
 
4
+ import type * as Attestation from '../attestation/Types.js'
4
5
  import * as Challenge from '../Challenge.js'
5
6
  import type * as Mcp from '../Mcp.js'
6
7
  import * as Method from '../Method.js'
@@ -73,6 +74,22 @@ describe('create.Config', () => {
73
74
  expectTypeOf(mppx.fetch).toBeFunction()
74
75
  })
75
76
 
77
+ test('accepts request attestation for HTTP transport only', () => {
78
+ const signer = {} as Attestation.Signer
79
+ const mppx = Mppx.create({
80
+ attestation: { webBotAuth: signer },
81
+ methods: [charge()],
82
+ })
83
+ expectTypeOf(mppx.fetch).toBeFunction()
84
+
85
+ Mppx.create({
86
+ // @ts-expect-error request attestation applies to HTTP transport only.
87
+ attestation: { webBotAuth: signer },
88
+ methods: [charge()],
89
+ transport: Transport.mcp(),
90
+ })
91
+ })
92
+
76
93
  test('paymentPreferences callback exposes typed method keys', () => {
77
94
  const mppx = Mppx.create({
78
95
  methods: [tempo({ account: {} as Account })],
@@ -151,29 +151,29 @@ describe('createCredential', () => {
151
151
  })
152
152
  }
153
153
 
154
- test('behavior: routes duplicate tempo/session client methods by sessionProtocol', async () => {
155
- const tip1034 = taggedSessionMethod(
156
- 'v2',
154
+ test('behavior: routes duplicate tempo/session client methods by challenge predicate', async () => {
155
+ const primary = taggedSessionMethod(
156
+ 'primary',
157
157
  ({ challenge }) =>
158
158
  (challenge.request.methodDetails as { sessionProtocol?: string } | undefined)
159
- ?.sessionProtocol === 'v2',
159
+ ?.sessionProtocol === 'primary',
160
160
  )
161
- const legacy = taggedSessionMethod('v1', ({ challenge }) => {
161
+ const fallback = taggedSessionMethod('fallback', ({ challenge }) => {
162
162
  const sessionProtocol = (
163
163
  challenge.request.methodDetails as { sessionProtocol?: string } | undefined
164
164
  )?.sessionProtocol
165
- return sessionProtocol === undefined || sessionProtocol === 'v1'
165
+ return sessionProtocol === undefined || sessionProtocol === 'fallback'
166
166
  })
167
- const mppx = Mppx.create({ polyfill: false, methods: [tip1034, legacy] })
167
+ const mppx = Mppx.create({ polyfill: false, methods: [primary, fallback] })
168
168
 
169
- const [newCredential, legacyCredential, oldCredential] = await Promise.all([
170
- mppx.createCredential(paymentRequiredResponse(sessionChallenge('new', 'v2'))),
171
- mppx.createCredential(paymentRequiredResponse(sessionChallenge('v1', 'v1'))),
172
- mppx.createCredential(paymentRequiredResponse(sessionChallenge('old'))),
169
+ const [primaryCredential, fallbackCredential, unmarkedCredential] = await Promise.all([
170
+ mppx.createCredential(paymentRequiredResponse(sessionChallenge('primary', 'primary'))),
171
+ mppx.createCredential(paymentRequiredResponse(sessionChallenge('fallback', 'fallback'))),
172
+ mppx.createCredential(paymentRequiredResponse(sessionChallenge('unmarked'))),
173
173
  ])
174
- expect(Credential.deserialize(newCredential).payload).toEqual({ tag: 'v2' })
175
- expect(Credential.deserialize(legacyCredential).payload).toEqual({ tag: 'v1' })
176
- expect(Credential.deserialize(oldCredential).payload).toEqual({ tag: 'v1' })
174
+ expect(Credential.deserialize(primaryCredential).payload).toEqual({ tag: 'primary' })
175
+ expect(Credential.deserialize(fallbackCredential).payload).toEqual({ tag: 'fallback' })
176
+ expect(Credential.deserialize(unmarkedCredential).payload).toEqual({ tag: 'fallback' })
177
177
  })
178
178
 
179
179
  test('behavior: rejects unknown tempo/session sessionProtocol', async () => {
@@ -1,3 +1,5 @@
1
+ import * as AttestationClient from '../attestation/Client.js'
2
+ import type * as Attestation from '../attestation/Types.js'
1
3
  import type * as Challenge from '../Challenge.js'
2
4
  import * as Expires from '../Expires.js'
3
5
  import * as AcceptPayment from '../internal/AcceptPayment.js'
@@ -100,6 +102,7 @@ export function create<
100
102
  >,
101
103
  >(config: create.Config<methods, transport>): Mppx<methods, transport> {
102
104
  const {
105
+ attestation,
103
106
  maxPaymentRetries,
104
107
  onChallenge,
105
108
  orderChallenges,
@@ -111,6 +114,9 @@ export function create<
111
114
  } = config
112
115
 
113
116
  const rawFetch = config.fetch ?? globalThis.fetch
117
+ const attestedFetch = attestation
118
+ ? createAttestedFetch(rawFetch, attestation as Attestation.SignerMap)
119
+ : rawFetch
114
120
  const methods = config.methods.flat() as unknown as FlattenMethods<methods>
115
121
  const acceptPayment = AcceptPayment.resolve(methods, config.paymentPreferences)
116
122
  const events = Fetch.createEventDispatcher<FlattenMethods<methods>, EventResponseOf<transport>>()
@@ -121,7 +127,7 @@ export function create<
121
127
  const config_fetch = {
122
128
  acceptPayment,
123
129
  acceptPaymentPolicy,
124
- ...(config.fetch && { fetch: config.fetch }),
130
+ ...((config.fetch || attestation) && { fetch: attestedFetch }),
125
131
  eventDispatcher: events,
126
132
  ...(maxPaymentRetries !== undefined && { maxPaymentRetries }),
127
133
  ...(resolvedOnChallenge && { onChallenge: resolvedOnChallenge }),
@@ -188,9 +194,7 @@ export function create<
188
194
  context?: unknown,
189
195
  options?: createCredential.Options<FlattenMethods<methods>>,
190
196
  ) {
191
- const challenges = transport.getChallenges
192
- ? await transport.getChallenges(response as never)
193
- : [await transport.getChallenge(response as never)]
197
+ const challenges = await transport.getChallenges(response as never)
194
198
  const preferences = resolveChallengePreferences(acceptPayment.entries, options?.acceptPayment)
195
199
 
196
200
  let challenge: Challenge.Challenge | undefined
@@ -287,6 +291,10 @@ export declare namespace create {
287
291
  methods extends Methods = Methods,
288
292
  transport extends Transport.AnyTransport = Transport.Transport,
289
293
  > = {
294
+ /** Request-attestation signers applied to every outbound HTTP attempt. */
295
+ attestation?: transport extends Transport.Transport<RequestInit, Response>
296
+ ? Attestation.SignerMap | undefined
297
+ : never
290
298
  /** Controls when `Accept-Payment` is injected. */
291
299
  acceptPaymentPolicy?: Fetch.from.Config['acceptPaymentPolicy'] | undefined
292
300
  /** Custom fetch function to wrap. Defaults to `globalThis.fetch`. */
@@ -315,6 +323,19 @@ export declare namespace create {
315
323
  }
316
324
  }
317
325
 
326
+ function createAttestedFetch(
327
+ fetch: typeof globalThis.fetch,
328
+ signers: Attestation.SignerMap,
329
+ ): typeof globalThis.fetch {
330
+ const values = Object.values(signers)
331
+ if (values.length === 0)
332
+ throw new TypeError('Mppx client attestation must configure at least one signer.')
333
+ return AttestationClient.wrapFetch(
334
+ fetch,
335
+ AttestationClient.composeSigners(...(values as [Attestation.Signer, ...Attestation.Signer[]])),
336
+ )
337
+ }
338
+
318
339
  /**
319
340
  * Union of all context types from all methods that have context schemas.
320
341
  * @internal