mppx 0.8.15 → 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 (464) hide show
  1. package/CHANGELOG.md +36 -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/client/Mppx.d.ts +3 -0
  66. package/dist/client/Mppx.d.ts.map +1 -1
  67. package/dist/client/Mppx.js +13 -5
  68. package/dist/client/Mppx.js.map +1 -1
  69. package/dist/client/Transport.d.ts +3 -5
  70. package/dist/client/Transport.d.ts.map +1 -1
  71. package/dist/client/Transport.js +1 -17
  72. package/dist/client/Transport.js.map +1 -1
  73. package/dist/client/internal/Fetch.d.ts.map +1 -1
  74. package/dist/client/internal/Fetch.js +2 -6
  75. package/dist/client/internal/Fetch.js.map +1 -1
  76. package/dist/client/node.js.map +1 -1
  77. package/dist/discovery/OpenApi.d.ts +3 -5
  78. package/dist/discovery/OpenApi.d.ts.map +1 -1
  79. package/dist/discovery/OpenApi.js +13 -34
  80. package/dist/discovery/OpenApi.js.map +1 -1
  81. package/dist/discovery/internal/Metadata.d.ts +20 -0
  82. package/dist/discovery/internal/Metadata.d.ts.map +1 -0
  83. package/dist/discovery/internal/Metadata.js +36 -0
  84. package/dist/discovery/internal/Metadata.js.map +1 -0
  85. package/dist/evm/Methods.d.ts +11 -11
  86. package/dist/evm/Methods.d.ts.map +1 -1
  87. package/dist/evm/Types.d.ts +17 -17
  88. package/dist/evm/Types.d.ts.map +1 -1
  89. package/dist/evm/client/Charge.d.ts +11 -11
  90. package/dist/evm/client/Methods.d.ts +11 -11
  91. package/dist/evm/server/Charge.d.ts +1 -1
  92. package/dist/evm/server/Charge.d.ts.map +1 -1
  93. package/dist/evm/server/Charge.js +2 -0
  94. package/dist/evm/server/Charge.js.map +1 -1
  95. package/dist/evm/server/Methods.d.ts +11 -11
  96. package/dist/internal/HeaderCodec.d.ts +2 -2
  97. package/dist/internal/HeaderCodec.d.ts.map +1 -1
  98. package/dist/internal/types.d.ts +6 -0
  99. package/dist/internal/types.d.ts.map +1 -1
  100. package/dist/middlewares/elysia.js.map +1 -1
  101. package/dist/middlewares/express.js.map +1 -1
  102. package/dist/middlewares/hono.js.map +1 -1
  103. package/dist/middlewares/nextjs.js.map +1 -1
  104. package/dist/proxy/Proxy.d.ts +2 -0
  105. package/dist/proxy/Proxy.d.ts.map +1 -1
  106. package/dist/proxy/Proxy.js +117 -9
  107. package/dist/proxy/Proxy.js.map +1 -1
  108. package/dist/proxy/Service.d.ts +36 -1
  109. package/dist/proxy/Service.d.ts.map +1 -1
  110. package/dist/proxy/Service.js +9 -8
  111. package/dist/proxy/Service.js.map +1 -1
  112. package/dist/proxy/services/anthropic.d.ts.map +1 -1
  113. package/dist/proxy/services/anthropic.js +1 -0
  114. package/dist/proxy/services/anthropic.js.map +1 -1
  115. package/dist/proxy/services/openai.d.ts.map +1 -1
  116. package/dist/proxy/services/openai.js +1 -0
  117. package/dist/proxy/services/openai.js.map +1 -1
  118. package/dist/proxy/services/stripe.d.ts.map +1 -1
  119. package/dist/proxy/services/stripe.js +1 -0
  120. package/dist/proxy/services/stripe.js.map +1 -1
  121. package/dist/server/Mppx.d.ts +75 -13
  122. package/dist/server/Mppx.d.ts.map +1 -1
  123. package/dist/server/Mppx.js +201 -23
  124. package/dist/server/Mppx.js.map +1 -1
  125. package/dist/server/internal/html/config.d.ts +9 -9
  126. package/dist/server/internal/html/config.d.ts.map +1 -1
  127. package/dist/server/internal/html/constants.d.ts +17 -17
  128. package/dist/server/internal/html/constants.d.ts.map +1 -1
  129. package/dist/stripe/Methods.d.ts +10 -10
  130. package/dist/stripe/Methods.d.ts.map +1 -1
  131. package/dist/stripe/client/Charge.d.ts +10 -10
  132. package/dist/stripe/client/Methods.d.ts +10 -10
  133. package/dist/stripe/internal/constants.d.ts +1 -1
  134. package/dist/stripe/internal/constants.js +1 -1
  135. package/dist/stripe/internal/types.d.ts +1 -0
  136. package/dist/stripe/internal/types.d.ts.map +1 -1
  137. package/dist/stripe/server/Charge.d.ts +11 -11
  138. package/dist/stripe/server/Charge.d.ts.map +1 -1
  139. package/dist/stripe/server/Charge.js +49 -1
  140. package/dist/stripe/server/Charge.js.map +1 -1
  141. package/dist/stripe/server/Methods.d.ts +137 -48
  142. package/dist/stripe/server/Methods.d.ts.map +1 -1
  143. package/dist/stripe/server/Methods.js +259 -4
  144. package/dist/stripe/server/Methods.js.map +1 -1
  145. package/dist/stripe/server/internal/deposit-address.d.ts +13 -0
  146. package/dist/stripe/server/internal/deposit-address.d.ts.map +1 -0
  147. package/dist/stripe/server/internal/deposit-address.js +28 -0
  148. package/dist/stripe/server/internal/deposit-address.js.map +1 -0
  149. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  150. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
  151. package/dist/stripe/server/internal/html.gen.js +1 -1
  152. package/dist/stripe/server/internal/html.gen.js.map +1 -1
  153. package/dist/stripe/server/internal/record-payment.d.ts +15 -0
  154. package/dist/stripe/server/internal/record-payment.d.ts.map +1 -0
  155. package/dist/stripe/server/internal/record-payment.js +42 -0
  156. package/dist/stripe/server/internal/record-payment.js.map +1 -0
  157. package/dist/stripe/server/internal/request.d.ts +25 -0
  158. package/dist/stripe/server/internal/request.d.ts.map +1 -0
  159. package/dist/stripe/server/internal/request.js +29 -0
  160. package/dist/stripe/server/internal/request.js.map +1 -0
  161. package/dist/tap/Constants.d.ts +28 -0
  162. package/dist/tap/Constants.d.ts.map +1 -0
  163. package/dist/tap/Constants.js +32 -0
  164. package/dist/tap/Constants.js.map +1 -0
  165. package/dist/tap/Types.d.ts +11 -0
  166. package/dist/tap/Types.d.ts.map +1 -0
  167. package/dist/tap/Types.js +2 -0
  168. package/dist/tap/Types.js.map +1 -0
  169. package/dist/tap/client/index.d.ts +26 -0
  170. package/dist/tap/client/index.d.ts.map +1 -0
  171. package/dist/tap/client/index.js +33 -0
  172. package/dist/tap/client/index.js.map +1 -0
  173. package/dist/tap/index.d.ts +5 -0
  174. package/dist/tap/index.d.ts.map +1 -0
  175. package/dist/tap/index.js +5 -0
  176. package/dist/tap/index.js.map +1 -0
  177. package/dist/tap/server/index.d.ts +20 -0
  178. package/dist/tap/server/index.d.ts.map +1 -0
  179. package/dist/tap/server/index.js +36 -0
  180. package/dist/tap/server/index.js.map +1 -0
  181. package/dist/tempo/Attribution.d.ts +1 -1
  182. package/dist/tempo/Methods.d.ts +60 -60
  183. package/dist/tempo/Methods.d.ts.map +1 -1
  184. package/dist/tempo/Proof.d.ts +16 -16
  185. package/dist/tempo/client/Charge.d.ts +19 -19
  186. package/dist/tempo/client/Charge.d.ts.map +1 -1
  187. package/dist/tempo/client/Charge.js +1 -7
  188. package/dist/tempo/client/Charge.js.map +1 -1
  189. package/dist/tempo/client/Methods.d.ts +38 -38
  190. package/dist/tempo/client/Methods.js.map +1 -1
  191. package/dist/tempo/client/Subscription.d.ts +23 -23
  192. package/dist/tempo/client/Subscription.js.map +1 -1
  193. package/dist/tempo/internal/address.d.ts +2 -1
  194. package/dist/tempo/internal/address.d.ts.map +1 -1
  195. package/dist/tempo/internal/address.js +3 -1
  196. package/dist/tempo/internal/address.js.map +1 -1
  197. package/dist/tempo/internal/auto-swap.d.ts.map +1 -1
  198. package/dist/tempo/internal/auto-swap.js +4 -19
  199. package/dist/tempo/internal/auto-swap.js.map +1 -1
  200. package/dist/tempo/internal/defaults.d.ts +6 -6
  201. package/dist/tempo/internal/defaults.d.ts.map +1 -1
  202. package/dist/tempo/internal/fee-payer.d.ts +12 -12
  203. package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
  204. package/dist/tempo/internal/fee-payer.js.map +1 -1
  205. package/dist/tempo/internal/proof.d.ts +17 -17
  206. package/dist/tempo/internal/proof.d.ts.map +1 -1
  207. package/dist/tempo/legacy/client/Session.d.ts +20 -20
  208. package/dist/tempo/legacy/client/Session.js.map +1 -1
  209. package/dist/tempo/legacy/client/SessionManager.js.map +1 -1
  210. package/dist/tempo/legacy/index.d.ts +1 -3
  211. package/dist/tempo/legacy/index.d.ts.map +1 -1
  212. package/dist/tempo/legacy/index.js +1 -3
  213. package/dist/tempo/legacy/index.js.map +1 -1
  214. package/dist/tempo/legacy/session/escrow.abi.d.ts +374 -374
  215. package/dist/tempo/legacy/session/escrow.abi.d.ts.map +1 -1
  216. package/dist/tempo/server/Charge.d.ts +25 -11
  217. package/dist/tempo/server/Charge.d.ts.map +1 -1
  218. package/dist/tempo/server/Charge.js +44 -39
  219. package/dist/tempo/server/Charge.js.map +1 -1
  220. package/dist/tempo/server/Methods.d.ts +37 -52
  221. package/dist/tempo/server/Methods.d.ts.map +1 -1
  222. package/dist/tempo/server/Methods.js +0 -14
  223. package/dist/tempo/server/Methods.js.map +1 -1
  224. package/dist/tempo/server/Relay.d.ts +1 -1
  225. package/dist/tempo/server/Relay.d.ts.map +1 -1
  226. package/dist/tempo/server/Relay.js +2 -2
  227. package/dist/tempo/server/Relay.js.map +1 -1
  228. package/dist/tempo/server/Subscription.d.ts +25 -25
  229. package/dist/tempo/server/Subscription.d.ts.map +1 -1
  230. package/dist/tempo/server/Subscription.js +2 -0
  231. package/dist/tempo/server/Subscription.js.map +1 -1
  232. package/dist/tempo/server/index.d.ts +1 -1
  233. package/dist/tempo/server/index.d.ts.map +1 -1
  234. package/dist/tempo/server/index.js +1 -1
  235. package/dist/tempo/server/index.js.map +1 -1
  236. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  237. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  238. package/dist/tempo/server/internal/html.gen.js +1 -1
  239. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  240. package/dist/tempo/server/internal/transport.d.ts +2 -0
  241. package/dist/tempo/server/internal/transport.d.ts.map +1 -1
  242. package/dist/tempo/server/internal/transport.js +9 -2
  243. package/dist/tempo/server/internal/transport.js.map +1 -1
  244. package/dist/tempo/session/client/ChannelOps.js.map +1 -1
  245. package/dist/tempo/session/client/CredentialState.d.ts +1 -1
  246. package/dist/tempo/session/client/CredentialState.js.map +1 -1
  247. package/dist/tempo/session/client/ReceiptCoordinator.js.map +1 -1
  248. package/dist/tempo/session/client/Runtime.js.map +1 -1
  249. package/dist/tempo/session/client/Session.d.ts +19 -19
  250. package/dist/tempo/session/client/Session.js.map +1 -1
  251. package/dist/tempo/session/client/SessionManager.js.map +1 -1
  252. package/dist/tempo/session/client/Transports.d.ts.map +1 -1
  253. package/dist/tempo/session/precompile/Chain.d.ts +27 -0
  254. package/dist/tempo/session/precompile/Chain.d.ts.map +1 -1
  255. package/dist/tempo/session/precompile/Chain.js +68 -7
  256. package/dist/tempo/session/precompile/Chain.js.map +1 -1
  257. package/dist/tempo/session/precompile/Protocol.js.map +1 -1
  258. package/dist/tempo/session/precompile/Voucher.d.ts +4 -4
  259. package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -1
  260. package/dist/tempo/session/precompile/escrow.abi.d.ts +306 -306
  261. package/dist/tempo/session/precompile/escrow.abi.d.ts.map +1 -1
  262. package/dist/tempo/session/server/ChannelStore.d.ts +9 -0
  263. package/dist/tempo/session/server/ChannelStore.d.ts.map +1 -1
  264. package/dist/tempo/session/server/ChannelStore.js +16 -8
  265. package/dist/tempo/session/server/ChannelStore.js.map +1 -1
  266. package/dist/tempo/session/server/CredentialVerification.d.ts +30 -13
  267. package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -1
  268. package/dist/tempo/session/server/CredentialVerification.js +207 -13
  269. package/dist/tempo/session/server/CredentialVerification.js.map +1 -1
  270. package/dist/tempo/session/server/MeteredStream.d.ts +3 -0
  271. package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -1
  272. package/dist/tempo/session/server/MeteredStream.js +3 -1
  273. package/dist/tempo/session/server/MeteredStream.js.map +1 -1
  274. package/dist/tempo/session/server/Session.d.ts +32 -21
  275. package/dist/tempo/session/server/Session.d.ts.map +1 -1
  276. package/dist/tempo/session/server/Session.js +116 -53
  277. package/dist/tempo/session/server/Session.js.map +1 -1
  278. package/dist/tempo/session/server/Sse.d.ts +3 -1
  279. package/dist/tempo/session/server/Sse.d.ts.map +1 -1
  280. package/dist/tempo/session/server/Sse.js +2 -1
  281. package/dist/tempo/session/server/Sse.js.map +1 -1
  282. package/dist/tempo/session/server/Transports.d.ts +1 -1
  283. package/dist/tempo/session/server/Transports.d.ts.map +1 -1
  284. package/dist/tempo/session/server/Transports.js +1 -0
  285. package/dist/tempo/session/server/Transports.js.map +1 -1
  286. package/dist/tempo/session/server/Ws.d.ts +6 -1
  287. package/dist/tempo/session/server/Ws.d.ts.map +1 -1
  288. package/dist/tempo/session/server/Ws.js +1 -0
  289. package/dist/tempo/session/server/Ws.js.map +1 -1
  290. package/dist/tempo/subscription/KeyAuthorization.d.ts +39 -39
  291. package/dist/tempo/subscription/KeyAuthorization.d.ts.map +1 -1
  292. package/dist/viem/Account.d.ts.map +1 -1
  293. package/dist/viem/Account.js.map +1 -1
  294. package/dist/web-bot-auth/Constants.d.ts +20 -0
  295. package/dist/web-bot-auth/Constants.d.ts.map +1 -0
  296. package/dist/web-bot-auth/Constants.js +24 -0
  297. package/dist/web-bot-auth/Constants.js.map +1 -0
  298. package/dist/web-bot-auth/Types.d.ts +10 -0
  299. package/dist/web-bot-auth/Types.d.ts.map +1 -0
  300. package/dist/web-bot-auth/Types.js +2 -0
  301. package/dist/web-bot-auth/Types.js.map +1 -0
  302. package/dist/web-bot-auth/client/index.d.ts +29 -0
  303. package/dist/web-bot-auth/client/index.d.ts.map +1 -0
  304. package/dist/web-bot-auth/client/index.js +64 -0
  305. package/dist/web-bot-auth/client/index.js.map +1 -0
  306. package/dist/web-bot-auth/index.d.ts +7 -0
  307. package/dist/web-bot-auth/index.d.ts.map +1 -0
  308. package/dist/web-bot-auth/index.js +7 -0
  309. package/dist/web-bot-auth/index.js.map +1 -0
  310. package/dist/web-bot-auth/internal/JwkThumbprint.d.ts +5 -0
  311. package/dist/web-bot-auth/internal/JwkThumbprint.d.ts.map +1 -0
  312. package/dist/web-bot-auth/internal/JwkThumbprint.js +20 -0
  313. package/dist/web-bot-auth/internal/JwkThumbprint.js.map +1 -0
  314. package/dist/web-bot-auth/internal/SignatureAgent.d.ts +3 -0
  315. package/dist/web-bot-auth/internal/SignatureAgent.d.ts.map +1 -0
  316. package/dist/web-bot-auth/internal/SignatureAgent.js +18 -0
  317. package/dist/web-bot-auth/internal/SignatureAgent.js.map +1 -0
  318. package/dist/web-bot-auth/server/index.d.ts +35 -0
  319. package/dist/web-bot-auth/server/index.d.ts.map +1 -0
  320. package/dist/web-bot-auth/server/index.js +88 -0
  321. package/dist/web-bot-auth/server/index.js.map +1 -0
  322. package/dist/x402/Assets.d.ts.map +1 -1
  323. package/dist/x402/Types.d.ts +6 -6
  324. package/dist/x402/Types.d.ts.map +1 -1
  325. package/dist/x402/server/EvmCharge.d.ts.map +1 -1
  326. package/dist/x402/server/EvmCharge.js +32 -20
  327. package/dist/x402/server/EvmCharge.js.map +1 -1
  328. package/package.json +19 -3
  329. package/src/Challenge.fuzz.test.ts +80 -47
  330. package/src/Challenge.test.ts +65 -0
  331. package/src/Challenge.ts +39 -35
  332. package/src/Method.ts +82 -68
  333. package/src/Store.test-d.ts +16 -0
  334. package/src/Store.test.ts +50 -0
  335. package/src/Store.ts +68 -0
  336. package/src/attestation/Attestation.integration.test.ts +208 -0
  337. package/src/attestation/Client.test.ts +83 -0
  338. package/src/attestation/Client.ts +34 -0
  339. package/src/attestation/Constants.ts +15 -0
  340. package/src/attestation/Server.test.ts +60 -0
  341. package/src/attestation/Server.ts +12 -0
  342. package/src/attestation/Types.test-d.ts +54 -0
  343. package/src/attestation/Types.ts +77 -0
  344. package/src/attestation/index.ts +5 -0
  345. package/src/attestation/internal/HttpMessageSignature.test.ts +101 -0
  346. package/src/attestation/internal/HttpMessageSignature.ts +429 -0
  347. package/src/attestation/internal/SigningContext.ts +13 -0
  348. package/src/bin.js +2 -0
  349. package/src/cli/cli.ts +1 -0
  350. package/src/client/Mppx.test-d.ts +17 -0
  351. package/src/client/Mppx.test.ts +14 -14
  352. package/src/client/Mppx.ts +25 -4
  353. package/src/client/Transport.test.ts +12 -45
  354. package/src/client/Transport.ts +3 -24
  355. package/src/client/internal/Fetch.ts +2 -6
  356. package/src/discovery/OpenApi.test.ts +170 -0
  357. package/src/discovery/OpenApi.ts +16 -48
  358. package/src/discovery/internal/Metadata.ts +51 -0
  359. package/src/evm/server/Charge.ts +6 -1
  360. package/src/internal/AcceptPayment.test.ts +12 -8
  361. package/src/internal/types.ts +9 -0
  362. package/src/mcp/client/McpClient.integration.test.ts +19 -32
  363. package/src/middlewares/elysia.test.ts +2 -12
  364. package/src/middlewares/express.test.ts +2 -12
  365. package/src/middlewares/hono.test.ts +6 -9
  366. package/src/middlewares/nextjs.test.ts +2 -12
  367. package/src/proxy/Proxy.test.ts +26 -19
  368. package/src/proxy/Proxy.ts +147 -9
  369. package/src/proxy/Proxy.upstreamError.test.ts +364 -0
  370. package/src/proxy/Service.test.ts +73 -3
  371. package/src/proxy/Service.ts +50 -23
  372. package/src/proxy/services/anthropic.ts +1 -0
  373. package/src/proxy/services/hooks.test-d.ts +14 -0
  374. package/src/proxy/services/hooks.test.ts +44 -0
  375. package/src/proxy/services/openai.ts +1 -0
  376. package/src/proxy/services/stripe.ts +1 -0
  377. package/src/server/Methods.test-d.ts +88 -0
  378. package/src/server/Methods.test.ts +69 -0
  379. package/src/server/Mppx.test-d.ts +141 -7
  380. package/src/server/Mppx.test.ts +1017 -119
  381. package/src/server/Mppx.ts +350 -54
  382. package/src/stripe/internal/constants.ts +1 -1
  383. package/src/stripe/internal/types.ts +1 -0
  384. package/src/stripe/server/Charge.test-d.ts +16 -1
  385. package/src/stripe/server/Charge.test.ts +79 -0
  386. package/src/stripe/server/Charge.ts +54 -1
  387. package/src/stripe/server/Methods.test-d.ts +157 -0
  388. package/src/stripe/server/Methods.test.ts +403 -0
  389. package/src/stripe/server/Methods.ts +423 -6
  390. package/src/stripe/server/internal/deposit-address.ts +57 -0
  391. package/src/stripe/server/internal/html/node_modules/.bin/mppx +3 -3
  392. package/src/stripe/server/internal/html/package.json +1 -1
  393. package/src/stripe/server/internal/html.gen.ts +1 -1
  394. package/src/stripe/server/internal/record-payment.ts +66 -0
  395. package/src/stripe/server/internal/request.ts +49 -0
  396. package/src/tap/Constants.ts +32 -0
  397. package/src/tap/Tap.test.ts +125 -0
  398. package/src/tap/Types.ts +11 -0
  399. package/src/tap/client/index.ts +54 -0
  400. package/src/tap/index.ts +4 -0
  401. package/src/tap/server/index.ts +48 -0
  402. package/src/tempo/PublicExports.test-d.ts +3 -3
  403. package/src/tempo/client/Charge.ts +1 -19
  404. package/src/tempo/internal/address.test.ts +42 -0
  405. package/src/tempo/internal/address.ts +3 -3
  406. package/src/tempo/internal/auto-swap.test.ts +4 -4
  407. package/src/tempo/internal/auto-swap.ts +7 -50
  408. package/src/tempo/legacy/README.md +5 -5
  409. package/src/tempo/legacy/index.ts +1 -3
  410. package/src/tempo/server/AtomicStore.test-d.ts +13 -0
  411. package/src/tempo/server/Charge.test.ts +19 -84
  412. package/src/tempo/server/Charge.ts +83 -55
  413. package/src/tempo/server/Methods.ts +0 -20
  414. package/src/tempo/server/Relay.test.ts +5 -5
  415. package/src/tempo/server/Relay.ts +2 -2
  416. package/src/tempo/server/Subscription.ts +4 -1
  417. package/src/tempo/server/index.ts +1 -1
  418. package/src/tempo/server/internal/html/node_modules/.bin/mppx +3 -3
  419. package/src/tempo/server/internal/html/package.json +1 -1
  420. package/src/tempo/server/internal/html.gen.ts +1 -1
  421. package/src/tempo/server/internal/transport.test.ts +22 -3
  422. package/src/tempo/server/internal/transport.ts +15 -3
  423. package/src/tempo/session/README.md +112 -0
  424. package/src/tempo/session/precompile/Chain.ts +131 -11
  425. package/src/tempo/session/server/ChannelStore.ts +33 -12
  426. package/src/tempo/session/server/CredentialVerification.test.ts +4 -4
  427. package/src/tempo/session/server/CredentialVerification.ts +340 -28
  428. package/src/tempo/session/server/MeteredStream.ts +5 -1
  429. package/src/tempo/session/server/Session.test.ts +428 -43
  430. package/src/tempo/session/server/Session.ts +159 -60
  431. package/src/tempo/session/server/Sse.test.ts +77 -0
  432. package/src/tempo/session/server/Sse.ts +8 -1
  433. package/src/tempo/session/server/Transports.ts +2 -1
  434. package/src/tempo/session/server/Ws.test.ts +171 -0
  435. package/src/tempo/session/server/Ws.ts +7 -1
  436. package/src/web-bot-auth/Constants.ts +24 -0
  437. package/src/web-bot-auth/Types.ts +9 -0
  438. package/src/web-bot-auth/WebBotAuth.test.ts +182 -0
  439. package/src/web-bot-auth/client/index.ts +84 -0
  440. package/src/web-bot-auth/index.ts +6 -0
  441. package/src/web-bot-auth/internal/JwkThumbprint.ts +21 -0
  442. package/src/web-bot-auth/internal/SignatureAgent.ts +18 -0
  443. package/src/web-bot-auth/server/index.ts +113 -0
  444. package/src/x402/Exact.e2e.test.ts +121 -81
  445. package/src/x402/Exact.localnet.test.ts +1 -1
  446. package/src/x402/server/EvmCharge.ts +35 -19
  447. package/dist/tempo/legacy/server/Session.d.ts +0 -208
  448. package/dist/tempo/legacy/server/Session.d.ts.map +0 -1
  449. package/dist/tempo/legacy/server/Session.js +0 -698
  450. package/dist/tempo/legacy/server/Session.js.map +0 -1
  451. package/dist/tempo/legacy/server/index.d.ts +0 -5
  452. package/dist/tempo/legacy/server/index.d.ts.map +0 -1
  453. package/dist/tempo/legacy/server/index.js +0 -5
  454. package/dist/tempo/legacy/server/index.js.map +0 -1
  455. package/dist/tempo/legacy/session/ChannelStore.d.ts +0 -22
  456. package/dist/tempo/legacy/session/ChannelStore.d.ts.map +0 -1
  457. package/dist/tempo/legacy/session/ChannelStore.js +0 -6
  458. package/dist/tempo/legacy/session/ChannelStore.js.map +0 -1
  459. package/src/tempo/legacy/server/Defaults.test-d.ts +0 -9
  460. package/src/tempo/legacy/server/Session.test.ts +0 -6370
  461. package/src/tempo/legacy/server/Session.ts +0 -1024
  462. package/src/tempo/legacy/server/index.ts +0 -4
  463. package/src/tempo/legacy/session/ChannelStore.test.ts +0 -58
  464. package/src/tempo/legacy/session/ChannelStore.ts +0 -39
