mppx 0.6.30 → 0.7.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 (483) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/Challenge.d.ts.map +1 -1
  3. package/dist/Challenge.js +9 -7
  4. package/dist/Challenge.js.map +1 -1
  5. package/dist/Constants.d.ts +46 -0
  6. package/dist/Constants.d.ts.map +1 -0
  7. package/dist/Constants.js +46 -0
  8. package/dist/Constants.js.map +1 -0
  9. package/dist/Credential.d.ts.map +1 -1
  10. package/dist/Credential.js +5 -4
  11. package/dist/Credential.js.map +1 -1
  12. package/dist/Method.d.ts +32 -4
  13. package/dist/Method.d.ts.map +1 -1
  14. package/dist/Method.js +5 -2
  15. package/dist/Method.js.map +1 -1
  16. package/dist/Receipt.d.ts.map +1 -1
  17. package/dist/Receipt.js +3 -2
  18. package/dist/Receipt.js.map +1 -1
  19. package/dist/cli/cli.d.ts.map +1 -1
  20. package/dist/cli/cli.js +19 -11
  21. package/dist/cli/cli.js.map +1 -1
  22. package/dist/cli/plugins/tempo.d.ts.map +1 -1
  23. package/dist/cli/plugins/tempo.js +17 -6
  24. package/dist/cli/plugins/tempo.js.map +1 -1
  25. package/dist/cli/utils.d.ts +5 -0
  26. package/dist/cli/utils.d.ts.map +1 -1
  27. package/dist/cli/utils.js +10 -0
  28. package/dist/cli/utils.js.map +1 -1
  29. package/dist/client/Methods.d.ts +5 -2
  30. package/dist/client/Methods.d.ts.map +1 -1
  31. package/dist/client/Methods.js +5 -2
  32. package/dist/client/Methods.js.map +1 -1
  33. package/dist/client/Transport.d.ts.map +1 -1
  34. package/dist/client/Transport.js +4 -5
  35. package/dist/client/Transport.js.map +1 -1
  36. package/dist/client/index.d.ts +2 -1
  37. package/dist/client/index.d.ts.map +1 -1
  38. package/dist/client/index.js +2 -1
  39. package/dist/client/index.js.map +1 -1
  40. package/dist/client/internal/Fetch.d.ts.map +1 -1
  41. package/dist/client/internal/Fetch.js +14 -6
  42. package/dist/client/internal/Fetch.js.map +1 -1
  43. package/dist/evm/server/Methods.d.ts +1 -1
  44. package/dist/evm/server/Methods.d.ts.map +1 -1
  45. package/dist/index.d.ts +1 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +1 -0
  48. package/dist/index.js.map +1 -1
  49. package/dist/internal/AcceptPayment.d.ts +3 -0
  50. package/dist/internal/AcceptPayment.d.ts.map +1 -1
  51. package/dist/internal/AcceptPayment.js +15 -11
  52. package/dist/internal/AcceptPayment.js.map +1 -1
  53. package/dist/mcp-sdk/client/McpClient.d.ts +12 -5
  54. package/dist/mcp-sdk/client/McpClient.d.ts.map +1 -1
  55. package/dist/mcp-sdk/client/McpClient.js +55 -42
  56. package/dist/mcp-sdk/client/McpClient.js.map +1 -1
  57. package/dist/server/Mppx.d.ts +11 -3
  58. package/dist/server/Mppx.d.ts.map +1 -1
  59. package/dist/server/Mppx.js +76 -27
  60. package/dist/server/Mppx.js.map +1 -1
  61. package/dist/server/Request.js +24 -10
  62. package/dist/server/Request.js.map +1 -1
  63. package/dist/server/Response.d.ts.map +1 -1
  64. package/dist/server/Response.js +2 -1
  65. package/dist/server/Response.js.map +1 -1
  66. package/dist/server/Transport.d.ts.map +1 -1
  67. package/dist/server/Transport.js +4 -3
  68. package/dist/server/Transport.js.map +1 -1
  69. package/dist/server/index.d.ts +1 -0
  70. package/dist/server/index.d.ts.map +1 -1
  71. package/dist/server/index.js +1 -0
  72. package/dist/server/index.js.map +1 -1
  73. package/dist/stripe/client/Charge.d.ts +1 -1
  74. package/dist/stripe/client/Charge.d.ts.map +1 -1
  75. package/dist/stripe/client/Charge.js +3 -1
  76. package/dist/stripe/client/Charge.js.map +1 -1
  77. package/dist/stripe/server/Charge.d.ts +1 -1
  78. package/dist/stripe/server/Charge.d.ts.map +1 -1
  79. package/dist/stripe/server/Charge.js +9 -2
  80. package/dist/stripe/server/Charge.js.map +1 -1
  81. package/dist/stripe/server/Methods.d.ts +1 -1
  82. package/dist/stripe/server/Methods.d.ts.map +1 -1
  83. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  84. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
  85. package/dist/stripe/server/internal/html.gen.js +1 -1
  86. package/dist/stripe/server/internal/html.gen.js.map +1 -1
  87. package/dist/tempo/Methods.d.ts +18 -0
  88. package/dist/tempo/Methods.d.ts.map +1 -1
  89. package/dist/tempo/Methods.js +16 -1
  90. package/dist/tempo/Methods.js.map +1 -1
  91. package/dist/tempo/client/Charge.d.ts +6 -0
  92. package/dist/tempo/client/Charge.d.ts.map +1 -1
  93. package/dist/tempo/client/Charge.js +9 -2
  94. package/dist/tempo/client/Charge.js.map +1 -1
  95. package/dist/tempo/client/Methods.d.ts +36 -7
  96. package/dist/tempo/client/Methods.d.ts.map +1 -1
  97. package/dist/tempo/client/Methods.js +12 -5
  98. package/dist/tempo/client/Methods.js.map +1 -1
  99. package/dist/tempo/client/index.d.ts +7 -4
  100. package/dist/tempo/client/index.d.ts.map +1 -1
  101. package/dist/tempo/client/index.js +5 -3
  102. package/dist/tempo/client/index.js.map +1 -1
  103. package/dist/tempo/index.d.ts +1 -0
  104. package/dist/tempo/index.d.ts.map +1 -1
  105. package/dist/tempo/index.js +1 -0
  106. package/dist/tempo/index.js.map +1 -1
  107. package/dist/tempo/internal/fee-payer.d.ts +21 -1
  108. package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
  109. package/dist/tempo/internal/fee-payer.js +109 -4
  110. package/dist/tempo/internal/fee-payer.js.map +1 -1
  111. package/dist/tempo/{client → legacy/client}/ChannelOps.d.ts +19 -6
  112. package/dist/tempo/legacy/client/ChannelOps.d.ts.map +1 -0
  113. package/dist/tempo/{client → legacy/client}/ChannelOps.js +9 -3
  114. package/dist/tempo/legacy/client/ChannelOps.js.map +1 -0
  115. package/dist/tempo/{client → legacy/client}/Session.d.ts +23 -4
  116. package/dist/tempo/legacy/client/Session.d.ts.map +1 -0
  117. package/dist/tempo/{client → legacy/client}/Session.js +14 -7
  118. package/dist/tempo/legacy/client/Session.js.map +1 -0
  119. package/dist/tempo/{client → legacy/client}/SessionManager.d.ts +20 -5
  120. package/dist/tempo/legacy/client/SessionManager.d.ts.map +1 -0
  121. package/dist/tempo/{client → legacy/client}/SessionManager.js +20 -16
  122. package/dist/tempo/legacy/client/SessionManager.js.map +1 -0
  123. package/dist/tempo/legacy/client/index.d.ts +7 -0
  124. package/dist/tempo/legacy/client/index.d.ts.map +1 -0
  125. package/dist/tempo/legacy/client/index.js +5 -0
  126. package/dist/tempo/legacy/client/index.js.map +1 -0
  127. package/dist/tempo/legacy/index.d.ts +7 -0
  128. package/dist/tempo/legacy/index.d.ts.map +1 -0
  129. package/dist/tempo/legacy/index.js +7 -0
  130. package/dist/tempo/legacy/index.js.map +1 -0
  131. package/dist/tempo/{server → legacy/server}/Session.d.ts +28 -11
  132. package/dist/tempo/legacy/server/Session.d.ts.map +1 -0
  133. package/dist/tempo/{server → legacy/server}/Session.js +28 -23
  134. package/dist/tempo/legacy/server/Session.js.map +1 -0
  135. package/dist/tempo/legacy/server/index.d.ts +5 -0
  136. package/dist/tempo/legacy/server/index.d.ts.map +1 -0
  137. package/dist/tempo/legacy/server/index.js +5 -0
  138. package/dist/tempo/legacy/server/index.js.map +1 -0
  139. package/dist/tempo/{session → legacy/session}/Chain.d.ts +30 -23
  140. package/dist/tempo/legacy/session/Chain.d.ts.map +1 -0
  141. package/dist/tempo/{session → legacy/session}/Chain.js +12 -11
  142. package/dist/tempo/legacy/session/Chain.js.map +1 -0
  143. package/dist/tempo/{session → legacy/session}/Channel.d.ts +1 -0
  144. package/dist/tempo/legacy/session/Channel.d.ts.map +1 -0
  145. package/dist/tempo/legacy/session/Channel.js.map +1 -0
  146. package/dist/tempo/legacy/session/ChannelStore.d.ts +22 -0
  147. package/dist/tempo/legacy/session/ChannelStore.d.ts.map +1 -0
  148. package/dist/tempo/legacy/session/ChannelStore.js +6 -0
  149. package/dist/tempo/legacy/session/ChannelStore.js.map +1 -0
  150. package/dist/tempo/legacy/session/Types.d.ts +73 -0
  151. package/dist/tempo/legacy/session/Types.d.ts.map +1 -0
  152. package/dist/tempo/legacy/session/Types.js.map +1 -0
  153. package/dist/tempo/{session → legacy/session}/Voucher.d.ts +4 -4
  154. package/dist/tempo/legacy/session/Voucher.d.ts.map +1 -0
  155. package/dist/tempo/{session → legacy/session}/Voucher.js +1 -1
  156. package/dist/tempo/legacy/session/Voucher.js.map +1 -0
  157. package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts +1 -0
  158. package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts.map +1 -1
  159. package/dist/tempo/{session → legacy/session}/escrow.abi.js +1 -0
  160. package/dist/tempo/legacy/session/escrow.abi.js.map +1 -0
  161. package/dist/tempo/legacy/session/index.d.ts +9 -0
  162. package/dist/tempo/legacy/session/index.d.ts.map +1 -0
  163. package/dist/tempo/legacy/session/index.js +9 -0
  164. package/dist/tempo/legacy/session/index.js.map +1 -0
  165. package/dist/tempo/server/Charge.d.ts +1 -1
  166. package/dist/tempo/server/Charge.d.ts.map +1 -1
  167. package/dist/tempo/server/Charge.js +13 -16
  168. package/dist/tempo/server/Charge.js.map +1 -1
  169. package/dist/tempo/server/Methods.d.ts +63 -6
  170. package/dist/tempo/server/Methods.d.ts.map +1 -1
  171. package/dist/tempo/server/Methods.js +36 -8
  172. package/dist/tempo/server/Methods.js.map +1 -1
  173. package/dist/tempo/server/Subscription.d.ts +1 -1
  174. package/dist/tempo/server/Subscription.d.ts.map +1 -1
  175. package/dist/tempo/server/index.d.ts +6 -5
  176. package/dist/tempo/server/index.d.ts.map +1 -1
  177. package/dist/tempo/server/index.js +5 -5
  178. package/dist/tempo/server/index.js.map +1 -1
  179. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  180. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  181. package/dist/tempo/server/internal/html.gen.js +1 -1
  182. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  183. package/dist/tempo/server/internal/request-body.d.ts +7 -2
  184. package/dist/tempo/server/internal/request-body.d.ts.map +1 -1
  185. package/dist/tempo/server/internal/request-body.js +20 -3
  186. package/dist/tempo/server/internal/request-body.js.map +1 -1
  187. package/dist/tempo/server/internal/transport.d.ts +8 -4
  188. package/dist/tempo/server/internal/transport.d.ts.map +1 -1
  189. package/dist/tempo/server/internal/transport.js +8 -7
  190. package/dist/tempo/server/internal/transport.js.map +1 -1
  191. package/dist/tempo/session/Snapshot.d.ts +32 -0
  192. package/dist/tempo/session/Snapshot.d.ts.map +1 -0
  193. package/dist/tempo/session/Snapshot.js +37 -0
  194. package/dist/tempo/session/Snapshot.js.map +1 -0
  195. package/dist/tempo/session/client/ChannelOps.d.ts +82 -0
  196. package/dist/tempo/session/client/ChannelOps.d.ts.map +1 -0
  197. package/dist/tempo/session/client/ChannelOps.js +204 -0
  198. package/dist/tempo/session/client/ChannelOps.js.map +1 -0
  199. package/dist/tempo/session/client/CredentialState.d.ts +262 -0
  200. package/dist/tempo/session/client/CredentialState.d.ts.map +1 -0
  201. package/dist/tempo/session/client/CredentialState.js +417 -0
  202. package/dist/tempo/session/client/CredentialState.js.map +1 -0
  203. package/dist/tempo/session/client/ReceiptCoordinator.d.ts +26 -0
  204. package/dist/tempo/session/client/ReceiptCoordinator.d.ts.map +1 -0
  205. package/dist/tempo/session/client/ReceiptCoordinator.js +61 -0
  206. package/dist/tempo/session/client/ReceiptCoordinator.js.map +1 -0
  207. package/dist/tempo/session/client/Runtime.d.ts +464 -0
  208. package/dist/tempo/session/client/Runtime.d.ts.map +1 -0
  209. package/dist/tempo/session/client/Runtime.js +499 -0
  210. package/dist/tempo/session/client/Runtime.js.map +1 -0
  211. package/dist/tempo/session/client/Session.d.ts +132 -0
  212. package/dist/tempo/session/client/Session.d.ts.map +1 -0
  213. package/dist/tempo/session/client/Session.js +55 -0
  214. package/dist/tempo/session/client/Session.js.map +1 -0
  215. package/dist/tempo/session/client/SessionManager.d.ts +120 -0
  216. package/dist/tempo/session/client/SessionManager.d.ts.map +1 -0
  217. package/dist/tempo/session/client/SessionManager.js +627 -0
  218. package/dist/tempo/session/client/SessionManager.js.map +1 -0
  219. package/dist/tempo/session/client/Transports.d.ts +449 -0
  220. package/dist/tempo/session/client/Transports.d.ts.map +1 -0
  221. package/dist/tempo/session/client/Transports.js +721 -0
  222. package/dist/tempo/session/client/Transports.js.map +1 -0
  223. package/dist/tempo/session/client/index.d.ts +12 -0
  224. package/dist/tempo/session/client/index.d.ts.map +1 -0
  225. package/dist/tempo/session/client/index.js +5 -0
  226. package/dist/tempo/session/client/index.js.map +1 -0
  227. package/dist/tempo/session/index.d.ts +7 -8
  228. package/dist/tempo/session/index.d.ts.map +1 -1
  229. package/dist/tempo/session/index.js +7 -8
  230. package/dist/tempo/session/index.js.map +1 -1
  231. package/dist/tempo/session/precompile/Chain.d.ts +319 -0
  232. package/dist/tempo/session/precompile/Chain.d.ts.map +1 -0
  233. package/dist/tempo/session/precompile/Chain.js +492 -0
  234. package/dist/tempo/session/precompile/Chain.js.map +1 -0
  235. package/dist/tempo/session/precompile/Channel.d.ts +46 -0
  236. package/dist/tempo/session/precompile/Channel.d.ts.map +1 -0
  237. package/dist/tempo/session/precompile/Channel.js +56 -0
  238. package/dist/tempo/session/precompile/Channel.js.map +1 -0
  239. package/dist/tempo/session/precompile/Protocol.d.ts +308 -0
  240. package/dist/tempo/session/precompile/Protocol.d.ts.map +1 -0
  241. package/dist/tempo/session/precompile/Protocol.js +264 -0
  242. package/dist/tempo/session/precompile/Protocol.js.map +1 -0
  243. package/dist/tempo/session/precompile/Voucher.d.ts +40 -0
  244. package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -0
  245. package/dist/tempo/session/precompile/Voucher.js +126 -0
  246. package/dist/tempo/session/precompile/Voucher.js.map +1 -0
  247. package/dist/tempo/session/precompile/escrow.abi.d.ts +522 -0
  248. package/dist/tempo/session/precompile/escrow.abi.d.ts.map +1 -0
  249. package/dist/tempo/session/precompile/escrow.abi.js +224 -0
  250. package/dist/tempo/session/precompile/escrow.abi.js.map +1 -0
  251. package/dist/tempo/session/precompile/index.d.ts +24 -0
  252. package/dist/tempo/session/precompile/index.d.ts.map +1 -0
  253. package/dist/tempo/session/precompile/index.js +22 -0
  254. package/dist/tempo/session/precompile/index.js.map +1 -0
  255. package/dist/tempo/session/server/ChannelOps.d.ts +56 -0
  256. package/dist/tempo/session/server/ChannelOps.d.ts.map +1 -0
  257. package/dist/tempo/session/server/ChannelOps.js +91 -0
  258. package/dist/tempo/session/server/ChannelOps.js.map +1 -0
  259. package/dist/tempo/session/server/ChannelStore.d.ts +347 -0
  260. package/dist/tempo/session/server/ChannelStore.d.ts.map +1 -0
  261. package/dist/tempo/session/server/ChannelStore.js +404 -0
  262. package/dist/tempo/session/server/ChannelStore.js.map +1 -0
  263. package/dist/tempo/session/server/CredentialVerification.d.ts +85 -0
  264. package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -0
  265. package/dist/tempo/session/server/CredentialVerification.js +494 -0
  266. package/dist/tempo/session/server/CredentialVerification.js.map +1 -0
  267. package/dist/tempo/session/server/MeteredStream.d.ts +40 -0
  268. package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -0
  269. package/dist/tempo/session/server/MeteredStream.js +42 -0
  270. package/dist/tempo/session/server/MeteredStream.js.map +1 -0
  271. package/dist/tempo/session/server/RequestState.d.ts +208 -0
  272. package/dist/tempo/session/server/RequestState.d.ts.map +1 -0
  273. package/dist/tempo/session/server/RequestState.js +252 -0
  274. package/dist/tempo/session/server/RequestState.js.map +1 -0
  275. package/dist/tempo/session/server/Session.d.ts +169 -0
  276. package/dist/tempo/session/server/Session.d.ts.map +1 -0
  277. package/dist/tempo/session/server/Session.js +351 -0
  278. package/dist/tempo/session/server/Session.js.map +1 -0
  279. package/dist/tempo/session/server/Settlement.d.ts +185 -0
  280. package/dist/tempo/session/server/Settlement.d.ts.map +1 -0
  281. package/dist/tempo/session/server/Settlement.js +250 -0
  282. package/dist/tempo/session/server/Settlement.js.map +1 -0
  283. package/dist/tempo/session/{Sse.d.ts → server/Sse.d.ts} +9 -56
  284. package/dist/tempo/session/server/Sse.d.ts.map +1 -0
  285. package/dist/tempo/session/server/Sse.js +184 -0
  286. package/dist/tempo/session/server/Sse.js.map +1 -0
  287. package/dist/tempo/session/server/Transports.d.ts +89 -0
  288. package/dist/tempo/session/server/Transports.d.ts.map +1 -0
  289. package/dist/tempo/session/server/Transports.js +149 -0
  290. package/dist/tempo/session/server/Transports.js.map +1 -0
  291. package/dist/tempo/session/server/Ws.d.ts +48 -0
  292. package/dist/tempo/session/server/Ws.d.ts.map +1 -0
  293. package/dist/tempo/session/server/Ws.js +244 -0
  294. package/dist/tempo/session/server/Ws.js.map +1 -0
  295. package/dist/tempo/session/server/index.d.ts +4 -0
  296. package/dist/tempo/session/server/index.d.ts.map +1 -0
  297. package/dist/tempo/session/server/index.js +2 -0
  298. package/dist/tempo/session/server/index.js.map +1 -0
  299. package/package.json +8 -3
  300. package/src/Challenge.ts +9 -7
  301. package/src/Constants.ts +58 -0
  302. package/src/Credential.ts +5 -4
  303. package/src/Method.ts +46 -5
  304. package/src/Receipt.ts +3 -2
  305. package/src/cli/cli.test.ts +23 -28
  306. package/src/cli/cli.ts +23 -10
  307. package/src/cli/mcp.test.ts +21 -7
  308. package/src/cli/plugins/tempo.ts +21 -8
  309. package/src/cli/utils.test.ts +25 -1
  310. package/src/cli/utils.ts +10 -0
  311. package/src/client/Methods.ts +5 -2
  312. package/src/client/Mppx.test-d.ts +10 -0
  313. package/src/client/Mppx.test.ts +75 -0
  314. package/src/client/Transport.ts +4 -5
  315. package/src/client/index.ts +11 -1
  316. package/src/client/internal/Fetch.test.ts +29 -4
  317. package/src/client/internal/Fetch.ts +17 -5
  318. package/src/env.d.ts +1 -1
  319. package/src/index.ts +1 -0
  320. package/src/internal/AcceptPayment.test.ts +61 -0
  321. package/src/internal/AcceptPayment.ts +21 -14
  322. package/src/mcp-sdk/client/McpClient.integration.test.ts +8 -7
  323. package/src/mcp-sdk/client/McpClient.test-d.ts +7 -0
  324. package/src/mcp-sdk/client/McpClient.ts +99 -67
  325. package/src/mcp-sdk/client/McpClient.unit.test.ts +131 -0
  326. package/src/middlewares/elysia.test.ts +8 -4
  327. package/src/middlewares/express.test.ts +8 -4
  328. package/src/middlewares/hono.test.ts +4 -4
  329. package/src/middlewares/nextjs.test.ts +8 -4
  330. package/src/proxy/Proxy.test.ts +8 -8
  331. package/src/server/Mppx.test-d.ts +54 -0
  332. package/src/server/Mppx.test.ts +274 -7
  333. package/src/server/Mppx.ts +487 -406
  334. package/src/server/Request.test.ts +81 -0
  335. package/src/server/Request.ts +23 -9
  336. package/src/server/Response.ts +2 -1
  337. package/src/server/Transport.ts +4 -3
  338. package/src/server/index.ts +1 -0
  339. package/src/stripe/client/Charge.test.ts +20 -5
  340. package/src/stripe/client/Charge.ts +6 -2
  341. package/src/stripe/server/Charge.test.ts +114 -1
  342. package/src/stripe/server/Charge.ts +13 -2
  343. package/src/stripe/server/internal/html/package.json +1 -1
  344. package/src/stripe/server/internal/html.gen.ts +1 -1
  345. package/src/tempo/AccessKeyAuthorization.test.ts +4 -94
  346. package/src/tempo/Methods.test.ts +45 -17
  347. package/src/tempo/Methods.ts +22 -0
  348. package/src/tempo/PublicExports.test-d.ts +105 -0
  349. package/src/tempo/client/Charge.test.ts +85 -0
  350. package/src/tempo/client/Charge.ts +19 -2
  351. package/src/tempo/client/Methods.ts +18 -6
  352. package/src/tempo/client/index.ts +15 -4
  353. package/src/tempo/index.ts +1 -0
  354. package/src/tempo/internal/fee-payer.test.ts +241 -17
  355. package/src/tempo/internal/fee-payer.ts +150 -4
  356. package/src/tempo/internal/fee-token.test.ts +14 -9
  357. package/src/tempo/legacy/AccessKeyAuthorization.test.ts +162 -0
  358. package/src/tempo/legacy/README.md +9 -0
  359. package/src/tempo/{client → legacy/client}/ChannelOps.test.ts +6 -7
  360. package/src/tempo/{client → legacy/client}/ChannelOps.ts +22 -9
  361. package/src/tempo/{client → legacy/client}/Session.test.ts +51 -9
  362. package/src/tempo/{client → legacy/client}/Session.ts +25 -11
  363. package/src/tempo/{client → legacy/client}/SessionManager.test.ts +81 -9
  364. package/src/tempo/{client → legacy/client}/SessionManager.ts +41 -20
  365. package/src/tempo/legacy/client/index.ts +6 -0
  366. package/src/tempo/legacy/index.ts +6 -0
  367. package/src/tempo/{server → legacy/server}/Session.test.ts +162 -63
  368. package/src/tempo/{server → legacy/server}/Session.ts +49 -37
  369. package/src/tempo/legacy/server/index.ts +4 -0
  370. package/src/tempo/{session → legacy/session}/Chain.test.ts +3 -4
  371. package/src/tempo/{session → legacy/session}/Chain.ts +94 -63
  372. package/src/tempo/{session → legacy/session}/Channel.ts +1 -0
  373. package/src/tempo/legacy/session/ChannelStore.test.ts +58 -0
  374. package/src/tempo/legacy/session/ChannelStore.ts +39 -0
  375. package/src/tempo/legacy/session/Types.ts +91 -0
  376. package/src/tempo/{session → legacy/session}/Voucher.ts +12 -8
  377. package/src/tempo/{session → legacy/session}/escrow.abi.ts +1 -0
  378. package/src/tempo/legacy/session/index.ts +8 -0
  379. package/src/tempo/server/AtomicStore.test-d.ts +16 -11
  380. package/src/tempo/server/Charge.test.ts +92 -14
  381. package/src/tempo/server/Charge.ts +18 -16
  382. package/src/tempo/server/Methods.ts +54 -8
  383. package/src/tempo/server/Sse.test.ts +2 -2
  384. package/src/tempo/server/index.ts +6 -5
  385. package/src/tempo/server/internal/html/package.json +1 -1
  386. package/src/tempo/server/internal/html.gen.ts +1 -1
  387. package/src/tempo/server/internal/request-body.test.ts +37 -4
  388. package/src/tempo/server/internal/request-body.ts +25 -6
  389. package/src/tempo/server/internal/transport.test.ts +4 -4
  390. package/src/tempo/server/internal/transport.ts +19 -10
  391. package/src/tempo/session/Snapshot.test.ts +41 -0
  392. package/src/tempo/session/Snapshot.ts +74 -0
  393. package/src/tempo/session/client/ChannelOps.test.ts +163 -0
  394. package/src/tempo/session/client/ChannelOps.ts +344 -0
  395. package/src/tempo/session/client/CredentialState.test.ts +645 -0
  396. package/src/tempo/session/client/CredentialState.ts +814 -0
  397. package/src/tempo/session/client/ReceiptCoordinator.ts +95 -0
  398. package/src/tempo/session/client/Runtime.test.ts +1092 -0
  399. package/src/tempo/session/client/Runtime.ts +986 -0
  400. package/src/tempo/session/client/Session.test.ts +734 -0
  401. package/src/tempo/session/client/Session.ts +97 -0
  402. package/src/tempo/session/client/SessionManager.test.ts +1308 -0
  403. package/src/tempo/session/client/SessionManager.ts +845 -0
  404. package/src/tempo/session/client/Transports.test.ts +837 -0
  405. package/src/tempo/session/client/Transports.ts +1292 -0
  406. package/src/tempo/session/client/index.ts +37 -0
  407. package/src/tempo/session/index.ts +7 -8
  408. package/src/tempo/session/precompile/Chain.integration.test.ts +321 -0
  409. package/src/tempo/session/precompile/Chain.test.ts +1258 -0
  410. package/src/tempo/session/precompile/Chain.ts +979 -0
  411. package/src/tempo/session/precompile/Channel.test.ts +138 -0
  412. package/src/tempo/session/precompile/Channel.ts +103 -0
  413. package/src/tempo/session/precompile/Protocol.test.ts +358 -0
  414. package/src/tempo/session/precompile/Protocol.ts +520 -0
  415. package/src/tempo/session/precompile/Voucher.test.ts +316 -0
  416. package/src/tempo/session/precompile/Voucher.ts +160 -0
  417. package/src/tempo/session/precompile/escrow.abi.ts +226 -0
  418. package/src/tempo/session/precompile/index.ts +33 -0
  419. package/src/tempo/session/server/ChannelOps.test.ts +129 -0
  420. package/src/tempo/session/server/ChannelOps.ts +157 -0
  421. package/src/tempo/session/{ChannelStore.test.ts → server/ChannelStore.test.ts} +536 -29
  422. package/src/tempo/session/server/ChannelStore.ts +835 -0
  423. package/src/tempo/session/server/CredentialVerification.test.ts +146 -0
  424. package/src/tempo/session/server/CredentialVerification.ts +710 -0
  425. package/src/tempo/session/server/MeteredStream.ts +88 -0
  426. package/src/tempo/session/server/RequestState.test.ts +531 -0
  427. package/src/tempo/session/server/RequestState.ts +499 -0
  428. package/src/tempo/session/server/Session.integration.test.ts +444 -0
  429. package/src/tempo/session/server/Session.test.ts +3253 -0
  430. package/src/tempo/session/server/Session.ts +543 -0
  431. package/src/tempo/session/server/Settlement.test.ts +242 -0
  432. package/src/tempo/session/server/Settlement.ts +470 -0
  433. package/src/tempo/session/{Sse.test.ts → server/Sse.test.ts} +37 -3
  434. package/src/tempo/session/server/Sse.ts +256 -0
  435. package/src/tempo/session/server/Transports.test.ts +346 -0
  436. package/src/tempo/session/server/Transports.ts +255 -0
  437. package/src/tempo/session/{Ws.test.ts → server/Ws.test.ts} +4 -4
  438. package/src/tempo/session/server/Ws.ts +384 -0
  439. package/src/tempo/session/server/index.ts +8 -0
  440. package/dist/tempo/client/ChannelOps.d.ts.map +0 -1
  441. package/dist/tempo/client/ChannelOps.js.map +0 -1
  442. package/dist/tempo/client/Session.d.ts.map +0 -1
  443. package/dist/tempo/client/Session.js.map +0 -1
  444. package/dist/tempo/client/SessionManager.d.ts.map +0 -1
  445. package/dist/tempo/client/SessionManager.js.map +0 -1
  446. package/dist/tempo/server/Session.d.ts.map +0 -1
  447. package/dist/tempo/server/Session.js.map +0 -1
  448. package/dist/tempo/session/Chain.d.ts.map +0 -1
  449. package/dist/tempo/session/Chain.js.map +0 -1
  450. package/dist/tempo/session/Channel.d.ts.map +0 -1
  451. package/dist/tempo/session/Channel.js.map +0 -1
  452. package/dist/tempo/session/ChannelStore.d.ts +0 -117
  453. package/dist/tempo/session/ChannelStore.d.ts.map +0 -1
  454. package/dist/tempo/session/ChannelStore.js +0 -172
  455. package/dist/tempo/session/ChannelStore.js.map +0 -1
  456. package/dist/tempo/session/Receipt.d.ts +0 -22
  457. package/dist/tempo/session/Receipt.d.ts.map +0 -1
  458. package/dist/tempo/session/Receipt.js +0 -34
  459. package/dist/tempo/session/Receipt.js.map +0 -1
  460. package/dist/tempo/session/Sse.d.ts.map +0 -1
  461. package/dist/tempo/session/Sse.js +0 -363
  462. package/dist/tempo/session/Sse.js.map +0 -1
  463. package/dist/tempo/session/Types.d.ts +0 -78
  464. package/dist/tempo/session/Types.d.ts.map +0 -1
  465. package/dist/tempo/session/Types.js.map +0 -1
  466. package/dist/tempo/session/Voucher.d.ts.map +0 -1
  467. package/dist/tempo/session/Voucher.js.map +0 -1
  468. package/dist/tempo/session/Ws.d.ts +0 -87
  469. package/dist/tempo/session/Ws.d.ts.map +0 -1
  470. package/dist/tempo/session/Ws.js +0 -443
  471. package/dist/tempo/session/Ws.js.map +0 -1
  472. package/dist/tempo/session/escrow.abi.js.map +0 -1
  473. package/src/tempo/session/ChannelStore.ts +0 -308
  474. package/src/tempo/session/Receipt.test.ts +0 -89
  475. package/src/tempo/session/Receipt.ts +0 -46
  476. package/src/tempo/session/Sse.ts +0 -462
  477. package/src/tempo/session/Types.ts +0 -86
  478. package/src/tempo/session/Ws.ts +0 -576
  479. /package/dist/tempo/{session → legacy/session}/Channel.js +0 -0
  480. /package/dist/tempo/{session → legacy/session}/Types.js +0 -0
  481. /package/src/tempo/{session → legacy/session}/Channel.test.ts +0 -0
  482. /package/src/tempo/{session → legacy/session}/Voucher.test.ts +0 -0
  483. /package/src/tempo/session/{Sse.fuzz.test.ts → server/Sse.fuzz.test.ts} +0 -0
