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,814 @@
1
+ import {
2
+ isAddress,
3
+ parseUnits,
4
+ type Account as ViemAccount,
5
+ type Address,
6
+ type Client,
7
+ type Hex,
8
+ } from 'viem'
9
+
10
+ import type * as Challenge from '../../../Challenge.js'
11
+ import * as Constants from '../../../Constants.js'
12
+ import * as Account from '../../../viem/Account.js'
13
+ import * as z from '../../../zod.js'
14
+ import * as Chain from '../precompile/Chain.js'
15
+ import * as Channel from '../precompile/Channel.js'
16
+ import type { SessionCredentialPayload } from '../precompile/Protocol.js'
17
+ import type { SessionSnapshot } from '../Snapshot.js'
18
+ import {
19
+ createClosePayload,
20
+ createOpenPayload,
21
+ createTopUpPayload,
22
+ createVoucherPayload,
23
+ isSameAddress,
24
+ resolveAuthorizedSigner,
25
+ resolveEscrow,
26
+ type ChannelEntry,
27
+ } from './ChannelOps.js'
28
+ import { assertWithinMaxDeposit, resolveOpeningDeposit } from './Runtime.js'
29
+
30
+ /** Credential payload variants that carry cumulative voucher authorization. */
31
+ export type CumulativeCredentialPayload = Extract<
32
+ SessionCredentialPayload,
33
+ { cumulativeAmount: string }
34
+ >
35
+
36
+ /** In-memory client channel cache used by automatic precompile session credential planning. */
37
+ export type ChannelCache = {
38
+ /** Maps reusable channel keys to cached channel metadata. */
39
+ channels: Map<string, ChannelEntry>
40
+ /** Maps channel IDs back to reusable channel keys for manual credential cache updates. */
41
+ channelIdToKey: Map<string, string>
42
+ /** Emits cache updates to the public `onChannelUpdate` callback. */
43
+ notifyUpdate(entry: ChannelEntry): void
44
+ }
45
+
46
+ /** Creates an empty client channel cache with an optional update callback. */
47
+ export function createChannelCache(
48
+ onUpdate?: ((entry: ChannelEntry) => void) | undefined,
49
+ ): ChannelCache {
50
+ return {
51
+ channels: new Map(),
52
+ channelIdToKey: new Map(),
53
+ notifyUpdate: (entry) => onUpdate?.(entry),
54
+ } satisfies ChannelCache
55
+ }
56
+
57
+ /** Returns the cache key for a reusable payer session channel. */
58
+ export function channelKey(payee: Address, token: Address, escrow: Address): string {
59
+ return `${payee.toLowerCase()}:${token.toLowerCase()}:${escrow.toLowerCase()}`
60
+ }
61
+
62
+ /** Stores a channel entry and notifies observers. */
63
+ export function storeChannelEntry(cache: ChannelCache, key: string, entry: ChannelEntry): void {
64
+ cache.channels.set(key, entry)
65
+ cache.channelIdToKey.set(entry.channelId, key)
66
+ cache.notifyUpdate(entry)
67
+ }
68
+
69
+ /** Returns whether a credential payload carries cumulative voucher authorization. */
70
+ export function hasCredentialCumulativeAmount(
71
+ payload: SessionCredentialPayload,
72
+ ): payload is CumulativeCredentialPayload {
73
+ return 'cumulativeAmount' in payload
74
+ }
75
+
76
+ /** Reads cumulative authorization from a credential payload when the action carries one. */
77
+ export function readCredentialCumulativeAmount(
78
+ payload: SessionCredentialPayload,
79
+ ): bigint | undefined {
80
+ if (!hasCredentialCumulativeAmount(payload)) return undefined
81
+ return BigInt(payload.cumulativeAmount)
82
+ }
83
+
84
+ /** Applies a credential payload's cumulative amount to an existing cached channel. */
85
+ export function updateCachedCumulative(
86
+ cache: ChannelCache,
87
+ channelId: Hex,
88
+ payload: SessionCredentialPayload,
89
+ ): void {
90
+ const key = cache.channelIdToKey.get(channelId)
91
+ const cumulativeAmount = readCredentialCumulativeAmount(payload)
92
+ if (!key || cumulativeAmount === undefined) return
93
+ const entry = cache.channels.get(key)
94
+ if (!entry) return
95
+ entry.cumulativeAmount =
96
+ entry.cumulativeAmount > cumulativeAmount ? entry.cumulativeAmount : cumulativeAmount
97
+ if (payload.action === 'close') entry.opened = false
98
+ cache.notifyUpdate(entry)
99
+ }
100
+
101
+ const hexSchema = z.custom<Hex>(
102
+ (value) => typeof value === 'string' && /^0x[0-9a-fA-F]*$/.test(value),
103
+ )
104
+ const hashSchema = z.custom<Hex>(
105
+ (value) => typeof value === 'string' && /^0x[0-9a-fA-F]{64}$/.test(value),
106
+ )
107
+
108
+ /** Runtime schema for low-level TIP-1034 session credential context. */
109
+ export const sessionContextSchema = z.object({
110
+ account: z.optional(z.custom<Account.getResolver.Parameters['account']>()),
111
+ action: z.optional(z.enum(['open', 'topUp', 'voucher', 'close'])),
112
+ channelId: z.optional(hashSchema),
113
+ cumulativeAmount: z.optional(z.amount()),
114
+ cumulativeAmountRaw: z.optional(z.string()),
115
+ transaction: z.optional(hexSchema),
116
+ descriptor: z.optional(z.custom<Channel.ChannelDescriptor>()),
117
+ additionalDeposit: z.optional(z.amount()),
118
+ additionalDepositRaw: z.optional(z.string()),
119
+ depositRaw: z.optional(z.string()),
120
+ })
121
+
122
+ /** Low-level context accepted by `tempo.session()` for manual credentials. */
123
+ export type SessionContext = {
124
+ /** Optional account override used for this credential only. */
125
+ account?: Account.getResolver.Parameters['account'] | undefined
126
+ /** Manual credential action. Omit for automatic open/recover/voucher management. */
127
+ action?: 'open' | 'topUp' | 'voucher' | 'close' | undefined
128
+ /** Channel ID being reused or manually operated on. */
129
+ channelId?: Hex | undefined
130
+ /** Human-readable cumulative voucher authorization, parsed with configured decimals. */
131
+ cumulativeAmount?: string | undefined
132
+ /** Raw cumulative voucher authorization. Takes precedence over `cumulativeAmount`. */
133
+ cumulativeAmountRaw?: string | undefined
134
+ /** Signed Tempo transaction for manual open/top-up credentials. */
135
+ transaction?: Hex | undefined
136
+ /** TIP-1034 descriptor required for recovery and manual credentials. */
137
+ descriptor?: Channel.ChannelDescriptor | undefined
138
+ /** Human-readable additional top-up deposit, parsed with configured decimals. */
139
+ additionalDeposit?: string | undefined
140
+ /** Raw additional top-up deposit. Takes precedence over `additionalDeposit`. */
141
+ additionalDepositRaw?: string | undefined
142
+ /** Raw opening deposit override for automatic open credentials. */
143
+ depositRaw?: string | undefined
144
+ }
145
+
146
+ /** Manual low-level TIP-1034 session action name. */
147
+ export type SessionAction = NonNullable<SessionContext['action']>
148
+
149
+ /** Context amount fields that may be supplied as human-readable or raw token units. */
150
+ export type SessionAmountField = 'additionalDeposit' | 'cumulativeAmount'
151
+
152
+ /** Session context narrowed to an explicit manual action. */
153
+ export type ManualSessionContext = SessionContext & { action: SessionAction }
154
+
155
+ /** Manual session action context after the required channel descriptor is present. */
156
+ export type ManualSessionDescriptorContext = ManualSessionContext & {
157
+ /** TIP-1034 channel descriptor used by manual open/top-up/voucher/close actions. */
158
+ descriptor: Channel.ChannelDescriptor
159
+ }
160
+
161
+ /** Session context narrowed to a recoverable TIP-1034 channel descriptor. */
162
+ export type DescriptorSessionContext = SessionContext & { descriptor: Channel.ChannelDescriptor }
163
+
164
+ /** Returns whether a session context contains an explicit manual action. */
165
+ export function hasSessionAction(
166
+ context: SessionContext | undefined,
167
+ ): context is ManualSessionContext {
168
+ return context?.action !== undefined
169
+ }
170
+
171
+ /** Returns whether a context is a manual action with the descriptor required to execute it. */
172
+ export function hasManualSessionDescriptor(
173
+ context: SessionContext | undefined,
174
+ ): context is ManualSessionDescriptorContext {
175
+ return hasSessionAction(context) && context.descriptor !== undefined
176
+ }
177
+
178
+ /** Returns whether a session context contains a recoverable channel descriptor. */
179
+ export function hasSessionDescriptor(
180
+ context: SessionContext | undefined,
181
+ ): context is DescriptorSessionContext {
182
+ return context?.descriptor !== undefined
183
+ }
184
+
185
+ /** Parses an optional session context amount, preferring the raw-unit field when present. */
186
+ export function parseOptionalContextAmount(
187
+ context: SessionContext,
188
+ decimals: number,
189
+ field: SessionAmountField,
190
+ ): bigint | undefined {
191
+ const raw =
192
+ field === 'additionalDeposit' ? context.additionalDepositRaw : context.cumulativeAmountRaw
193
+ const amount =
194
+ field === 'additionalDeposit' ? context.additionalDeposit : context.cumulativeAmount
195
+ if (raw) return BigInt(raw)
196
+ if (amount) return parseUnits(amount, decimals)
197
+ return undefined
198
+ }
199
+
200
+ /** Parses a required session context amount and throws with action-specific context when absent. */
201
+ export function requireContextAmount(
202
+ context: SessionContext,
203
+ decimals: number,
204
+ field: SessionAmountField,
205
+ action: string,
206
+ ): bigint {
207
+ const amount = parseOptionalContextAmount(context, decimals, field)
208
+ if (amount === undefined) throw new Error(`${field} required for ${action} action`)
209
+ return amount
210
+ }
211
+
212
+ /** Tempo-specific details embedded in a `tempo/session` challenge request. */
213
+ export type ClientSessionMethodDetails = {
214
+ /** Chain ID used for voucher domain and channel ID derivation. */
215
+ chainId?: number | undefined
216
+ /** Escrow contract address advertised by the server. */
217
+ escrowContract?: Address | undefined
218
+ /** Legacy escrow hint accepted during migration. */
219
+ escrow?: Address | undefined
220
+ /** Whether the challenge allows fee-sponsored open/top-up transactions. */
221
+ feePayer?: boolean | undefined
222
+ /** Channel operator address advertised by the server. */
223
+ operator?: Address | undefined
224
+ /** Server bootstrap snapshot for a reusable session channel. */
225
+ sessionSnapshot?: SessionSnapshot | undefined
226
+ }
227
+
228
+ /** Dependencies used to resolve a challenge into typed credential-planning data. */
229
+ export type ResolveChallengeContextParameters = {
230
+ /** Challenge received from the 402 response. */
231
+ challenge: Challenge.Challenge
232
+ /** Optional local escrow override. */
233
+ escrowOverride?: Address | undefined
234
+ /** Resolves the viem client for the challenge chain. */
235
+ getClient(parameters: { chainId?: number | undefined }): Client | Promise<Client>
236
+ }
237
+
238
+ /** Reads TIP-1034 channel state for a recovery candidate. */
239
+ export type ReadReusableChannelState = (
240
+ client: Client,
241
+ channelId: Hex,
242
+ escrow: Address,
243
+ ) => Promise<Chain.ChannelState>
244
+
245
+ /** Expected request fields used to prove a descriptor belongs to the current challenge. */
246
+ export type ReusableChannelExpectation = {
247
+ /** Chain ID used in the TIP-1034 channel ID derivation. */
248
+ chainId: number
249
+ /** Escrow precompile address used in the TIP-1034 channel ID derivation. */
250
+ escrow: Address
251
+ /** Payee expected by the current challenge. */
252
+ payee: Address
253
+ /** Payer address controlled by the local account. */
254
+ payer: Address
255
+ /** Voucher signer resolved from local account configuration. */
256
+ authorizedSigner: Address
257
+ /** Token expected by the current challenge. */
258
+ token: Address
259
+ }
260
+
261
+ /** Inputs for validating and loading an existing precompile session channel. */
262
+ export type ResolveReusableChannelParameters = {
263
+ /** Optional caller/server supplied channel ID. Must match the descriptor-derived ID. */
264
+ channelId?: string | undefined
265
+ /** Viem client used to read on-chain channel state. */
266
+ client: Client
267
+ /** Descriptor required by TIP-1034 vouchers and management transactions. */
268
+ descriptor: Channel.ChannelDescriptor
269
+ /** Expected challenge fields the descriptor must match. */
270
+ expected: ReusableChannelExpectation
271
+ /** Optional state reader for tests or custom clients. Defaults to `Chain.getChannelState`. */
272
+ readChannelState?: ReadReusableChannelState | undefined
273
+ }
274
+
275
+ /** Validated reusable channel data. */
276
+ export type ReusableChannel = {
277
+ /** Descriptor-derived TIP-1034 channel ID. */
278
+ channelId: Hex
279
+ /** On-chain channel state proving the channel is open and reusable. */
280
+ state: Chain.ChannelState
281
+ }
282
+
283
+ /** Resolved payment challenge fields used to plan a client-side session credential. */
284
+ export type ChallengeContext = {
285
+ amount: bigint
286
+ challenge: Challenge.Challenge
287
+ chainId: number
288
+ client: Client
289
+ escrow: Address
290
+ feePayer?: boolean | undefined
291
+ key: string
292
+ operator?: Address | undefined
293
+ payee: Address
294
+ snapshot?: SessionSnapshot | undefined
295
+ /** Server-provided raw deposit hint for opening a channel, before local maxDeposit capping. */
296
+ suggestedDepositRaw?: string | undefined
297
+ token: Address
298
+ }
299
+
300
+ /** Inputs used to choose the next client-side session credential operation. */
301
+ export type PlanCredentialParameters = {
302
+ account: ViemAccount
303
+ authorizedSigner?: Address | undefined
304
+ cache: ChannelCache
305
+ context?: SessionContext | undefined
306
+ decimals: number
307
+ maxDeposit?: bigint | undefined
308
+ resolved: ChallengeContext
309
+ }
310
+
311
+ /** Inputs used to derive reusable-channel recovery context from caller context and server hints. */
312
+ export type ResolveRecoverContextParameters = {
313
+ /** Caller-provided low-level session context, when present. */
314
+ context?: SessionContext | undefined
315
+ /** Server-provided session snapshot, when present. */
316
+ snapshot?: SessionSnapshot | undefined
317
+ }
318
+
319
+ /** Inputs used to choose the next cumulative authorization for a recovered channel. */
320
+ export type ResolveRecoveredCumulativeParameters = {
321
+ /** Caller or stored-channel recovery context. */
322
+ context: DescriptorSessionContext
323
+ /** Token decimals used to parse human-readable context amounts. */
324
+ decimals: number
325
+ /** Current request amount from the active challenge. */
326
+ requestAmount: bigint
327
+ /** Server snapshot for the recovered channel, when present. */
328
+ snapshot?: SessionSnapshot | undefined
329
+ /** On-chain settled amount used when no local/server accounting is available. */
330
+ settled: bigint
331
+ }
332
+
333
+ /** Data-first description of the next credential operation the client should execute. */
334
+ export type CredentialPlan =
335
+ /** No reusable channel is available, so create an open transaction and initial voucher. */
336
+ | {
337
+ type: 'open'
338
+ account: ViemAccount
339
+ authorizedSigner?: Address | undefined
340
+ context?: SessionContext | undefined
341
+ maxDeposit?: bigint | undefined
342
+ resolved: ChallengeContext
343
+ }
344
+ /** Rehydrate a known channel from server snapshot or caller descriptor before signing. */
345
+ | {
346
+ type: 'recover'
347
+ account: ViemAccount
348
+ authorizedSigner?: Address | undefined
349
+ context: DescriptorSessionContext
350
+ decimals: number
351
+ maxDeposit?: bigint | undefined
352
+ resolved: ChallengeContext
353
+ }
354
+ /** Reuse an active cached channel by increasing the cumulative voucher amount. */
355
+ | {
356
+ type: 'voucher'
357
+ account: ViemAccount
358
+ entry: ChannelEntry
359
+ maxDeposit?: bigint | undefined
360
+ resolved: ChallengeContext
361
+ }
362
+ /** Caller supplied an explicit low-level action such as top-up, voucher, or close. */
363
+ | {
364
+ type: 'manual'
365
+ account: ViemAccount
366
+ authorizedSigner?: Address | undefined
367
+ context: ManualSessionDescriptorContext
368
+ decimals: number
369
+ resolved: ChallengeContext
370
+ }
371
+
372
+ type ManualCredentialParameters = Pick<
373
+ Extract<CredentialPlan, { type: 'manual' }>,
374
+ 'account' | 'context' | 'decimals' | 'resolved'
375
+ > & {
376
+ channelId: Hex
377
+ descriptor: Channel.ChannelDescriptor
378
+ }
379
+
380
+ function isObject(value: unknown): value is Record<string, unknown> {
381
+ return typeof value === 'object' && value !== null
382
+ }
383
+
384
+ function readOptionalAddress(value: unknown): Address | undefined {
385
+ return typeof value === 'string' && isAddress(value, { strict: false }) ? value : undefined
386
+ }
387
+
388
+ function readMethodDetails(challenge: Challenge.Challenge): ClientSessionMethodDetails {
389
+ const methodDetails = challenge.request.methodDetails
390
+ if (!isObject(methodDetails)) return {}
391
+ return {
392
+ chainId: typeof methodDetails.chainId === 'number' ? methodDetails.chainId : undefined,
393
+ escrowContract: readOptionalAddress(methodDetails.escrowContract),
394
+ escrow: readOptionalAddress(methodDetails.escrow),
395
+ feePayer: typeof methodDetails.feePayer === 'boolean' ? methodDetails.feePayer : undefined,
396
+ operator: readOptionalAddress(methodDetails.operator),
397
+ sessionSnapshot: Constants.getMethodDetail<SessionSnapshot>(
398
+ methodDetails,
399
+ Constants.MethodDetailKeys.sessionSnapshot,
400
+ ),
401
+ }
402
+ }
403
+
404
+ function readAddress(value: unknown, label: string): Address {
405
+ if (typeof value === 'string' && isAddress(value, { strict: false })) return value
406
+ throw new Error(`tempo session challenge missing ${label}`)
407
+ }
408
+
409
+ function readAmount(value: unknown): bigint {
410
+ if (typeof value === 'string') return BigInt(value)
411
+ throw new Error('tempo session challenge missing amount')
412
+ }
413
+
414
+ function readSuggestedDeposit(value: unknown): string | undefined {
415
+ return typeof value === 'string' ? value : undefined
416
+ }
417
+
418
+ /** Resolves raw challenge fields into the typed data required by client credential planning. */
419
+ export async function resolveChallengeContext(
420
+ parameters: ResolveChallengeContextParameters,
421
+ ): Promise<ChallengeContext> {
422
+ const { challenge, escrowOverride, getClient } = parameters
423
+ const methodDetails = readMethodDetails(challenge)
424
+ const client = await getClient({ chainId: methodDetails.chainId })
425
+ const chainId = methodDetails.chainId ?? client.chain?.id
426
+ if (!chainId) throw new Error('No chainId configured for TIP-1034 session challenge.')
427
+
428
+ const escrow = resolveEscrow(challenge, escrowOverride)
429
+ const payee = readAddress(challenge.request.recipient, 'recipient')
430
+ const token = readAddress(challenge.request.currency, 'currency')
431
+
432
+ return {
433
+ amount: readAmount(challenge.request.amount),
434
+ challenge,
435
+ chainId,
436
+ client,
437
+ escrow,
438
+ feePayer: methodDetails.feePayer,
439
+ key: channelKey(payee, token, escrow),
440
+ operator: methodDetails.operator,
441
+ payee,
442
+ snapshot: methodDetails.sessionSnapshot,
443
+ suggestedDepositRaw: readSuggestedDeposit(challenge.request.suggestedDeposit),
444
+ token,
445
+ }
446
+ }
447
+
448
+ /** Validates descriptor identity and reads open channel state for client-side recovery. */
449
+ export async function resolveReusableChannel(
450
+ parameters: ResolveReusableChannelParameters,
451
+ ): Promise<ReusableChannel> {
452
+ const {
453
+ channelId,
454
+ client,
455
+ descriptor,
456
+ expected,
457
+ readChannelState = Chain.getChannelState,
458
+ } = parameters
459
+ const expectedChannelId = Channel.computeId({
460
+ ...descriptor,
461
+ chainId: expected.chainId,
462
+ escrow: expected.escrow,
463
+ })
464
+
465
+ assertReusableChannelDescriptor({
466
+ channelId,
467
+ descriptor,
468
+ expectedChannelId,
469
+ payee: expected.payee,
470
+ payer: expected.payer,
471
+ authorizedSigner: expected.authorizedSigner,
472
+ token: expected.token,
473
+ })
474
+
475
+ const state = await readChannelState(client, expectedChannelId, expected.escrow)
476
+ if (state.deposit === 0n)
477
+ throw new Error(`Channel ${expectedChannelId} cannot be reused (closed or not found on-chain).`)
478
+ if (state.closeRequestedAt !== 0)
479
+ throw new Error(`Channel ${expectedChannelId} cannot be reused (pending close request).`)
480
+
481
+ return { channelId: expectedChannelId, state }
482
+ }
483
+
484
+ function assertReusableChannelDescriptor(parameters: {
485
+ channelId?: string | undefined
486
+ descriptor: Channel.ChannelDescriptor
487
+ expectedChannelId: string
488
+ payee: Address
489
+ payer: Address
490
+ authorizedSigner: Address
491
+ token: Address
492
+ }) {
493
+ const { authorizedSigner, channelId, descriptor, expectedChannelId, payee, payer, token } =
494
+ parameters
495
+ if (channelId && channelId.toLowerCase() !== expectedChannelId.toLowerCase())
496
+ throw new Error('context channelId does not match descriptor')
497
+ if (!isSameAddress(descriptor.payee, payee))
498
+ throw new Error('context descriptor payee does not match challenge')
499
+ if (!isSameAddress(descriptor.token, token))
500
+ throw new Error('context descriptor token does not match challenge')
501
+ if (!isSameAddress(descriptor.payer, payer))
502
+ throw new Error('context descriptor payer does not match account')
503
+ if (!isSameAddress(descriptor.authorizedSigner, authorizedSigner))
504
+ throw new Error('context descriptor authorizedSigner does not match account')
505
+ }
506
+
507
+ /** Resolves descriptor-based recovery data, preferring caller context over server hints. */
508
+ export function resolveRecoverContext(
509
+ parameters: ResolveRecoverContextParameters,
510
+ ): DescriptorSessionContext | undefined {
511
+ const { context, snapshot } = parameters
512
+ const descriptor = context?.descriptor ?? snapshot?.descriptor
513
+ if (!descriptor) return undefined
514
+ return {
515
+ ...context,
516
+ channelId: context?.channelId ?? snapshot?.channelId,
517
+ descriptor,
518
+ }
519
+ }
520
+
521
+ /** Resolves a voucher boundary that can satisfy the resumed request. */
522
+ export function resolveRecoveredCumulative(
523
+ parameters: ResolveRecoveredCumulativeParameters,
524
+ ): bigint {
525
+ const { context, decimals, requestAmount, snapshot, settled } = parameters
526
+
527
+ if (snapshot) {
528
+ return BigInt(snapshot.spent) + requestAmount
529
+ }
530
+
531
+ const contextCumulative = parseOptionalContextAmount(context, decimals, 'cumulativeAmount')
532
+ if (contextCumulative !== undefined) return contextCumulative + requestAmount
533
+ return settled + requestAmount
534
+ }
535
+
536
+ /** Chooses the next credential plan from local channel cache and optional caller context. */
537
+ export function planCredential(parameters: PlanCredentialParameters): CredentialPlan {
538
+ const { account, authorizedSigner, cache, context, decimals, maxDeposit, resolved } = parameters
539
+
540
+ if (hasSessionAction(context)) {
541
+ if (!hasManualSessionDescriptor(context))
542
+ throw new Error('descriptor required for TIP-1034 session action')
543
+ return {
544
+ type: 'manual',
545
+ account,
546
+ authorizedSigner,
547
+ context,
548
+ decimals,
549
+ resolved,
550
+ }
551
+ }
552
+
553
+ const entry = cache.channels.get(resolved.key)
554
+ if (!entry && context?.channelId && !context.descriptor)
555
+ throw new Error('descriptor required to reuse TIP-1034 channel')
556
+ const recoverContext = resolveRecoverContext({ context, snapshot: resolved.snapshot })
557
+ if (!entry && recoverContext) {
558
+ return {
559
+ type: 'recover',
560
+ account,
561
+ authorizedSigner,
562
+ context: recoverContext,
563
+ decimals,
564
+ maxDeposit,
565
+ resolved,
566
+ }
567
+ }
568
+ if (entry?.opened) return { type: 'voucher', account, entry, maxDeposit, resolved }
569
+ return { type: 'open', account, authorizedSigner, context, maxDeposit, resolved }
570
+ }
571
+
572
+ /** Executes a credential plan and returns the concrete session credential payload. */
573
+ export async function executeCredentialPlan(
574
+ plan: CredentialPlan,
575
+ cache: ChannelCache,
576
+ ): Promise<SessionCredentialPayload> {
577
+ switch (plan.type) {
578
+ case 'open':
579
+ return open(plan, cache)
580
+ case 'recover':
581
+ return recover(plan, cache)
582
+ case 'voucher':
583
+ return voucher(plan, cache)
584
+ case 'manual':
585
+ return manual(plan, cache)
586
+ }
587
+ }
588
+
589
+ async function open(
590
+ plan: Extract<CredentialPlan, { type: 'open' }>,
591
+ cache: ChannelCache,
592
+ ): Promise<SessionCredentialPayload> {
593
+ const { account, authorizedSigner, resolved } = plan
594
+ const deposit = resolveOpeningDeposit({
595
+ contextDepositRaw: plan.context?.depositRaw,
596
+ maxDeposit: plan.maxDeposit,
597
+ requestAmount: resolved.amount,
598
+ suggestedDepositRaw: resolved.suggestedDepositRaw,
599
+ })
600
+ const payload = await createOpenPayload(resolved.client, account, {
601
+ authorizedSigner,
602
+ chainId: resolved.chainId,
603
+ deposit,
604
+ escrow: resolved.escrow,
605
+ feePayer: resolved.feePayer,
606
+ initialAmount: resolved.amount,
607
+ operator: resolved.operator,
608
+ payee: resolved.payee,
609
+ token: resolved.token,
610
+ })
611
+ storeChannelEntry(cache, resolved.key, {
612
+ channelId: payload.channelId,
613
+ cumulativeAmount: resolved.amount,
614
+ deposit,
615
+ descriptor: payload.descriptor,
616
+ escrow: resolved.escrow,
617
+ chainId: resolved.chainId,
618
+ opened: true,
619
+ })
620
+ return payload
621
+ }
622
+
623
+ async function recover(
624
+ plan: Extract<CredentialPlan, { type: 'recover' }>,
625
+ cache: ChannelCache,
626
+ ): Promise<SessionCredentialPayload> {
627
+ const { account, context, decimals, maxDeposit, resolved } = plan
628
+ const { descriptor } = context
629
+ const reusable = await resolveReusableChannel({
630
+ channelId: context.channelId,
631
+ client: resolved.client,
632
+ descriptor,
633
+ expected: {
634
+ chainId: resolved.chainId,
635
+ escrow: resolved.escrow,
636
+ payee: resolved.payee,
637
+ payer: account.address,
638
+ authorizedSigner: resolveAuthorizedSigner(account, plan.authorizedSigner),
639
+ token: resolved.token,
640
+ },
641
+ })
642
+ const cumulativeAmount = resolveRecoveredCumulative({
643
+ context,
644
+ decimals,
645
+ requestAmount: resolved.amount,
646
+ settled: reusable.state.settled,
647
+ snapshot: resolved.snapshot,
648
+ })
649
+ if (cumulativeAmount > reusable.state.deposit)
650
+ throw new Error('recovered voucher amount exceeds on-chain channel deposit')
651
+ assertWithinMaxDeposit(cumulativeAmount, maxDeposit)
652
+ const payload = await createVoucherPayload(
653
+ resolved.client,
654
+ account,
655
+ descriptor,
656
+ cumulativeAmount,
657
+ resolved.chainId,
658
+ resolved.escrow,
659
+ )
660
+ storeChannelEntry(cache, resolved.key, {
661
+ channelId: reusable.channelId,
662
+ cumulativeAmount,
663
+ deposit: reusable.state.deposit,
664
+ descriptor,
665
+ escrow: resolved.escrow,
666
+ chainId: resolved.chainId,
667
+ opened: true,
668
+ })
669
+ return payload
670
+ }
671
+
672
+ async function voucher(
673
+ plan: Extract<CredentialPlan, { type: 'voucher' }>,
674
+ cache: ChannelCache,
675
+ ): Promise<SessionCredentialPayload> {
676
+ const { account, entry, resolved } = plan
677
+ const cumulativeAmount = entry.cumulativeAmount + resolved.amount
678
+ assertWithinMaxDeposit(cumulativeAmount, plan.maxDeposit)
679
+ const payload = await createVoucherPayload(
680
+ resolved.client,
681
+ account,
682
+ entry.descriptor,
683
+ cumulativeAmount,
684
+ resolved.chainId,
685
+ resolved.escrow,
686
+ )
687
+ entry.cumulativeAmount = cumulativeAmount
688
+ cache.notifyUpdate(entry)
689
+ return payload
690
+ }
691
+
692
+ async function manual(
693
+ plan: Extract<CredentialPlan, { type: 'manual' }>,
694
+ cache: ChannelCache,
695
+ ): Promise<SessionCredentialPayload> {
696
+ const { account, context, decimals, resolved } = plan
697
+ const { descriptor } = context
698
+ const channelId = Channel.computeId({
699
+ ...descriptor,
700
+ chainId: resolved.chainId,
701
+ escrow: resolved.escrow,
702
+ })
703
+ assertReusableChannelDescriptor({
704
+ channelId: context.channelId,
705
+ descriptor,
706
+ expectedChannelId: channelId,
707
+ payee: resolved.payee,
708
+ payer: account.address,
709
+ authorizedSigner: resolveAuthorizedSigner(account, plan.authorizedSigner),
710
+ token: resolved.token,
711
+ })
712
+
713
+ const payload = await executeManualCredential({
714
+ account,
715
+ channelId,
716
+ context,
717
+ decimals,
718
+ descriptor,
719
+ resolved,
720
+ })
721
+ updateCachedCumulative(cache, channelId, payload)
722
+ return payload
723
+ }
724
+
725
+ async function executeManualCredential(
726
+ parameters: ManualCredentialParameters,
727
+ ): Promise<SessionCredentialPayload> {
728
+ switch (parameters.context.action) {
729
+ case 'open':
730
+ return manualOpen(parameters)
731
+ case 'topUp':
732
+ return manualTopUp(parameters)
733
+ case 'voucher':
734
+ return manualVoucher(parameters)
735
+ case 'close':
736
+ return manualClose(parameters)
737
+ }
738
+ }
739
+
740
+ async function manualOpen(
741
+ parameters: ManualCredentialParameters,
742
+ ): Promise<SessionCredentialPayload> {
743
+ const { account, channelId, context, decimals, descriptor, resolved } = parameters
744
+ if (!context.transaction) throw new Error('transaction required for open action')
745
+ const cumulativeAmount = requireContextAmount(context, decimals, 'cumulativeAmount', 'open')
746
+ const voucher = await createVoucherPayload(
747
+ resolved.client,
748
+ account,
749
+ descriptor,
750
+ cumulativeAmount,
751
+ resolved.chainId,
752
+ resolved.escrow,
753
+ )
754
+ return {
755
+ action: 'open',
756
+ type: 'transaction',
757
+ channelId,
758
+ transaction: context.transaction,
759
+ signature: voucher.signature,
760
+ descriptor,
761
+ cumulativeAmount: cumulativeAmount.toString(),
762
+ authorizedSigner: descriptor.authorizedSigner,
763
+ }
764
+ }
765
+
766
+ async function manualTopUp(
767
+ parameters: ManualCredentialParameters,
768
+ ): Promise<SessionCredentialPayload> {
769
+ const { account, channelId, context, decimals, descriptor, resolved } = parameters
770
+ const additionalDeposit = requireContextAmount(context, decimals, 'additionalDeposit', 'topUp')
771
+ if (context.transaction) {
772
+ return {
773
+ action: 'topUp',
774
+ type: 'transaction',
775
+ channelId,
776
+ transaction: context.transaction,
777
+ descriptor,
778
+ additionalDeposit: additionalDeposit.toString(),
779
+ }
780
+ }
781
+ return createTopUpPayload(
782
+ resolved.client,
783
+ account,
784
+ descriptor,
785
+ additionalDeposit,
786
+ resolved.chainId,
787
+ resolved.feePayer,
788
+ resolved.escrow,
789
+ )
790
+ }
791
+
792
+ function manualVoucher(parameters: ManualCredentialParameters): Promise<SessionCredentialPayload> {
793
+ const { account, context, decimals, descriptor, resolved } = parameters
794
+ return createVoucherPayload(
795
+ resolved.client,
796
+ account,
797
+ descriptor,
798
+ requireContextAmount(context, decimals, 'cumulativeAmount', 'voucher'),
799
+ resolved.chainId,
800
+ resolved.escrow,
801
+ )
802
+ }
803
+
804
+ function manualClose(parameters: ManualCredentialParameters): Promise<SessionCredentialPayload> {
805
+ const { account, context, decimals, descriptor, resolved } = parameters
806
+ return createClosePayload(
807
+ resolved.client,
808
+ account,
809
+ descriptor,
810
+ requireContextAmount(context, decimals, 'cumulativeAmount', 'close'),
811
+ resolved.chainId,
812
+ resolved.escrow,
813
+ )
814
+ }