@@ -6,20 +6,22 @@ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/
6
6
  import { createMcpExpressApp } from '@modelcontextprotocol/sdk/server/express.js'
7
7
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
8
8
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
9
- import { sessionLegacy as tempo_session_client, tempo as tempo_client } from 'mppx/client'
9
+ import { session as tempo_session_client, tempo as tempo_client } from 'mppx/client'
10
10
  import { Mppx as Mppx_server, tempo as tempo_server } from 'mppx/server'
11
11
  import type { Address } from 'viem'
12
12
  import { readContract } from 'viem/actions'
13
13
  import { Actions, Addresses } from 'viem/tempo'
14
14
  import { beforeAll, describe, expect, test } from 'vp/test'
15
15
  import { tempoNetwork } from '~test/config.js'
16
- import { deployEscrow, signTopUpChannel } from '~test/tempo/legacy/session.js'
17
16
  import { accounts, asset, client as testClient, fundAccount } from '~test/tempo/viem.js'
18
17
 
19
18
  import * as Credential from '../../Credential.js'
20
19
  import * as core_Mcp from '../../Mcp.js'
21
20
  import * as Store from '../../Store.js'
22
- import type { SessionReceipt } from '../../tempo/session/precompile/Protocol.js'
21
+ import type {
22
+ SessionCredentialPayload,
23
+ SessionReceipt,
24
+ } from '../../tempo/session/precompile/Protocol.js'
23
25
  import * as ChannelStore from '../../tempo/session/server/ChannelStore.js'