@@ -0,0 +1,255 @@
1
+ import type { Hex } from 'viem'
2
+
3
+ import { ChannelClosedError } from '../../../Errors.js'
4
+ import type { NeedVoucherEvent } from '../precompile/Protocol.js'
5
+ import * as ChannelStore from './ChannelStore.js'
6
+
7
+ /** Parameters for reserving voucher headroom before emitting a stream item. */
8
+ export type ReserveChargeParameters = {
9
+ /** Amount required for the next stream item. */
10
+ amount: bigint
11
+ /** Channel being metered. */
12
+ channelId: Hex
13
+ /** Emits the transport-specific need-voucher frame. */
14
+ emit: (message: string) => void | Promise<void>
15
+ /** Formats a transport-specific need-voucher frame. */
16
+ formatNeedVoucher(parameters: NeedVoucherEvent): string
17
+ /** Store polling interval when `waitForUpdate` is unavailable. */
18
+ pollIntervalMs: number
19
+ /** Amount already reserved but not yet committed by this stream loop. */
20
+ reservedAmount: bigint
21
+ /** Optional abort signal for long waits. */
22
+ signal?: AbortSignal | undefined
23
+ /** Channel store used for state reads and waits. */
24
+ store: ChannelStore.ChannelStore
25
+ }
26
+
27
+ /** Parameters for committing previously reserved stream charges. */
28
+ export type CommitReservedChargesParameters = {
29
+ /** Reserved amount to commit. */
30
+ amount: bigint
31
+ /** Channel being metered. */
32
+ channelId: Hex
33
+ /** Channel store used for atomic updates. */
34
+ store: ChannelStore.ChannelStore
35
+ /** Number of charge units to add. */
36
+ units: number
37
+ }
38
+
39
+ /**
40
+ * Reserves voucher headroom for a future stream emission.
41
+ *
42
+ * If the channel lacks headroom, emits one need-voucher frame, then waits for
43
+ * a store update or polling interval until the accepted voucher covers both
44
+ * already-reserved charges and the next requested amount.
45
+ */
46
+ export async function reserveChargeOrWait(options: ReserveChargeParameters): Promise<void> {
47
+ const {
48
+ amount,
49
+ channelId,
50
+ emit,
51
+ formatNeedVoucher,
52
+ pollIntervalMs,
53
+ reservedAmount,
54
+ signal,
55
+ store,
56
+ } = options
57
+
58
+ let channel = await store.getChannel(channelId)
59
+ if (!channel) throw new Error('channel not found')
60
+ throwIfChannelClosed(channel)
61
+
62
+ const hasHeadroom = (state: ChannelStore.State) =>
63
+ state.highestVoucherAmount - state.spent - reservedAmount >= amount
64
+
65
+ if (hasHeadroom(channel)) return
66
+
67
+ await Promise.resolve(
68
+ emit(
69
+ formatNeedVoucher({
70
+ channelId,
71
+ requiredCumulative: (channel.spent + reservedAmount + amount).toString(),
72
+ acceptedCumulative: channel.highestVoucherAmount.toString(),
73
+ deposit: channel.deposit.toString(),
74
+ }),
75
+ ),
76
+ )
77
+
78
+ while (!hasHeadroom(channel)) {
79
+ await waitForUpdate(store, channelId, pollIntervalMs, signal)
80
+ channel = await store.getChannel(channelId)
81
+ if (!channel) throw new Error('channel not found')
82
+ throwIfChannelClosed(channel)
83
+ }
84
+ }
85
+
86
+ /** Atomically commits previously reserved stream charges to channel spend and unit counters. */
87
+ export async function commitReservedCharges(
88
+ options: CommitReservedChargesParameters,
89
+ ): Promise<void> {
90
+ const { amount, channelId, store, units } = options
91
+ if (amount === 0n || units === 0) return
92
+
93
+ let committed = false
94
+ const channel = await store.updateChannel(channelId, (current) => {
95
+ if (!current) return null
96
+ if (current.finalized) return current
97
+ if (current.closeRequestedAt !== 0n) return current
98
+ if (current.highestVoucherAmount - current.spent < amount) return current
99
+ committed = true
100
+ return {
101
+ ...current,
102
+ spent: current.spent + amount,
103
+ units: current.units + units,
104
+ }
105
+ })
106
+
107
+ if (!channel) throw new Error('channel not found')
108
+ throwIfChannelClosed(channel)
109
+ if (!committed) throw new Error('reserved voucher coverage is no longer available')
110
+ }
111
+
112
+ /** Throws when a channel can no longer be used for streaming charges. */
113
+ export function throwIfChannelClosed(channel: ChannelStore.State): void {
114
+ if (channel.finalized) throw new ChannelClosedError({ reason: 'channel is finalized' })
115
+ if (channel.closeRequestedAt !== 0n)
116
+ throw new ChannelClosedError({ reason: 'channel has a pending close request' })
117
+ }
118
+
119
+ async function waitForUpdate(
120
+ store: ChannelStore.ChannelStore,
121
+ channelId: Hex,
122
+ pollIntervalMs: number,
123
+ signal?: AbortSignal,
124
+ ): Promise<void> {
125
+ throwIfAborted(signal)
126
+
127
+ if (store.waitForUpdate) {
128
+ await Promise.race([
129
+ store.waitForUpdate(channelId),
130
+ sleep(pollIntervalMs, signal),
131
+ ...(signal ? [onceAborted(signal)] : []),
132
+ ])
133
+ } else {
134
+ await sleep(pollIntervalMs, signal)
135
+ }
136
+
137
+ throwIfAborted(signal)
138
+ }
139
+
140
+ function sleep(ms: number, signal?: AbortSignal) {
141
+ return new Promise<void>((resolve, reject) => {
142
+ const timeout = setTimeout(() => {
143
+ signal?.removeEventListener('abort', onAbort)
144
+ resolve()
145
+ }, ms)
146
+ const onAbort = () => {
147
+ clearTimeout(timeout)
148
+ reject(signal?.reason ?? new Error('aborted'))
149
+ }
150
+ signal?.addEventListener('abort', onAbort, { once: true })
151
+ })
152
+ }
153
+
154
+ function onceAborted(signal: AbortSignal) {
155
+ return new Promise<never>((_, reject) => {
156
+ if (signal.aborted) {
157
+ reject(signal.reason ?? new Error('aborted'))
158
+ return
159
+ }
160
+ signal.addEventListener('abort', () => reject(signal.reason ?? new Error('aborted')), {
161
+ once: true,
162
+ })
163
+ })
164
+ }
165
+
166
+ function throwIfAborted(signal?: AbortSignal) {
167
+ if (signal?.aborted) throw signal.reason ?? new Error('aborted')
168
+ }
169
+
170
+ /** Minimal socket event map supported by browser and Node-style WebSocket runtimes. */
171
+ export type SocketEventMap = {
172
+ close: Event | { code?: number | undefined; reason?: string | undefined; type?: string }
173
+ error: Event | { type?: string }
174
+ message: Event | { data: unknown; type?: string }
175
+ }
176
+
177
+ /** Socket event listener accepted by browser and Node-style runtimes. */
178
+ export type SocketEventListener<type extends keyof SocketEventMap> =
179
+ | ((event: SocketEventMap[type]) => void)
180
+ | { handleEvent(event: SocketEventMap[type]): void }
181
+
182
+ /** Minimal socket shape required by the session WebSocket adapter. */
183
+ export type Socket = {
184
+ close(code?: number, reason?: string): unknown
185
+ send(data: string): unknown
186
+ addEventListener?: <type extends keyof SocketEventMap>(
187
+ type: type,
188
+ listener: SocketEventListener<type>,
189
+ ) => unknown
190
+ removeEventListener?: <type extends keyof SocketEventMap>(
191
+ type: type,
192
+ listener: SocketEventListener<type>,
193
+ ) => unknown
194
+ on?: <type extends keyof SocketEventMap>(
195
+ type: type,
196
+ listener: (event: SocketEventMap[type]) => void,
197
+ ) => unknown
198
+ off?: <type extends keyof SocketEventMap>(
199
+ type: type,
200
+ listener: (event: SocketEventMap[type]) => void,
201
+ ) => unknown
202
+ }
203
+
204
+ /** Handlers for socket lifecycle and message events. */
205
+ export type SocketHandlers = {
206
+ /** Called when the socket closes. */
207
+ close(): void
208
+ /** Called when the socket reports an error. */
209
+ error(): void
210
+ /** Called with raw message payloads. */
211
+ message(payload: unknown): void
212
+ }
213
+
214
+ /** Subscribes to browser or Node-style socket events and returns an unsubscribe callback. */
215
+ export function subscribe(socket: Socket, handlers: SocketHandlers) {
216
+ if (socket.addEventListener && socket.removeEventListener) {
217
+ const onMessage = (event: SocketEventMap['message']) =>
218
+ handlers.message('data' in event ? event.data : undefined)
219
+ socket.addEventListener('message', onMessage)
220
+ socket.addEventListener('close', handlers.close)
221
+ socket.addEventListener('error', handlers.error)
222
+ return () => {
223
+ socket.removeEventListener?.('message', onMessage)
224
+ socket.removeEventListener?.('close', handlers.close)
225
+ socket.removeEventListener?.('error', handlers.error)
226
+ }
227
+ }
228
+
229
+ if (socket.on && socket.off) {
230
+ const onMessage = (data: unknown) => handlers.message(data)
231
+ socket.on('message', onMessage)
232
+ socket.on('close', handlers.close)
233
+ socket.on('error', handlers.error)
234
+ return () => {
235
+ socket.off?.('message', onMessage)
236
+ socket.off?.('close', handlers.close)
237
+ socket.off?.('error', handlers.error)
238
+ }
239
+ }
240
+
241
+ throw new Error('unsupported websocket implementation')
242
+ }
243
+
244
+ /** Sends a text frame through sync or async socket implementations. */
245
+ export async function send(socket: Socket, data: string) {
246
+ await Promise.resolve(socket.send(data))
247
+ }
248
+
249
+ /** Converts socket message payloads into text frames when possible. */
250
+ export function toText(value: unknown): string | null {
251
+ if (typeof value === 'string') return value
252
+ if (value instanceof ArrayBuffer) return new TextDecoder().decode(value)
253
+ if (ArrayBuffer.isView(value)) return new TextDecoder().decode(value)
254
+ return null
255
+ }
@@ -1,11 +1,11 @@
1
1
  import type { Address } from 'viem'
