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,734 @@
1
+ import { type Address, createClient, custom, decodeFunctionData, encodeFunctionResult } from 'viem'
2
+ import { privateKeyToAccount } from 'viem/accounts'
3
+ import { Transaction } from 'viem/tempo'
4
+ import { describe, expect, test } from 'vp/test'
5
+
6
+ import type { Challenge } from '../../../Challenge.js'
7
+ import * as Constants from '../../../Constants.js'
8
+ import * as Credential from '../../../Credential.js'
9
+ import * as z from '../../../zod.js'
10
+ import * as Methods from '../../Methods.js'
11
+ import * as Channel from '../precompile/Channel.js'
12
+ import { escrowAbi } from '../precompile/escrow.abi.js'
13
+ import { tip20ChannelEscrow } from '../precompile/Protocol.js'
14
+ import * as Types from '../precompile/Protocol.js'
15
+ import * as Voucher from '../precompile/Voucher.js'
16
+ import { session } from './Session.js'
17
+
18
+ const account = privateKeyToAccount(
19
+ '0xac0974bec39a17e36ba6a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
20
+ )
21
+ const chainId = 42431
22
+ const client = createClient({
23
+ account,
24
+ chain: { id: chainId } as never,
25
+ transport: custom({
26
+ async request(args) {
27
+ if (args.method === 'eth_chainId') return `0x${chainId.toString(16)}`
28
+ if (args.method === 'eth_getTransactionCount') return '0x0'
29
+ if (args.method === 'eth_estimateGas') return '0x5208'
30
+ if (args.method === 'eth_maxPriorityFeePerGas') return '0x1'
31
+ if (args.method === 'eth_getBlockByNumber') return { baseFeePerGas: '0x1' }
32
+ if (args.method === 'eth_call')
33
+ return encodeFunctionResult({
34
+ abi: escrowAbi,
35
+ functionName: 'getChannelState',
36
+ result: { settled: 0n, deposit: 1_000n, closeRequestedAt: 0 },
37
+ })
38
+ throw new Error(`unexpected rpc request: ${args.method}`)
39
+ },
40
+ }),
41
+ })
42
+
43
+ const descriptor = {
44
+ payer: account.address,
45
+ payee: '0x0000000000000000000000000000000000000002' as Address,
46
+ operator: '0x0000000000000000000000000000000000000000' as Address,
47
+ token: '0x0000000000000000000000000000000000000003' as Address,
48
+ salt: `0x${'11'.repeat(32)}` as `0x${string}`,
49
+ authorizedSigner: account.address,
50
+ expiringNonceHash: `0x${'22'.repeat(32)}` as `0x${string}`,
51
+ } satisfies Channel.ChannelDescriptor
52
+
53
+ type SessionChallenge = Challenge<
54
+ z.output<typeof Methods.session.schema.request>,
55
+ typeof Methods.session.intent,
56
+ typeof Methods.session.name
57
+ >
58
+
59
+ function makeChallenge(overrides: Partial<SessionChallenge['request']> = {}): SessionChallenge {
60
+ const request: SessionChallenge['request'] = {
61
+ amount: '100',
62
+ currency: descriptor.token,
63
+ recipient: descriptor.payee,
64
+ unitType: 'request',
65
+ methodDetails: { chainId, escrowContract: tip20ChannelEscrow },
66
+ }
67
+
68
+ return {
69
+ id: 'test-id',
70
+ realm: 'test.com',
71
+ method: 'tempo',
72
+ intent: 'session',
73
+ request: Object.assign(request, overrides),
74
+ }
75
+ }
76
+
77
+ function deserialize(credential: string) {
78
+ return Credential.deserialize(credential).payload as Types.SessionCredentialPayload
79
+ }
80
+
81
+ function deserializeCredential(credential: string) {
82
+ return Credential.deserialize<Types.SessionCredentialPayload>(credential)
83
+ }
84
+
85
+ function openArgs(payload: Types.SessionCredentialPayload) {
86
+ if (payload.action !== 'open') throw new Error('expected open payload')
87
+ const transaction = Transaction.deserialize(payload.transaction)
88
+ if (!('calls' in transaction)) throw new Error('expected tempo calls')
89
+ const calls = transaction.calls as readonly { to?: Address; data?: `0x${string}` }[]
90
+ const call = calls[0]!
91
+ const decoded = decodeFunctionData({ abi: escrowAbi, data: call.data! })
92
+ if (decoded.functionName !== 'open') throw new Error('expected open call')
93
+ return decoded.args
94
+ }
95
+
96
+ function openDeposit(payload: Types.SessionCredentialPayload): bigint {
97
+ return openArgs(payload)[3]
98
+ }
99
+
100
+ describe('precompile client session', () => {
101
+ test('handles only TIP-1034 session challenges', () => {
102
+ const method = session({ account, getClient: () => client })
103
+
104
+ expect(
105
+ method.canHandleChallenge?.({
106
+ challenge: makeChallenge({
107
+ methodDetails: {
108
+ chainId,
109
+ escrowContract: tip20ChannelEscrow,
110
+ sessionProtocol: Constants.SessionProtocols.v2,
111
+ },
112
+ }),
113
+ }),
114
+ ).toBe(true)
115
+ expect(method.canHandleChallenge?.({ challenge: makeChallenge() })).toBe(false)
116
+ expect(
117
+ method.canHandleChallenge?.({
118
+ challenge: makeChallenge({
119
+ methodDetails: {
120
+ chainId,
121
+ escrowContract: tip20ChannelEscrow,
122
+ sessionProtocol: Constants.SessionProtocols.v1,
123
+ },
124
+ }),
125
+ }),
126
+ ).toBe(false)
127
+ })
128
+
129
+ test('opens for the current amount without client deposit configuration', async () => {
130
+ const method = session({ account, getClient: () => client })
131
+ const payload = deserialize(
132
+ await method.createCredential({ challenge: makeChallenge(), context: {} }),
133
+ )
134
+
135
+ expect(payload.action).toBe('open')
136
+ expect(openDeposit(payload)).toBe(100n)
137
+ })
138
+
139
+ test('uses client chain ID when the challenge omits chain ID', async () => {
140
+ const method = session({ account, getClient: () => client })
141
+ const credential = deserializeCredential(
142
+ await method.createCredential({
143
+ challenge: makeChallenge({
144
+ methodDetails: { escrowContract: tip20ChannelEscrow },
145
+ }),
146
+ context: {},
147
+ }),
148
+ )
149
+ const payload = credential.payload
150
+
151
+ if (payload.action !== 'open') throw new Error('expected open payload')
152
+ expect(credential.source).toBe(`did:pkh:eip155:${chainId}:${account.address}`)
153
+ expect(payload.channelId).toBe(
154
+ Channel.computeId({ ...payload.descriptor, chainId, escrow: tip20ChannelEscrow }),
155
+ )
156
+ })
157
+
158
+ test('uses explicit context depositRaw before server hints', async () => {
159
+ const method = session({ account, getClient: () => client })
160
+ const payload = deserialize(
161
+ await method.createCredential({
162
+ challenge: makeChallenge(),
163
+ context: { depositRaw: '500' },
164
+ }),
165
+ )
166
+
167
+ expect(payload.action).toBe('open')
168
+ expect(openDeposit(payload)).toBe(500n)
169
+ })
170
+
171
+ test('caps suggestedDeposit by maxDeposit', async () => {
172
+ const method = session({ account, decimals: 0, maxDeposit: '500', getClient: () => client })
173
+ const payload = deserialize(
174
+ await method.createCredential({
175
+ challenge: makeChallenge({ suggestedDeposit: '1000' }),
176
+ context: {},
177
+ }),
178
+ )
179
+
180
+ expect(payload.action).toBe('open')
181
+ expect(openDeposit(payload)).toBe(500n)
182
+ })
183
+
184
+ test('uses suggestedDeposit when below maxDeposit', async () => {
185
+ const method = session({ account, decimals: 0, maxDeposit: '1000', getClient: () => client })
186
+ const payload = deserialize(
187
+ await method.createCredential({
188
+ challenge: makeChallenge({ suggestedDeposit: '700' }),
189
+ context: {},
190
+ }),
191
+ )
192
+
193
+ expect(payload.action).toBe('open')
194
+ expect(openDeposit(payload)).toBe(700n)
195
+ })
196
+
197
+ test('uses current amount without suggestedDeposit even when maxDeposit is higher', async () => {
198
+ const method = session({ account, decimals: 0, maxDeposit: '1000', getClient: () => client })
199
+ const payload = deserialize(
200
+ await method.createCredential({ challenge: makeChallenge(), context: {} }),
201
+ )
202
+
203
+ expect(payload.action).toBe('open')
204
+ expect(openDeposit(payload)).toBe(100n)
205
+ })
206
+
207
+ test('rejects open when maxDeposit is below the request amount', async () => {
208
+ const method = session({ account, decimals: 0, maxDeposit: '50', getClient: () => client })
209
+
210
+ await expect(
211
+ method.createCredential({ challenge: makeChallenge(), context: {} }),
212
+ ).rejects.toThrow('requested voucher amount 100 exceeds local maxDeposit 50')
213
+ })
214
+
215
+ test('rejects explicit opening deposits below the request amount', async () => {
216
+ const method = session({ account, decimals: 0, maxDeposit: '1000', getClient: () => client })
217
+
218
+ await expect(
219
+ method.createCredential({
220
+ challenge: makeChallenge(),
221
+ context: { depositRaw: '50' },
222
+ }),
223
+ ).rejects.toThrow('opening deposit 50 below request amount 100')
224
+ })
225
+
226
+ test('uses resolved escrow address for open transactions', async () => {
227
+ const challengeEscrow = '0x0000000000000000000000000000000000000005' as Address
228
+ const method = session({ account, decimals: 0, getClient: () => client })
229
+ const payload = deserialize(
230
+ await method.createCredential({
231
+ challenge: makeChallenge({
232
+ methodDetails: { chainId, escrowContract: challengeEscrow },
233
+ }),
234
+ context: {},
235
+ }),
236
+ )
237
+
238
+ if (payload.action !== 'open') throw new Error('expected open payload')
239
+ const transaction = Transaction.deserialize(payload.transaction)
240
+ if (!('calls' in transaction)) throw new Error('expected tempo calls')
241
+ const calls = transaction.calls as readonly { to?: Address; data?: `0x${string}` }[]
242
+ expect(calls[0]!.to?.toLowerCase()).toBe(challengeEscrow.toLowerCase())
243
+ expect(payload.channelId).toBe(
244
+ Channel.computeId({ ...payload.descriptor, chainId, escrow: challengeEscrow }),
245
+ )
246
+ })
247
+
248
+ test('uses challenge-advertised operator for open transactions', async () => {
249
+ const operator = '0x0000000000000000000000000000000000000006' as Address
250
+ const method = session({ account, decimals: 0, getClient: () => client })
251
+ const payload = deserialize(
252
+ await method.createCredential({
253
+ challenge: makeChallenge({
254
+ methodDetails: { chainId, escrowContract: tip20ChannelEscrow, operator },
255
+ }),
256
+ context: {},
257
+ }),
258
+ )
259
+
260
+ if (payload.action !== 'open') throw new Error('expected open payload')
261
+ expect(openArgs(payload)[1].toLowerCase()).toBe(operator.toLowerCase())
262
+ expect(payload.descriptor.operator.toLowerCase()).toBe(operator.toLowerCase())
263
+ })
264
+
265
+ test('tracks cumulative amount and calls onChannelUpdate in auto mode', async () => {
266
+ const updates: bigint[] = []
267
+ const method = session({
268
+ account,
269
+ decimals: 0,
270
+ maxDeposit: '1000',
271
+ getClient: () => client,
272
+ onChannelUpdate: (entry) => updates.push(entry.cumulativeAmount),
273
+ })
274
+ const first = deserialize(
275
+ await method.createCredential({ challenge: makeChallenge(), context: {} }),
276
+ )
277
+ const second = deserialize(
278
+ await method.createCredential({ challenge: makeChallenge(), context: {} }),
279
+ )
280
+
281
+ expect(first.action).toBe('open')
282
+ expect(second.action).toBe('voucher')
283
+ if (second.action !== 'voucher') throw new Error('expected voucher')
284
+ expect(second.channelId).toBe(first.channelId)
285
+ expect(second.cumulativeAmount).toBe('200')
286
+ expect(updates).toEqual([100n, 200n])
287
+ })
288
+
289
+ test('enforces maxDeposit when reusing a cached auto-mode channel', async () => {
290
+ const updates: bigint[] = []
291
+ const method = session({
292
+ account,
293
+ decimals: 0,
294
+ maxDeposit: '150',
295
+ getClient: () => client,
296
+ onChannelUpdate: (entry) => updates.push(entry.cumulativeAmount),
297
+ })
298
+
299
+ await method.createCredential({ challenge: makeChallenge(), context: {} })
300
+
301
+ await expect(
302
+ method.createCredential({ challenge: makeChallenge(), context: {} }),
303
+ ).rejects.toThrow('requested voucher amount 200 exceeds local maxDeposit 150')
304
+ expect(updates).toEqual([100n])
305
+ })
306
+
307
+ test('recovers and reuses a descriptor supplied in context', async () => {
308
+ const updates: bigint[] = []
309
+ const method = session({
310
+ account,
311
+ decimals: 0,
312
+ maxDeposit: '1000',
313
+ getClient: () => client,
314
+ onChannelUpdate: (entry) => updates.push(entry.cumulativeAmount),
315
+ })
316
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
317
+ const recovered = deserialize(
318
+ await method.createCredential({
319
+ challenge: makeChallenge(),
320
+ context: { channelId, descriptor },
321
+ }),
322
+ )
323
+ const next = deserialize(
324
+ await method.createCredential({ challenge: makeChallenge(), context: {} }),
325
+ )
326
+
327
+ expect(recovered.action).toBe('voucher')
328
+ if (recovered.action !== 'voucher' || next.action !== 'voucher')
329
+ throw new Error('expected voucher')
330
+ expect(recovered.channelId).toBe(channelId)
331
+ expect(recovered.cumulativeAmount).toBe('100')
332
+ expect(next.channelId).toBe(channelId)
333
+ expect(next.cumulativeAmount).toBe('200')
334
+ expect(updates).toEqual([100n, 200n])
335
+ })
336
+
337
+ test('increments stored cumulative when recovering without a server snapshot', async () => {
338
+ const method = session({ account, decimals: 0, maxDeposit: '1000', getClient: () => client })
339
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
340
+ const payload = deserialize(
341
+ await method.createCredential({
342
+ challenge: makeChallenge(),
343
+ context: { channelId, cumulativeAmountRaw: '100', descriptor },
344
+ }),
345
+ )
346
+
347
+ expect(payload.action).toBe('voucher')
348
+ if (payload.action !== 'voucher') throw new Error('expected voucher')
349
+ expect(payload.channelId).toBe(channelId)
350
+ expect(payload.cumulativeAmount).toBe('200')
351
+ })
352
+
353
+ test('uses required server snapshot cumulative when recovering a channel', async () => {
354
+ const method = session({ account, decimals: 0, maxDeposit: '1000', getClient: () => client })
355
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
356
+ const payload = deserialize(
357
+ await method.createCredential({
358
+ challenge: makeChallenge({
359
+ methodDetails: {
360
+ chainId,
361
+ escrowContract: tip20ChannelEscrow,
362
+ sessionSnapshot: {
363
+ acceptedCumulative: '400',
364
+ chainId,
365
+ channelId,
366
+ deposit: '1000',
367
+ descriptor,
368
+ escrow: tip20ChannelEscrow,
369
+ requiredCumulative: '400',
370
+ settled: '0',
371
+ spent: '300',
372
+ units: 3,
373
+ },
374
+ },
375
+ }),
376
+ context: {},
377
+ }),
378
+ )
379
+
380
+ expect(payload.action).toBe('voucher')
381
+ if (payload.action !== 'voucher') throw new Error('expected voucher')
382
+ expect(payload.channelId).toBe(channelId)
383
+ expect(payload.descriptor).toEqual(descriptor)
384
+ expect(payload.cumulativeAmount).toBe('400')
385
+ })
386
+
387
+ test('ignores accepted snapshot headroom above current request spend', async () => {
388
+ const method = session({ account, decimals: 0, maxDeposit: '1000', getClient: () => client })
389
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
390
+ const payload = deserialize(
391
+ await method.createCredential({
392
+ challenge: makeChallenge({
393
+ methodDetails: {
394
+ chainId,
395
+ escrowContract: tip20ChannelEscrow,
396
+ sessionSnapshot: {
397
+ acceptedCumulative: '500',
398
+ chainId,
399
+ channelId,
400
+ deposit: '1000',
401
+ descriptor,
402
+ escrow: tip20ChannelEscrow,
403
+ requiredCumulative: '400',
404
+ settled: '0',
405
+ spent: '300',
406
+ units: 3,
407
+ },
408
+ },
409
+ }),
410
+ context: {},
411
+ }),
412
+ )
413
+
414
+ expect(payload.action).toBe('voucher')
415
+ if (payload.action !== 'voucher') throw new Error('expected voucher')
416
+ expect(payload.cumulativeAmount).toBe('400')
417
+ })
418
+
419
+ test('caps recovered voucher authorization by maxDeposit', async () => {
420
+ const method = session({ account, decimals: 0, maxDeposit: '300', getClient: () => client })
421
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
422
+
423
+ await expect(
424
+ method.createCredential({
425
+ challenge: makeChallenge({
426
+ methodDetails: {
427
+ chainId,
428
+ escrowContract: tip20ChannelEscrow,
429
+ sessionSnapshot: {
430
+ acceptedCumulative: '300',
431
+ chainId,
432
+ channelId,
433
+ deposit: '1000',
434
+ descriptor,
435
+ escrow: tip20ChannelEscrow,
436
+ requiredCumulative: '300',
437
+ settled: '0',
438
+ spent: '200',
439
+ },
440
+ },
441
+ }),
442
+ context: {},
443
+ }),
444
+ ).resolves.toBeDefined()
445
+
446
+ const overLimitMethod = session({
447
+ account,
448
+ decimals: 0,
449
+ maxDeposit: '300',
450
+ getClient: () => client,
451
+ })
452
+ await expect(
453
+ overLimitMethod.createCredential({
454
+ challenge: makeChallenge({
455
+ amount: '400',
456
+ methodDetails: {
457
+ chainId,
458
+ escrowContract: tip20ChannelEscrow,
459
+ sessionSnapshot: {
460
+ acceptedCumulative: '1000',
461
+ chainId,
462
+ channelId,
463
+ deposit: '1000',
464
+ descriptor,
465
+ escrow: tip20ChannelEscrow,
466
+ requiredCumulative: '1000',
467
+ settled: '0',
468
+ spent: '300',
469
+ },
470
+ },
471
+ }),
472
+ context: {},
473
+ }),
474
+ ).rejects.toThrow('requested voucher amount 700 exceeds local maxDeposit 300')
475
+ })
476
+
477
+ test('rejects descriptor recovery for closed or missing channels', async () => {
478
+ const closedClient = createClient({
479
+ account,
480
+ chain: { id: chainId } as never,
481
+ transport: custom({
482
+ async request(args) {
483
+ if (args.method === 'eth_chainId') return `0x${chainId.toString(16)}`
484
+ if (args.method === 'eth_call')
485
+ return encodeFunctionResult({
486
+ abi: escrowAbi,
487
+ functionName: 'getChannelState',
488
+ result: { settled: 0n, deposit: 0n, closeRequestedAt: 0 },
489
+ })
490
+ throw new Error(`unexpected rpc request: ${args.method}`)
491
+ },
492
+ }),
493
+ })
494
+ const method = session({
495
+ account,
496
+ decimals: 0,
497
+ maxDeposit: '1000',
498
+ getClient: () => closedClient,
499
+ })
500
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
501
+
502
+ await expect(
503
+ method.createCredential({
504
+ challenge: makeChallenge(),
505
+ context: { channelId, descriptor },
506
+ }),
507
+ ).rejects.toThrow(/cannot be reused \(closed or not found on-chain\)/)
508
+ })
509
+
510
+ test('rejects channel recovery without descriptor', async () => {
511
+ const method = session({ account, decimals: 0, maxDeposit: '1000', getClient: () => client })
512
+
513
+ await expect(
514
+ method.createCredential({
515
+ challenge: makeChallenge(),
516
+ context: { channelId: `0x${'33'.repeat(32)}` },
517
+ }),
518
+ ).rejects.toThrow('descriptor required to reuse TIP-1034 channel')
519
+ })
520
+
521
+ test('defaults precompile authorizedSigner to account access key address', async () => {
522
+ const accessKeyAddress = '0x0000000000000000000000000000000000000009' as Address
523
+ const accessKeyAccount = Object.assign({}, account, { accessKeyAddress })
524
+ const method = session({
525
+ account: accessKeyAccount,
526
+ decimals: 0,
527
+ maxDeposit: '1000',
528
+ getClient: () => client,
529
+ })
530
+ const payload = deserialize(
531
+ await method.createCredential({ challenge: makeChallenge(), context: {} }),
532
+ )
533
+
534
+ expect(payload.action).toBe('open')
535
+ if (payload.action !== 'open') throw new Error('expected open payload')
536
+ expect(payload.descriptor.authorizedSigner).toBe(accessKeyAddress)
537
+ })
538
+
539
+ test('manual open requires transaction', async () => {
540
+ const method = session({ account, getClient: () => client })
541
+
542
+ await expect(
543
+ method.createCredential({
544
+ challenge: makeChallenge(),
545
+ context: { action: 'open', descriptor, cumulativeAmountRaw: '100' },
546
+ }),
547
+ ).rejects.toThrow('transaction required for open action')
548
+ })
549
+
550
+ test('manual open requires cumulativeAmount', async () => {
551
+ const method = session({ account, getClient: () => client })
552
+
553
+ await expect(
554
+ method.createCredential({
555
+ challenge: makeChallenge(),
556
+ context: { action: 'open', descriptor, transaction: '0x1234' },
557
+ }),
558
+ ).rejects.toThrow('cumulativeAmount required for open action')
559
+ })
560
+
561
+ test('manual topUp requires additionalDeposit', async () => {
562
+ const method = session({ account, getClient: () => client })
563
+
564
+ await expect(
565
+ method.createCredential({
566
+ challenge: makeChallenge(),
567
+ context: { action: 'topUp', descriptor, transaction: '0x1234' },
568
+ }),
569
+ ).rejects.toThrow('additionalDeposit required for topUp action')
570
+ })
571
+
572
+ test('manual voucher requires cumulativeAmount', async () => {
573
+ const method = session({ account, getClient: () => client })
574
+
575
+ await expect(
576
+ method.createCredential({
577
+ challenge: makeChallenge(),
578
+ context: { action: 'voucher', descriptor },
579
+ }),
580
+ ).rejects.toThrow('cumulativeAmount required for voucher action')
581
+ })
582
+
583
+ test('manual close requires cumulativeAmount', async () => {
584
+ const method = session({ account, getClient: () => client })
585
+
586
+ await expect(
587
+ method.createCredential({
588
+ challenge: makeChallenge(),
589
+ context: { action: 'close', descriptor },
590
+ }),
591
+ ).rejects.toThrow('cumulativeAmount required for close action')
592
+ })
593
+
594
+ test('manual actions require descriptors', async () => {
595
+ const method = session({ account, getClient: () => client })
596
+
597
+ await expect(
598
+ method.createCredential({
599
+ challenge: makeChallenge(),
600
+ context: { action: 'voucher', cumulativeAmountRaw: '100' },
601
+ }),
602
+ ).rejects.toThrow('descriptor required for TIP-1034 session action')
603
+ })
604
+
605
+ test('creates manual voucher credentials with descriptor payloads', async () => {
606
+ const method = session({ account, getClient: () => client })
607
+ const credential = await method.createCredential({
608
+ challenge: makeChallenge(),
609
+ context: {
610
+ action: 'voucher',
611
+ descriptor,
612
+ cumulativeAmountRaw: '250',
613
+ },
614
+ })
615
+
616
+ const decoded = deserializeCredential(credential)
617
+ const payload = decoded.payload as Types.SessionCredentialPayload
618
+ const cumulativeAmount = Types.uint96(250n)
619
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
620
+
621
+ expect(decoded.challenge.id).toBe('test-id')
622
+ expect(decoded.challenge.realm).toBe('test.com')
623
+ expect(decoded.challenge.method).toBe('tempo')
624
+ expect(decoded.challenge.intent).toBe('session')
625
+ expect(payload.action).toBe('voucher')
626
+ if (payload.action !== 'voucher') throw new Error('expected voucher payload')
627
+ expect(payload.channelId).toBe(channelId)
628
+ expect(payload.descriptor).toEqual(descriptor)
629
+ expect(payload.cumulativeAmount).toBe('250')
630
+ expect(decoded.source).toBe(`did:pkh:eip155:${chainId}:${account.address}`)
631
+ expect(
632
+ Voucher.verifyVoucher(
633
+ tip20ChannelEscrow,
634
+ chainId,
635
+ { channelId, cumulativeAmount, signature: payload.signature },
636
+ descriptor.authorizedSigner,
637
+ ),
638
+ ).toBe(true)
639
+ })
640
+
641
+ test('creates manual open credentials with descriptor payloads', async () => {
642
+ const method = session({ account, getClient: () => client })
643
+ const credential = await method.createCredential({
644
+ challenge: makeChallenge(),
645
+ context: {
646
+ action: 'open',
647
+ descriptor,
648
+ cumulativeAmountRaw: '250',
649
+ transaction: '0x1234',
650
+ },
651
+ })
652
+
653
+ const decoded = deserializeCredential(credential)
654
+ const payload = decoded.payload
655
+ const cumulativeAmount = Types.uint96(250n)
656
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
657
+
658
+ expect(decoded.challenge.id).toBe('test-id')
659
+ expect(payload.action).toBe('open')
660
+ if (payload.action !== 'open') throw new Error('expected open payload')
661
+ expect(payload.type).toBe('transaction')
662
+ expect(payload.channelId).toBe(channelId)
663
+ expect(payload.descriptor).toEqual(descriptor)
664
+ expect(payload.transaction).toBe('0x1234')
665
+ expect(payload.cumulativeAmount).toBe('250')
666
+ expect(payload.authorizedSigner).toBe(descriptor.authorizedSigner)
667
+ expect(decoded.source).toBe(`did:pkh:eip155:${chainId}:${account.address}`)
668
+ expect(
669
+ Voucher.verifyVoucher(
670
+ tip20ChannelEscrow,
671
+ chainId,
672
+ { channelId, cumulativeAmount, signature: payload.signature },
673
+ descriptor.authorizedSigner,
674
+ ),
675
+ ).toBe(true)
676
+ })
677
+
678
+ test('creates manual top-up credentials from provided transactions', async () => {
679
+ const method = session({ account, getClient: () => client })
680
+ const credential = await method.createCredential({
681
+ challenge: makeChallenge(),
682
+ context: {
683
+ action: 'topUp',
684
+ descriptor,
685
+ additionalDepositRaw: '500',
686
+ transaction: '0x1234',
687
+ },
688
+ })
689
+
690
+ const decoded = deserializeCredential(credential)
691
+ const payload = decoded.payload as Types.SessionCredentialPayload
692
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
693
+
694
+ expect(payload.action).toBe('topUp')
695
+ if (payload.action !== 'topUp') throw new Error('expected topUp payload')
696
+ expect(payload.channelId).toBe(channelId)
697
+ expect(payload.descriptor).toEqual(descriptor)
698
+ expect(payload.additionalDeposit).toBe('500')
699
+ expect(payload.transaction).toBe('0x1234')
700
+ expect(decoded.source).toBe(`did:pkh:eip155:${chainId}:${account.address}`)
701
+ })
702
+
703
+ test('creates manual close credentials with descriptor payloads', async () => {
704
+ const method = session({ account, getClient: () => client })
705
+ const credential = await method.createCredential({
706
+ challenge: makeChallenge(),
707
+ context: {
708
+ action: 'close',
709
+ descriptor,
710
+ cumulativeAmountRaw: '250',
711
+ },
712
+ })
713
+
714
+ const decoded = deserializeCredential(credential)
715
+ const payload = decoded.payload
716
+ const cumulativeAmount = Types.uint96(250n)
717
+ const channelId = Channel.computeId({ ...descriptor, chainId, escrow: tip20ChannelEscrow })
718
+
719
+ expect(payload.action).toBe('close')
720
+ if (payload.action !== 'close') throw new Error('expected close payload')
721
+ expect(payload.channelId).toBe(channelId)
722
+ expect(payload.descriptor).toEqual(descriptor)
723
+ expect(payload.cumulativeAmount).toBe('250')
724
+ expect(decoded.source).toBe(`did:pkh:eip155:${chainId}:${account.address}`)
725
+ expect(
726
+ Voucher.verifyVoucher(
727
+ tip20ChannelEscrow,
728
+ chainId,
729
+ { channelId, cumulativeAmount, signature: payload.signature },
730
+ descriptor.authorizedSigner,
731
+ ),
732
+ ).toBe(true)
733
+ })
734
+ })