mppx 0.6.31 → 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 (477) hide show
  1. package/CHANGELOG.md +17 -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/Response.d.ts.map +1 -1
  62. package/dist/server/Response.js +2 -1
  63. package/dist/server/Response.js.map +1 -1
  64. package/dist/server/Transport.d.ts.map +1 -1
  65. package/dist/server/Transport.js +4 -3
  66. package/dist/server/Transport.js.map +1 -1
  67. package/dist/server/index.d.ts +1 -0
  68. package/dist/server/index.d.ts.map +1 -1
  69. package/dist/server/index.js +1 -0
  70. package/dist/server/index.js.map +1 -1
  71. package/dist/stripe/client/Charge.d.ts +1 -1
  72. package/dist/stripe/client/Charge.d.ts.map +1 -1
  73. package/dist/stripe/client/Charge.js +3 -1
  74. package/dist/stripe/client/Charge.js.map +1 -1
  75. package/dist/stripe/server/Charge.d.ts +1 -1
  76. package/dist/stripe/server/Charge.d.ts.map +1 -1
  77. package/dist/stripe/server/Charge.js +9 -2
  78. package/dist/stripe/server/Charge.js.map +1 -1
  79. package/dist/stripe/server/Methods.d.ts +1 -1
  80. package/dist/stripe/server/Methods.d.ts.map +1 -1
  81. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  82. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
  83. package/dist/stripe/server/internal/html.gen.js +1 -1
  84. package/dist/stripe/server/internal/html.gen.js.map +1 -1
  85. package/dist/tempo/Methods.d.ts +18 -0
  86. package/dist/tempo/Methods.d.ts.map +1 -1
  87. package/dist/tempo/Methods.js +16 -1
  88. package/dist/tempo/Methods.js.map +1 -1
  89. package/dist/tempo/client/Charge.d.ts +6 -0
  90. package/dist/tempo/client/Charge.d.ts.map +1 -1
  91. package/dist/tempo/client/Charge.js +9 -2
  92. package/dist/tempo/client/Charge.js.map +1 -1
  93. package/dist/tempo/client/Methods.d.ts +36 -7
  94. package/dist/tempo/client/Methods.d.ts.map +1 -1
  95. package/dist/tempo/client/Methods.js +12 -5
  96. package/dist/tempo/client/Methods.js.map +1 -1
  97. package/dist/tempo/client/index.d.ts +7 -4
  98. package/dist/tempo/client/index.d.ts.map +1 -1
  99. package/dist/tempo/client/index.js +5 -3
  100. package/dist/tempo/client/index.js.map +1 -1
  101. package/dist/tempo/index.d.ts +1 -0
  102. package/dist/tempo/index.d.ts.map +1 -1
  103. package/dist/tempo/index.js +1 -0
  104. package/dist/tempo/index.js.map +1 -1
  105. package/dist/tempo/internal/fee-payer.d.ts +21 -1
  106. package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
  107. package/dist/tempo/internal/fee-payer.js +109 -4
  108. package/dist/tempo/internal/fee-payer.js.map +1 -1
  109. package/dist/tempo/{client → legacy/client}/ChannelOps.d.ts +19 -6
  110. package/dist/tempo/legacy/client/ChannelOps.d.ts.map +1 -0
  111. package/dist/tempo/{client → legacy/client}/ChannelOps.js +9 -3
  112. package/dist/tempo/legacy/client/ChannelOps.js.map +1 -0
  113. package/dist/tempo/{client → legacy/client}/Session.d.ts +23 -4
  114. package/dist/tempo/legacy/client/Session.d.ts.map +1 -0
  115. package/dist/tempo/{client → legacy/client}/Session.js +14 -7
  116. package/dist/tempo/legacy/client/Session.js.map +1 -0
  117. package/dist/tempo/{client → legacy/client}/SessionManager.d.ts +20 -5
  118. package/dist/tempo/legacy/client/SessionManager.d.ts.map +1 -0
  119. package/dist/tempo/{client → legacy/client}/SessionManager.js +20 -16
  120. package/dist/tempo/legacy/client/SessionManager.js.map +1 -0
  121. package/dist/tempo/legacy/client/index.d.ts +7 -0
  122. package/dist/tempo/legacy/client/index.d.ts.map +1 -0
  123. package/dist/tempo/legacy/client/index.js +5 -0
  124. package/dist/tempo/legacy/client/index.js.map +1 -0
  125. package/dist/tempo/legacy/index.d.ts +7 -0
  126. package/dist/tempo/legacy/index.d.ts.map +1 -0
  127. package/dist/tempo/legacy/index.js +7 -0
  128. package/dist/tempo/legacy/index.js.map +1 -0
  129. package/dist/tempo/{server → legacy/server}/Session.d.ts +28 -11
  130. package/dist/tempo/legacy/server/Session.d.ts.map +1 -0
  131. package/dist/tempo/{server → legacy/server}/Session.js +12 -10
  132. package/dist/tempo/legacy/server/Session.js.map +1 -0
  133. package/dist/tempo/legacy/server/index.d.ts +5 -0
  134. package/dist/tempo/legacy/server/index.d.ts.map +1 -0
  135. package/dist/tempo/legacy/server/index.js +5 -0
  136. package/dist/tempo/legacy/server/index.js.map +1 -0
  137. package/dist/tempo/{session → legacy/session}/Chain.d.ts +30 -23
  138. package/dist/tempo/legacy/session/Chain.d.ts.map +1 -0
  139. package/dist/tempo/{session → legacy/session}/Chain.js +12 -11
  140. package/dist/tempo/legacy/session/Chain.js.map +1 -0
  141. package/dist/tempo/{session → legacy/session}/Channel.d.ts +1 -0
  142. package/dist/tempo/legacy/session/Channel.d.ts.map +1 -0
  143. package/dist/tempo/legacy/session/Channel.js.map +1 -0
  144. package/dist/tempo/legacy/session/ChannelStore.d.ts +22 -0
  145. package/dist/tempo/legacy/session/ChannelStore.d.ts.map +1 -0
  146. package/dist/tempo/legacy/session/ChannelStore.js +6 -0
  147. package/dist/tempo/legacy/session/ChannelStore.js.map +1 -0
  148. package/dist/tempo/legacy/session/Types.d.ts +73 -0
  149. package/dist/tempo/legacy/session/Types.d.ts.map +1 -0
  150. package/dist/tempo/legacy/session/Types.js.map +1 -0
  151. package/dist/tempo/{session → legacy/session}/Voucher.d.ts +4 -4
  152. package/dist/tempo/legacy/session/Voucher.d.ts.map +1 -0
  153. package/dist/tempo/{session → legacy/session}/Voucher.js +1 -1
  154. package/dist/tempo/legacy/session/Voucher.js.map +1 -0
  155. package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts +1 -0
  156. package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts.map +1 -1
  157. package/dist/tempo/{session → legacy/session}/escrow.abi.js +1 -0
  158. package/dist/tempo/legacy/session/escrow.abi.js.map +1 -0
  159. package/dist/tempo/legacy/session/index.d.ts +9 -0
  160. package/dist/tempo/legacy/session/index.d.ts.map +1 -0
  161. package/dist/tempo/legacy/session/index.js +9 -0
  162. package/dist/tempo/legacy/session/index.js.map +1 -0
  163. package/dist/tempo/server/Charge.d.ts +1 -1
  164. package/dist/tempo/server/Charge.d.ts.map +1 -1
  165. package/dist/tempo/server/Charge.js +13 -16
  166. package/dist/tempo/server/Charge.js.map +1 -1
  167. package/dist/tempo/server/Methods.d.ts +63 -6
  168. package/dist/tempo/server/Methods.d.ts.map +1 -1
  169. package/dist/tempo/server/Methods.js +36 -8
  170. package/dist/tempo/server/Methods.js.map +1 -1
  171. package/dist/tempo/server/Subscription.d.ts +1 -1
  172. package/dist/tempo/server/Subscription.d.ts.map +1 -1
  173. package/dist/tempo/server/index.d.ts +6 -5
  174. package/dist/tempo/server/index.d.ts.map +1 -1
  175. package/dist/tempo/server/index.js +5 -5
  176. package/dist/tempo/server/index.js.map +1 -1
  177. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  178. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  179. package/dist/tempo/server/internal/html.gen.js +1 -1
  180. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  181. package/dist/tempo/server/internal/request-body.d.ts +7 -2
  182. package/dist/tempo/server/internal/request-body.d.ts.map +1 -1
  183. package/dist/tempo/server/internal/request-body.js +20 -3
  184. package/dist/tempo/server/internal/request-body.js.map +1 -1
  185. package/dist/tempo/server/internal/transport.d.ts +8 -4
  186. package/dist/tempo/server/internal/transport.d.ts.map +1 -1
  187. package/dist/tempo/server/internal/transport.js +8 -7
  188. package/dist/tempo/server/internal/transport.js.map +1 -1
  189. package/dist/tempo/session/Snapshot.d.ts +32 -0
  190. package/dist/tempo/session/Snapshot.d.ts.map +1 -0
  191. package/dist/tempo/session/Snapshot.js +37 -0
  192. package/dist/tempo/session/Snapshot.js.map +1 -0
  193. package/dist/tempo/session/client/ChannelOps.d.ts +82 -0
  194. package/dist/tempo/session/client/ChannelOps.d.ts.map +1 -0
  195. package/dist/tempo/session/client/ChannelOps.js +204 -0
  196. package/dist/tempo/session/client/ChannelOps.js.map +1 -0
  197. package/dist/tempo/session/client/CredentialState.d.ts +262 -0
  198. package/dist/tempo/session/client/CredentialState.d.ts.map +1 -0
  199. package/dist/tempo/session/client/CredentialState.js +417 -0
  200. package/dist/tempo/session/client/CredentialState.js.map +1 -0
  201. package/dist/tempo/session/client/ReceiptCoordinator.d.ts +26 -0
  202. package/dist/tempo/session/client/ReceiptCoordinator.d.ts.map +1 -0
  203. package/dist/tempo/session/client/ReceiptCoordinator.js +61 -0
  204. package/dist/tempo/session/client/ReceiptCoordinator.js.map +1 -0
  205. package/dist/tempo/session/client/Runtime.d.ts +464 -0
  206. package/dist/tempo/session/client/Runtime.d.ts.map +1 -0
  207. package/dist/tempo/session/client/Runtime.js +499 -0
  208. package/dist/tempo/session/client/Runtime.js.map +1 -0
  209. package/dist/tempo/session/client/Session.d.ts +132 -0
  210. package/dist/tempo/session/client/Session.d.ts.map +1 -0
  211. package/dist/tempo/session/client/Session.js +55 -0
  212. package/dist/tempo/session/client/Session.js.map +1 -0
  213. package/dist/tempo/session/client/SessionManager.d.ts +120 -0
  214. package/dist/tempo/session/client/SessionManager.d.ts.map +1 -0
  215. package/dist/tempo/session/client/SessionManager.js +627 -0
  216. package/dist/tempo/session/client/SessionManager.js.map +1 -0
  217. package/dist/tempo/session/client/Transports.d.ts +449 -0
  218. package/dist/tempo/session/client/Transports.d.ts.map +1 -0
  219. package/dist/tempo/session/client/Transports.js +721 -0
  220. package/dist/tempo/session/client/Transports.js.map +1 -0
  221. package/dist/tempo/session/client/index.d.ts +12 -0
  222. package/dist/tempo/session/client/index.d.ts.map +1 -0
  223. package/dist/tempo/session/client/index.js +5 -0
  224. package/dist/tempo/session/client/index.js.map +1 -0
  225. package/dist/tempo/session/index.d.ts +7 -8
  226. package/dist/tempo/session/index.d.ts.map +1 -1
  227. package/dist/tempo/session/index.js +7 -8
  228. package/dist/tempo/session/index.js.map +1 -1
  229. package/dist/tempo/session/precompile/Chain.d.ts +319 -0
  230. package/dist/tempo/session/precompile/Chain.d.ts.map +1 -0
  231. package/dist/tempo/session/precompile/Chain.js +492 -0
  232. package/dist/tempo/session/precompile/Chain.js.map +1 -0
  233. package/dist/tempo/session/precompile/Channel.d.ts +46 -0
  234. package/dist/tempo/session/precompile/Channel.d.ts.map +1 -0
  235. package/dist/tempo/session/precompile/Channel.js +56 -0
  236. package/dist/tempo/session/precompile/Channel.js.map +1 -0
  237. package/dist/tempo/session/precompile/Protocol.d.ts +308 -0
  238. package/dist/tempo/session/precompile/Protocol.d.ts.map +1 -0
  239. package/dist/tempo/session/precompile/Protocol.js +264 -0
  240. package/dist/tempo/session/precompile/Protocol.js.map +1 -0
  241. package/dist/tempo/session/precompile/Voucher.d.ts +40 -0
  242. package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -0
  243. package/dist/tempo/session/precompile/Voucher.js +126 -0
  244. package/dist/tempo/session/precompile/Voucher.js.map +1 -0
  245. package/dist/tempo/session/precompile/escrow.abi.d.ts +522 -0
  246. package/dist/tempo/session/precompile/escrow.abi.d.ts.map +1 -0
  247. package/dist/tempo/session/precompile/escrow.abi.js +224 -0
  248. package/dist/tempo/session/precompile/escrow.abi.js.map +1 -0
  249. package/dist/tempo/session/precompile/index.d.ts +24 -0
  250. package/dist/tempo/session/precompile/index.d.ts.map +1 -0
  251. package/dist/tempo/session/precompile/index.js +22 -0
  252. package/dist/tempo/session/precompile/index.js.map +1 -0
  253. package/dist/tempo/session/server/ChannelOps.d.ts +56 -0
  254. package/dist/tempo/session/server/ChannelOps.d.ts.map +1 -0
  255. package/dist/tempo/session/server/ChannelOps.js +91 -0
  256. package/dist/tempo/session/server/ChannelOps.js.map +1 -0
  257. package/dist/tempo/session/server/ChannelStore.d.ts +347 -0
  258. package/dist/tempo/session/server/ChannelStore.d.ts.map +1 -0
  259. package/dist/tempo/session/server/ChannelStore.js +404 -0
  260. package/dist/tempo/session/server/ChannelStore.js.map +1 -0
  261. package/dist/tempo/session/server/CredentialVerification.d.ts +85 -0
  262. package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -0
  263. package/dist/tempo/session/server/CredentialVerification.js +494 -0
  264. package/dist/tempo/session/server/CredentialVerification.js.map +1 -0
  265. package/dist/tempo/session/server/MeteredStream.d.ts +40 -0
  266. package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -0
  267. package/dist/tempo/session/server/MeteredStream.js +42 -0
  268. package/dist/tempo/session/server/MeteredStream.js.map +1 -0
  269. package/dist/tempo/session/server/RequestState.d.ts +208 -0
  270. package/dist/tempo/session/server/RequestState.d.ts.map +1 -0
  271. package/dist/tempo/session/server/RequestState.js +252 -0
  272. package/dist/tempo/session/server/RequestState.js.map +1 -0
  273. package/dist/tempo/session/server/Session.d.ts +169 -0
  274. package/dist/tempo/session/server/Session.d.ts.map +1 -0
  275. package/dist/tempo/session/server/Session.js +351 -0
  276. package/dist/tempo/session/server/Session.js.map +1 -0
  277. package/dist/tempo/session/server/Settlement.d.ts +185 -0
  278. package/dist/tempo/session/server/Settlement.d.ts.map +1 -0
  279. package/dist/tempo/session/server/Settlement.js +250 -0
  280. package/dist/tempo/session/server/Settlement.js.map +1 -0
  281. package/dist/tempo/session/{Sse.d.ts → server/Sse.d.ts} +9 -56
  282. package/dist/tempo/session/server/Sse.d.ts.map +1 -0
  283. package/dist/tempo/session/server/Sse.js +184 -0
  284. package/dist/tempo/session/server/Sse.js.map +1 -0
  285. package/dist/tempo/session/server/Transports.d.ts +89 -0
  286. package/dist/tempo/session/server/Transports.d.ts.map +1 -0
  287. package/dist/tempo/session/server/Transports.js +149 -0
  288. package/dist/tempo/session/server/Transports.js.map +1 -0
  289. package/dist/tempo/session/server/Ws.d.ts +48 -0
  290. package/dist/tempo/session/server/Ws.d.ts.map +1 -0
  291. package/dist/tempo/session/server/Ws.js +244 -0
  292. package/dist/tempo/session/server/Ws.js.map +1 -0
  293. package/dist/tempo/session/server/index.d.ts +4 -0
  294. package/dist/tempo/session/server/index.d.ts.map +1 -0
  295. package/dist/tempo/session/server/index.js +2 -0
  296. package/dist/tempo/session/server/index.js.map +1 -0
  297. package/package.json +6 -1
  298. package/src/Challenge.ts +9 -7
  299. package/src/Constants.ts +58 -0
  300. package/src/Credential.ts +5 -4
  301. package/src/Method.ts +46 -5
  302. package/src/Receipt.ts +3 -2
  303. package/src/cli/cli.test.ts +23 -28
  304. package/src/cli/cli.ts +23 -10
  305. package/src/cli/mcp.test.ts +21 -7
  306. package/src/cli/plugins/tempo.ts +21 -8
  307. package/src/cli/utils.test.ts +25 -1
  308. package/src/cli/utils.ts +10 -0
  309. package/src/client/Methods.ts +5 -2
  310. package/src/client/Mppx.test-d.ts +10 -0
  311. package/src/client/Mppx.test.ts +75 -0
  312. package/src/client/Transport.ts +4 -5
  313. package/src/client/index.ts +11 -1
  314. package/src/client/internal/Fetch.test.ts +29 -4
  315. package/src/client/internal/Fetch.ts +17 -5
  316. package/src/env.d.ts +1 -1
  317. package/src/index.ts +1 -0
  318. package/src/internal/AcceptPayment.test.ts +61 -0
  319. package/src/internal/AcceptPayment.ts +21 -14
  320. package/src/mcp-sdk/client/McpClient.integration.test.ts +8 -7
  321. package/src/mcp-sdk/client/McpClient.test-d.ts +7 -0
  322. package/src/mcp-sdk/client/McpClient.ts +99 -67
  323. package/src/mcp-sdk/client/McpClient.unit.test.ts +131 -0
  324. package/src/middlewares/elysia.test.ts +8 -4
  325. package/src/middlewares/express.test.ts +8 -4
  326. package/src/middlewares/hono.test.ts +4 -4
  327. package/src/middlewares/nextjs.test.ts +8 -4
  328. package/src/proxy/Proxy.test.ts +8 -8
  329. package/src/server/Mppx.test-d.ts +54 -0
  330. package/src/server/Mppx.test.ts +200 -7
  331. package/src/server/Mppx.ts +487 -406
  332. package/src/server/Response.ts +2 -1
  333. package/src/server/Transport.ts +4 -3
  334. package/src/server/index.ts +1 -0
  335. package/src/stripe/client/Charge.test.ts +20 -5
  336. package/src/stripe/client/Charge.ts +6 -2
  337. package/src/stripe/server/Charge.test.ts +114 -1
  338. package/src/stripe/server/Charge.ts +13 -2
  339. package/src/stripe/server/internal/html.gen.ts +1 -1
  340. package/src/tempo/AccessKeyAuthorization.test.ts +4 -94
  341. package/src/tempo/Methods.test.ts +45 -17
  342. package/src/tempo/Methods.ts +22 -0
  343. package/src/tempo/PublicExports.test-d.ts +105 -0
  344. package/src/tempo/client/Charge.test.ts +85 -0
  345. package/src/tempo/client/Charge.ts +19 -2
  346. package/src/tempo/client/Methods.ts +18 -6
  347. package/src/tempo/client/index.ts +15 -4
  348. package/src/tempo/index.ts +1 -0
  349. package/src/tempo/internal/fee-payer.test.ts +241 -17
  350. package/src/tempo/internal/fee-payer.ts +150 -4
  351. package/src/tempo/internal/fee-token.test.ts +14 -9
  352. package/src/tempo/legacy/AccessKeyAuthorization.test.ts +162 -0
  353. package/src/tempo/legacy/README.md +9 -0
  354. package/src/tempo/{client → legacy/client}/ChannelOps.test.ts +6 -7
  355. package/src/tempo/{client → legacy/client}/ChannelOps.ts +22 -9
  356. package/src/tempo/{client → legacy/client}/Session.test.ts +51 -9
  357. package/src/tempo/{client → legacy/client}/Session.ts +25 -11
  358. package/src/tempo/{client → legacy/client}/SessionManager.test.ts +81 -9
  359. package/src/tempo/{client → legacy/client}/SessionManager.ts +41 -20
  360. package/src/tempo/legacy/client/index.ts +6 -0
  361. package/src/tempo/legacy/index.ts +6 -0
  362. package/src/tempo/{server → legacy/server}/Session.test.ts +45 -45
  363. package/src/tempo/{server → legacy/server}/Session.ts +32 -23
  364. package/src/tempo/legacy/server/index.ts +4 -0
  365. package/src/tempo/{session → legacy/session}/Chain.test.ts +3 -4
  366. package/src/tempo/{session → legacy/session}/Chain.ts +94 -63
  367. package/src/tempo/{session → legacy/session}/Channel.ts +1 -0
  368. package/src/tempo/legacy/session/ChannelStore.test.ts +58 -0
  369. package/src/tempo/legacy/session/ChannelStore.ts +39 -0
  370. package/src/tempo/legacy/session/Types.ts +91 -0
  371. package/src/tempo/{session → legacy/session}/Voucher.ts +12 -8
  372. package/src/tempo/{session → legacy/session}/escrow.abi.ts +1 -0
  373. package/src/tempo/legacy/session/index.ts +8 -0
  374. package/src/tempo/server/AtomicStore.test-d.ts +16 -11
  375. package/src/tempo/server/Charge.test.ts +92 -14
  376. package/src/tempo/server/Charge.ts +18 -16
  377. package/src/tempo/server/Methods.ts +54 -8
  378. package/src/tempo/server/Sse.test.ts +2 -2
  379. package/src/tempo/server/index.ts +6 -5
  380. package/src/tempo/server/internal/html.gen.ts +1 -1
  381. package/src/tempo/server/internal/request-body.test.ts +37 -4
  382. package/src/tempo/server/internal/request-body.ts +25 -6
  383. package/src/tempo/server/internal/transport.test.ts +4 -4
  384. package/src/tempo/server/internal/transport.ts +19 -10
  385. package/src/tempo/session/Snapshot.test.ts +41 -0
  386. package/src/tempo/session/Snapshot.ts +74 -0
  387. package/src/tempo/session/client/ChannelOps.test.ts +163 -0
  388. package/src/tempo/session/client/ChannelOps.ts +344 -0
  389. package/src/tempo/session/client/CredentialState.test.ts +645 -0
  390. package/src/tempo/session/client/CredentialState.ts +814 -0
  391. package/src/tempo/session/client/ReceiptCoordinator.ts +95 -0
  392. package/src/tempo/session/client/Runtime.test.ts +1092 -0
  393. package/src/tempo/session/client/Runtime.ts +986 -0
  394. package/src/tempo/session/client/Session.test.ts +734 -0
  395. package/src/tempo/session/client/Session.ts +97 -0
  396. package/src/tempo/session/client/SessionManager.test.ts +1308 -0
  397. package/src/tempo/session/client/SessionManager.ts +845 -0
  398. package/src/tempo/session/client/Transports.test.ts +837 -0
  399. package/src/tempo/session/client/Transports.ts +1292 -0
  400. package/src/tempo/session/client/index.ts +37 -0
  401. package/src/tempo/session/index.ts +7 -8
  402. package/src/tempo/session/precompile/Chain.integration.test.ts +321 -0
  403. package/src/tempo/session/precompile/Chain.test.ts +1258 -0
  404. package/src/tempo/session/precompile/Chain.ts +979 -0
  405. package/src/tempo/session/precompile/Channel.test.ts +138 -0
  406. package/src/tempo/session/precompile/Channel.ts +103 -0
  407. package/src/tempo/session/precompile/Protocol.test.ts +358 -0
  408. package/src/tempo/session/precompile/Protocol.ts +520 -0
  409. package/src/tempo/session/precompile/Voucher.test.ts +316 -0
  410. package/src/tempo/session/precompile/Voucher.ts +160 -0
  411. package/src/tempo/session/precompile/escrow.abi.ts +226 -0
  412. package/src/tempo/session/precompile/index.ts +33 -0
  413. package/src/tempo/session/server/ChannelOps.test.ts +129 -0
  414. package/src/tempo/session/server/ChannelOps.ts +157 -0
  415. package/src/tempo/session/{ChannelStore.test.ts → server/ChannelStore.test.ts} +536 -29
  416. package/src/tempo/session/server/ChannelStore.ts +835 -0
  417. package/src/tempo/session/server/CredentialVerification.test.ts +146 -0
  418. package/src/tempo/session/server/CredentialVerification.ts +710 -0
  419. package/src/tempo/session/server/MeteredStream.ts +88 -0
  420. package/src/tempo/session/server/RequestState.test.ts +531 -0
  421. package/src/tempo/session/server/RequestState.ts +499 -0
  422. package/src/tempo/session/server/Session.integration.test.ts +444 -0
  423. package/src/tempo/session/server/Session.test.ts +3253 -0
  424. package/src/tempo/session/server/Session.ts +543 -0
  425. package/src/tempo/session/server/Settlement.test.ts +242 -0
  426. package/src/tempo/session/server/Settlement.ts +470 -0
  427. package/src/tempo/session/{Sse.test.ts → server/Sse.test.ts} +37 -3
  428. package/src/tempo/session/server/Sse.ts +256 -0
  429. package/src/tempo/session/server/Transports.test.ts +346 -0
  430. package/src/tempo/session/server/Transports.ts +255 -0
  431. package/src/tempo/session/{Ws.test.ts → server/Ws.test.ts} +4 -4
  432. package/src/tempo/session/server/Ws.ts +384 -0
  433. package/src/tempo/session/server/index.ts +8 -0
  434. package/dist/tempo/client/ChannelOps.d.ts.map +0 -1
  435. package/dist/tempo/client/ChannelOps.js.map +0 -1
  436. package/dist/tempo/client/Session.d.ts.map +0 -1
  437. package/dist/tempo/client/Session.js.map +0 -1
  438. package/dist/tempo/client/SessionManager.d.ts.map +0 -1
  439. package/dist/tempo/client/SessionManager.js.map +0 -1
  440. package/dist/tempo/server/Session.d.ts.map +0 -1
  441. package/dist/tempo/server/Session.js.map +0 -1
  442. package/dist/tempo/session/Chain.d.ts.map +0 -1
  443. package/dist/tempo/session/Chain.js.map +0 -1
  444. package/dist/tempo/session/Channel.d.ts.map +0 -1
  445. package/dist/tempo/session/Channel.js.map +0 -1
  446. package/dist/tempo/session/ChannelStore.d.ts +0 -117
  447. package/dist/tempo/session/ChannelStore.d.ts.map +0 -1
  448. package/dist/tempo/session/ChannelStore.js +0 -172
  449. package/dist/tempo/session/ChannelStore.js.map +0 -1
  450. package/dist/tempo/session/Receipt.d.ts +0 -22
  451. package/dist/tempo/session/Receipt.d.ts.map +0 -1
  452. package/dist/tempo/session/Receipt.js +0 -34
  453. package/dist/tempo/session/Receipt.js.map +0 -1
  454. package/dist/tempo/session/Sse.d.ts.map +0 -1
  455. package/dist/tempo/session/Sse.js +0 -363
  456. package/dist/tempo/session/Sse.js.map +0 -1
  457. package/dist/tempo/session/Types.d.ts +0 -78
  458. package/dist/tempo/session/Types.d.ts.map +0 -1
  459. package/dist/tempo/session/Types.js.map +0 -1
  460. package/dist/tempo/session/Voucher.d.ts.map +0 -1
  461. package/dist/tempo/session/Voucher.js.map +0 -1
  462. package/dist/tempo/session/Ws.d.ts +0 -87
  463. package/dist/tempo/session/Ws.d.ts.map +0 -1
  464. package/dist/tempo/session/Ws.js +0 -443
  465. package/dist/tempo/session/Ws.js.map +0 -1
  466. package/dist/tempo/session/escrow.abi.js.map +0 -1
  467. package/src/tempo/session/ChannelStore.ts +0 -308
  468. package/src/tempo/session/Receipt.test.ts +0 -89
  469. package/src/tempo/session/Receipt.ts +0 -46
  470. package/src/tempo/session/Sse.ts +0 -462
  471. package/src/tempo/session/Types.ts +0 -86
  472. package/src/tempo/session/Ws.ts +0 -576
  473. /package/dist/tempo/{session → legacy/session}/Channel.js +0 -0
  474. /package/dist/tempo/{session → legacy/session}/Types.js +0 -0
  475. /package/src/tempo/{session → legacy/session}/Channel.test.ts +0 -0
  476. /package/src/tempo/{session → legacy/session}/Voucher.test.ts +0 -0
  477. /package/src/tempo/session/{Sse.fuzz.test.ts → server/Sse.fuzz.test.ts} +0 -0