2
2
  import { describe, expect, test } from 'vp/test'
3
3
 
4
- import * as Challenge from '../../Challenge.js'
5
- import * as Credential from '../../Credential.js'
6
- import * as Store from '../../Store.js'
4
+ import * as Challenge from '../../../Challenge.js'
5
+ import * as Credential from '../../../Credential.js'
6
+ import * as Store from '../../../Store.js'
7
+ import { createSessionReceipt, serializeSessionReceipt } from '../precompile/Protocol.js'
7
8
  import * as ChannelStore from './ChannelStore.js'
8
- import { createSessionReceipt, serializeSessionReceipt } from './Receipt.js'
9
9
  import * as Ws from './Ws.js'
10
10
 
11
11
  const challenge = Challenge.from({
@@ -0,0 +1,384 @@
1
+ import * as Constants from '../../../Constants.js'
2
+ import * as Credential from '../../../Credential.js'
3
+ import {
4
+ createSessionReceipt,
5
+ deserializeSessionReceipt,
6
+ formatApplicationMessage,
7
+ formatAuthorizationMessage,
8
+ formatCloseReadyMessage,
9
+ formatCloseRequestMessage,
10
+ formatErrorMessage,
11
+ formatNeedVoucherMessage,
12
+ formatReceiptMessage,
13
+ parseMessage,
14
+ readSessionChallengeAmount,
15
+ requireSessionCredentialContext,
16
+ type ErrorMessageParameters,
17
+ type Message,
18
+ type SessionCredentialContext,
19
+ type SessionReceipt,
20
+ } from '../precompile/Protocol.js'
21
+ import * as ChannelStore from './ChannelStore.js'
22
+ import type { SessionController } from './MeteredStream.js'
23
+ export type { SessionController } from './MeteredStream.js'
24
+ export type { Socket } from './Transports.js'
25
+ import { meterIterable } from './MeteredStream.js'
26
+ import { send, subscribe, toText, type Socket } from './Transports.js'
27
+
28
+ /** Public WebSocket payment frame helpers. */
29
+ export {
30
+ formatApplicationMessage,
31
+ formatAuthorizationMessage,
32
+ formatCloseReadyMessage,
33
+ formatCloseRequestMessage,
34
+ formatErrorMessage,
35
+ formatNeedVoucherMessage,
36
+ formatReceiptMessage,
37
+ parseMessage,
38
+ type ErrorMessageParameters,
39
+ type Message,
40
+ } from '../precompile/Protocol.js'
41
+
42
+ /** Result returned by an HTTP route before upgrading or authorizing a WebSocket session. */
43
+ export type SessionRouteResult =
44
+ | { status: 402; challenge: Response }
45
+ | { status: 200; withReceipt(response?: Response): Response }
46
+
47
+ /** HTTP route used to perform a WebSocket payment probe. */
48
+ export type SessionRoute = (request: Request) => Promise<SessionRouteResult>
49
+
50
+ type StreamContext = {
51
+ challengeId: string
52
+ channelId: SessionCredentialContext['channelId']
53
+ tickCost: bigint
54
+ }
55
+
56
+ /** Result of verifying one in-band authorization frame through the HTTP payment route. */
57
+ type AuthorizationResult =
58
+ | {
59
+ status: 'accepted'
60
+ receipt: SessionReceipt
61
+ }
62
+ | {
63
+ status: 'rejected'
64
+ message: string
65
+ responseStatus: number
66
+ }
67
+
68
+ /** Mutable server-side runtime state for one paid WebSocket connection. */
69
+ type ServeRuntime = {
70
+ /** Whether the socket has been closed or externally disconnected. */
71
+ closed: boolean
72
+ /** Whether a final close-ready receipt has already been sent. */
73
+ closeReadySent: boolean
74
+ /** Whether an in-band close request has already been processed. */
75
+ closeRequestHandled: boolean
76
+ /** Whether the client has requested close and no new stream should start. */
77
+ closeRequested: boolean
78
+ /** Whether application streaming has started for this connection. */
79
+ streamStarted: boolean
80
+ /** Active stream task, when application generation is in progress. */
81
+ streamTask: Promise<void> | null
82
+ /** Active payment context for the stream. */
83
+ streamContext: StreamContext | null
84
+ /** Serialized payment-management action queue. */
85
+ action: Promise<void>
86
+ /** Number of queued payment-management messages waiting behind `action`. */
87
+ queuedActions: number
88
+ }
89
+
90
+ /**
91
+ * Bridge a WebSocket connection to a Tempo session payment flow.
92
+ *
93
+ * Credential verification is performed by routing each in-band authorization
94
+ * frame through `route` as a **synthetic `POST` request** that carries only
95
+ * the `Authorization` header. The synthetic request does not include cookies,
96
+ * bodies, query parameters, or other headers from the original WebSocket
97
+ * upgrade request. Do not wrap `route` with middleware that depends on
98
+ * HTTP-specific context beyond the `Authorization` header.
99
+ */
100
+ export async function serve(options: serve.Options): Promise<void> {
101
+ const {
102
+ amount: expectedAmount,
103
+ generate,
104
+ pollIntervalMs = 100,
105
+ route,
106
+ socket,
107
+ store: rawStore,
108
+ url,
109
+ } = options
110
+ const store = 'getChannel' in rawStore ? rawStore : ChannelStore.fromStore(rawStore)
111
+ const requestUrl = normalizeHttpUrl(url)
112
+ const maxQueuedPaymentMessages = 32
113
+
114
+ const abortController = new AbortController()
115
+ const runtime: ServeRuntime = {
116
+ closed: false,
117
+ closeReadySent: false,
118
+ closeRequestHandled: false,
119
+ closeRequested: false,
120
+ streamStarted: false,
121
+ streamTask: null,
122
+ streamContext: null,
123
+ action: Promise.resolve(),
124
+ queuedActions: 0,
125
+ }
126
+
127
+ const close = async (code = 1000, reason?: string) => {
128
+ if (runtime.closed) return
129
+ runtime.closed = true
130
+ abortController.abort()
131
+ unsubscribe()
132
+ await Promise.resolve(socket.close(code, reason))
133
+ }
134
+
135
+ const sendCloseReady = async () => {
136
+ if (runtime.closeReadySent || !runtime.streamContext || runtime.closed) return
137
+ runtime.closeReadySent = true
138
+
139
+ const channel = await store.getChannel(runtime.streamContext.channelId)
140
+ if (!channel) throw new Error('channel not found')
141
+
142
+ const receipt = createSessionReceipt({
143
+ challengeId: runtime.streamContext.challengeId,
144
+ channelId: runtime.streamContext.channelId,
145
+ acceptedCumulative: channel.highestVoucherAmount,
146
+ spent: channel.spent,
147
+ units: channel.units,
148
+ })
149
+ await send(socket, formatCloseReadyMessage(receipt))
150
+ }
151
+
152
+ const runStream = async (context: StreamContext) => {
153
+ try {
154
+ for await (const value of meterIterable({
155
+ store,
156
+ channelId: context.channelId,
157
+ tickCost: context.tickCost,
158
+ generate,
159
+ pollIntervalMs,
160
+ signal: abortController.signal,
161
+ emitNeedVoucher: (message) => send(socket, message),
162
+ formatNeedVoucher: formatNeedVoucherMessage,
163
+ })) {
164
+ if (abortController.signal.aborted) break
165
+ await send(socket, formatApplicationMessage(value))
166
+ }
167
+
168
+ if (!abortController.signal.aborted) await sendCloseReady()
169
+ } catch (error) {
170
+ if (!abortController.signal.aborted) {
171
+ await send(
172
+ socket,
173
+ formatErrorMessage({
174
+ message: error instanceof Error ? error.message : 'websocket session failed',
175
+ status: 500,
176
+ }),
177
+ )
178
+ await close(1011, 'websocket session failed')
179
+ }
180
+ } finally {
181
+ runtime.streamTask = null
182
+ }
183
+ }
184
+
185
+ const requestClose = async () => {
186
+ if (runtime.closed) return
187
+ if (runtime.closeRequestHandled) return
188
+ runtime.closeRequestHandled = true
189
+ runtime.closeRequested = true
190
+ abortController.abort()
191
+ await runtime.streamTask?.catch(() => {})
192
+ await sendCloseReady()
193
+ }
194
+
195
+ const processAuthorization = async (authorization: string) => {
196
+ if (runtime.closed) return
197
+ const credential = Credential.deserialize(authorization)
198
+ const payload = requireSessionCredentialContext(credential.payload)
199
+ if (payload.action === 'close') runtime.closeRequested = true
200
+
201
+ if (expectedAmount && credential.challenge.request.amount !== expectedAmount) {
202
+ await send(
203
+ socket,
204
+ formatErrorMessage({
205
+ message: 'credential amount does not match this endpoint',
206
+ status: 402,
207
+ }),
208
+ )
209
+ await close(1008, 'credential amount does not match this endpoint')
210
+ return
211
+ }
212
+
213
+ const authorizationResult = await authorizePaymentFrame({ authorization, requestUrl, route })
214
+ if (authorizationResult.status === 'rejected') {
215
+ await send(
216
+ socket,
217
+ formatErrorMessage({
218
+ message: authorizationResult.message,
219
+ status: authorizationResult.responseStatus,
220
+ }),
221
+ )
222
+ await close(1008, authorizationResult.message)
223
+ return
224
+ }
225
+
226
+ const { receipt } = authorizationResult
227
+ await send(socket, formatReceiptMessage(receipt))
228
+
229
+ if (payload.action === 'close') {
230
+ await close(1000, 'payment session closed')
231
+ return
232
+ }
233
+
234
+ if (payload.action === 'topUp') return
235
+ if (runtime.streamStarted || runtime.closeRequested) return
236
+ runtime.streamStarted = true
237
+ runtime.streamContext = {
238
+ challengeId: credential.challenge.id,
239
+ channelId: payload.channelId,
240
+ tickCost: readSessionChallengeAmount(credential.challenge),
241
+ }
242
+ // Defer the first application frame until after the client receives the
243
+ // auth receipt and has a chance to install its own message listeners.
244
+ setTimeout(() => {
245
+ if (runtime.closeRequested || runtime.closed || !runtime.streamContext) return
246
+ runtime.streamTask = runStream(runtime.streamContext)
247
+ }, 0)
248
+ }
249
+
250
+ const onMessage = (payload: unknown) => {
251
+ if (runtime.closed) return
252
+ const raw = toText(payload)
253
+ if (!raw) return
254
+ const message = parseMessage(raw)
255
+ if (!message) return
256
+
257
+ if (message.mpp === 'payment-close-request') {
258
+ runtime.closeRequested = true
259
+ abortController.abort()
260
+ }
261
+
262
+ const work =
263
+ message.mpp === 'authorization'
264
+ ? () => processAuthorization(message.authorization)
265
+ : message.mpp === 'payment-close-request'
266
+ ? () => requestClose()
267
+ : null
268
+
269
+ if (!work) return
270
+ if (runtime.queuedActions >= maxQueuedPaymentMessages) {
271
+ void send(
272
+ socket,
273
+ formatErrorMessage({
274
+ message: 'too many queued payment messages',
275
+ status: 429,
276
+ }),
277
+ ).catch(() => {})
278
+ void close(1008, 'too many queued payment messages')
279
+ return
280
+ }
281
+
282
+ runtime.queuedActions++
283
+ runtime.action = runtime.action
284
+ .then(async () => {
285
+ try {
286
+ if (runtime.closed) return
287
+ await work()
288
+ } finally {
289
+ runtime.queuedActions--
290
+ }
291
+ })
292
+ .catch(async (error) => {
293
+ if (!runtime.closed) {
294
+ await send(
295
+ socket,
296
+ formatErrorMessage({
297
+ message: error instanceof Error ? error.message : 'invalid payment message',
298
+ status: 400,
299
+ }),
300
+ )
301
+ await close(1008, 'invalid payment message')
302
+ }
303
+ })
304
+ }
305
+
306
+ const onClose = () => {
307
+ if (runtime.closed) return
308
+ runtime.closed = true
309
+ abortController.abort()
310
+ unsubscribe()
311
+ }
312
+
313
+ const unsubscribe = subscribe(socket, {
314
+ close: onClose,
315
+ error: onClose,
316
+ message: onMessage,
317
+ })
318
+ }
319
+
320
+ /** Type helpers for {@link serve}. */
321
+ export declare namespace serve {
322
+ type Options = {
323
+ /** Expected per-tick amount in raw units. When set, credentials whose
324
+ * challenge `request.amount` does not match are rejected. Use this to
325
+ * pin the price when the route is backed by `Mppx.compose()` with
326
+ * multiple offers — otherwise a client can select the cheapest offer
327
+ * and still receive the same stream. */
328
+ amount?: string | undefined
329
+ generate: AsyncIterable<string> | ((stream: SessionController) => AsyncIterable<string>)
330
+ pollIntervalMs?: number | undefined
331
+ /** Payment route handler. Receives synthetic `POST` requests with only
332
+ * the `Authorization` header — no cookies, bodies, or upgrade headers. */
333
+ route: SessionRoute
334
+ socket: Socket
335
+ store: ChannelStore.ChannelStore | import('../../../Store.js').Store
336
+ url: string | URL
337
+ }
338
+ }
339
+
340
+ function normalizeHttpUrl(value: string | URL): string {
341
+ const url = new URL(value.toString())
342
+ if (url.protocol === 'ws:') url.protocol = 'http:'
343
+ if (url.protocol === 'wss:') url.protocol = 'https:'
344
+ return url.toString()
345
+ }
346
+
347
+ /** Inputs used to verify a WebSocket authorization frame through the HTTP route. */
348
+ type AuthorizePaymentFrameParameters = {
349
+ /** Serialized `Payment` credential from the WebSocket authorization frame. */
350
+ authorization: string
351
+ /** Normalized HTTP URL used for the synthetic management request. */
352
+ requestUrl: string
353
+ /** HTTP payment route used to verify management credentials. */
354
+ route: SessionRoute
355
+ }
356
+
357
+ /** Verifies a WebSocket authorization frame and returns either a receipt or a payment error. */
358
+ async function authorizePaymentFrame(
359
+ parameters: AuthorizePaymentFrameParameters,
360
+ ): Promise<AuthorizationResult> {
361
+ const result = await parameters.route(
362
+ new Request(parameters.requestUrl, {
363
+ method: 'POST',
364
+ headers: { [Constants.Headers.authorization]: parameters.authorization },
365
+ }),
366
+ )
367
+
368
+ if (result.status === 402) {
369
+ const response = result.challenge
370
+ return {
371
+ status: 'rejected',
372
+ message:
373
+ (await response.text().catch(() => '')) ||
374
+ response.statusText ||
375
+ 'payment verification failed',
376
+ responseStatus: response.status,
377
+ }
378
+ }
379
+
380
+ const response = result.withReceipt(new Response(null, { status: 204 }))
381
+ const receiptHeader = response.headers.get(Constants.Headers.paymentReceipt)
382
+ if (!receiptHeader) throw new Error('management response missing Payment-Receipt header')
383
+ return { status: 'accepted', receipt: deserializeSessionReceipt(receiptHeader) }
384
+ }
@@ -0,0 +1,8 @@
1
+ export { charge, session, settle, settleBatch } from './Session.js'
2
+ /** Server-side automatic settlement schedule. */
3
+ export type {
4
+ ResolveSessionChannelId,
5
+ ResolveSessionChannelIdParameters,
6
+ SessionChannelIdRequest,
7
+ SettlementSchedule,
8
+ } from './Session.js'
@@ -1 +0,0 @@
1
- {"version":3,"file":"ChannelOps.d.ts","sourceRoot":"","sources":["../../../src/tempo/client/ChannelOps.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,OAAO,IAAI,YAAY,EAC5B,KAAK,MAAM,IAAI,WAAW,EAC3B,MAAM,MAAM,CAAA;AAIb,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAMnD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAGnE,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,GAAG,CAAC,GAAG,CAAA;IAClB,IAAI,EAAE,GAAG,CAAC,GAAG,CAAA;IACb,gBAAgB,EAAE,MAAM,CAAA;IACxB,cAAc,EAAE,OAAO,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AASD,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAG3D;AAED,wBAAgB,aAAa,CAC3B,SAAS,EAAE;IAAE,OAAO,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,EACnD,OAAO,EAAE,MAAM,EACf,sBAAsB,CAAC,EAAE,OAAO,GAC/B,OAAO,CAYT;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,wBAAwB,EACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,GACpB,MAAM,CAMR;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,GAAG,CAAC,GAAG,EAClB,gBAAgB,EAAE,MAAM,EACxB,cAAc,EAAE,OAAO,EACvB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,YAAY,GAAG,SAAS,GACvC,OAAO,CAAC,wBAAwB,CAAC,CAgBnC;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,GAAG,CAAC,GAAG,EAClB,gBAAgB,EAAE,MAAM,EACxB,cAAc,EAAE,OAAO,EACvB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,YAAY,GAAG,SAAS,GACvC,OAAO,CAAC,wBAAwB,CAAC,CAgBnC;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE;IACP,aAAa,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;IACxC,cAAc,EAAE,OAAO,CAAA;IACvB,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC/B,GACA,OAAO,CAAC;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,wBAAwB,CAAA;CAAE,CAAC,CAuErE;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,WAAW,EACnB,cAAc,EAAE,OAAO,EACvB,SAAS,EAAE,GAAG,CAAC,GAAG,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAiBnC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ChannelOps.js","sourceRoot":"","sources":["../../../src/tempo/client/ChannelOps.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Session.d.ts","sourceRoot":"","sources":["../../../src/tempo/client/Session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,OAAO,EAAc,KAAK,OAAO,IAAI,YAAY,EAAE,MAAM,MAAM,CAAA;AAI7E,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAA;AAChD,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAA;AAC9C,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AAMjC,OAAO,EACL,KAAK,YAAY,EAMlB,MAAM,iBAAiB,CAAA;AAExB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;iBAU/B,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,OAAO,CAAC,UAAU,GAAE,OAAO,CAAC,UAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA0R1D;AAED,MAAM,CAAC,OAAO,WAAW,OAAO,CAAC;IAC/B,KAAK,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,UAAU,GAC9C,MAAM,CAAC,WAAW,CAAC,UAAU,GAAG;QAC9B,oIAAoI;QACpI,aAAa,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;QACxC,sEAAsE;QACtE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAC7B,4LAA4L;QAC5L,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAC5B,4FAA4F;QAC5F,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;QACpC,yIAAyI;QACzI,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAC/B,8EAA8E;QAC9E,eAAe,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;KAC9D,CAAA;CACJ"}