mppx 0.0.1 → 0.1.0

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 (446) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/dist/BodyDigest.d.ts +42 -0
  4. package/dist/BodyDigest.d.ts.map +1 -0
  5. package/dist/BodyDigest.js +40 -0
  6. package/dist/BodyDigest.js.map +1 -0
  7. package/dist/Challenge.d.ts +271 -0
  8. package/dist/Challenge.d.ts.map +1 -0
  9. package/dist/Challenge.js +291 -0
  10. package/dist/Challenge.js.map +1 -0
  11. package/dist/Credential.d.ts +91 -0
  12. package/dist/Credential.d.ts.map +1 -0
  13. package/dist/Credential.js +122 -0
  14. package/dist/Credential.js.map +1 -0
  15. package/dist/Errors.d.ts +243 -0
  16. package/dist/Errors.d.ts.map +1 -0
  17. package/dist/Errors.js +201 -0
  18. package/dist/Errors.js.map +1 -0
  19. package/dist/Expires.d.ts +15 -0
  20. package/dist/Expires.d.ts.map +1 -0
  21. package/dist/Expires.js +29 -0
  22. package/dist/Expires.js.map +1 -0
  23. package/dist/Intent.d.ts +101 -0
  24. package/dist/Intent.d.ts.map +1 -0
  25. package/dist/Intent.js +83 -0
  26. package/dist/Intent.js.map +1 -0
  27. package/dist/Mcp.d.ts +74 -0
  28. package/dist/Mcp.d.ts.map +1 -0
  29. package/dist/Mcp.js +9 -0
  30. package/dist/Mcp.js.map +1 -0
  31. package/dist/MethodIntent.d.ts +225 -0
  32. package/dist/MethodIntent.d.ts.map +1 -0
  33. package/dist/MethodIntent.js +156 -0
  34. package/dist/MethodIntent.js.map +1 -0
  35. package/dist/PaymentRequest.d.ts +88 -0
  36. package/dist/PaymentRequest.d.ts.map +1 -0
  37. package/dist/PaymentRequest.js +81 -0
  38. package/dist/PaymentRequest.js.map +1 -0
  39. package/dist/Receipt.d.ts +110 -0
  40. package/dist/Receipt.d.ts.map +1 -0
  41. package/dist/Receipt.js +105 -0
  42. package/dist/Receipt.js.map +1 -0
  43. package/dist/Store.d.ts +28 -0
  44. package/dist/Store.d.ts.map +1 -0
  45. package/dist/Store.js +61 -0
  46. package/dist/Store.js.map +1 -0
  47. package/dist/cli.d.ts +3 -0
  48. package/dist/cli.d.ts.map +1 -0
  49. package/dist/cli.js +1219 -0
  50. package/dist/cli.js.map +1 -0
  51. package/dist/client/Methods.d.ts +4 -0
  52. package/dist/client/Methods.d.ts.map +1 -0
  53. package/dist/client/Methods.js +4 -0
  54. package/dist/client/Methods.js.map +1 -0
  55. package/dist/client/Mppx.d.ts +84 -0
  56. package/dist/client/Mppx.d.ts.map +1 -0
  57. package/dist/client/Mppx.js +64 -0
  58. package/dist/client/Mppx.js.map +1 -0
  59. package/dist/client/Transport.d.ts +56 -0
  60. package/dist/client/Transport.d.ts.map +1 -0
  61. package/dist/client/Transport.js +81 -0
  62. package/dist/client/Transport.js.map +1 -0
  63. package/dist/client/index.d.ts +5 -0
  64. package/dist/client/index.d.ts.map +1 -0
  65. package/dist/client/index.js +5 -0
  66. package/dist/client/index.js.map +1 -0
  67. package/dist/client/internal/Fetch.d.ts +85 -0
  68. package/dist/client/internal/Fetch.d.ts.map +1 -0
  69. package/dist/client/internal/Fetch.js +95 -0
  70. package/dist/client/internal/Fetch.js.map +1 -0
  71. package/dist/index.d.ts +13 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +13 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/internal/types.d.ts +302 -0
  76. package/dist/internal/types.d.ts.map +1 -0
  77. package/dist/internal/types.js +2 -0
  78. package/dist/internal/types.js.map +1 -0
  79. package/dist/mcp-sdk/client/McpClient.d.ts +78 -0
  80. package/dist/mcp-sdk/client/McpClient.d.ts.map +1 -0
  81. package/dist/mcp-sdk/client/McpClient.js +98 -0
  82. package/dist/mcp-sdk/client/McpClient.js.map +1 -0
  83. package/dist/mcp-sdk/client/index.d.ts +3 -0
  84. package/dist/mcp-sdk/client/index.d.ts.map +1 -0
  85. package/dist/mcp-sdk/client/index.js +3 -0
  86. package/dist/mcp-sdk/client/index.js.map +1 -0
  87. package/dist/mcp-sdk/server/Transport.d.ts +43 -0
  88. package/dist/mcp-sdk/server/Transport.d.ts.map +1 -0
  89. package/dist/mcp-sdk/server/Transport.js +71 -0
  90. package/dist/mcp-sdk/server/Transport.js.map +1 -0
  91. package/dist/mcp-sdk/server/index.d.ts +2 -0
  92. package/dist/mcp-sdk/server/index.d.ts.map +1 -0
  93. package/dist/mcp-sdk/server/index.js +2 -0
  94. package/dist/mcp-sdk/server/index.js.map +1 -0
  95. package/dist/middlewares/elysia.d.ts +51 -0
  96. package/dist/middlewares/elysia.d.ts.map +1 -0
  97. package/dist/middlewares/elysia.js +59 -0
  98. package/dist/middlewares/elysia.js.map +1 -0
  99. package/dist/middlewares/express.d.ts +46 -0
  100. package/dist/middlewares/express.d.ts.map +1 -0
  101. package/dist/middlewares/express.js +69 -0
  102. package/dist/middlewares/express.js.map +1 -0
  103. package/dist/middlewares/hono.d.ts +46 -0
  104. package/dist/middlewares/hono.d.ts.map +1 -0
  105. package/dist/middlewares/hono.js +57 -0
  106. package/dist/middlewares/hono.js.map +1 -0
  107. package/dist/middlewares/internal/mppx.d.ts +16 -0
  108. package/dist/middlewares/internal/mppx.d.ts.map +1 -0
  109. package/dist/middlewares/internal/mppx.js +16 -0
  110. package/dist/middlewares/internal/mppx.js.map +1 -0
  111. package/dist/middlewares/nextjs.d.ts +45 -0
  112. package/dist/middlewares/nextjs.d.ts.map +1 -0
  113. package/dist/middlewares/nextjs.js +57 -0
  114. package/dist/middlewares/nextjs.js.map +1 -0
  115. package/dist/proxy/Proxy.d.ts +47 -0
  116. package/dist/proxy/Proxy.d.ts.map +1 -0
  117. package/dist/proxy/Proxy.js +126 -0
  118. package/dist/proxy/Proxy.js.map +1 -0
  119. package/dist/proxy/Service.d.ts +100 -0
  120. package/dist/proxy/Service.d.ts.map +1 -0
  121. package/dist/proxy/Service.js +147 -0
  122. package/dist/proxy/Service.js.map +1 -0
  123. package/dist/proxy/index.d.ts +7 -0
  124. package/dist/proxy/index.d.ts.map +1 -0
  125. package/dist/proxy/index.js +7 -0
  126. package/dist/proxy/index.js.map +1 -0
  127. package/dist/proxy/internal/Headers.d.ts +3 -0
  128. package/dist/proxy/internal/Headers.d.ts.map +1 -0
  129. package/dist/proxy/internal/Headers.js +41 -0
  130. package/dist/proxy/internal/Headers.js.map +1 -0
  131. package/dist/proxy/internal/Route.d.ts +14 -0
  132. package/dist/proxy/internal/Route.d.ts.map +1 -0
  133. package/dist/proxy/internal/Route.js +47 -0
  134. package/dist/proxy/internal/Route.js.map +1 -0
  135. package/dist/proxy/services/anthropic.d.ts +29 -0
  136. package/dist/proxy/services/anthropic.d.ts.map +1 -0
  137. package/dist/proxy/services/anthropic.js +30 -0
  138. package/dist/proxy/services/anthropic.js.map +1 -0
  139. package/dist/proxy/services/openai.d.ts +29 -0
  140. package/dist/proxy/services/openai.d.ts.map +1 -0
  141. package/dist/proxy/services/openai.js +30 -0
  142. package/dist/proxy/services/openai.js.map +1 -0
  143. package/dist/proxy/services/stripe.d.ts +29 -0
  144. package/dist/proxy/services/stripe.d.ts.map +1 -0
  145. package/dist/proxy/services/stripe.js +30 -0
  146. package/dist/proxy/services/stripe.js.map +1 -0
  147. package/dist/server/Methods.d.ts +3 -0
  148. package/dist/server/Methods.d.ts.map +1 -0
  149. package/dist/server/Methods.js +3 -0
  150. package/dist/server/Methods.js.map +1 -0
  151. package/dist/server/Mppx.d.ts +116 -0
  152. package/dist/server/Mppx.d.ts.map +1 -0
  153. package/dist/server/Mppx.js +207 -0
  154. package/dist/server/Mppx.js.map +1 -0
  155. package/dist/server/NodeListener.d.ts +3 -0
  156. package/dist/server/NodeListener.d.ts.map +1 -0
  157. package/dist/server/NodeListener.js +3 -0
  158. package/dist/server/NodeListener.js.map +1 -0
  159. package/dist/server/Request.d.ts +24 -0
  160. package/dist/server/Request.d.ts.map +1 -0
  161. package/dist/server/Request.js +26 -0
  162. package/dist/server/Request.js.map +1 -0
  163. package/dist/server/Response.d.ts +10 -0
  164. package/dist/server/Response.d.ts.map +1 -0
  165. package/dist/server/Response.js +15 -0
  166. package/dist/server/Response.js.map +1 -0
  167. package/dist/server/Transport.d.ts +93 -0
  168. package/dist/server/Transport.d.ts.map +1 -0
  169. package/dist/server/Transport.js +132 -0
  170. package/dist/server/Transport.js.map +1 -0
  171. package/dist/server/index.d.ts +9 -0
  172. package/dist/server/index.d.ts.map +1 -0
  173. package/dist/server/index.js +9 -0
  174. package/dist/server/index.js.map +1 -0
  175. package/dist/stripe/Intents.d.ts +54 -0
  176. package/dist/stripe/Intents.d.ts.map +1 -0
  177. package/dist/stripe/Intents.js +27 -0
  178. package/dist/stripe/Intents.js.map +1 -0
  179. package/dist/stripe/client/Charge.d.ts +114 -0
  180. package/dist/stripe/client/Charge.d.ts.map +1 -0
  181. package/dist/stripe/client/Charge.js +77 -0
  182. package/dist/stripe/client/Charge.js.map +1 -0
  183. package/dist/stripe/client/MethodIntents.d.ts +80 -0
  184. package/dist/stripe/client/MethodIntents.d.ts.map +1 -0
  185. package/dist/stripe/client/MethodIntents.js +34 -0
  186. package/dist/stripe/client/MethodIntents.js.map +1 -0
  187. package/dist/stripe/client/index.d.ts +3 -0
  188. package/dist/stripe/client/index.d.ts.map +1 -0
  189. package/dist/stripe/client/index.js +3 -0
  190. package/dist/stripe/client/index.js.map +1 -0
  191. package/dist/stripe/index.d.ts +2 -0
  192. package/dist/stripe/index.d.ts.map +1 -0
  193. package/dist/stripe/index.js +2 -0
  194. package/dist/stripe/index.js.map +1 -0
  195. package/dist/stripe/server/Charge.d.ts +74 -0
  196. package/dist/stripe/server/Charge.d.ts.map +1 -0
  197. package/dist/stripe/server/Charge.js +79 -0
  198. package/dist/stripe/server/Charge.js.map +1 -0
  199. package/dist/stripe/server/MethodIntents.d.ts +65 -0
  200. package/dist/stripe/server/MethodIntents.d.ts.map +1 -0
  201. package/dist/stripe/server/MethodIntents.js +21 -0
  202. package/dist/stripe/server/MethodIntents.js.map +1 -0
  203. package/dist/stripe/server/index.d.ts +3 -0
  204. package/dist/stripe/server/index.d.ts.map +1 -0
  205. package/dist/stripe/server/index.js +3 -0
  206. package/dist/stripe/server/index.js.map +1 -0
  207. package/dist/tempo/Attribution.d.ts +101 -0
  208. package/dist/tempo/Attribution.d.ts.map +1 -0
  209. package/dist/tempo/Attribution.js +124 -0
  210. package/dist/tempo/Attribution.js.map +1 -0
  211. package/dist/tempo/Intents.d.ts +132 -0
  212. package/dist/tempo/Intents.d.ts.map +1 -0
  213. package/dist/tempo/Intents.js +81 -0
  214. package/dist/tempo/Intents.js.map +1 -0
  215. package/dist/tempo/client/ChannelOps.d.ts +54 -0
  216. package/dist/tempo/client/ChannelOps.d.ts.map +1 -0
  217. package/dist/tempo/client/ChannelOps.js +138 -0
  218. package/dist/tempo/client/ChannelOps.js.map +1 -0
  219. package/dist/tempo/client/Charge.d.ts +76 -0
  220. package/dist/tempo/client/Charge.d.ts.map +1 -0
  221. package/dist/tempo/client/Charge.js +69 -0
  222. package/dist/tempo/client/Charge.js.map +1 -0
  223. package/dist/tempo/client/MethodIntents.d.ts +157 -0
  224. package/dist/tempo/client/MethodIntents.d.ts.map +1 -0
  225. package/dist/tempo/client/MethodIntents.js +25 -0
  226. package/dist/tempo/client/MethodIntents.js.map +1 -0
  227. package/dist/tempo/client/Session.d.ts +159 -0
  228. package/dist/tempo/client/Session.d.ts.map +1 -0
  229. package/dist/tempo/client/Session.js +263 -0
  230. package/dist/tempo/client/Session.js.map +1 -0
  231. package/dist/tempo/client/SessionManager.d.ts +62 -0
  232. package/dist/tempo/client/SessionManager.d.ts.map +1 -0
  233. package/dist/tempo/client/SessionManager.js +196 -0
  234. package/dist/tempo/client/SessionManager.js.map +1 -0
  235. package/dist/tempo/client/index.d.ts +6 -0
  236. package/dist/tempo/client/index.d.ts.map +1 -0
  237. package/dist/tempo/client/index.js +5 -0
  238. package/dist/tempo/client/index.js.map +1 -0
  239. package/dist/tempo/index.d.ts +3 -0
  240. package/dist/tempo/index.d.ts.map +1 -0
  241. package/dist/tempo/index.js +3 -0
  242. package/dist/tempo/index.js.map +1 -0
  243. package/dist/tempo/internal/account.d.ts +32 -0
  244. package/dist/tempo/internal/account.d.ts.map +1 -0
  245. package/dist/tempo/internal/account.js +33 -0
  246. package/dist/tempo/internal/account.js.map +1 -0
  247. package/dist/tempo/internal/defaults.d.ts +18 -0
  248. package/dist/tempo/internal/defaults.d.ts.map +1 -0
  249. package/dist/tempo/internal/defaults.js +18 -0
  250. package/dist/tempo/internal/defaults.js.map +1 -0
  251. package/dist/tempo/internal/types.d.ts +11 -0
  252. package/dist/tempo/internal/types.d.ts.map +1 -0
  253. package/dist/tempo/internal/types.js +2 -0
  254. package/dist/tempo/internal/types.js.map +1 -0
  255. package/dist/tempo/server/Charge.d.ts +77 -0
  256. package/dist/tempo/server/Charge.d.ts.map +1 -0
  257. package/dist/tempo/server/Charge.js +228 -0
  258. package/dist/tempo/server/Charge.js.map +1 -0
  259. package/dist/tempo/server/MethodIntents.d.ts +140 -0
  260. package/dist/tempo/server/MethodIntents.d.ts.map +1 -0
  261. package/dist/tempo/server/MethodIntents.js +26 -0
  262. package/dist/tempo/server/MethodIntents.js.map +1 -0
  263. package/dist/tempo/server/Session.d.ts +148 -0
  264. package/dist/tempo/server/Session.d.ts.map +1 -0
  265. package/dist/tempo/server/Session.js +529 -0
  266. package/dist/tempo/server/Session.js.map +1 -0
  267. package/dist/tempo/server/internal/transport.d.ts +47 -0
  268. package/dist/tempo/server/internal/transport.d.ts.map +1 -0
  269. package/dist/tempo/server/internal/transport.js +118 -0
  270. package/dist/tempo/server/internal/transport.js.map +1 -0
  271. package/dist/tempo/stream/Chain.d.ts +52 -0
  272. package/dist/tempo/stream/Chain.d.ts.map +1 -0
  273. package/dist/tempo/stream/Chain.js +215 -0
  274. package/dist/tempo/stream/Chain.js.map +1 -0
  275. package/dist/tempo/stream/Channel.d.ts +26 -0
  276. package/dist/tempo/stream/Channel.d.ts.map +1 -0
  277. package/dist/tempo/stream/Channel.js +27 -0
  278. package/dist/tempo/stream/Channel.js.map +1 -0
  279. package/dist/tempo/stream/ChannelStore.d.ts +103 -0
  280. package/dist/tempo/stream/ChannelStore.d.ts.map +1 -0
  281. package/dist/tempo/stream/ChannelStore.js +100 -0
  282. package/dist/tempo/stream/ChannelStore.js.map +1 -0
  283. package/dist/tempo/stream/Receipt.d.ts +22 -0
  284. package/dist/tempo/stream/Receipt.d.ts.map +1 -0
  285. package/dist/tempo/stream/Receipt.js +34 -0
  286. package/dist/tempo/stream/Receipt.js.map +1 -0
  287. package/dist/tempo/stream/Sse.d.ts +134 -0
  288. package/dist/tempo/stream/Sse.d.ts.map +1 -0
  289. package/dist/tempo/stream/Sse.js +288 -0
  290. package/dist/tempo/stream/Sse.js.map +1 -0
  291. package/dist/tempo/stream/Types.d.ts +78 -0
  292. package/dist/tempo/stream/Types.d.ts.map +1 -0
  293. package/dist/tempo/stream/Types.js +2 -0
  294. package/dist/tempo/stream/Types.js.map +1 -0
  295. package/dist/tempo/stream/Voucher.d.ts +20 -0
  296. package/dist/tempo/stream/Voucher.d.ts.map +1 -0
  297. package/dist/tempo/stream/Voucher.js +98 -0
  298. package/dist/tempo/stream/Voucher.js.map +1 -0
  299. package/dist/tempo/stream/escrow.abi.d.ts +598 -0
  300. package/dist/tempo/stream/escrow.abi.d.ts.map +1 -0
  301. package/dist/tempo/stream/escrow.abi.js +760 -0
  302. package/dist/tempo/stream/escrow.abi.js.map +1 -0
  303. package/dist/tempo/stream/index.d.ts +8 -0
  304. package/dist/tempo/stream/index.d.ts.map +1 -0
  305. package/dist/tempo/stream/index.js +8 -0
  306. package/dist/tempo/stream/index.js.map +1 -0
  307. package/dist/viem/Account.d.ts +12 -0
  308. package/dist/viem/Account.d.ts.map +1 -0
  309. package/dist/viem/Account.js +14 -0
  310. package/dist/viem/Account.js.map +1 -0
  311. package/dist/viem/Client.d.ts +21 -0
  312. package/dist/viem/Client.d.ts.map +1 -0
  313. package/dist/viem/Client.js +19 -0
  314. package/dist/viem/Client.js.map +1 -0
  315. package/dist/zod.d.ts +17 -0
  316. package/dist/zod.d.ts.map +1 -0
  317. package/dist/zod.js +35 -0
  318. package/dist/zod.js.map +1 -0
  319. package/package.json +117 -4
  320. package/src/BodyDigest.test.ts +43 -0
  321. package/src/BodyDigest.ts +53 -0
  322. package/src/Challenge.test-d.ts +81 -0
  323. package/src/Challenge.test.ts +414 -0
  324. package/src/Challenge.ts +429 -0
  325. package/src/Credential.test.ts +227 -0
  326. package/src/Credential.ts +154 -0
  327. package/src/Errors.test.ts +402 -0
  328. package/src/Errors.ts +348 -0
  329. package/src/Expires.ts +34 -0
  330. package/src/Intent.test.ts +180 -0
  331. package/src/Intent.ts +109 -0
  332. package/src/Mcp.ts +81 -0
  333. package/src/MethodIntent.test.ts +303 -0
  334. package/src/MethodIntent.ts +388 -0
  335. package/src/PaymentRequest.test.ts +152 -0
  336. package/src/PaymentRequest.ts +107 -0
  337. package/src/Receipt.test.ts +98 -0
  338. package/src/Receipt.ts +129 -0
  339. package/src/Store.ts +84 -0
  340. package/src/cli.test.ts +542 -0
  341. package/src/cli.ts +1319 -0
  342. package/src/client/Methods.ts +3 -0
  343. package/src/client/Mppx.test-d.ts +90 -0
  344. package/src/client/Mppx.test.ts +468 -0
  345. package/src/client/Mppx.ts +149 -0
  346. package/src/client/Transport.test.ts +283 -0
  347. package/src/client/Transport.ts +115 -0
  348. package/src/client/index.ts +4 -0
  349. package/src/client/internal/Fetch.test-d.ts +57 -0
  350. package/src/client/internal/Fetch.test.ts +281 -0
  351. package/src/client/internal/Fetch.ts +157 -0
  352. package/src/env.d.ts +11 -0
  353. package/src/index.ts +12 -0
  354. package/src/internal/types.ts +403 -0
  355. package/src/mcp-sdk/client/McpClient.test-d.ts +109 -0
  356. package/src/mcp-sdk/client/McpClient.test.ts +219 -0
  357. package/src/mcp-sdk/client/McpClient.ts +187 -0
  358. package/src/mcp-sdk/client/index.ts +2 -0
  359. package/src/mcp-sdk/server/Transport.ts +94 -0
  360. package/src/mcp-sdk/server/index.ts +1 -0
  361. package/src/middlewares/elysia.ts +66 -0
  362. package/src/middlewares/express.test.ts +155 -0
  363. package/src/middlewares/express.ts +82 -0
  364. package/src/middlewares/hono.test.ts +148 -0
  365. package/src/middlewares/hono.ts +62 -0
  366. package/src/middlewares/internal/mppx.ts +30 -0
  367. package/src/middlewares/nextjs.test.ts +164 -0
  368. package/src/middlewares/nextjs.ts +66 -0
  369. package/src/proxy/Proxy.test.ts +472 -0
  370. package/src/proxy/Proxy.ts +175 -0
  371. package/src/proxy/Service.test.ts +125 -0
  372. package/src/proxy/Service.ts +227 -0
  373. package/src/proxy/index.ts +6 -0
  374. package/src/proxy/internal/Headers.test.ts +100 -0
  375. package/src/proxy/internal/Headers.ts +40 -0
  376. package/src/proxy/internal/Route.test.ts +143 -0
  377. package/src/proxy/internal/Route.ts +54 -0
  378. package/src/proxy/services/anthropic.ts +45 -0
  379. package/src/proxy/services/openai.test.ts +97 -0
  380. package/src/proxy/services/openai.ts +48 -0
  381. package/src/proxy/services/stripe.ts +49 -0
  382. package/src/server/Methods.ts +2 -0
  383. package/src/server/Mppx.test-d.ts +343 -0
  384. package/src/server/Mppx.test.ts +342 -0
  385. package/src/server/Mppx.ts +378 -0
  386. package/src/server/NodeListener.test.ts +188 -0
  387. package/src/server/NodeListener.ts +3 -0
  388. package/src/server/Request.test.ts +102 -0
  389. package/src/server/Request.ts +33 -0
  390. package/src/server/Response.test.ts +31 -0
  391. package/src/server/Response.ts +27 -0
  392. package/src/server/Transport.test.ts +294 -0
  393. package/src/server/Transport.ts +222 -0
  394. package/src/server/index.ts +8 -0
  395. package/src/stripe/Charge.integration.test.ts +326 -0
  396. package/src/stripe/Intents.test.ts +52 -0
  397. package/src/stripe/Intents.ts +27 -0
  398. package/src/stripe/client/Charge.ts +119 -0
  399. package/src/stripe/client/MethodIntents.ts +37 -0
  400. package/src/stripe/client/index.ts +2 -0
  401. package/src/stripe/index.ts +1 -0
  402. package/src/stripe/server/Charge.ts +121 -0
  403. package/src/stripe/server/MethodIntents.ts +24 -0
  404. package/src/stripe/server/index.ts +2 -0
  405. package/src/tempo/Attribution.test.ts +187 -0
  406. package/src/tempo/Attribution.ts +156 -0
  407. package/src/tempo/Intents.test.ts +84 -0
  408. package/src/tempo/Intents.ts +93 -0
  409. package/src/tempo/client/ChannelOps.ts +233 -0
  410. package/src/tempo/client/Charge.ts +84 -0
  411. package/src/tempo/client/MethodIntents.ts +28 -0
  412. package/src/tempo/client/Session.ts +369 -0
  413. package/src/tempo/client/SessionManager.test.ts +223 -0
  414. package/src/tempo/client/SessionManager.ts +270 -0
  415. package/src/tempo/client/index.ts +5 -0
  416. package/src/tempo/index.ts +2 -0
  417. package/src/tempo/internal/account.ts +47 -0
  418. package/src/tempo/internal/defaults.ts +20 -0
  419. package/src/tempo/internal/types.ts +8 -0
  420. package/src/tempo/server/Charge.test.ts +847 -0
  421. package/src/tempo/server/Charge.ts +309 -0
  422. package/src/tempo/server/MethodIntents.ts +29 -0
  423. package/src/tempo/server/Session.test.ts +1349 -0
  424. package/src/tempo/server/Session.ts +773 -0
  425. package/src/tempo/server/Sse.test.ts +289 -0
  426. package/src/tempo/server/index.ts +5 -0
  427. package/src/tempo/server/internal/transport.ts +153 -0
  428. package/src/tempo/stream/Chain.ts +333 -0
  429. package/src/tempo/stream/Channel.ts +50 -0
  430. package/src/tempo/stream/ChannelStore.test.ts +473 -0
  431. package/src/tempo/stream/ChannelStore.ts +202 -0
  432. package/src/tempo/stream/Receipt.test.ts +84 -0
  433. package/src/tempo/stream/Receipt.ts +45 -0
  434. package/src/tempo/stream/Sse.test.ts +401 -0
  435. package/src/tempo/stream/Sse.ts +375 -0
  436. package/src/tempo/stream/Types.ts +86 -0
  437. package/src/tempo/stream/Voucher.test.ts +134 -0
  438. package/src/tempo/stream/Voucher.ts +123 -0
  439. package/src/tempo/stream/escrow.abi.ts +759 -0
  440. package/src/tempo/stream/index.ts +7 -0
  441. package/src/tsconfig.json +10 -0
  442. package/src/viem/Account.test.ts +71 -0
  443. package/src/viem/Account.ts +30 -0
  444. package/src/viem/Client.test.ts +58 -0
  445. package/src/viem/Client.ts +33 -0
  446. package/src/zod.ts +47 -0