@@ -0,0 +1,88 @@
1
+ import type { Hex } from 'viem'
2
+
3
+ import type { NeedVoucherEvent } from '../precompile/Protocol.js'
4
+ import * as ChannelStore from './ChannelStore.js'
5
+ import { commitReservedCharges, reserveChargeOrWait } from './Transports.js'
6
+
7
+ /** Controller passed to manual-charge streaming generators. */
8
+ export type SessionController = {
9
+ /**
10
+ * Reserve voucher coverage for the next emitted chunk.
11
+ *
12
+ * The reservation blocks until sufficient voucher headroom exists, but the
13
+ * charge is only committed once a chunk is actually emitted. If the stream
14
+ * ends or aborts before that emission, the reservation is dropped.
15
+ */
16
+ charge(): Promise<void>
17
+ }
18
+
19
+ /** Async stream source accepted by paid session transports. */
20
+ export type SessionStreamGenerator =
21
+ | AsyncIterable<string>
22
+ | ((stream: SessionController) => AsyncIterable<string>)
23
+
24
+ /** Options for metering a paid stream before transport-specific formatting. */
25
+ export type MeteredStreamOptions = {
26
+ /** Channel being metered. */
27
+ channelId: Hex
28
+ /** Emits a transport-specific need-voucher frame. */
29
+ emitNeedVoucher(message: string): void | Promise<void>
30
+ /** Formats a transport-specific need-voucher frame. */
31
+ formatNeedVoucher(parameters: NeedVoucherEvent): string
32
+ /** Async source or manual-charge source. */
33
+ generate: SessionStreamGenerator
34
+ /** Store polling interval when `waitForUpdate` is unavailable. */
35
+ pollIntervalMs: number
36
+ /** Pre-authorized units that may be emitted without reserving new voucher headroom. */
37
+ prepaidUnits?: number | undefined
38
+ /** Optional abort signal for stream cancellation. */
39
+ signal?: AbortSignal | undefined
40
+ /** Channel store used for state reads and atomic charge commits. */
41
+ store: ChannelStore.ChannelStore
42
+ /** Raw token cost per emitted value. */
43
+ tickCost: bigint
44
+ }
45
+
46
+ /** Applies voucher reservation and spend commits to an async session stream. */
47
+ export async function* meterIterable(options: MeteredStreamOptions): AsyncGenerator<string> {
48
+ let prepaidUnits = options.prepaidUnits ?? 0
49
+ let reservedAmount = 0n
50
+ let reservedUnits = 0
51
+
52
+ const charge = async () => {
53
+ if (prepaidUnits > 0) {
54
+ prepaidUnits -= 1
55
+ return
56
+ }
57
+
58
+ await reserveChargeOrWait({
59
+ store: options.store,
60
+ channelId: options.channelId,
61
+ amount: options.tickCost,
62
+ reservedAmount,
63
+ emit: options.emitNeedVoucher,
64
+ formatNeedVoucher: options.formatNeedVoucher,
65
+ pollIntervalMs: options.pollIntervalMs,
66
+ signal: options.signal,
67
+ })
68
+ reservedAmount += options.tickCost
69
+ reservedUnits += 1
70
+ }
71
+
72
+ const iterable =
73
+ typeof options.generate === 'function' ? options.generate({ charge }) : options.generate
74
+
75
+ for await (const value of iterable) {
76
+ if (options.signal?.aborted) break
77
+ if (typeof options.generate !== 'function') await charge()
78
+ await commitReservedCharges({
79
+ store: options.store,
80
+ channelId: options.channelId,
81
+ amount: reservedAmount,
82
+ units: reservedUnits,
83
+ })
84
+ reservedAmount = 0n
85
+ reservedUnits = 0
86
+ yield value
87
+ }
88
+ }
@@ -0,0 +1,531 @@
1
+ import type { Address, Hex } from 'viem'
2
+ import { privateKeyToAccount } from 'viem/accounts'
3
+ import { describe, expect, test } from 'vp/test'
4
+
5
+ import type * as Credential from '../../../Credential.js'
6
+ import type { SessionCredentialPayload } from '../precompile/Protocol.js'
7
+ import type * as ChannelStore from './ChannelStore.js'
8
+ import {
9
+ requireSessionCredentialAction,
10
+ requireSessionCredentialPayloadHeader,
11
+ } from './CredentialVerification.js'
12
+ import {
13
+ getChallengePaymentFields,
14
+ getCredentialChannelId,
15
+ normalizeSessionChannelId,
16
+ respondToSessionCredential,
17
+ resolveCredentialVerificationContext,
18
+ resolveSessionChannelId,
19
+ resolveSessionPaymentRequest,
20
+ resolveSessionSnapshot,
21
+ resolveVerificationRequest,
22
+ } from './RequestState.js'
23
+
24
+ describe('RequestContext', () => {
25
+ const channelId = `0x${'aa'.repeat(32)}` as Hex
26
+ const escrowContract = '0x4D50500000000000000000000000000000000000' as Address
27
+ const feePayer = privateKeyToAccount(
28
+ '0x59c6995e998f97a5a0044966f0945383c7ac45c5a0642d5c9fa4f071979ab3c1',
29
+ )
30
+
31
+ describe('precompile session request context', () => {
32
+ test('reads action without requiring channel context', () => {
33
+ expect(requireSessionCredentialAction({ action: 'close' })).toBe('close')
34
+ expect(requireSessionCredentialAction({ action: 'topUp' })).toBe('topUp')
35
+ })
36
+
37
+ test('rejects missing or unknown actions', () => {
38
+ expect(() => requireSessionCredentialAction(null)).toThrow(
39
+ 'invalid session credential payload',
40
+ )
41
+ expect(() => requireSessionCredentialAction({ action: 'refund' })).toThrow(
42
+ 'invalid session credential action',
43
+ )
44
+ })
45
+
46
+ test('reads action and channel ID for verification payloads', () => {
47
+ expect(requireSessionCredentialPayloadHeader({ action: 'voucher', channelId })).toEqual({
48
+ action: 'voucher',
49
+ channelId,
50
+ })
51
+ })
52
+
53
+ test('rejects verification payload headers without channel ID', () => {
54
+ expect(() => requireSessionCredentialPayloadHeader({ action: 'voucher' })).toThrow(
55
+ 'invalid session credential channelId',
56
+ )
57
+ })
58
+
59
+ test('normalizes credential channel IDs for bootstrap hints', () => {
60
+ const mixedCase = `0x${'AA'.repeat(32)}` as Hex
61
+ const credential = {
62
+ challenge: {},
63
+ payload: { channelId: mixedCase },
64
+ } as Credential.Credential
65
+
66
+ expect(getCredentialChannelId(credential)).toBe(channelId)
67
+ expect(getCredentialChannelId(null)).toBeUndefined()
68
+ expect(
69
+ getCredentialChannelId({ challenge: {}, payload: {} } as Credential.Credential),
70
+ ).toBeUndefined()
71
+ })
72
+
73
+ test('reads typed challenge payment fields', () => {
74
+ expect(
75
+ getChallengePaymentFields({
76
+ id: 'challenge-id',
77
+ realm: 'test',
78
+ method: 'tempo',
79
+ intent: 'session',
80
+ request: {
81
+ amount: '123',
82
+ currency: escrowContract,
83
+ recipient: feePayer.address,
84
+ },
85
+ }),
86
+ ).toEqual({
87
+ amount: 123n,
88
+ currency: escrowContract,
89
+ recipient: feePayer.address,
90
+ })
91
+ })
92
+
93
+ test('rejects challenge payment fields with missing destination', () => {
94
+ expect(() =>
95
+ getChallengePaymentFields({
96
+ id: 'challenge-id',
97
+ realm: 'test',
98
+ method: 'tempo',
99
+ intent: 'session',
100
+ request: {
101
+ amount: '123',
102
+ currency: escrowContract,
103
+ },
104
+ }),
105
+ ).toThrow('missing challenge recipient')
106
+ })
107
+
108
+ test('rejects challenge payment fields with invalid token addresses', () => {
109
+ expect(() =>
110
+ getChallengePaymentFields({
111
+ id: 'challenge-id',
112
+ realm: 'test',
113
+ method: 'tempo',
114
+ intent: 'session',
115
+ request: {
116
+ amount: '123',
117
+ currency: 'pathUSD',
118
+ recipient: feePayer.address,
119
+ },
120
+ }),
121
+ ).toThrow('missing challenge currency')
122
+ })
123
+
124
+ test('rejects invalid request escrow contracts before challenge creation', async () => {
125
+ await expect(
126
+ resolveSessionPaymentRequest({
127
+ credential: null,
128
+ decimals: 2,
129
+ getClient: async () => ({ chain: { id: 42431 } }),
130
+ request: {
131
+ amount: '1',
132
+ chainId: 42431,
133
+ currency: escrowContract,
134
+ decimals: 2,
135
+ escrowContract: 'not-an-address' as Address,
136
+ recipient: feePayer.address,
137
+ unitType: 'request',
138
+ },
139
+ store: {
140
+ async getChannel() {
141
+ return null
142
+ },
143
+ async updateChannel() {
144
+ return null
145
+ },
146
+ },
147
+ }),
148
+ ).rejects.toThrow('Invalid escrowContract configured for tempo.session().')
149
+ })
150
+
151
+ test('resolves verification context from canonical method details', async () => {
152
+ const client = { chain: { id: 42431 } } as never
153
+ const context = await resolveCredentialVerificationContext({
154
+ decimals: 2,
155
+ feePayer,
156
+ getClient: async () => client,
157
+ minVoucherDelta: '1.25',
158
+ request: {
159
+ amount: '100',
160
+ currency: 'pathUSD',
161
+ methodDetails: {
162
+ chainId: 42431,
163
+ escrowContract,
164
+ feePayer: true,
165
+ },
166
+ unitType: 'request',
167
+ },
168
+ })
169
+
170
+ expect(context).toMatchObject({
171
+ chainId: 42431,
172
+ client,
173
+ escrow: escrowContract,
174
+ feePayer,
175
+ minVoucherDelta: 125n,
176
+ })
177
+ })
178
+
179
+ test('uses challenge minVoucherDelta before server default', async () => {
180
+ const context = await resolveCredentialVerificationContext({
181
+ decimals: 2,
182
+ getClient: async () => ({}) as never,
183
+ minVoucherDelta: '1.25',
184
+ request: {
185
+ amount: '100',
186
+ currency: 'pathUSD',
187
+ methodDetails: {
188
+ chainId: 42431,
189
+ escrowContract,
190
+ minVoucherDelta: '7',
191
+ },
192
+ unitType: 'request',
193
+ },
194
+ })
195
+
196
+ expect(context.minVoucherDelta).toBe(7n)
197
+ })
198
+
199
+ test('accepts already canonical challenge requests after schema parse fallback', () => {
200
+ const request = {
201
+ amount: '100',
202
+ currency: 'pathUSD',
203
+ methodDetails: {
204
+ chainId: 42431,
205
+ escrowContract,
206
+ },
207
+ unitType: 'request',
208
+ }
209
+
210
+ expect(resolveVerificationRequest(request)).toBe(request)
211
+ })
212
+
213
+ test('rejects invalid canonical fallback requests', () => {
214
+ expect(() =>
215
+ resolveVerificationRequest({
216
+ amount: '100',
217
+ methodDetails: {
218
+ chainId: 42431,
219
+ escrowContract,
220
+ },
221
+ }),
222
+ ).toThrow('invalid session request')
223
+ })
224
+
225
+ test('rejects canonical fallback requests with invalid escrow contracts', () => {
226
+ expect(() =>
227
+ resolveVerificationRequest({
228
+ amount: '100',
229
+ currency: escrowContract,
230
+ methodDetails: {
231
+ chainId: 42431,
232
+ escrowContract: 'not-an-address',
233
+ },
234
+ unitType: 'request',
235
+ }),
236
+ ).toThrow('invalid session request')
237
+ })
238
+ })
239
+ })
240
+
241
+ describe('ResponseGate', () => {
242
+ function respond(action: SessionCredentialPayload['action'], input: Request) {
243
+ return respondToSessionCredential({
244
+ input,
245
+ payload: { action },
246
+ })
247
+ }
248
+
249
+ describe('ResponseGate', () => {
250
+ test('returns 204 for close and top-up management actions', () => {
251
+ expect(respond('close', new Request('http://localhost', { method: 'GET' }))?.status).toBe(204)
252
+ expect(respond('topUp', new Request('http://localhost', { method: 'POST' }))?.status).toBe(
253
+ 204,
254
+ )
255
+ })
256
+
257
+ test('returns 204 for empty open and voucher POST management actions', () => {
258
+ expect(respond('open', new Request('http://localhost', { method: 'POST' }))?.status).toBe(204)
259
+ expect(respond('voucher', new Request('http://localhost', { method: 'POST' }))?.status).toBe(
260
+ 204,
261
+ )
262
+ })
263
+
264
+ test('lets open and voucher content requests through', () => {
265
+ expect(respond('open', new Request('http://localhost', { method: 'GET' }))).toBeUndefined()
266
+ expect(
267
+ respond(
268
+ 'voucher',
269
+ new Request('http://localhost', {
270
+ method: 'POST',
271
+ headers: { 'content-length': '1' },
272
+ }),
273
+ ),
274
+ ).toBeUndefined()
275
+ })
276
+
277
+ test('uses captured request metadata when supplied', () => {
278
+ expect(
279
+ respondToSessionCredential({
280
+ input: new Request('http://localhost', { method: 'POST' }),
281
+ payload: { action: 'voucher' },
282
+ capturedRequest: {
283
+ headers: new Headers({ 'content-length': '1' }),
284
+ hasBody: false,
285
+ method: 'POST',
286
+ },
287
+ }),
288
+ ).toBeUndefined()
289
+ })
290
+ })
291
+ })
292
+
293
+ describe('SessionSnapshotHints', () => {
294
+ const channelId = `0x${'aa'.repeat(32)}` as Hex
295
+ const escrowContract = '0x4D50500000000000000000000000000000000000' as Address
296
+ const descriptor = {
297
+ authorizedSigner: '0x0000000000000000000000000000000000000001',
298
+ expiringNonceHash: `0x${'11'.repeat(32)}`,
299
+ operator: '0x0000000000000000000000000000000000000000',
300
+ payee: '0x0000000000000000000000000000000000000002',
301
+ payer: '0x0000000000000000000000000000000000000003',
302
+ salt: `0x${'22'.repeat(32)}`,
303
+ token: '0x20c0000000000000000000000000000000000001',
304
+ } as const
305
+
306
+ function channel(overrides: Partial<ChannelStore.State> = {}): ChannelStore.State {
307
+ return {
308
+ authorizedSigner: descriptor.authorizedSigner,
309
+ backend: 'precompile',
310
+ chainId: 4217,
311
+ channelId,
312
+ closeRequestedAt: 0n,
313
+ createdAt: new Date(0).toISOString(),
314
+ deposit: 1_000n,
315
+ descriptor,
316
+ escrowContract,
317
+ expiringNonceHash: descriptor.expiringNonceHash,
318
+ finalized: false,
319
+ highestVoucher: null,
320
+ highestVoucherAmount: 500n,
321
+ operator: descriptor.operator,
322
+ payee: descriptor.payee,
323
+ payer: descriptor.payer,
324
+ salt: descriptor.salt,
325
+ settledOnChain: 100n,
326
+ spent: 300n,
327
+ token: descriptor.token,
328
+ units: 3,
329
+ ...overrides,
330
+ }
331
+ }
332
+
333
+ function store(state: ChannelStore.State | null): ChannelStore.ChannelStore {
334
+ return {
335
+ async getChannel() {
336
+ return state
337
+ },
338
+ async updateChannel() {
339
+ throw new Error('unexpected update')
340
+ },
341
+ }
342
+ }
343
+
344
+ describe('SessionSnapshotHints', () => {
345
+ test('normalizes optional channel ID hints', () => {
346
+ expect(normalizeSessionChannelId(`0x${'AA'.repeat(32)}`)).toBe(channelId)
347
+ expect(normalizeSessionChannelId(undefined)).toBeUndefined()
348
+ expect(normalizeSessionChannelId(123)).toBeUndefined()
349
+ expect(normalizeSessionChannelId('0x1234')).toBeUndefined()
350
+ expect(normalizeSessionChannelId(`0x${'zz'.repeat(32)}`)).toBeUndefined()
351
+ })
352
+
353
+ test('resolves channel IDs from explicit request hints before custom resolver', async () => {
354
+ let called = false
355
+ const resolved = await resolveSessionChannelId({
356
+ credential: null,
357
+ request: {
358
+ amount: '1',
359
+ channelId: `0x${'AA'.repeat(32)}`,
360
+ currency: descriptor.token,
361
+ decimals: 0,
362
+ recipient: descriptor.payee,
363
+ unitType: 'request',
364
+ },
365
+ resolveChannelId() {
366
+ called = true
367
+ return `0x${'bb'.repeat(32)}`
368
+ },
369
+ store: store(null),
370
+ })
371
+
372
+ expect(resolved).toBe(channelId)
373
+ expect(called).toBe(false)
374
+ })
375
+
376
+ test('does not trust credential channel IDs before verification', async () => {
377
+ const resolved = await resolveSessionChannelId({
378
+ credential: {
379
+ challenge: {},
380
+ payload: { channelId: `0x${'AA'.repeat(32)}` },
381
+ } as Credential.Credential,
382
+ request: {
383
+ amount: '1',
384
+ currency: descriptor.token,
385
+ decimals: 0,
386
+ recipient: descriptor.payee,
387
+ unitType: 'request',
388
+ },
389
+ resolveChannelId({ credential, source }) {
390
+ expect(credential).toBeNull()
391
+ expect(source).toBeUndefined()
392
+ return undefined
393
+ },
394
+ store: store(null),
395
+ })
396
+
397
+ expect(resolved).toBeUndefined()
398
+ })
399
+
400
+ test('uses custom resolver when no explicit channel ID is present', async () => {
401
+ const resolved = await resolveSessionChannelId({
402
+ capturedRequest: {
403
+ headers: new Headers({ cookie: 'sid=abc' }),
404
+ method: 'GET',
405
+ url: new URL('https://api.example.com/resource'),
406
+ },
407
+ credential: null,
408
+ request: {
409
+ amount: '1',
410
+ currency: descriptor.token,
411
+ decimals: 0,
412
+ recipient: descriptor.payee,
413
+ unitType: 'request',
414
+ },
415
+ resolveChannelId({ request, paymentRequest }) {
416
+ expect(request?.headers.get('cookie')).toBe('sid=abc')
417
+ expect(paymentRequest.unitType).toBe('request')
418
+ return `0x${'AA'.repeat(32)}`
419
+ },
420
+ store: store(null),
421
+ })
422
+
423
+ expect(resolved).toBe(channelId)
424
+ })
425
+
426
+ test('rejects invalid channel IDs returned by custom resolver', async () => {
427
+ await expect(
428
+ resolveSessionChannelId({
429
+ credential: null,
430
+ request: {
431
+ amount: '1',
432
+ currency: descriptor.token,
433
+ decimals: 0,
434
+ recipient: descriptor.payee,
435
+ unitType: 'request',
436
+ },
437
+ resolveChannelId: () => '0x1234',
438
+ store: store(null),
439
+ }),
440
+ ).rejects.toThrow('Invalid session channel ID.')
441
+ })
442
+
443
+ test('builds reusable channel hints without lowering accepted cumulative', async () => {
444
+ await expect(
445
+ resolveSessionSnapshot({ amount: 50n, channelId, store: store(channel()) }),
446
+ ).resolves.toEqual({
447
+ acceptedCumulative: '500',
448
+ chainId: 4217,
449
+ channelId,
450
+ closeRequestedAt: undefined,
451
+ deposit: '1000',
452
+ descriptor,
453
+ escrow: escrowContract,
454
+ requiredCumulative: '350',
455
+ settled: '100',
456
+ spent: '300',
457
+ units: 3,
458
+ })
459
+ })
460
+
461
+ test('raises accepted cumulative when next request exceeds current authorization', async () => {
462
+ const snapshot = await resolveSessionSnapshot({
463
+ amount: 300n,
464
+ channelId,
465
+ store: store(channel()),
466
+ })
467
+
468
+ expect(snapshot?.requiredCumulative).toBe('600')
469
+ expect(snapshot?.acceptedCumulative).toBe('600')
470
+ })
471
+
472
+ test('omits reusable channel hints when payment fields do not match', async () => {
473
+ const cases = [
474
+ {
475
+ name: 'chainId',
476
+ expected: { chainId: 1 },
477
+ },
478
+ {
479
+ name: 'escrow',
480
+ expected: { escrowContract: '0x0000000000000000000000000000000000000004' },
481
+ },
482
+ {
483
+ name: 'recipient',
484
+ expected: { recipient: '0x0000000000000000000000000000000000000005' },
485
+ },
486
+ {
487
+ name: 'currency',
488
+ expected: { currency: '0x0000000000000000000000000000000000000006' },
489
+ },
490
+ ] as const
491
+
492
+ for (const item of cases) {
493
+ await expect(
494
+ resolveSessionSnapshot({
495
+ amount: 50n,
496
+ channelId,
497
+ expected: {
498
+ chainId: 4217,
499
+ currency: descriptor.token,
500
+ escrowContract,
501
+ recipient: descriptor.payee,
502
+ ...item.expected,
503
+ },
504
+ store: store(channel()),
505
+ }),
506
+ item.name,
507
+ ).resolves.toBeUndefined()
508
+ }
509
+ })
510
+
511
+ test('omits hints for missing, non-precompile, or finalized channels', async () => {
512
+ await expect(
513
+ resolveSessionSnapshot({ amount: 1n, channelId, store: store(null) }),
514
+ ).resolves.toBe(undefined)
515
+ await expect(
516
+ resolveSessionSnapshot({
517
+ amount: 1n,
518
+ channelId,
519
+ store: store(channel({ backend: 'external' } as Partial<ChannelStore.State>)),
520
+ }),
521
+ ).resolves.toBe(undefined)
522
+ await expect(
523
+ resolveSessionSnapshot({
524
+ amount: 1n,
525
+ channelId,
526
+ store: store(channel({ finalized: true })),
527
+ }),
528
+ ).resolves.toBe(undefined)
529
+ })
530
+ })
531
+ })