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
@@ -0,0 +1,42 @@
1
+ import { TempoAddress } from 'ox/tempo'
2
+ import { describe, expect, test } from 'vp/test'
3
+
4
+ import { isEqual } from './address.js'
5
+
6
+ const address = '0x742d35Cc6634C0532925a3b844Bc9e7595F2bD28'
7
+ const otherAddress = '0x52908400098527886E0F7030069857D2E4169EE7'
8
+
9
+ describe('isEqual', () => {
10
+ const representations = [
11
+ { name: 'mixed-case hex', value: address },
12
+ { name: 'lowercase hex', value: address.toLowerCase() as `0x${string}` },
13
+ { name: 'Tempo-formatted', value: TempoAddress.format(address) },
14
+ ] as const
15
+
16
+ const otherRepresentations = [
17
+ { name: 'mixed-case hex', value: otherAddress },
18
+ { name: 'lowercase hex', value: otherAddress.toLowerCase() as `0x${string}` },
19
+ { name: 'Tempo-formatted', value: TempoAddress.format(otherAddress) },
20
+ ] as const
21
+
22
+ test.each([
23
+ ...representations.flatMap((a) =>
24
+ representations.map((b) => ({
25
+ a: a.value,
26
+ b: b.value,
27
+ expected: true,
28
+ name: `${a.name} and ${b.name} representations of the same address`,
29
+ })),
30
+ ),
31
+ ...representations.flatMap((a) =>
32
+ otherRepresentations.map((b) => ({
33
+ a: a.value,
34
+ b: b.value,
35
+ expected: false,
36
+ name: `${a.name} and ${b.name} representations of different addresses`,
37
+ })),
38
+ ),
39
+ ])('$name', ({ a, b, expected }) => {
40
+ expect(isEqual(a, b)).toBe(expected)
41
+ })
42
+ })
@@ -1,6 +1,6 @@
1
- // TODO: Add `isEqual` to `TempoAddress`.
2
- import type { TempoAddress } from 'ox/tempo'
1
+ import { TempoAddress } from 'ox/tempo'
3
2
 
3
+ /** Returns whether two hex or Tempo-formatted addresses resolve to the same address. */
4
4
  export function isEqual(a: TempoAddress.Address, b: TempoAddress.Address) {
5
- return a.toLowerCase() === b.toLowerCase()
5
+ return TempoAddress.resolve(a).toLowerCase() === TempoAddress.resolve(b).toLowerCase()
6
6
  }
@@ -103,7 +103,7 @@ describe('resolve', () => {
103
103
  })
104
104
 