@@ -0,0 +1,3 @@
1
+ export { stripe } from '../stripe/client/MethodIntents.js'
2
+ export { tempo } from '../tempo/client/MethodIntents.js'
3
+ export { session } from '../tempo/client/Session.js'
@@ -0,0 +1,90 @@
1
+ import type { Account } from 'viem'
2
+ import { describe, expectTypeOf, test } from 'vitest'
3
+ import * as MethodIntent from '../MethodIntent.js'
4
+ import { charge } from '../tempo/client/Charge.js'
5
+ import * as Intents from '../tempo/Intents.js'
6
+ import * as z from '../zod.js'
7
+ import * as Mppx from './Mppx.js'
8
+
9
+ describe('Mppx', () => {
10
+ test('has methods array', () => {
11
+ const method = charge({
12
+ account: {} as Account,
13
+ })
14
+ const mppx = Mppx.create({ methods: [method] })
15
+
16
+ expectTypeOf(mppx.methods).toMatchTypeOf<readonly MethodIntent.AnyClient[]>()
17
+ expectTypeOf(mppx.methods[0]?.name).toEqualTypeOf<'charge'>()
18
+ })
19
+
20
+ test('has createCredential function', () => {
21
+ const method = charge({
22
+ account: {} as Account,
23
+ })
24
+ const mppx = Mppx.create({ methods: [method] })
25
+
26
+ expectTypeOf(mppx.createCredential).toBeFunction()
27
+ expectTypeOf(mppx.createCredential).returns.toMatchTypeOf<Promise<string>>()
28
+ })
29
+ })
30
+
31
+ describe('create.Config', () => {
32
+ test('requires methods array', () => {
33
+ type Config = Mppx.create.Config
34
+
35
+ expectTypeOf<Config>().toHaveProperty('methods')
36
+ })
37
+ })
38
+
39
+ describe('Method.toClient', () => {
40
+ test('createCredential receives typed challenge', () => {
41
+ MethodIntent.toClient(Intents.charge, {
42
+ async createCredential({ challenge }) {
43
+ expectTypeOf(challenge.method).toBeString()
44
+ expectTypeOf(challenge.intent).toBeString()
45
+ expectTypeOf(challenge.request).toHaveProperty('amount')
46
+ expectTypeOf(challenge.request).toHaveProperty('currency')
47
+ expectTypeOf(challenge.request).toHaveProperty('recipient')
48
+
49
+ return 'Payment ...'
50
+ },
51
+ })
52
+ })
53
+
54
+ test('createCredential receives typed context when provided', () => {
55
+ MethodIntent.toClient(Intents.charge, {
56
+ context: z.object({
57
+ account: z.custom<Account>(),
58
+ extra: z.optional(z.string()),
59
+ }),
60
+ async createCredential({ context }) {
61
+ expectTypeOf(context.account).toEqualTypeOf<Account>()
62
+ expectTypeOf(context.extra).toEqualTypeOf<string | undefined>()
63
+
64
+ return 'Payment ...'
65
+ },
66
+ })
67
+ })
68
+ })
69
+
70
+ describe('Mppx with context', () => {
71
+ test('createCredential accepts context matching method schema', () => {
72
+ const method = charge()
73
+
74
+ const mppx = Mppx.create({ methods: [method] })
75
+
76
+ expectTypeOf(mppx.createCredential).toBeFunction()
77
+ expectTypeOf(mppx.createCredential).returns.toMatchTypeOf<Promise<string>>()
78
+ })
79
+
80
+ test('createCredential context is optional when account provided at creation', () => {
81
+ const method = charge({
82
+ account: {} as Account,
83
+ })
84
+
85
+ const mppx = Mppx.create({ methods: [method] })
86
+
87
+ expectTypeOf(mppx.createCredential).toBeFunction()
88
+ expectTypeOf(mppx.createCredential).returns.toMatchTypeOf<Promise<string>>()
89
+ })
90
+ })
@@ -0,0 +1,468 @@
1
+ import { Challenge, Credential, Intent, Mcp, MethodIntent, Receipt } from 'mppx'
2
+ import { Mppx, Transport, tempo } from 'mppx/client'
3
+ import { Mppx as Mppx_server, tempo as tempo_server } from 'mppx/server'
4
+ import { MethodIntents } from 'mppx/tempo'
5
+ import { afterEach, describe, expect, test } from 'vitest'
6
+ import * as Http from '~test/Http.js'
7
+ import { accounts, asset, client } from '~test/tempo/viem.js'
8
+
9
+ const realm = 'api.example.com'
10
+ const secretKey = 'test-secret-key'
11
+
12
+ afterEach(() => {
13
+ Mppx.restore()
14
+ })
15
+
16
+ describe('Mppx.create', () => {
17
+ test('default', () => {
18
+ const mppx = Mppx.create({
19
+ polyfill: false,
20
+ methods: [tempo({ account: accounts[1], getClient: () => client })],
21
+ })
22
+
23
+ expect(mppx.methods).toHaveLength(2)
24
+ expect(mppx.methods[0]?.method).toBe('tempo')
25
+ expect(mppx.methods[0]?.name).toBe('charge')
26
+ expect(mppx.methods[1]?.method).toBe('tempo')
27
+ expect(mppx.methods[1]?.name).toBe('session')
28
+ expect(mppx.transport.name).toBe('http')
29
+ expect(typeof mppx.createCredential).toBe('function')
30
+ expect(typeof mppx.fetch).toBe('function')
31
+ })
32
+
33
+ test('behavior: with mcp transport', () => {
34
+ const mppx = Mppx.create({
35
+ polyfill: false,
36
+ methods: [tempo({ account: accounts[1], getClient: () => client })],
37
+ transport: Transport.mcp(),
38
+ })
39
+
40
+ expect(mppx.transport.name).toBe('mcp')
41
+ })
42
+
43
+ test('behavior: with multiple methods', () => {
44
+ const stripeCharge = MethodIntent.fromIntent(Intent.charge, {
45
+ method: 'stripe',
46
+ schema: {
47
+ credential: {
48
+ payload: MethodIntents.charge.schema.credential.payload,
49
+ },
50
+ },
51
+ })
52
+ const stripeMethod = MethodIntent.toClient(stripeCharge, {
53
+ async createCredential({ challenge }) {
54
+ return Credential.serialize({
55
+ challenge,
56
+ payload: { signature: '0xstripe', type: 'transaction' },
57
+ })
58
+ },
59
+ })
60
+
61
+ const mppx = Mppx.create({
62
+ polyfill: false,
63
+ methods: [tempo({ account: accounts[1], getClient: () => client }), stripeMethod],
64
+ })
65
+
66
+ expect(mppx.methods).toHaveLength(3)
67
+ expect(mppx.methods[0]?.method).toBe('tempo')
68
+ expect(mppx.methods[1]?.method).toBe('tempo')
69
+ expect(mppx.methods[2]?.method).toBe('stripe')
70
+ })
71
+ })
72
+
73
+ describe('createCredential', () => {
74
+ test('behavior: routes to correct method based on challenge', async () => {
75
+ const mppx = Mppx.create({
76
+ polyfill: false,
77
+ methods: [tempo({ account: accounts[1], getClient: () => client })],
78
+ })
79
+
80
+ const challenge = Challenge.fromIntent(MethodIntents.charge, {
81
+ realm,
82
+ secretKey,
83
+ request: {
84
+ amount: '1000',
85
+ currency: '0x1234567890123456789012345678901234567890',
86
+ decimals: 6,
87
+ recipient: '0x1234567890123456789012345678901234567890',
88
+ expires: new Date(Date.now() + 60_000).toISOString(),
89
+ },
90
+ })
91
+
92
+ const response = new Response(null, {
93
+ status: 402,
94
+ headers: {
95
+ 'WWW-Authenticate': Challenge.serialize(challenge),
96
+ },
97
+ })
98
+
99
+ const credential = await mppx.createCredential(response)
100
+
101
+ expect(credential).toMatch(/^Payment /)
102
+
103
+ const parsed = Credential.deserialize(credential)
104
+ expect((parsed.payload as { type: string }).type).toBe('transaction')
105
+ expect(parsed.challenge.method).toBe('tempo')
106
+ })
107
+
108
+ test('behavior: throws when method not found', async () => {
109
+ const mppx = Mppx.create({
110
+ polyfill: false,
111
+ methods: [tempo({ account: accounts[1], getClient: () => client })],
112
+ })
113
+
114
+ const challenge = Challenge.from({
115
+ id: 'test-id',
116
+ realm,
117
+ method: 'unknown',
118
+ intent: 'charge',
119
+ request: { amount: '1000', currency: '0x1234' },
120
+ })
121
+
122
+ const response = new Response(null, {
123
+ status: 402,
124
+ headers: {
125
+ 'WWW-Authenticate': Challenge.serialize(challenge),
126
+ },
127
+ })
128
+
129
+ await expect(mppx.createCredential(response)).rejects.toThrow(
130
+ 'No method intent found for "unknown.charge". Available: tempo.charge, tempo.session',
131
+ )
132
+ })
133
+
134
+ test('behavior: routes to correct method with multiple methods', async () => {
135
+ const stripeCharge = MethodIntent.fromIntent(Intent.charge, {
136
+ method: 'stripe',
137
+ schema: {
138
+ credential: {
139
+ payload: MethodIntents.charge.schema.credential.payload,
140
+ },
141
+ },
142
+ })
143
+
144
+ const stripe = MethodIntent.toClient(stripeCharge, {
145
+ async createCredential({ challenge }) {
146
+ return Credential.serialize({
147
+ challenge,
148
+ payload: { signature: '0xstripe', type: 'transaction' },
149
+ })
150
+ },
151
+ })
152
+
153
+ const mppx = Mppx.create({
154
+ polyfill: false,
155
+ methods: [tempo({ account: accounts[1], getClient: () => client }), stripe],
156
+ })
157
+
158
+ const stripeChallenge = Challenge.from({
159
+ id: 'stripe-challenge-id',
160
+ realm,
161
+ method: 'stripe',
162
+ intent: 'charge',
163
+ request: {
164
+ amount: '2000',
165
+ currency: '0xabcd',
166
+ recipient: '0xefgh',
167
+ expires: new Date(Date.now() + 60_000).toISOString(),
168
+ },
169
+ })
170
+
171
+ const response = new Response(null, {
172
+ status: 402,
173
+ headers: {
174
+ 'WWW-Authenticate': Challenge.serialize(stripeChallenge),
175
+ },
176
+ })
177
+
178
+ const credential = await mppx.createCredential(response)
179
+ const parsed = Credential.deserialize(credential)
180
+
181
+ expect(parsed.payload).toEqual({ signature: '0xstripe', type: 'transaction' })
182
+ expect(parsed.challenge.method).toBe('stripe')
183
+ })
184
+
185
+ test('behavior: passes context to createCredential', async () => {
186
+ const mppx = Mppx.create({
187
+ polyfill: false,
188
+ methods: [tempo({ getClient: () => client })],
189
+ })
190
+
191
+ const challenge = Challenge.fromIntent(MethodIntents.charge, {
192
+ realm,
193
+ secretKey,
194
+ request: {
195
+ amount: '1000',
196
+ currency: '0x1234567890123456789012345678901234567890',
197
+ decimals: 6,
198
+ recipient: '0x1234567890123456789012345678901234567890',
199
+ expires: new Date(Date.now() + 60_000).toISOString(),
200
+ },
201
+ })
202
+
203
+ const response = new Response(null, {
204
+ status: 402,
205
+ headers: {
206
+ 'WWW-Authenticate': Challenge.serialize(challenge),
207
+ },
208
+ })
209
+
210
+ const credential = await mppx.createCredential(response, { account: accounts[1] })
211
+
212
+ const parsed = Credential.deserialize(credential)
213
+ expect((parsed.payload as { type: string }).type).toBe('transaction')
214
+ expect(parsed.source).toContain(accounts[1].address)
215
+ })
216
+
217
+ test('behavior: works without context when account provided at creation', async () => {
218
+ const mppx = Mppx.create({
219
+ polyfill: false,
220
+ methods: [tempo({ account: accounts[1], getClient: () => client })],
221
+ })
222
+
223
+ const challenge = Challenge.fromIntent(MethodIntents.charge, {
224
+ realm,
225
+ secretKey,
226
+ request: {
227
+ amount: '1000',
228
+ currency: '0x1234567890123456789012345678901234567890',
229
+ decimals: 6,
230
+ recipient: '0x1234567890123456789012345678901234567890',
231
+ expires: new Date(Date.now() + 60_000).toISOString(),
232
+ },
233
+ })
234
+
235
+ const response = new Response(null, {
236
+ status: 402,
237
+ headers: {
238
+ 'WWW-Authenticate': Challenge.serialize(challenge),
239
+ },
240
+ })
241
+
242
+ const credential = await mppx.createCredential(response)
243
+ const parsed = Credential.deserialize(credential)
244
+ expect((parsed.payload as { type: string }).type).toBe('transaction')
245
+ })
246
+
247
+ test('behavior: with mcp transport', async () => {
248
+ const mppx = Mppx.create({
249
+ polyfill: false,
250
+ methods: [tempo({ account: accounts[1], getClient: () => client })],
251
+ transport: Transport.mcp(),
252
+ })
253
+
254
+ const challenge = Challenge.fromIntent(MethodIntents.charge, {
255
+ realm,
256
+ secretKey,
257
+ request: {
258
+ amount: '1000',
259
+ currency: '0x1234567890123456789012345678901234567890',
260
+ decimals: 6,
261
+ recipient: '0x1234567890123456789012345678901234567890',
262
+ expires: new Date(Date.now() + 60_000).toISOString(),
263
+ },
264
+ })
265
+
266
+ const mcpResponse: Mcp.Response = {
267
+ jsonrpc: '2.0',
268
+ id: 1,
269
+ error: {
270
+ code: Mcp.paymentRequiredCode,
271
+ message: 'Payment Required',
272
+ data: {
273
+ httpStatus: 402,
274
+ challenges: [challenge],
275
+ },
276
+ },
277
+ }
278
+
279
+ const credential = await mppx.createCredential(mcpResponse)
280
+ const parsed = Credential.deserialize(credential)
281
+ expect((parsed.payload as { type: string }).type).toBe('transaction')
282
+ expect(parsed.challenge.method).toBe('tempo')
283
+ })
284
+ })
285
+
286
+ const server = Mppx_server.create({
287
+ methods: [
288
+ tempo_server.charge({
289
+ currency: asset,
290
+ getClient: () => client,
291
+ recipient: accounts[0].address,
292
+ }),
293
+ ],
294
+ })
295
+
296
+ describe('fetch', () => {
297
+ test('default: handles 402 automatically', async () => {
298
+ const mppx = Mppx.create({
299
+ polyfill: false,
300
+ methods: [
301
+ tempo({
302
+ account: accounts[1],
303
+ getClient: () => client,
304
+ }),
305
+ ],
306
+ })
307
+
308
+ const httpServer = await Http.createServer(async (req, res) => {
309
+ const result = await Mppx_server.toNodeListener(
310
+ server.charge({
311
+ amount: '1',
312
+ }),
313
+ )(req, res)
314
+ if (result.status === 402) return
315
+ res.end('OK')
316
+ })
317
+
318
+ const response = await mppx.fetch(httpServer.url)
319
+ expect(response.status).toBe(200)
320
+
321
+ const receipt = Receipt.fromResponse(response)
322
+ expect(receipt.status).toBe('success')
323
+ expect(receipt.method).toBe('tempo')
324
+
325
+ httpServer.close()
326
+ })
327
+
328
+ test('behavior: passes through non-402 responses', async () => {
329
+ const mppx = Mppx.create({
330
+ polyfill: false,
331
+ methods: [
332
+ tempo({
333
+ account: accounts[1],
334
+ getClient: () => client,
335
+ }),
336
+ ],
337
+ })
338
+
339
+ const httpServer = await Http.createServer(async (_req, res) => {
340
+ res.writeHead(200)
341
+ res.end('OK')
342
+ })
343
+
344
+ const response = await mppx.fetch(httpServer.url)
345
+ expect(response.status).toBe(200)
346
+ expect(await response.text()).toBe('OK')
347
+
348
+ httpServer.close()
349
+ })
350
+
351
+ test('behavior: supports context', async () => {
352
+ const mppx = Mppx.create({
353
+ polyfill: false,
354
+ methods: [
355
+ tempo({
356
+ getClient: () => client,
357
+ }),
358
+ ],
359
+ })
360
+
361
+ const httpServer = await Http.createServer(async (req, res) => {
362
+ const result = await Mppx_server.toNodeListener(
363
+ server.charge({
364
+ amount: '1',
365
+ }),
366
+ )(req, res)
367
+ if (result.status === 402) return
368
+ res.end('OK')
369
+ })
370
+
371
+ const response = await mppx.fetch(httpServer.url, {
372
+ context: { account: accounts[1] },
373
+ })
374
+ expect(response.status).toBe(200)
375
+
376
+ httpServer.close()
377
+ })
378
+ })
379
+
380
+ describe('polyfill', () => {
381
+ test('default: polyfills globalThis.fetch', async () => {
382
+ const originalFetch = globalThis.fetch
383
+
384
+ Mppx.create({
385
+ methods: [
386
+ tempo({
387
+ account: accounts[1],
388
+ getClient: () => client,
389
+ }),
390
+ ],
391
+ })
392
+
393
+ expect(globalThis.fetch).not.toBe(originalFetch)
394
+
395
+ const httpServer = await Http.createServer(async (req, res) => {
396
+ const result = await Mppx_server.toNodeListener(
397
+ server.charge({
398
+ amount: '1',
399
+ }),
400
+ )(req, res)
401
+ if (result.status === 402) return
402
+ res.end('OK')
403
+ })
404
+
405
+ const response = await fetch(httpServer.url)
406
+ expect(response.status).toBe(200)
407
+
408
+ const receipt = Receipt.fromResponse(response)
409
+ expect(receipt.status).toBe('success')
410
+
411
+ httpServer.close()
412
+ })
413
+
414
+ test('behavior: polyfill false does not mutate globalThis.fetch', () => {
415
+ const originalFetch = globalThis.fetch
416
+
417
+ Mppx.create({
418
+ polyfill: false,
419
+ methods: [
420
+ tempo({
421
+ account: accounts[1],
422
+ getClient: () => client,
423
+ }),
424
+ ],
425
+ })
426
+
427
+ expect(globalThis.fetch).toBe(originalFetch)
428
+ })
429
+ })
430
+
431
+ describe('restore', () => {
432
+ test('default: restores original fetch', () => {
433
+ const originalFetch = globalThis.fetch
434
+
435
+ Mppx.create({
436
+ methods: [
437
+ tempo({
438
+ account: accounts[1],
439
+ getClient: () => client,
440
+ }),
441
+ ],
442
+ })
443
+
444
+ expect(globalThis.fetch).not.toBe(originalFetch)
445
+
446
+ Mppx.restore()
447
+
448
+ expect(globalThis.fetch).toBe(originalFetch)
449
+ })
450
+
451
+ test('behavior: noop when not polyfilled', () => {
452
+ const originalFetch = globalThis.fetch
453
+
454
+ Mppx.create({
455
+ polyfill: false,
456
+ methods: [
457
+ tempo({
458
+ account: accounts[1],
459
+ getClient: () => client,
460
+ }),
461
+ ],
462
+ })
463
+
464
+ Mppx.restore()
465
+
466
+ expect(globalThis.fetch).toBe(originalFetch)
467
+ })
468
+ })
@@ -0,0 +1,149 @@
1
+ import type * as Challenge from '../Challenge.js'
2
+ import type * as MethodIntent from '../MethodIntent.js'
3
+ import type * as z from '../zod.js'
4
+ import * as Fetch from './internal/Fetch.js'
5
+ import * as Transport from './Transport.js'
6
+
7
+ export type Methods = readonly (MethodIntent.AnyClient | readonly MethodIntent.AnyClient[])[]
8
+
9
+ /**
10
+ * Client-side payment handler.
11
+ */
12
+ export type Mppx<
13
+ methods extends Methods = Methods,
14
+ transport extends Transport.Transport = Transport.Transport,
15
+ > = {
16
+ /** Payment-aware fetch function that automatically handles 402 responses. */
17
+ fetch: Fetch.from.Fetch<FlattenMethods<methods>>
18
+ /** Methods to configure. */
19
+ methods: FlattenMethods<methods>
20
+ /** The transport used. */
21
+ transport: transport
22
+ /** Creates a credential from a payment-required response by routing to the correct method. */
23
+ createCredential: (
24
+ response: Transport.ResponseOf<transport>,
25
+ context?: AnyContextFor<FlattenMethods<methods>> | undefined,
26
+ ) => Promise<string>
27
+ }
28
+
29
+ /**
30
+ * Creates a client-side payment handler from an array of method intents.
31
+ *
32
+ * Returns a payment handler with a `fetch` function that automatically handles
33
+ * 402 Payment Required responses. By default, also polyfills `globalThis.fetch`.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import { Mppx, tempo } from 'mppx/client'
38
+ *
39
+ * const mppx = Mppx.create({
40
+ * methods: [tempo({ account })],
41
+ * })
42
+ *
43
+ * // Use the returned fetch — handles 402 automatically
44
+ * const res = await mppx.fetch('/resource')
45
+ *
46
+ * // Or use globalThis.fetch (polyfilled by default)
47
+ * const res2 = await fetch('/resource')
48
+ * ```
49
+ */
50
+ export function create<
51
+ const methods extends Methods,
52
+ const transport extends Transport.Transport<any, any> = Transport.Transport<
53
+ RequestInit,
54
+ Response
55
+ >,
56
+ >(config: create.Config<methods, transport>): Mppx<methods, transport> {
57
+ const { polyfill = true, transport = Transport.http() as transport } = config
58
+
59
+ const methods = config.methods.flat() as unknown as FlattenMethods<methods>
60
+
61
+ const config_fetch = { ...(config.fetch && { fetch: config.fetch }), methods }
62
+ const fetch = Fetch.from(config_fetch)
63
+
64
+ if (polyfill) Fetch.polyfill(config_fetch)
65
+ return {
66
+ fetch,
67
+ methods,
68
+ transport,
69
+ async createCredential(response: Transport.ResponseOf<transport>, context?: unknown) {
70
+ const challenge = transport.getChallenge(response as never) as Challenge.Challenge
71
+
72
+ const mi = methods.find((m) => m.method === challenge.method && m.name === challenge.intent)
73
+ if (!mi)
74
+ throw new Error(
75
+ `No method intent found for "${challenge.method}.${challenge.intent}". Available: ${methods.map((m) => `${m.method}.${m.name}`).join(', ')}`,
76
+ )
77
+
78
+ const parsedContext =
79
+ mi.context && context !== undefined ? mi.context.parse(context) : undefined
80
+
81
+ return mi.createCredential(
82
+ parsedContext !== undefined
83
+ ? { challenge, context: parsedContext }
84
+ : ({ challenge } as never),
85
+ )
86
+ },
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Restores the original `fetch` after `create()` polyfilled it.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * import { Mppx, tempo } from 'mppx/client'
96
+ *
97
+ * Mppx.create({ methods: [tempo({ account })] })
98
+ *
99
+ * // ... use payment-aware fetch ...
100
+ *
101
+ * Mppx.restore()
102
+ * ```
103
+ */
104
+ export function restore(): void {
105
+ Fetch.restore()
106
+ }
107
+
108
+ export declare namespace create {
109
+ type Config<
110
+ methods extends Methods = Methods,
111
+ transport extends Transport.Transport = Transport.Transport,
112
+ > = {
113
+ /** Custom fetch function to wrap. Defaults to `globalThis.fetch`. */
114
+ fetch?: typeof globalThis.fetch
115
+ /** Array of method intents to use. Accepts individual clients or tuples (e.g. from `tempo()`). */
116
+ methods: methods
117
+ /** Whether to polyfill `globalThis.fetch` with the payment-aware wrapper. @default true */
118
+ polyfill?: boolean | undefined
119
+ /** Transport to use (defaults to HTTP). */
120
+ transport?: transport | undefined
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Union of all context types from all methods that have context schemas.
126
+ * @internal
127
+ */
128
+ type AnyContextFor<methods extends readonly MethodIntent.AnyClient[]> = {
129
+ [method in keyof methods]: methods[method] extends MethodIntent.Client<any, infer context>
130
+ ? context extends z.ZodMiniType
131
+ ? z.input<context>
132
+ : undefined
133
+ : undefined
134
+ }[number]
135
+
136
+ /**
137
+ * Flattens a methods config tuple, preserving positional types.
138
+ * @internal
139
+ */
140
+ type FlattenMethods<methods extends Methods> = methods extends readonly [
141
+ infer head,
142
+ ...infer tail extends Methods,
143
+ ]
144
+ ? head extends readonly MethodIntent.AnyClient[]
145
+ ? readonly [...head, ...FlattenMethods<tail>]
146
+ : head extends MethodIntent.AnyClient
147
+ ? readonly [head, ...FlattenMethods<tail>]
148
+ : never
149
+ : readonly []