24
26
  import * as McpServer_transport from '../server/Transport.js'
25
27
  import * as McpClient from './McpClient.js'
@@ -31,21 +33,11 @@ const doubleSessionAmountRaw = chargeAmountRaw * 2n
31
33
  const topUpAmountRaw = chargeAmountRaw * 3n
32
34
  const isLocalnet = tempoNetwork === 'localnet'
33
35
 
34
- let escrowContract: Address
35
-
36
- // TODO: Remove once the minimum viem version is >=2.54.0, which uses client-first Tempo call builders.
37
36
  function tokenGetBalanceCall(parameters: { account: Address; token: Address }) {
38
- const call = Actions.token.getBalance.call as unknown as {
39
- length: number
40
- (parameters: { account: Address; token: Address }): unknown
41
- (client: unknown, parameters: { account: Address; token: Address }): unknown
42
- }
43
- if (call.length >= 2) return call(testClient, parameters)
44
- return call(parameters)
37
+ return Actions.token.getBalance.call(testClient, parameters)
45
38
  }
46
39
 
47
40
  beforeAll(async () => {
48
- escrowContract = await deployEscrow()
49
41
  await fundAccount({ address: accounts[4].address, token: Addresses.pathUsd })
50
42
  await fundAccount({ address: accounts[4].address, token: asset })
51
43
  await fundAccount({ address: accounts[2].address, token: Addresses.pathUsd })
@@ -171,6 +163,7 @@ describe.runIf(isLocalnet)('McpClient.wrap integration', () => {
171
163
  action: 'voucher',
172
164
  channelId: openReceipt!.channelId,
173
165
  cumulativeAmountRaw: replayedCumulativeRaw,
166
+ descriptor: credentialDescriptor(openCredential),
174
167
  },
175
168
  })
176
169
  const firstVoucher = await callToolWithCredential(
@@ -236,7 +229,7 @@ describe.runIf(isLocalnet)('McpClient.wrap integration', () => {
236
229
  {
237
230
  name: 'session intent can top up a live MCP channel and continue metering on the same channel',
238
231
  sessionFeePayer: true,
239
- sessionMaxDeposit: '2',
232
+ sessionMaxDeposit: '5',
240
233
  async run(harness: Harness) {
241
234
  const openChallenge = await getPaymentChallenge(harness.sdkClient, 'session_tool')
242
235
  const openCredential = await harness.sessionMethod.createCredential({
@@ -269,14 +262,6 @@ describe.runIf(isLocalnet)('McpClient.wrap integration', () => {
269
262
  expect(meteredReceipt?.channelId).toBe(openReceipt?.channelId)
270
263
  expect(meteredReceipt?.acceptedCumulative).toBe((chargeAmountRaw * 2n).toString())
271
264
 
272
- const { serializedTransaction } = await signTopUpChannel({
273
- escrow: escrowContract,
274
- feePayer: true,
275
- payer: accounts[2],
276
- channelId: openReceipt!.channelId,
277
- token: asset,
278
- amount: topUpAmountRaw,
279
- })
280
265
  const topUpChallenge = await getPaymentChallenge(harness.sdkClient, 'session_tool')
281
266
  const topUpCredential = await harness.sessionMethod.createCredential({
282
267
  challenge: topUpChallenge,
@@ -284,7 +269,7 @@ describe.runIf(isLocalnet)('McpClient.wrap integration', () => {
284
269
  action: 'topUp',
285
270
  additionalDepositRaw: topUpAmountRaw.toString(),
286
271
  channelId: openReceipt!.channelId,
287
- transaction: serializedTransaction,
272
+ descriptor: credentialDescriptor(openCredential),
288
273
  },
289
274
  })
290
275
  const toppedUp = await callToolWithCredential(
@@ -317,7 +302,7 @@ describe.runIf(isLocalnet)('McpClient.wrap integration', () => {
317
302
  expect(resumedReceipt?.acceptedCumulative).toBe((chargeAmountRaw * 3n).toString())
318
303
 
319
304
  const channel = await harness.sessionStore.getChannel(openReceipt!.channelId)
320
- expect(channel?.deposit).toBe(chargeAmountRaw * 2n + topUpAmountRaw)
305
+ expect(channel?.deposit).toBe(chargeAmountRaw * 5n + topUpAmountRaw)
321
306
  expect(channel?.highestVoucherAmount).toBe(chargeAmountRaw * 3n)
322
307
  expect(channel?.spent).toBeGreaterThanOrEqual(BigInt(topUpReceipt!.spent))
323
308
  expect(channel?.units).toBeGreaterThanOrEqual(topUpReceipt?.units ?? 0)
@@ -362,6 +347,7 @@ describe.runIf(isLocalnet)('McpClient.wrap integration', () => {
362
347
  action: 'close',
363
348
  channelId: openReceipt!.channelId,
364
349
  cumulativeAmountRaw: (chargeAmountRaw * 2n).toString(),
350
+ descriptor: credentialDescriptor(openCredential),
365
351
  },
366
352
  })
367
353
  const closed = await callToolWithCredential(
@@ -452,7 +438,6 @@ type Harness = {
452
438
 
453
439
  async function createHarness(options?: {
454
440
  sessionFeePayer?: boolean | undefined
455
- sessionDeposit?: string | undefined
456
441
  sessionMaxDeposit?: string | undefined
457
442
  }): Promise<Harness> {
458
443
  const sessionBackingStore = Store.memory()
@@ -463,11 +448,8 @@ async function createHarness(options?: {
463
448
  })
464
449
  const sessionMethod = tempo_session_client({
465
450
  account: accounts[2],
466
- escrowContract,
467
451
  getClient: () => testClient,
468
- ...(options?.sessionMaxDeposit
469
- ? { maxDeposit: options.sessionMaxDeposit }
470
- : { deposit: options?.sessionDeposit ?? '5' }),
452
+ ...(options?.sessionMaxDeposit ? { maxDeposit: options.sessionMaxDeposit } : {}),
471
453
  })
472
454
 
473
455
  const payment = Mppx_server.create({
@@ -477,10 +459,9 @@ async function createHarness(options?: {
477
459
  currency: asset,
478
460
  getClient: () => testClient,
479
461
  }),
480
- tempo_server.sessionLegacy({
462
+ tempo_server.session({
481
463
  account: accounts[0],
482
464
  currency: asset,
483
- escrowContract,
484
465
  getClient: () => testClient,
485
466
  store: sessionBackingStore,
486
467
  ...(options?.sessionFeePayer ? { feePayer: accounts[4] } : {}),
@@ -578,6 +559,12 @@ async function createHarness(options?: {
578
559
  }
579
560
  }
580
561
 
562
+ function credentialDescriptor(serializedCredential: string) {
563
+ const payload = Credential.deserialize<SessionCredentialPayload>(serializedCredential).payload
564
+ if (!payload.descriptor) throw new Error('Session credential is missing its channel descriptor.')
565
+ return payload.descriptor
566
+ }
567
+
581
568
  async function getPaymentChallenge(client: Client, toolName: string): Promise<SessionChallenge> {
582
569
  try {
583
570
  await client.callTool({ name: toolName, arguments: {} })
@@ -2,18 +2,12 @@ import * as http from 'node:http'
2
2
 
3
3
  import { Elysia } from 'elysia'
4
4
  import { Receipt } from 'mppx'
5
- import {
6
- Mppx as Mppx_client,
7
- sessionLegacy as sessionIntent,
8
- tempo as tempo_client,
9
- } from 'mppx/client'
5
+ import { Mppx as Mppx_client, session as sessionIntent, tempo as tempo_client } from 'mppx/client'
10
6
  import { Mppx, discovery, payment } from 'mppx/elysia'
11
7
  import { tempo as tempo_server } from 'mppx/server'
12
- import type { Address } from 'viem'
13
8
  import { Addresses } from 'viem/tempo'
14
9
  import { beforeAll, describe, expect, test } from 'vp/test'
15
10
  import * as TestHttp from '~test/Http.js'
16
- import { deployEscrow } from '~test/tempo/legacy/session.js'
17
11
  import { accounts, asset, client, fundAccount } from '~test/tempo/viem.js'
18
12
 
19
13
  function createServer(app: Elysia<any, any, any, any, any, any, any>) {
@@ -201,16 +195,13 @@ describe('charge', () => {
201
195
  })
202
196
 
203
197
  describe('session', () => {
204
- let escrowContract: Address
205
-
206
198
  function createSessionHarness(feePayer: boolean) {
207
199
  const mppx = Mppx.create({
208
200
  methods: [
209
- tempo_server.sessionLegacy({
201
+ tempo_server.session({
210
202
  getClient: () => client,
211
203
  account: accounts[0],
212
204
  currency: asset,
213
- escrowContract,
214
205
  ...(feePayer ? { feePayer: accounts[1] } : {}),
215
206
  } as any),
216
207
  ],
@@ -232,7 +223,6 @@ describe('session', () => {
232
223
  }
233
224
 
234
225
  beforeAll(async () => {
235
- escrowContract = await deployEscrow()
236
226
  await fundAccount({ address: accounts[1].address, token: Addresses.pathUsd })
237
227
  await fundAccount({ address: accounts[1].address, token: asset })
238
228
  await fundAccount({ address: accounts[2].address, token: Addresses.pathUsd })
@@ -1,17 +1,11 @@
1
1
  import express from 'express'
2
2
  import { Receipt } from 'mppx'
3
- import {
4
- Mppx as Mppx_client,
5
- sessionLegacy as sessionIntent,
6
- tempo as tempo_client,
7
- } from 'mppx/client'
3
+ import { Mppx as Mppx_client, session as sessionIntent, tempo as tempo_client } from 'mppx/client'
8
4
  import { Mppx, discovery, payment } from 'mppx/express'
9
5
  import { Mppx as Mppx_server, tempo as tempo_server } from 'mppx/server'
10
- import type { Address } from 'viem'
11
6
  import { Addresses } from 'viem/tempo'
12
7
  import { beforeAll, describe, expect, test } from 'vp/test'
13
8
  import * as Http from '~test/Http.js'
14
- import { deployEscrow } from '~test/tempo/legacy/session.js'
15
9
  import { accounts, asset, client, fundAccount } from '~test/tempo/viem.js'
16
10
 
17
11
  function createServer(app: express.Express) {
@@ -195,16 +189,13 @@ describe('payment', () => {
195
189
  })
196
190
 
197
191
  describe('session', () => {
198
- let escrowContract: Address
199
-
200
192
  function createSessionHarness(feePayer: boolean) {
201
193
  const mppx = Mppx.create({
202
194
  methods: [
203
- tempo_server.sessionLegacy({
195
+ tempo_server.session({
204
196
  getClient: () => client,
205
197
  account: accounts[0],
206
198
  currency: asset,
207
- escrowContract,
208
199
  ...(feePayer ? { feePayer: accounts[1] } : {}),
209
200
  } as any),
210
201
  ],
@@ -226,7 +217,6 @@ describe('session', () => {
226
217
  }
227
218
 
228
219
  beforeAll(async () => {
229
- escrowContract = await deployEscrow()
230
220
  await fundAccount({ address: accounts[1].address, token: Addresses.pathUsd })
231
221
  await fundAccount({ address: accounts[1].address, token: asset })
232
222
  await fundAccount({ address: accounts[2].address, token: Addresses.pathUsd })
@@ -4,7 +4,7 @@ import { Challenge, Credential, Method, Receipt, z } from 'mppx'
4
4
  import {
5
5
  evm as evm_client,
6
6
  Mppx as Mppx_client,
7
- sessionLegacy as sessionIntent,
7
+ session as sessionIntent,
8
8
  tempo as tempo_client,
9
9
  } from 'mppx/client'
10
10
  import { Mppx, discovery, payment } from 'mppx/hono'
@@ -15,11 +15,9 @@ import {
15
15
  paymentSignatureHeader,
16
16
  type PaymentPayload,
17
17
  } from 'mppx/x402'
18
- import type { Address } from 'viem'
19
18
  import { Addresses } from 'viem/tempo'
20
19
  import { beforeAll, describe, expect, test } from 'vp/test'
21
20
  import * as Http from '~test/Http.js'
22
- import { deployEscrow } from '~test/tempo/legacy/session.js'
23
21
  import { accounts, asset, client, fundAccount } from '~test/tempo/viem.js'
24
22
 
25
23
  function createServer(app: Hono) {
@@ -203,7 +201,9 @@ describe('charge', () => {
203
201
  const { mppx } = createChargeHarness(false)
204
202
 
205
203
  const app = new Hono()
206
- app.get('/', mppx.charge({ amount: '1' }), (c) => c.json({ fortune: 'You will be rich' }))
204
+ app.get('/', mppx.charge({ amount: '1', description: 'Daily fortune' }), (c) =>
205
+ c.json({ fortune: 'You will be rich' }),
206
+ )
207
207
  discovery(app, mppx, { auto: true, info: { title: 'Auto API', version: '2.0.0' } })
208
208
 
209
209
  const server = await createServer(app)
@@ -216,6 +216,7 @@ describe('charge', () => {
216
216
  expect(body.paths['/'].get['x-payment-info'].offers[0]).toMatchObject({
217
217
  amount: '1000000',
218
218
  currency: asset,
219
+ description: 'Daily fortune',
219
220
  intent: 'charge',
220
221
  method: 'tempo',
221
222
  })
@@ -386,16 +387,13 @@ describe('scope binding', () => {
386
387
  })
387
388
 
388
389
  describe('session', () => {
389
- let escrowContract: Address
390
-
391
390
  function createSessionHarness(feePayer: boolean) {
392
391
  const mppx = Mppx.create({
393
392
  methods: [
394
- tempo_server.sessionLegacy({
393
+ tempo_server.session({
395
394
  getClient: () => client,
396
395
  account: accounts[0],
397
396
  currency: asset,
398
- escrowContract,
399
397
  ...(feePayer ? { feePayer: accounts[1] } : {}),
400
398
  } as any),
401
399
  ],
@@ -417,7 +415,6 @@ describe('session', () => {
417
415
  }
418
416
 
419
417
  beforeAll(async () => {
420
- escrowContract = await deployEscrow()
421
418
  await fundAccount({ address: accounts[1].address, token: Addresses.pathUsd })
422
419
  await fundAccount({ address: accounts[1].address, token: asset })
423
420
  await fundAccount({ address: accounts[2].address, token: Addresses.pathUsd })
@@ -1,18 +1,12 @@
1
1
  import * as http from 'node:http'
2
2
 
3
3
  import { Challenge, Credential, Receipt } from 'mppx'
4
- import {
5
- Mppx as Mppx_client,
6
- sessionLegacy as sessionIntent,
7
- tempo as tempo_client,
8
- } from 'mppx/client'
4
+ import { Mppx as Mppx_client, session as sessionIntent, tempo as tempo_client } from 'mppx/client'
9
5
  import { Mppx, discovery, payment } from 'mppx/nextjs'
10
6
  import { tempo as tempo_server } from 'mppx/server'
11
- import type { Address } from 'viem'
12
7
  import { Addresses } from 'viem/tempo'
13
8
  import { beforeAll, describe, expect, test } from 'vp/test'
14
9
  import * as TestHttp from '~test/Http.js'
15
- import { deployEscrow } from '~test/tempo/legacy/session.js'
16
10
  import { accounts, asset, chain, client, fundAccount } from '~test/tempo/viem.js'
17
11
 
18
12
  function createServer(handler: (request: Request) => Promise<Response> | Response) {
@@ -278,16 +272,13 @@ describe('charge', () => {
278
272
  })
279
273
 
280
274
  describe('session', () => {
281
- let escrowContract: Address
282
-
283
275
  function createSessionHarness(feePayer: boolean) {
284
276
  const mppx = Mppx.create({
285
277
  methods: [
286
- tempo_server.sessionLegacy({
278
+ tempo_server.session({
287
279
  getClient: () => client,
288
280
  account: accounts[0],
289
281
  currency: asset,
290
- escrowContract,
291
282
  ...(feePayer ? { feePayer: accounts[1] } : {}),
292
283
  } as any),
293
284
  ],
@@ -309,7 +300,6 @@ describe('session', () => {
309
300
  }
310
301
 
311
302
  beforeAll(async () => {
312
- escrowContract = await deployEscrow()
313
303
  await fundAccount({ address: accounts[1].address, token: Addresses.pathUsd })
314
304
  await fundAccount({ address: accounts[1].address, token: asset })
315
305
  await fundAccount({ address: accounts[2].address, token: Addresses.pathUsd })
@@ -1,14 +1,12 @@
1
1
  import { Challenge, Credential, Method, Receipt, z } from 'mppx'
2
2
  import { Mppx as Mppx_client, tempo as tempo_client } from 'mppx/client'
3
3
  import { Mppx as Mppx_server, tempo as tempo_server } from 'mppx/server'
4
- import type { Address } from 'viem'
5
- import { afterEach, beforeAll, describe, expect, test } from 'vp/test'
4
+ import { afterEach, describe, expect, test } from 'vp/test'
6
5
  import { tempoNetwork } from '~test/config.js'
7
6
  import * as Http from '~test/Http.js'
8
- import { deployEscrow } from '~test/tempo/legacy/session.js'
9
7
  import { accounts, asset, client } from '~test/tempo/viem.js'
10
8
 
11
- import { sessionManager } from '../tempo/legacy/client/index.js'
9
+ import { sessionManager } from '../tempo/session/client/SessionManager.js'
12
10
  import { deserializeSessionReceipt } from '../tempo/session/precompile/Protocol.js'
13
11
  import * as ApiProxy from './Proxy.js'
14
12
  import * as Service from './Service.js'
@@ -76,13 +74,6 @@ const mppx_client = Mppx_client.create({
76
74
 
77
75
  let upstream: Awaited<ReturnType<typeof Http.createServer>> | undefined
78
76
  let proxyServer: Awaited<ReturnType<typeof Http.createServer>> | undefined
79
- let sessionEscrow: Address
80
-
81
- beforeAll(async () => {
82
- if (!isLocalnet) return
83
- sessionEscrow = await deployEscrow()
84
- })
85
-
86
77
  afterEach(() => {
87
78
  upstream?.close()
88
79
  proxyServer?.close()
@@ -181,6 +172,7 @@ describe('create', () => {
181
172
  })
182
173
 
183
174
  test('behavior: GET /openapi.json returns discovery JSON', async () => {
175
+ const alternateAsset = '0x20c0000000000000000000000000000000000002'
184
176
  const proxy = ApiProxy.create({
185
177
  categories: ['gateway'],
186
178
  docs: {
@@ -196,6 +188,10 @@ describe('create', () => {
196
188
  routes: {
197
189
  'GET /v1/models': true,
198
190
  'POST /v1/generate': mppx_server.charge({ amount: '1', description: 'Generate text' }),
191
+ 'POST /v1/multi': mppx_server.compose(
192
+ ['tempo/charge', { amount: '1', currency: asset, decimals: 6 }],
193
+ ['tempo/charge', { amount: '2', currency: alternateAsset, decimals: 6 }],
194
+ ),
199
195
  'POST /v1/stream': mppx_server.session({
200
196
  amount: '1',
201
197
  description: 'Stream text',
@@ -231,6 +227,20 @@ describe('create', () => {
231
227
  intent: 'charge',
232
228
  method: 'tempo',
233
229
  })
230
+ expect(body.paths['/api/v1/multi'].post['x-payment-info'].offers).toEqual([
231
+ expect.objectContaining({
232
+ amount: '1000000',
233
+ currency: asset,
234
+ intent: 'charge',
235
+ method: 'tempo',
236
+ }),
237
+ expect.objectContaining({
238
+ amount: '2000000',
239
+ currency: alternateAsset,
240
+ intent: 'charge',
241
+ method: 'tempo',
242
+ }),
243
+ ])
234
244
  expect(body.paths['/api/v1/stream'].post['x-payment-info'].offers[0]).toMatchObject({
235
245
  amount: '1000000',
236
246
  currency: asset,
@@ -576,7 +586,7 @@ describe('create', () => {
576
586
  expect(res.status).toBe(402)
577
587
  })
578
588
 
579
- test('behavior: management POST uses credential method binding to disambiguate same-path paid routes', async () => {
589
+ test('behavior: management POST uses composed credential binding to disambiguate same-path paid routes', async () => {
580
590
  const alpha = Method.from({
581
591
  name: 'alpha',
582
592
  intent: 'charge',
@@ -631,7 +641,7 @@ describe('create', () => {
631
641
  Service.from('api', {
632
642
  baseUrl: 'https://example.com',
633
643
  routes: {
634
- 'GET /v1/stream': handler['alpha/charge']({ amount: '1' }),
644
+ 'GET /v1/stream': handler.compose(['alpha/charge', { amount: '1' }]),
635
645
  'PATCH /v1/stream': handler['beta/charge']({ amount: '1' }),
636
646
  },
637
647
  }),
@@ -907,10 +917,9 @@ describe.runIf(isLocalnet)('plain HTTP session proxy', () => {
907
917
 
908
918
  const sessionHandler = Mppx_server.create({
909
919
  methods: [
910
- tempo_server.sessionLegacy({
920
+ tempo_server.session({
911
921
  account: accounts[0],
912
922
  currency: asset,
913
- escrowContract: sessionEscrow,
914
923
  getClient: () => client,
915
924
  chainId: client.chain!.id,
916
925
  }),
@@ -937,7 +946,6 @@ describe.runIf(isLocalnet)('plain HTTP session proxy', () => {
937
946
  const manager = sessionManager({
938
947
  account: accounts[1],
939
948
  client,
940
- escrowContract: sessionEscrow,
941
949
  fetch: globalThis.fetch,
942
950
  maxDeposit: '3',
943
951
  })
@@ -967,10 +975,9 @@ describe.runIf(isLocalnet)('plain HTTP session proxy', () => {
967
975
 
968
976
  const sessionHandler = Mppx_server.create({
969
977
  methods: [
970
- tempo_server.sessionLegacy({
978
+ tempo_server.session({
971
979
  account: accounts[0],
972
980
  currency: asset,
973
- escrowContract: sessionEscrow,
974
981
  getClient: () => client,
975
982
  chainId: client.chain!.id,
976
983
  }),
@@ -997,7 +1004,7 @@ describe.runIf(isLocalnet)('plain HTTP session proxy', () => {
997
1004
  const sessionClient = Mppx_client.create({
998
1005
  polyfill: false,
999
1006
  methods: [
1000
- tempo_client.sessionLegacy.method({
1007
+ tempo_client.session({
1001
1008
  account: accounts[1],
1002
1009
  getClient: () => client,
1003
1010
  maxDeposit: '2',
@@ -128,7 +128,14 @@ export function create(config: create.Config): Proxy {
128
128
  const endpoint = matched.value as Service.Endpoint
129
129
  const ctx: Service.Context = { request, service, upstreamPath }
130
130
 
131
- if (endpoint === true) return proxyUpstream({ request, service, ctx, proxy })
131
+ if (endpoint === true)
132
+ return proxyUpstream({
133
+ request,
134
+ service,
135
+ ctx,
136
+ proxy,
137
+ onUpstreamError: service.onUpstreamError ?? config.onUpstreamError,
138
+ })
132
139
 
133
140
  const handler = typeof endpoint === 'function' ? endpoint : endpoint.pay
134
141
  const scope =
@@ -161,6 +168,7 @@ export function create(config: create.Config): Proxy {
161
168
  service,
162
169
  ctx: { ...ctx, ...options },
163
170
  proxy,
171
+ onUpstreamError: service.onUpstreamError ?? config.onUpstreamError,
164
172
  })
165
173
  return result.withReceipt(upstreamRes)
166
174
  }
@@ -183,6 +191,8 @@ export declare namespace create {
183
191
  docs?: Service.Docs | undefined
184
192
  /** Custom `fetch` implementation. Defaults to `globalThis.fetch`. */
185
193
  fetch?: typeof globalThis.fetch | undefined
194
+ /** Default handler for failed upstream attempts. Services may override it. */
195
+ onUpstreamError?: Service.UpstreamErrorHandler | undefined
186
196
  /** Services to proxy. Each service is mounted at `/{serviceId}/`. */
187
197
  services: Service.Service[]
188
198
  /** Human-readable title for the proxy shown in `llms.txt`. */
@@ -195,6 +205,7 @@ export declare namespace create {
195
205
  declare namespace proxyUpstream {
196
206
  type Options = {
197
207
  ctx: Service.Context
208
+ onUpstreamError?: Service.UpstreamErrorHandler | undefined
198
209
  proxy: (input: URL | RequestInfo, init?: RequestInit) => Promise<Response>
199
210
  request: globalThis.Request
200
211
  service: Service.Service
@@ -203,7 +214,7 @@ declare namespace proxyUpstream {
203
214
 
204
215
  /** @internal */
205
216
  async function proxyUpstream(options: proxyUpstream.Options): Promise<Response> {
206
- const { request, service, ctx, proxy } = options
217
+ const { request, service, ctx, proxy, onUpstreamError } = options
207
218
  const url = ctx.upstreamPath + new URL(request.url).search
208
219
  const headers = Headers.scrub(request.headers)
209
220
 
@@ -221,17 +232,137 @@ async function proxyUpstream(options: proxyUpstream.Options): Promise<Response>
221
232
  init.duplex = 'half'
222
233
  }
223
234
 
224
- let upstreamReq = new globalThis.Request(new URL(url, new URL(service.baseUrl).origin), init)
235
+ const upstreamRequest = new globalThis.Request(
236
+ new URL(url, new URL(service.baseUrl).origin),
237
+ init,
238
+ )
239
+
240
+ if (!onUpstreamError)
241
+ return proxyUpstreamOnce({
242
+ ctx,
243
+ proxy,
244
+ service,
245
+ upstreamRequest,
246
+ })
247
+
248
+ for (let attempt = 1; ; attempt++) {
249
+ const outcome = await proxyUpstreamAttempt({
250
+ ctx,
251
+ proxy,
252
+ service,
253
+ upstreamRequest,
254
+ })
255
+
256
+ let response = outcome.response
257
+ if (response && service.rewriteResponse) response = await service.rewriteResponse(response, ctx)
258
+ if (response?.ok) return response
259
+
260
+ const handlerResponse = response?.clone()
225
261
 
226
- if (service.rewriteRequest) upstreamReq = await service.rewriteRequest(upstreamReq, ctx)
262
+ const action = await onUpstreamError({
263
+ ...ctx,
264
+ attempt,
265
+ error: outcome.error,
266
+ response: handlerResponse,
267
+ upstreamRequest: outcome.upstreamRequest,
268
+ })
269
+
270
+ if (!action.retry) {
271
+ if (action.response) {
272
+ if (response) void cancelResponseBody(response)
273
+ return action.response
274
+ }
275
+ if (response) {
276
+ if (handlerResponse) void cancelResponseBody(handlerResponse)
277
+ return response
278
+ }
279
+ throw outcome.error
280
+ }
281
+
282
+ for (const failedResponse of [response, handlerResponse])
283
+ if (failedResponse) void cancelResponseBody(failedResponse)
284
+ await waitForRetry(action.delay, request.signal)
285
+ }
286
+ }
287
+
288
+ /** Proxies one request without retaining a replay copy of its body. */
289
+ async function proxyUpstreamOnce(options: proxyUpstreamAttempt.Options): Promise<Response> {
290
+ const { ctx, proxy, service } = options
291
+ let upstreamRequest = options.upstreamRequest
227
292
 
228
- let upstreamRes = await proxy(upstreamReq)
293
+ if (service.rewriteRequest) upstreamRequest = await service.rewriteRequest(upstreamRequest, ctx)
229
294
 
230
- upstreamRes = Headers.scrubResponse(upstreamRes)
295
+ let response = await proxy(upstreamRequest)
296
+ response = Headers.scrubResponse(response)
231
297
 
232
- if (service.rewriteResponse) upstreamRes = await service.rewriteResponse(upstreamRes, ctx)
298
+ if (service.rewriteResponse) response = await service.rewriteResponse(response, ctx)
233
299
 
234
- return upstreamRes
300
+ return response
301
+ }
302
+
303
+ declare namespace proxyUpstreamAttempt {
304
+ type Options = {
305
+ ctx: Service.Context
306
+ proxy: (input: URL | RequestInfo, init?: RequestInit) => Promise<Response>
307
+ service: Service.Service
308
+ upstreamRequest: Request
309
+ }
310
+
311
+ type Result = {
312
+ error: unknown | undefined
313
+ response: Response | undefined
314
+ upstreamRequest: Request
315
+ }
316
+ }
317
+
318
+ /** Performs one independently replayable upstream request attempt. */
319
+ async function proxyUpstreamAttempt(
320
+ options: proxyUpstreamAttempt.Options,
321
+ ): Promise<proxyUpstreamAttempt.Result> {
322
+ const { ctx, proxy, service } = options
323
+ let upstreamRequest = options.upstreamRequest.clone()
324
+
325
+ try {
326
+ if (service.rewriteRequest) upstreamRequest = await service.rewriteRequest(upstreamRequest, ctx)
327
+
328
+ let response = await proxy(upstreamRequest)
329
+ response = Headers.scrubResponse(response)
330
+
331
+ return { error: undefined, response, upstreamRequest }
332
+ } catch (error) {
333
+ return { error, response: undefined, upstreamRequest }
334
+ }
335
+ }
336
+
337
+ /** Cancels an unused failed response body before a retry. */
338
+ async function cancelResponseBody(response: Response): Promise<void> {
339
+ if (!response.body || response.bodyUsed) return
340
+ try {
341
+ await response.body.cancel()
342
+ } catch {
343
+ return
344
+ }
345
+ }
346
+
347
+ /** Waits for a retry delay while respecting request cancellation. */
348
+ async function waitForRetry(delay = 0, signal: AbortSignal): Promise<void> {
349
+ if (signal.aborted)
350
+ throw signal.reason ?? new DOMException('The operation was aborted.', 'AbortError')
351
+ if (!Number.isFinite(delay) || delay <= 0) return
352
+
353
+ await new Promise<void>((resolve, reject) => {
354
+ const onAbort = () => {
355
+ clearTimeout(timeout)
356
+ signal.removeEventListener('abort', onAbort)
357
+ reject(signal.reason ?? new DOMException('The operation was aborted.', 'AbortError'))
358
+ }
359
+ const timeout = setTimeout(() => {
360
+ signal.removeEventListener('abort', onAbort)
361
+ resolve()
362
+ }, delay)
363
+ signal.addEventListener('abort', onAbort, { once: true })
364
+ if (signal.aborted) onAbort()
365
+ })
235
366
  }
236
367
 
237
368
  function buildDiscoveryRoutes(services: Service.Service[]) {
@@ -310,7 +441,14 @@ function matchesPaymentBinding(endpoint: unknown, binding: PaymentBinding | null
310
441
  if (!binding) return true
311
442
  const payment = Service.paymentOf(endpoint as Exclude<Service.Endpoint, true>)
312
443
  if (!payment) return true
313
- return payment.method === binding.method && payment.intent === binding.intent
444
+ const offers = Array.isArray(payment.offers) ? payment.offers : [payment]
445
+ return offers.some(
446
+ (offer) =>
447
+ typeof offer === 'object' &&
448
+ offer !== null &&
449
+ offer.method === binding.method &&
450
+ offer.intent === binding.intent,
451
+ )
314
452
  }
315
453
 
316
454
  function createFetchProxy(