105
105
  describe('findCalls', () => {
106
- test('passes the client to viem 2.54 Tempo token call builders', async () => {
106
+ test('uses current viem Tempo call builder signatures', async () => {
107
107
  vi.resetModules()
108
108
  const account = '0x1111111111111111111111111111111111111111' as Address
109
109
  const tokenOut = '0x2222222222222222222222222222222222222222' as Address
@@ -122,8 +122,8 @@ describe('findCalls', () => {
122
122
  return { kind: 'approve' }
123
123
  }
124
124
 
125
- function buyCall(client: unknown, parameters: Record<string, unknown>) {
126
- builderCalls.push({ client, name: 'buy', parameters })
125
+ function buyCall(parameters: Record<string, unknown>) {
126
+ builderCalls.push({ client: undefined, name: 'buy', parameters })
127
127
  return { kind: 'buy' }
128
128
  }
129
129
 
@@ -158,7 +158,7 @@ describe('findCalls', () => {
158
158
  })
159
159
 
160
160
  expect(calls).toHaveLength(2)
161
- expect(builderCalls.map((call) => call.client)).toEqual([client, client, client, client])
161
+ expect(builderCalls.map((call) => call.client)).toEqual([client, client, client, undefined])
162
162
  expect(builderCalls.map((call) => call.name)).toEqual([
163
163
  'getBalance',
164
164
  'getBalance',
@@ -1,7 +1,6 @@
1
1
  import type { Address, Client } from 'viem'
2
2
  import { readContract } from 'viem/actions'
3
3
  import { Actions, Addresses } from 'viem/tempo'
4
- import type { dex as viem_dex, token as viem_token } from 'viem/tempo/actions'
5
4
 
6
5
  import * as TempoAddress from './address.js'
7
6
  import * as defaults from './defaults.js'
@@ -15,51 +14,6 @@ export const defaultCurrencies: readonly Address[] = [
15
14
  defaults.tokens.usdc as Address,
16
15
  ]
17
16
 
18
- // TODO: Remove once the minimum viem version is >=2.54.0, which uses client-first Tempo call builders.
19
- function getBalanceCall(
20
- client: Client,
21
- parameters: viem_token.getBalance.Args,
22
- ): ReturnType<typeof viem_token.getBalance.call> {
23
- const call = Actions.token.getBalance.call as unknown as {
24
- length: number
25
- (parameters: viem_token.getBalance.Args): ReturnType<typeof viem_token.getBalance.call>
26
- (
27
- client: Client,
28
- parameters: viem_token.getBalance.Args,
29
- ): ReturnType<typeof viem_token.getBalance.call>
30
- }
31
- return call.length >= 2 ? call(client, parameters) : call(parameters)
32
- }
33
-
34
- // TODO: Remove once the minimum viem version is >=2.54.0, which uses client-first Tempo call builders.
35
- function getApproveCall(
36
- client: Client,
37
- parameters: viem_token.approve.Args,
38
- ): ReturnType<typeof viem_token.approve.call> {
39
- const call = Actions.token.approve.call as unknown as {
40
- length: number
41
- (parameters: viem_token.approve.Args): ReturnType<typeof viem_token.approve.call>
42
- (
43
- client: Client,
44
- parameters: viem_token.approve.Args,
45
- ): ReturnType<typeof viem_token.approve.call>
46
- }
47
- return call.length >= 2 ? call(client, parameters) : call(parameters)
48
- }
49
-
50
- // TODO: Remove once the minimum viem version is >=2.54.0, which uses client-first Tempo call builders.
51
- function getBuyCall(
52
- client: Client,
53
- parameters: viem_dex.buy.Args,
54
- ): ReturnType<typeof viem_dex.buy.call> {
55
- const call = Actions.dex.buy.call as unknown as {
56
- length: number
57
- (parameters: viem_dex.buy.Args): ReturnType<typeof viem_dex.buy.call>
58
- (client: Client, parameters: viem_dex.buy.Args): ReturnType<typeof viem_dex.buy.call>
59
- }
60
- return call.length >= 2 ? call(client, parameters) : call(parameters)
61
- }
62
-
63
17
  /**
64
18
  * Finds the optimal swap calls to acquire `amountOut` of `tokenOut`,
65
19
  * returning an approve + buy call sequence if a viable route is found.
@@ -76,9 +30,12 @@ export async function findCalls(
76
30
  const candidates = tokenIn.filter((t) => !TempoAddress.isEqual(t, tokenOut))
77
31
 
78
32
  const balanceResults = await Promise.allSettled([
79
- readContract(client, getBalanceCall(client, { account, token: tokenOut }) as never),
33
+ readContract(
34
+ client,
35
+ Actions.token.getBalance.call(client, { account, token: tokenOut }) as never,
36
+ ),
80
37
  ...candidates.map((t) =>
81
- readContract(client, getBalanceCall(client, { account, token: t }) as never),
38
+ readContract(client, Actions.token.getBalance.call(client, { account, token: t }) as never),
82
39
  ),
83
40
  ])
84
41
 
@@ -108,12 +65,12 @@ export async function findCalls(
108
65
  const maxAmountIn =
109
66
  quotedAmountIn + (quotedAmountIn * BigInt(Math.round(slippage * 100))) / bps
110
67
  return [
111
- getApproveCall(client, {
68
+ Actions.token.approve.call(client, {
112
69
  amount: maxAmountIn,
113
70
  spender: Addresses.stablecoinDex,
114
71
  token: tokenIn,
115
72
  }),
116
- getBuyCall(client, {
73
+ Actions.dex.buy.call({
117
74
  tokenIn,
118
75
  tokenOut,
119
76
  amountOut,
@@ -1,9 +1,9 @@
1
1
  # Tempo Legacy Session
2
2
 
3
- This directory contains the legacy smart-contract-backed `tempo/session`
4
- implementation.
3
+ This directory contains the retained client for the legacy smart-contract-backed
4
+ `tempo/session` implementation.
5
5
 
6
6
  The default `tempo.session` implementation is TIP-1034 precompile-backed and
7
- lives under `src/tempo/session/precompile`. Legacy code may import shared transport and
8
- accounting helpers from `src/tempo/session`, but legacy chain, channel, voucher,
9
- client, and server implementations should stay inside this directory.
7
+ lives under `src/tempo/session/precompile`. The legacy server implementation has
8
+ been removed, while legacy chain, channel, voucher, and client code remains here
9
+ for clients migrating existing sessions.
@@ -1,6 +1,4 @@
1
1
  /** Legacy contract-backed session client surface. */
2
2
  export * as Client from './client/index.js'
3
- /** Legacy contract-backed session server surface. */
4
- export * as Server from './server/index.js'
5
- /** Legacy contract-backed session channel primitives. */
3
+ /** Legacy contract-backed session channel primitives used by the client. */
6
4
  export * as Session from './session/index.js'
@@ -19,6 +19,19 @@ test('tempo.charge store parameter requires AtomicStore', () => {
19
19
  tempo.charge({ store: Store.memory() })
20
20
  })
21
21
 
22
+ test('tempo.charge sponsor budget store requires AtomicStore', () => {
23
+ const nonAtomic = Store.from({
24
+ get: async () => null,
25
+ put: async () => {},
26
+ delete: async () => {},
27
+ })
28
+
29
+ tempo.charge({ sponsorBudget: false })
30
+ // @ts-expect-error — sponsor budget coordination requires AtomicStore
31
+ tempo.charge({ sponsorBudget: { store: nonAtomic } })
32
+ tempo.charge({ sponsorBudget: { store: Store.memory() } })
33
+ })
34
+
22
35
  test('tempo.session store parameter requires AtomicStore', () => {
23
36
  type SessionParameters = NonNullable<Parameters<typeof tempo.session>[0]>
24
37
  expectTypeOf<SessionParameters['store']>().toEqualTypeOf<Store.AtomicStore | undefined>()
@@ -16,12 +16,6 @@ import { Abis, Account, Actions, Addresses, Secp256k1, Tick, Transaction } from
16
16
  import type { token as viem_token } from 'viem/tempo/actions'
17
17
  import { beforeAll, describe, expect, test } from 'vp/test'
18
18
  import * as Http from '~test/Http.js'
19
- import {
20
- closeChannelOnChain,
21
- deployEscrow,
22
- openChannel,
23
- signVoucher,
24
- } from '~test/tempo/legacy/session.js'
25
19
  import { accounts, asset, chain, client, fundAccount, http } from '~test/tempo/viem.js'
26
20
 
27
21
  import * as Store from '../../Store.js'
@@ -58,18 +52,8 @@ function sponsoredFeeExposure(credential: string) {
58
52
  return transaction.gas * transaction.maxFeePerGas
59
53
  }
60
54
 
61
- // TODO: Remove once the minimum viem version is >=2.54.0, which uses client-first Tempo call builders.
62
55
  function tokenTransferCall(parameters: viem_token.transfer.Args) {
63
- const call = Actions.token.transfer.call as unknown as {
64
- length: number
65
- (parameters: viem_token.transfer.Args): ReturnType<typeof viem_token.transfer.call>
66
- (
67
- client: unknown,
68
- parameters: viem_token.transfer.Args,
69
- ): ReturnType<typeof viem_token.transfer.call>
70
- }
71
- if (call.length >= 2) return call(client, parameters)
72
- return call(parameters)
56
+ return Actions.token.transfer.call(client, parameters)
73
57
  }
74
58
 
75
59
  type ProofAccessKeyContext = {
@@ -92,6 +76,21 @@ const server = Mppx_server.create({
92
76
  })
93
77
 
94
78
  describe('tempo', () => {
79
+ describe('sponsor budget configuration', () => {
80
+ test('validates structured limits', () => {
81
+ expect(() => tempo_server.charge({ sponsorBudget: { maxInFlightReservations: 0 } })).toThrow(
82
+ '`sponsorBudget.maxInFlightReservations` must be a positive safe integer.',
83
+ )
84
+ expect(() => tempo_server.charge({ sponsorBudget: { maxInFlightTotalFee: 0n } })).toThrow(
85
+ '`sponsorBudget.maxInFlightTotalFee` must be greater than zero.',
86
+ )
87
+ })
88
+
89
+ test('allows aggregate exposure to be enforced externally', () => {
90
+ expect(() => tempo_server.charge({ sponsorBudget: false })).not.toThrow()
91
+ })
92
+ })
93
+
95
94
  describe('intent: charge; type: hash', () => {
96
95
  test('default', async () => {
97
96
  const mppx = Mppx_client.create({
@@ -581,72 +580,6 @@ describe('tempo', () => {
581
580
  httpServer.close()
582
581
  })
583
582
 
584
- test('behavior: rejects session settlement tx hash used as charge credential', async () => {
585
- const chargeAmount = parseUnits('1', 6)
586
- const recipient = accounts[0].address
587
- const external = accounts[3]
588
-
589
- const escrow = await deployEscrow()
590
-
591
- await fundAccount({ address: external.address, token: Addresses.pathUsd })
592
- await fundAccount({ address: external.address, token: asset })
593
-
594
- const salt = '0x0000000000000000000000000000000000000000000000000000000000000001' as Hex.Hex
595
- const { channelId } = await openChannel({
596
- escrow,
597
- payer: external,
598
- payee: recipient,
599
- token: asset,
600
- deposit: chargeAmount,
601
- salt,
602
- })
603
-
604
- const voucherSig = await signVoucher(
605
- client,
606
- external,
607
- { channelId, cumulativeAmount: chargeAmount },
608
- escrow,
609
- chain.id,
610
- )
611
-
612
- const { txHash: settleTxHash } = await closeChannelOnChain({
613
- escrow,
614
- payee: accounts[0],
615
- channelId,
616
- cumulativeAmount: chargeAmount,
617
- signature: voucherSig,
618
- })
619
-
620
- const httpServer = await Http.createServer(async (req, res) => {
621
- const result = await Mppx_server.toNodeListener(server.charge({ amount: '1' }))(req, res)
622
- if (result.status === 402) return
623
- res.end('OK')
624
- })
625
-
626
- const response = await fetch(httpServer.url)
627
- expect(response.status).toBe(402)
628
-
629
- const challenge = Challenge.fromResponse(response, {
630
- methods: [tempo_client.charge()],
631
- })
632
-
633
- const credential = Credential.from({
634
- challenge,
635
- payload: { hash: settleTxHash, type: 'hash' as const },
636
- })
637
-
638
- {
639
- const response = await fetch(httpServer.url, {
640
- headers: { Authorization: Credential.serialize(credential) },
641
- })
642
- expect(response.status).toBe(402)
643
- const body = (await response.json()) as { detail: string }
644
- expect(body.detail).toContain('Payment verification failed: no matching transfer found.')
645
- }
646
-
647
- httpServer.close()
648
- })
649
-
650
583
  test('behavior: rejects replayed transaction hash', async () => {
651
584
  const dedupServer = Mppx_server.create({
652
585
  methods: [
@@ -1976,6 +1909,7 @@ describe('tempo', () => {
1976
1909
  }),
1977
1910
  })
1978
1911
 
1912
+ const replayStore = Store.memory()
1979
1913
  const sponsoredStore = Store.memory()
1980
1914
  const serverWithSlowSimulation = Mppx_server.create({
1981
1915
  methods: [
@@ -1985,7 +1919,8 @@ describe('tempo', () => {
1985
1919
  },
1986
1920
  currency: asset,
1987
1921
  account: accounts[0],
1988
- store: sponsoredStore,
1922
+ sponsorBudget: { store: sponsoredStore },
1923
+ store: replayStore,
1989
1924
  storeKeyPrefix: 'tenant:',
1990
1925
  }),
1991
1926
  ],
@@ -67,6 +67,7 @@ export function charge<const parameters extends charge.Parameters>(
67
67
  html,
68
68
  memo,
69
69
  relay,
70
+ sponsorBudget,
70
71
  splits,
71
72
  supportedModes,
72
73
  validateSender,
@@ -75,21 +76,31 @@ export function charge<const parameters extends charge.Parameters>(
75
76
  const storeKeyPrefix = parameters.storeKeyPrefix ?? ''
76
77
  const rawStore = (parameters.store ?? Store.memory()) as Store.AtomicStore<charge.StoreItemMap>
77
78
  const store = Store.from(rawStore, { keyPrefix: storeKeyPrefix })
78
- // Aggregate exposure belongs to the actual sponsor, not a caller-specific
79
- // replay namespace. Sharing the raw store gives every tenant/process the same
80
- // atomic sponsor-wide budget.
81
- const sponsorBudgetStore = Store.from(rawStore) as Store.AtomicStore<{
82
- [key: `mppx:charge:sponsor-budget:${string}`]: SponsorBudget.State
83
- }>
84
79
  const {
85
- maxInFlightReservations = 100,
86
- maxInFlightTotalFee = (feePayerPolicy?.maxTotalFee ?? 50_000_000_000_000_000n) * 10n,
80
+ maxInFlightReservations: legacyMaxInFlightReservations,
81
+ maxInFlightTotalFee: legacyMaxInFlightTotalFee,
87
82
  ...transactionFeePayerPolicy
88
83
  } = feePayerPolicy ?? {}
89
- if (!Number.isSafeInteger(maxInFlightReservations) || maxInFlightReservations <= 0)
90
- throw new Error('`feePayerPolicy.maxInFlightReservations` must be a positive safe integer.')
91
- if (maxInFlightTotalFee <= 0n)
92
- throw new Error('`feePayerPolicy.maxInFlightTotalFee` must be greater than zero.')
84
+ const sponsorBudgetConfig = sponsorBudget === false ? undefined : (sponsorBudget ?? {})
85
+ const maxInFlightReservations =
86
+ sponsorBudgetConfig?.maxInFlightReservations ?? legacyMaxInFlightReservations ?? 100
87
+ const maxInFlightTotalFee =
88
+ sponsorBudgetConfig?.maxInFlightTotalFee ??
89
+ legacyMaxInFlightTotalFee ??
90
+ (feePayerPolicy?.maxTotalFee ?? 50_000_000_000_000_000n) * 10n
91
+ if (sponsorBudgetConfig) {
92
+ if (!Number.isSafeInteger(maxInFlightReservations) || maxInFlightReservations <= 0)
93
+ throw new Error('`sponsorBudget.maxInFlightReservations` must be a positive safe integer.')
94
+ if (maxInFlightTotalFee <= 0n)
95
+ throw new Error('`sponsorBudget.maxInFlightTotalFee` must be greater than zero.')
96
+ }
97
+ // Aggregate exposure belongs to the actual sponsor, not a caller-specific replay namespace.
98
+ // Keep it unprefixed and shared across every tenant/process using the sponsor.
99
+ const sponsorBudgetStore = sponsorBudgetConfig
100
+ ? (Store.from(sponsorBudgetConfig.store ?? rawStore) as Store.AtomicStore<{
101
+ [key: `mppx:charge:sponsor-budget:${string}`]: SponsorBudget.State
102
+ }>)
103
+ : undefined
93
104
  const proofStore = parameters.store
94
105
  ? Store.from(parameters.store as Store.AtomicStore<charge.StoreItemMap>, {
95
106
  keyPrefix: storeKeyPrefix,
@@ -360,6 +371,8 @@ export function charge<const parameters extends charge.Parameters>(
360
371
 
361
372
  type Defaults = charge.DeriveDefaults<parameters>
362
373
  const method = Method.toServer<typeof Methods.charge, Defaults>(Methods.charge, {
374
+ canOffer: parameters.canOffer,
375
+ onPaymentSuccess: parameters.onPaymentSuccess,
363
376
  defaults: {
364
377
  amount,
365
378
  currency,
@@ -475,11 +488,13 @@ export function charge<const parameters extends charge.Parameters>(
475
488
  : feePayer
476
489
  : undefined
477
490
  const expires = challenge.expires
491
+ Expires.assert(expires, challenge.id)
492
+ const replayExpires = Date.parse(expires)
478
493
 
479
494
  switch (validated.type) {
480
495
  case 'hash': {
481
496
  const { hash, receipt } = validated
482
- if (!(await markHashUsed(store, hash))) {
497
+ if (!(await tryClaimHash(store, hash, replayExpires))) {
483
498
  throw new VerificationFailedError({
484
499
  reason: 'Transaction hash has already been used',
485
500
  })
@@ -488,7 +503,7 @@ export function charge<const parameters extends charge.Parameters>(
488
503
  }
489
504
 
490
505
  case 'proof': {
491
- if (proofStore && !(await markProofUsed(proofStore, challenge.id))) {
506
+ if (proofStore && !(await tryClaimProof(proofStore, challenge.id, replayExpires))) {
492
507
  throw new VerificationFailedError({
493
508
  reason: 'Proof credential has already been used',
494
509
  })
@@ -507,7 +522,7 @@ export function charge<const parameters extends charge.Parameters>(
507
522
 
508
523
  // Pre-broadcast dedup: catch exact byte-for-byte replays early.
509
524
  const hash = keccak256(serializedTransaction)
510
- if (!(await markHashUsed(store, hash))) {
525
+ if (!(await tryClaimHash(store, hash, replayExpires))) {
511
526
  throw new VerificationFailedError({
512
527
  reason: 'Transaction hash has already been used',
513
528
  })
@@ -589,7 +604,7 @@ export function charge<const parameters extends charge.Parameters>(
589
604
 
590
605
  if (
591
606
  finalHash.toLowerCase() !== hash.toLowerCase() &&
592
- !(await markHashUsed(store, finalHash))
607
+ !(await tryClaimHash(store, finalHash, replayExpires))
593
608
  )
594
609
  throw new VerificationFailedError({
595
610
  reason: 'Transaction hash has already been used',
@@ -614,20 +629,21 @@ export function charge<const parameters extends charge.Parameters>(
614
629
  expiresAt,
615
630
  expires ? Date.parse(expires) : Number.MAX_SAFE_INTEGER,
616
631
  )
617
- reservation = await SponsorBudget.reserve(sponsorBudgetStore, {
618
- chainId: reservationChainId,
619
- expiresAt,
620
- fee: totalFee,
621
- getReceipt: (transactionHash) =>
622
- getTransactionReceipt(client, { hash: transactionHash }),
623
- id: finalHash.toLowerCase(),
624
- maxReservations: maxInFlightReservations,
625
- maxTotalFee: maxInFlightTotalFee,
626
- owner: globalThis.crypto.randomUUID(),
627
- sponsor,
628
- transactionHash: finalHash,
629
- waitUntil,
630
- })
632
+ if (sponsorBudgetStore)
633
+ reservation = await SponsorBudget.reserve(sponsorBudgetStore, {
634
+ chainId: reservationChainId,
635
+ expiresAt,
636
+ fee: totalFee,
637
+ getReceipt: (transactionHash) =>
638
+ getTransactionReceipt(client, { hash: transactionHash }),
639
+ id: finalHash.toLowerCase(),
640
+ maxReservations: maxInFlightReservations,
641
+ maxTotalFee: maxInFlightTotalFee,
642
+ owner: globalThis.crypto.randomUUID(),
643
+ sponsor,
644
+ transactionHash: finalHash,
645
+ waitUntil,
646
+ })
631
647
  Expires.assert(challenge.expires, challenge.id)
632
648
  }
633
649
 
@@ -640,7 +656,7 @@ export function charge<const parameters extends charge.Parameters>(
640
656
 
641
657
  if (
642
658
  reservation &&
643
- !(await SponsorBudget.transition(sponsorBudgetStore, reservation, 'broadcasting'))
659
+ !(await SponsorBudget.transition(sponsorBudgetStore!, reservation, 'broadcasting'))
644
660
  )
645
661
  throw new VerificationFailedError({
646
662
  reason: 'Sponsor budget reservation ownership was lost before broadcast',
@@ -651,7 +667,7 @@ export function charge<const parameters extends charge.Parameters>(
651
667
  const receipt = await sendRawTransactionSync(client, {
652
668
  serializedTransaction: serializedTransaction_final,
653
669
  })
654
- if (reservation) await SponsorBudget.release(sponsorBudgetStore, reservation)
670
+ if (reservation) await SponsorBudget.release(sponsorBudgetStore!, reservation)
655
671
  const matchedLogs = await assertTransferLogs(receipt, {
656
672
  currency,
657
673
  sender: transaction.from! as `0x${string}`,
@@ -681,7 +697,7 @@ export function charge<const parameters extends charge.Parameters>(
681
697
  })
682
698
  if (
683
699
  reservation &&
684
- !(await SponsorBudget.transition(sponsorBudgetStore, reservation, 'pending'))
700
+ !(await SponsorBudget.transition(sponsorBudgetStore!, reservation, 'pending'))
685
701
  )
686
702
  throw new VerificationFailedError({
687
703
  reason: 'Sponsor budget reservation ownership was lost after broadcast',
@@ -694,7 +710,7 @@ export function charge<const parameters extends charge.Parameters>(
694
710
  } as const
695
711
  } catch (error) {
696
712
  if (!broadcastAttempted) {
697
- if (reservation) await SponsorBudget.release(sponsorBudgetStore, reservation)
713
+ if (reservation) await SponsorBudget.release(sponsorBudgetStore!, reservation)
698
714
  if (finalHash && finalHash.toLowerCase() !== hash.toLowerCase())
699
715
  await releaseHashUse(store, finalHash)
700
716
  await releaseHashUse(store, hash)
@@ -710,7 +726,7 @@ export function charge<const parameters extends charge.Parameters>(
710
726
 
711
727
  export declare namespace charge {
712
728
  type StoreItemMap = {
713
- [key: `mppx:charge:${string}`]: number | SponsorBudget.State
729
+ [key: `mppx:charge:${string}`]: number | SponsorBudget.State | Store.ReplayMarker
714
730
  }
715
731
 
716
732
  type Defaults = LooseOmit<Method.RequestDefaults<typeof Methods.charge>, 'feePayer' | 'recipient'>
@@ -739,13 +755,8 @@ export declare namespace charge {
739
755
  /**
740
756
  * Override the fee-sponsor policy used when co-signing Tempo charge
741
757
  * transactions. Defaults resolve per chain, including a higher
742
- * priority-fee ceiling on Moderato and a bounded aggregate in-flight fee
743
- * budget. Sponsored transactions reserve their declared maximum fee
744
- * atomically; independent expiring-nonce transactions run concurrently
745
- * while capacity remains and wait for capacity when the budget is full.
746
- *
747
- * If you increase `maxGas`, `maxFeePerGas`, or `maxTotalFee`, you may also
748
- * need to raise `maxInFlightTotalFee`.
758
+ * priority-fee ceiling on Moderato. Aggregate in-flight exposure is
759
+ * configured separately with `sponsorBudget`.
749
760
  */
750
761
  feePayerPolicy?: FeePayerPolicy | undefined
751
762
  /**
@@ -795,6 +806,14 @@ export declare namespace charge {
795
806
  * it again.
796
807
  */
797
808
  relay?: RelayOptions | undefined
809
+ /**
810
+ * Configures aggregate in-flight fee exposure for sponsored transactions.
811
+ *
812
+ * Set to `false` only when aggregate exposure is enforced outside mppx.
813
+ * The configured store must be shared by every process using the sponsor.
814
+ * @default `{}`
815
+ */
816
+ sponsorBudget?: SponsorBudgetConfig | false | undefined
798
817
  /**
799
818
  * Whether to wait for the charge transaction to confirm on-chain before
800
819
  * responding. @default true
@@ -809,7 +828,8 @@ export declare namespace charge {
809
828
  waitForConfirmation?: boolean | undefined
810
829
  } & Client.getResolver.Parameters &
811
830
  Account.resolve.Parameters &
812
- Defaults
831
+ Defaults &
832
+ Method.ComposableHooks<typeof Methods.charge>
813
833
 
814
834
  type DeriveDefaults<parameters extends Parameters> = types.DeriveDefaults<
815
835
  parameters,
@@ -821,16 +841,28 @@ export declare namespace charge {
821
841
  >
822
842
 
823
843
  type FeePayerPolicy = Partial<FeePayer.Policy> & {
824
- /** Maximum number of sponsored transactions awaiting a terminal receipt. @default 100 */
844
+ /**
845
+ * Maximum number of sponsored transactions awaiting a terminal receipt.
846
+ * @deprecated Use `sponsorBudget.maxInFlightReservations`.
847
+ */
825
848
  maxInFlightReservations?: number | undefined
826
849
  /**
827
850
  * Maximum aggregate declared fee exposure awaiting terminal receipts.
828
851
  *
829
- * @default `maxTotalFee * 10`
852
+ * @deprecated Use `sponsorBudget.maxInFlightTotalFee`.
830
853
  */
831
854
  maxInFlightTotalFee?: bigint | undefined
832
855
  }
833
856
 
857
+ type SponsorBudgetConfig = {
858
+ /** Maximum number of sponsored transactions awaiting a terminal receipt. @default 100 */
859
+ maxInFlightReservations?: number | undefined
860
+ /** Maximum aggregate declared fee exposure. @default `feePayerPolicy.maxTotalFee * 10` */
861
+ maxInFlightTotalFee?: bigint | undefined
862
+ /** Atomic store shared by every process using the sponsor. Defaults to `store`. */
863
+ store?: Store.AtomicStore | undefined
864
+ }
865
+
834
866
  /** Tempo API relay configuration for server-side charges. */
835
867
  type RelayOptions = Relay.configure.Options
836
868
  }
@@ -1173,14 +1205,12 @@ function getProofStoreKey(challengeId: string): `mppx:charge:${string}` {
1173
1205
  return `mppx:charge:proof:${challengeId}`
1174
1206
  }
1175
1207
 
1176
- async function markHashUsed(
1208
+ async function tryClaimHash(
1177
1209
  store: Store.AtomicStore<charge.StoreItemMap>,
1178
1210
  hash: `0x${string}`,
1211
+ expires: number,
1179
1212
  ): Promise<boolean> {
1180
- return store.update(getHashStoreKey(hash), (current) => {
1181
- if (current !== null) return { op: 'noop', result: false }
1182
- return { op: 'set', value: Date.now(), result: true }
1183
- })
1213
+ return Store.tryClaim(store, getHashStoreKey(hash), expires)
1184
1214
  }
1185
1215
 
1186
1216
  /** @internal */
@@ -1207,14 +1237,12 @@ function parseHashCredentialSource(parameters: {
1207
1237
  }
1208
1238
 
1209
1239
  /** @internal */
1210
- async function markProofUsed(
1240
+ async function tryClaimProof(
1211
1241
  store: Store.AtomicStore<charge.StoreItemMap>,
1212
1242
  challengeId: string,
1243
+ expires: number,
1213
1244
  ): Promise<boolean> {
1214
- return store.update(getProofStoreKey(challengeId), (current) => {
1215
- if (current !== null) return { op: 'noop', result: false }
1216
- return { op: 'set', value: Date.now(), result: true }
1217
- })
1245
+ return Store.tryClaim(store, getProofStoreKey(challengeId), expires)
1218
1246
  }
1219
1247
 
1220
1248
  function recoverAuthorizedProofSigner(parameters: {