mppx 0.6.31 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (477) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/Challenge.d.ts.map +1 -1
  3. package/dist/Challenge.js +9 -7
  4. package/dist/Challenge.js.map +1 -1
  5. package/dist/Constants.d.ts +46 -0
  6. package/dist/Constants.d.ts.map +1 -0
  7. package/dist/Constants.js +46 -0
  8. package/dist/Constants.js.map +1 -0
  9. package/dist/Credential.d.ts.map +1 -1
  10. package/dist/Credential.js +5 -4
  11. package/dist/Credential.js.map +1 -1
  12. package/dist/Method.d.ts +32 -4
  13. package/dist/Method.d.ts.map +1 -1
  14. package/dist/Method.js +5 -2
  15. package/dist/Method.js.map +1 -1
  16. package/dist/Receipt.d.ts.map +1 -1
  17. package/dist/Receipt.js +3 -2
  18. package/dist/Receipt.js.map +1 -1
  19. package/dist/cli/cli.d.ts.map +1 -1
  20. package/dist/cli/cli.js +19 -11
  21. package/dist/cli/cli.js.map +1 -1
  22. package/dist/cli/plugins/tempo.d.ts.map +1 -1
  23. package/dist/cli/plugins/tempo.js +17 -6
  24. package/dist/cli/plugins/tempo.js.map +1 -1
  25. package/dist/cli/utils.d.ts +5 -0
  26. package/dist/cli/utils.d.ts.map +1 -1
  27. package/dist/cli/utils.js +10 -0
  28. package/dist/cli/utils.js.map +1 -1
  29. package/dist/client/Methods.d.ts +5 -2
  30. package/dist/client/Methods.d.ts.map +1 -1
  31. package/dist/client/Methods.js +5 -2
  32. package/dist/client/Methods.js.map +1 -1
  33. package/dist/client/Transport.d.ts.map +1 -1
  34. package/dist/client/Transport.js +4 -5
  35. package/dist/client/Transport.js.map +1 -1
  36. package/dist/client/index.d.ts +2 -1
  37. package/dist/client/index.d.ts.map +1 -1
  38. package/dist/client/index.js +2 -1
  39. package/dist/client/index.js.map +1 -1
  40. package/dist/client/internal/Fetch.d.ts.map +1 -1
  41. package/dist/client/internal/Fetch.js +14 -6
  42. package/dist/client/internal/Fetch.js.map +1 -1
  43. package/dist/evm/server/Methods.d.ts +1 -1
  44. package/dist/evm/server/Methods.d.ts.map +1 -1
  45. package/dist/index.d.ts +1 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +1 -0
  48. package/dist/index.js.map +1 -1
  49. package/dist/internal/AcceptPayment.d.ts +3 -0
  50. package/dist/internal/AcceptPayment.d.ts.map +1 -1
  51. package/dist/internal/AcceptPayment.js +15 -11
  52. package/dist/internal/AcceptPayment.js.map +1 -1
  53. package/dist/mcp-sdk/client/McpClient.d.ts +12 -5
  54. package/dist/mcp-sdk/client/McpClient.d.ts.map +1 -1
  55. package/dist/mcp-sdk/client/McpClient.js +55 -42
  56. package/dist/mcp-sdk/client/McpClient.js.map +1 -1
  57. package/dist/server/Mppx.d.ts +11 -3
  58. package/dist/server/Mppx.d.ts.map +1 -1
  59. package/dist/server/Mppx.js +76 -27
  60. package/dist/server/Mppx.js.map +1 -1
  61. package/dist/server/Response.d.ts.map +1 -1
  62. package/dist/server/Response.js +2 -1
  63. package/dist/server/Response.js.map +1 -1
  64. package/dist/server/Transport.d.ts.map +1 -1
  65. package/dist/server/Transport.js +4 -3
  66. package/dist/server/Transport.js.map +1 -1
  67. package/dist/server/index.d.ts +1 -0
  68. package/dist/server/index.d.ts.map +1 -1
  69. package/dist/server/index.js +1 -0
  70. package/dist/server/index.js.map +1 -1
  71. package/dist/stripe/client/Charge.d.ts +1 -1
  72. package/dist/stripe/client/Charge.d.ts.map +1 -1
  73. package/dist/stripe/client/Charge.js +3 -1
  74. package/dist/stripe/client/Charge.js.map +1 -1
  75. package/dist/stripe/server/Charge.d.ts +1 -1
  76. package/dist/stripe/server/Charge.d.ts.map +1 -1
  77. package/dist/stripe/server/Charge.js +9 -2
  78. package/dist/stripe/server/Charge.js.map +1 -1
  79. package/dist/stripe/server/Methods.d.ts +1 -1
  80. package/dist/stripe/server/Methods.d.ts.map +1 -1
  81. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  82. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
  83. package/dist/stripe/server/internal/html.gen.js +1 -1
  84. package/dist/stripe/server/internal/html.gen.js.map +1 -1
  85. package/dist/tempo/Methods.d.ts +18 -0
  86. package/dist/tempo/Methods.d.ts.map +1 -1
  87. package/dist/tempo/Methods.js +16 -1
  88. package/dist/tempo/Methods.js.map +1 -1
  89. package/dist/tempo/client/Charge.d.ts +6 -0
  90. package/dist/tempo/client/Charge.d.ts.map +1 -1
  91. package/dist/tempo/client/Charge.js +9 -2
  92. package/dist/tempo/client/Charge.js.map +1 -1
  93. package/dist/tempo/client/Methods.d.ts +36 -7
  94. package/dist/tempo/client/Methods.d.ts.map +1 -1
  95. package/dist/tempo/client/Methods.js +12 -5
  96. package/dist/tempo/client/Methods.js.map +1 -1
  97. package/dist/tempo/client/index.d.ts +7 -4
  98. package/dist/tempo/client/index.d.ts.map +1 -1
  99. package/dist/tempo/client/index.js +5 -3
  100. package/dist/tempo/client/index.js.map +1 -1
  101. package/dist/tempo/index.d.ts +1 -0
  102. package/dist/tempo/index.d.ts.map +1 -1
  103. package/dist/tempo/index.js +1 -0
  104. package/dist/tempo/index.js.map +1 -1
  105. package/dist/tempo/internal/fee-payer.d.ts +21 -1
  106. package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
  107. package/dist/tempo/internal/fee-payer.js +109 -4
  108. package/dist/tempo/internal/fee-payer.js.map +1 -1
  109. package/dist/tempo/{client → legacy/client}/ChannelOps.d.ts +19 -6
  110. package/dist/tempo/legacy/client/ChannelOps.d.ts.map +1 -0
  111. package/dist/tempo/{client → legacy/client}/ChannelOps.js +9 -3
  112. package/dist/tempo/legacy/client/ChannelOps.js.map +1 -0
  113. package/dist/tempo/{client → legacy/client}/Session.d.ts +23 -4
  114. package/dist/tempo/legacy/client/Session.d.ts.map +1 -0
  115. package/dist/tempo/{client → legacy/client}/Session.js +14 -7
  116. package/dist/tempo/legacy/client/Session.js.map +1 -0
  117. package/dist/tempo/{client → legacy/client}/SessionManager.d.ts +20 -5
  118. package/dist/tempo/legacy/client/SessionManager.d.ts.map +1 -0
  119. package/dist/tempo/{client → legacy/client}/SessionManager.js +20 -16
  120. package/dist/tempo/legacy/client/SessionManager.js.map +1 -0
  121. package/dist/tempo/legacy/client/index.d.ts +7 -0
  122. package/dist/tempo/legacy/client/index.d.ts.map +1 -0
  123. package/dist/tempo/legacy/client/index.js +5 -0
  124. package/dist/tempo/legacy/client/index.js.map +1 -0
  125. package/dist/tempo/legacy/index.d.ts +7 -0
  126. package/dist/tempo/legacy/index.d.ts.map +1 -0
  127. package/dist/tempo/legacy/index.js +7 -0
  128. package/dist/tempo/legacy/index.js.map +1 -0
  129. package/dist/tempo/{server → legacy/server}/Session.d.ts +28 -11
  130. package/dist/tempo/legacy/server/Session.d.ts.map +1 -0
  131. package/dist/tempo/{server → legacy/server}/Session.js +12 -10
  132. package/dist/tempo/legacy/server/Session.js.map +1 -0
  133. package/dist/tempo/legacy/server/index.d.ts +5 -0
  134. package/dist/tempo/legacy/server/index.d.ts.map +1 -0
  135. package/dist/tempo/legacy/server/index.js +5 -0
  136. package/dist/tempo/legacy/server/index.js.map +1 -0
  137. package/dist/tempo/{session → legacy/session}/Chain.d.ts +30 -23
  138. package/dist/tempo/legacy/session/Chain.d.ts.map +1 -0
  139. package/dist/tempo/{session → legacy/session}/Chain.js +12 -11
  140. package/dist/tempo/legacy/session/Chain.js.map +1 -0
  141. package/dist/tempo/{session → legacy/session}/Channel.d.ts +1 -0
  142. package/dist/tempo/legacy/session/Channel.d.ts.map +1 -0
  143. package/dist/tempo/legacy/session/Channel.js.map +1 -0
  144. package/dist/tempo/legacy/session/ChannelStore.d.ts +22 -0
  145. package/dist/tempo/legacy/session/ChannelStore.d.ts.map +1 -0
  146. package/dist/tempo/legacy/session/ChannelStore.js +6 -0
  147. package/dist/tempo/legacy/session/ChannelStore.js.map +1 -0
  148. package/dist/tempo/legacy/session/Types.d.ts +73 -0
  149. package/dist/tempo/legacy/session/Types.d.ts.map +1 -0
  150. package/dist/tempo/legacy/session/Types.js.map +1 -0
  151. package/dist/tempo/{session → legacy/session}/Voucher.d.ts +4 -4
  152. package/dist/tempo/legacy/session/Voucher.d.ts.map +1 -0
  153. package/dist/tempo/{session → legacy/session}/Voucher.js +1 -1
  154. package/dist/tempo/legacy/session/Voucher.js.map +1 -0
  155. package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts +1 -0
  156. package/dist/tempo/{session → legacy/session}/escrow.abi.d.ts.map +1 -1
  157. package/dist/tempo/{session → legacy/session}/escrow.abi.js +1 -0
  158. package/dist/tempo/legacy/session/escrow.abi.js.map +1 -0
  159. package/dist/tempo/legacy/session/index.d.ts +9 -0
  160. package/dist/tempo/legacy/session/index.d.ts.map +1 -0
  161. package/dist/tempo/legacy/session/index.js +9 -0
  162. package/dist/tempo/legacy/session/index.js.map +1 -0
  163. package/dist/tempo/server/Charge.d.ts +1 -1
  164. package/dist/tempo/server/Charge.d.ts.map +1 -1
  165. package/dist/tempo/server/Charge.js +13 -16
  166. package/dist/tempo/server/Charge.js.map +1 -1
  167. package/dist/tempo/server/Methods.d.ts +63 -6
  168. package/dist/tempo/server/Methods.d.ts.map +1 -1
  169. package/dist/tempo/server/Methods.js +36 -8
  170. package/dist/tempo/server/Methods.js.map +1 -1
  171. package/dist/tempo/server/Subscription.d.ts +1 -1
  172. package/dist/tempo/server/Subscription.d.ts.map +1 -1
  173. package/dist/tempo/server/index.d.ts +6 -5
  174. package/dist/tempo/server/index.d.ts.map +1 -1
  175. package/dist/tempo/server/index.js +5 -5
  176. package/dist/tempo/server/index.js.map +1 -1
  177. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  178. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  179. package/dist/tempo/server/internal/html.gen.js +1 -1
  180. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  181. package/dist/tempo/server/internal/request-body.d.ts +7 -2
  182. package/dist/tempo/server/internal/request-body.d.ts.map +1 -1
  183. package/dist/tempo/server/internal/request-body.js +20 -3
  184. package/dist/tempo/server/internal/request-body.js.map +1 -1
  185. package/dist/tempo/server/internal/transport.d.ts +8 -4
  186. package/dist/tempo/server/internal/transport.d.ts.map +1 -1
  187. package/dist/tempo/server/internal/transport.js +8 -7
  188. package/dist/tempo/server/internal/transport.js.map +1 -1
  189. package/dist/tempo/session/Snapshot.d.ts +32 -0
  190. package/dist/tempo/session/Snapshot.d.ts.map +1 -0
  191. package/dist/tempo/session/Snapshot.js +37 -0
  192. package/dist/tempo/session/Snapshot.js.map +1 -0
  193. package/dist/tempo/session/client/ChannelOps.d.ts +82 -0
  194. package/dist/tempo/session/client/ChannelOps.d.ts.map +1 -0
  195. package/dist/tempo/session/client/ChannelOps.js +204 -0
  196. package/dist/tempo/session/client/ChannelOps.js.map +1 -0
  197. package/dist/tempo/session/client/CredentialState.d.ts +262 -0
  198. package/dist/tempo/session/client/CredentialState.d.ts.map +1 -0
  199. package/dist/tempo/session/client/CredentialState.js +417 -0
  200. package/dist/tempo/session/client/CredentialState.js.map +1 -0
  201. package/dist/tempo/session/client/ReceiptCoordinator.d.ts +26 -0
  202. package/dist/tempo/session/client/ReceiptCoordinator.d.ts.map +1 -0
  203. package/dist/tempo/session/client/ReceiptCoordinator.js +61 -0
  204. package/dist/tempo/session/client/ReceiptCoordinator.js.map +1 -0
  205. package/dist/tempo/session/client/Runtime.d.ts +464 -0
  206. package/dist/tempo/session/client/Runtime.d.ts.map +1 -0
  207. package/dist/tempo/session/client/Runtime.js +499 -0
  208. package/dist/tempo/session/client/Runtime.js.map +1 -0
  209. package/dist/tempo/session/client/Session.d.ts +132 -0
  210. package/dist/tempo/session/client/Session.d.ts.map +1 -0
  211. package/dist/tempo/session/client/Session.js +55 -0
  212. package/dist/tempo/session/client/Session.js.map +1 -0
  213. package/dist/tempo/session/client/SessionManager.d.ts +120 -0
  214. package/dist/tempo/session/client/SessionManager.d.ts.map +1 -0
  215. package/dist/tempo/session/client/SessionManager.js +627 -0
  216. package/dist/tempo/session/client/SessionManager.js.map +1 -0
  217. package/dist/tempo/session/client/Transports.d.ts +449 -0
  218. package/dist/tempo/session/client/Transports.d.ts.map +1 -0
  219. package/dist/tempo/session/client/Transports.js +721 -0
  220. package/dist/tempo/session/client/Transports.js.map +1 -0
  221. package/dist/tempo/session/client/index.d.ts +12 -0
  222. package/dist/tempo/session/client/index.d.ts.map +1 -0
  223. package/dist/tempo/session/client/index.js +5 -0
  224. package/dist/tempo/session/client/index.js.map +1 -0
  225. package/dist/tempo/session/index.d.ts +7 -8
  226. package/dist/tempo/session/index.d.ts.map +1 -1
  227. package/dist/tempo/session/index.js +7 -8
  228. package/dist/tempo/session/index.js.map +1 -1
  229. package/dist/tempo/session/precompile/Chain.d.ts +319 -0
  230. package/dist/tempo/session/precompile/Chain.d.ts.map +1 -0
  231. package/dist/tempo/session/precompile/Chain.js +492 -0
  232. package/dist/tempo/session/precompile/Chain.js.map +1 -0
  233. package/dist/tempo/session/precompile/Channel.d.ts +46 -0
  234. package/dist/tempo/session/precompile/Channel.d.ts.map +1 -0
  235. package/dist/tempo/session/precompile/Channel.js +56 -0
  236. package/dist/tempo/session/precompile/Channel.js.map +1 -0
  237. package/dist/tempo/session/precompile/Protocol.d.ts +308 -0
  238. package/dist/tempo/session/precompile/Protocol.d.ts.map +1 -0
  239. package/dist/tempo/session/precompile/Protocol.js +264 -0
  240. package/dist/tempo/session/precompile/Protocol.js.map +1 -0
  241. package/dist/tempo/session/precompile/Voucher.d.ts +40 -0
  242. package/dist/tempo/session/precompile/Voucher.d.ts.map +1 -0
  243. package/dist/tempo/session/precompile/Voucher.js +126 -0
  244. package/dist/tempo/session/precompile/Voucher.js.map +1 -0
  245. package/dist/tempo/session/precompile/escrow.abi.d.ts +522 -0
  246. package/dist/tempo/session/precompile/escrow.abi.d.ts.map +1 -0
  247. package/dist/tempo/session/precompile/escrow.abi.js +224 -0
  248. package/dist/tempo/session/precompile/escrow.abi.js.map +1 -0
  249. package/dist/tempo/session/precompile/index.d.ts +24 -0
  250. package/dist/tempo/session/precompile/index.d.ts.map +1 -0
  251. package/dist/tempo/session/precompile/index.js +22 -0
  252. package/dist/tempo/session/precompile/index.js.map +1 -0
  253. package/dist/tempo/session/server/ChannelOps.d.ts +56 -0
  254. package/dist/tempo/session/server/ChannelOps.d.ts.map +1 -0
  255. package/dist/tempo/session/server/ChannelOps.js +91 -0
  256. package/dist/tempo/session/server/ChannelOps.js.map +1 -0
  257. package/dist/tempo/session/server/ChannelStore.d.ts +347 -0
  258. package/dist/tempo/session/server/ChannelStore.d.ts.map +1 -0
  259. package/dist/tempo/session/server/ChannelStore.js +404 -0
  260. package/dist/tempo/session/server/ChannelStore.js.map +1 -0
  261. package/dist/tempo/session/server/CredentialVerification.d.ts +85 -0
  262. package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -0
  263. package/dist/tempo/session/server/CredentialVerification.js +494 -0
  264. package/dist/tempo/session/server/CredentialVerification.js.map +1 -0
  265. package/dist/tempo/session/server/MeteredStream.d.ts +40 -0
  266. package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -0
  267. package/dist/tempo/session/server/MeteredStream.js +42 -0
  268. package/dist/tempo/session/server/MeteredStream.js.map +1 -0
  269. package/dist/tempo/session/server/RequestState.d.ts +208 -0
  270. package/dist/tempo/session/server/RequestState.d.ts.map +1 -0
  271. package/dist/tempo/session/server/RequestState.js +252 -0
  272. package/dist/tempo/session/server/RequestState.js.map +1 -0
  273. package/dist/tempo/session/server/Session.d.ts +169 -0
  274. package/dist/tempo/session/server/Session.d.ts.map +1 -0
  275. package/dist/tempo/session/server/Session.js +351 -0
  276. package/dist/tempo/session/server/Session.js.map +1 -0
  277. package/dist/tempo/session/server/Settlement.d.ts +185 -0
  278. package/dist/tempo/session/server/Settlement.d.ts.map +1 -0
  279. package/dist/tempo/session/server/Settlement.js +250 -0
  280. package/dist/tempo/session/server/Settlement.js.map +1 -0
  281. package/dist/tempo/session/{Sse.d.ts → server/Sse.d.ts} +9 -56
  282. package/dist/tempo/session/server/Sse.d.ts.map +1 -0
  283. package/dist/tempo/session/server/Sse.js +184 -0
  284. package/dist/tempo/session/server/Sse.js.map +1 -0
  285. package/dist/tempo/session/server/Transports.d.ts +89 -0
  286. package/dist/tempo/session/server/Transports.d.ts.map +1 -0
  287. package/dist/tempo/session/server/Transports.js +149 -0
  288. package/dist/tempo/session/server/Transports.js.map +1 -0
  289. package/dist/tempo/session/server/Ws.d.ts +48 -0
  290. package/dist/tempo/session/server/Ws.d.ts.map +1 -0
  291. package/dist/tempo/session/server/Ws.js +244 -0
  292. package/dist/tempo/session/server/Ws.js.map +1 -0
  293. package/dist/tempo/session/server/index.d.ts +4 -0
  294. package/dist/tempo/session/server/index.d.ts.map +1 -0
  295. package/dist/tempo/session/server/index.js +2 -0
  296. package/dist/tempo/session/server/index.js.map +1 -0
  297. package/package.json +6 -1
  298. package/src/Challenge.ts +9 -7
  299. package/src/Constants.ts +58 -0
  300. package/src/Credential.ts +5 -4
  301. package/src/Method.ts +46 -5
  302. package/src/Receipt.ts +3 -2
  303. package/src/cli/cli.test.ts +23 -28
  304. package/src/cli/cli.ts +23 -10
  305. package/src/cli/mcp.test.ts +21 -7
  306. package/src/cli/plugins/tempo.ts +21 -8
  307. package/src/cli/utils.test.ts +25 -1
  308. package/src/cli/utils.ts +10 -0
  309. package/src/client/Methods.ts +5 -2
  310. package/src/client/Mppx.test-d.ts +10 -0
  311. package/src/client/Mppx.test.ts +75 -0
  312. package/src/client/Transport.ts +4 -5
  313. package/src/client/index.ts +11 -1
  314. package/src/client/internal/Fetch.test.ts +29 -4
  315. package/src/client/internal/Fetch.ts +17 -5
  316. package/src/env.d.ts +1 -1
  317. package/src/index.ts +1 -0
  318. package/src/internal/AcceptPayment.test.ts +61 -0
  319. package/src/internal/AcceptPayment.ts +21 -14
  320. package/src/mcp-sdk/client/McpClient.integration.test.ts +8 -7
  321. package/src/mcp-sdk/client/McpClient.test-d.ts +7 -0
  322. package/src/mcp-sdk/client/McpClient.ts +99 -67
  323. package/src/mcp-sdk/client/McpClient.unit.test.ts +131 -0
  324. package/src/middlewares/elysia.test.ts +8 -4
  325. package/src/middlewares/express.test.ts +8 -4
  326. package/src/middlewares/hono.test.ts +4 -4
  327. package/src/middlewares/nextjs.test.ts +8 -4
  328. package/src/proxy/Proxy.test.ts +8 -8
  329. package/src/server/Mppx.test-d.ts +54 -0
  330. package/src/server/Mppx.test.ts +200 -7
  331. package/src/server/Mppx.ts +487 -406
  332. package/src/server/Response.ts +2 -1
  333. package/src/server/Transport.ts +4 -3
  334. package/src/server/index.ts +1 -0
  335. package/src/stripe/client/Charge.test.ts +20 -5
  336. package/src/stripe/client/Charge.ts +6 -2
  337. package/src/stripe/server/Charge.test.ts +114 -1
  338. package/src/stripe/server/Charge.ts +13 -2
  339. package/src/stripe/server/internal/html.gen.ts +1 -1
  340. package/src/tempo/AccessKeyAuthorization.test.ts +4 -94
  341. package/src/tempo/Methods.test.ts +45 -17
  342. package/src/tempo/Methods.ts +22 -0
  343. package/src/tempo/PublicExports.test-d.ts +105 -0
  344. package/src/tempo/client/Charge.test.ts +85 -0
  345. package/src/tempo/client/Charge.ts +19 -2
  346. package/src/tempo/client/Methods.ts +18 -6
  347. package/src/tempo/client/index.ts +15 -4
  348. package/src/tempo/index.ts +1 -0
  349. package/src/tempo/internal/fee-payer.test.ts +241 -17
  350. package/src/tempo/internal/fee-payer.ts +150 -4
  351. package/src/tempo/internal/fee-token.test.ts +14 -9
  352. package/src/tempo/legacy/AccessKeyAuthorization.test.ts +162 -0
  353. package/src/tempo/legacy/README.md +9 -0
  354. package/src/tempo/{client → legacy/client}/ChannelOps.test.ts +6 -7
  355. package/src/tempo/{client → legacy/client}/ChannelOps.ts +22 -9
  356. package/src/tempo/{client → legacy/client}/Session.test.ts +51 -9
  357. package/src/tempo/{client → legacy/client}/Session.ts +25 -11
  358. package/src/tempo/{client → legacy/client}/SessionManager.test.ts +81 -9
  359. package/src/tempo/{client → legacy/client}/SessionManager.ts +41 -20
  360. package/src/tempo/legacy/client/index.ts +6 -0
  361. package/src/tempo/legacy/index.ts +6 -0
  362. package/src/tempo/{server → legacy/server}/Session.test.ts +45 -45
  363. package/src/tempo/{server → legacy/server}/Session.ts +32 -23
  364. package/src/tempo/legacy/server/index.ts +4 -0
  365. package/src/tempo/{session → legacy/session}/Chain.test.ts +3 -4
  366. package/src/tempo/{session → legacy/session}/Chain.ts +94 -63
  367. package/src/tempo/{session → legacy/session}/Channel.ts +1 -0
  368. package/src/tempo/legacy/session/ChannelStore.test.ts +58 -0
  369. package/src/tempo/legacy/session/ChannelStore.ts +39 -0
  370. package/src/tempo/legacy/session/Types.ts +91 -0
  371. package/src/tempo/{session → legacy/session}/Voucher.ts +12 -8
  372. package/src/tempo/{session → legacy/session}/escrow.abi.ts +1 -0
  373. package/src/tempo/legacy/session/index.ts +8 -0
  374. package/src/tempo/server/AtomicStore.test-d.ts +16 -11
  375. package/src/tempo/server/Charge.test.ts +92 -14
  376. package/src/tempo/server/Charge.ts +18 -16
  377. package/src/tempo/server/Methods.ts +54 -8
  378. package/src/tempo/server/Sse.test.ts +2 -2
  379. package/src/tempo/server/index.ts +6 -5
  380. package/src/tempo/server/internal/html.gen.ts +1 -1
  381. package/src/tempo/server/internal/request-body.test.ts +37 -4
  382. package/src/tempo/server/internal/request-body.ts +25 -6
  383. package/src/tempo/server/internal/transport.test.ts +4 -4
  384. package/src/tempo/server/internal/transport.ts +19 -10
  385. package/src/tempo/session/Snapshot.test.ts +41 -0
  386. package/src/tempo/session/Snapshot.ts +74 -0
  387. package/src/tempo/session/client/ChannelOps.test.ts +163 -0
  388. package/src/tempo/session/client/ChannelOps.ts +344 -0
  389. package/src/tempo/session/client/CredentialState.test.ts +645 -0
  390. package/src/tempo/session/client/CredentialState.ts +814 -0
  391. package/src/tempo/session/client/ReceiptCoordinator.ts +95 -0
  392. package/src/tempo/session/client/Runtime.test.ts +1092 -0
  393. package/src/tempo/session/client/Runtime.ts +986 -0
  394. package/src/tempo/session/client/Session.test.ts +734 -0
  395. package/src/tempo/session/client/Session.ts +97 -0
  396. package/src/tempo/session/client/SessionManager.test.ts +1308 -0
  397. package/src/tempo/session/client/SessionManager.ts +845 -0
  398. package/src/tempo/session/client/Transports.test.ts +837 -0
  399. package/src/tempo/session/client/Transports.ts +1292 -0
  400. package/src/tempo/session/client/index.ts +37 -0
  401. package/src/tempo/session/index.ts +7 -8
  402. package/src/tempo/session/precompile/Chain.integration.test.ts +321 -0
  403. package/src/tempo/session/precompile/Chain.test.ts +1258 -0
  404. package/src/tempo/session/precompile/Chain.ts +979 -0
  405. package/src/tempo/session/precompile/Channel.test.ts +138 -0
  406. package/src/tempo/session/precompile/Channel.ts +103 -0
  407. package/src/tempo/session/precompile/Protocol.test.ts +358 -0
  408. package/src/tempo/session/precompile/Protocol.ts +520 -0
  409. package/src/tempo/session/precompile/Voucher.test.ts +316 -0
  410. package/src/tempo/session/precompile/Voucher.ts +160 -0
  411. package/src/tempo/session/precompile/escrow.abi.ts +226 -0
  412. package/src/tempo/session/precompile/index.ts +33 -0
  413. package/src/tempo/session/server/ChannelOps.test.ts +129 -0
  414. package/src/tempo/session/server/ChannelOps.ts +157 -0
  415. package/src/tempo/session/{ChannelStore.test.ts → server/ChannelStore.test.ts} +536 -29
  416. package/src/tempo/session/server/ChannelStore.ts +835 -0
  417. package/src/tempo/session/server/CredentialVerification.test.ts +146 -0
  418. package/src/tempo/session/server/CredentialVerification.ts +710 -0
  419. package/src/tempo/session/server/MeteredStream.ts +88 -0
  420. package/src/tempo/session/server/RequestState.test.ts +531 -0
  421. package/src/tempo/session/server/RequestState.ts +499 -0
  422. package/src/tempo/session/server/Session.integration.test.ts +444 -0
  423. package/src/tempo/session/server/Session.test.ts +3253 -0
  424. package/src/tempo/session/server/Session.ts +543 -0
  425. package/src/tempo/session/server/Settlement.test.ts +242 -0
  426. package/src/tempo/session/server/Settlement.ts +470 -0
  427. package/src/tempo/session/{Sse.test.ts → server/Sse.test.ts} +37 -3
  428. package/src/tempo/session/server/Sse.ts +256 -0
  429. package/src/tempo/session/server/Transports.test.ts +346 -0
  430. package/src/tempo/session/server/Transports.ts +255 -0
  431. package/src/tempo/session/{Ws.test.ts → server/Ws.test.ts} +4 -4
  432. package/src/tempo/session/server/Ws.ts +384 -0
  433. package/src/tempo/session/server/index.ts +8 -0
  434. package/dist/tempo/client/ChannelOps.d.ts.map +0 -1
  435. package/dist/tempo/client/ChannelOps.js.map +0 -1
  436. package/dist/tempo/client/Session.d.ts.map +0 -1
  437. package/dist/tempo/client/Session.js.map +0 -1
  438. package/dist/tempo/client/SessionManager.d.ts.map +0 -1
  439. package/dist/tempo/client/SessionManager.js.map +0 -1
  440. package/dist/tempo/server/Session.d.ts.map +0 -1
  441. package/dist/tempo/server/Session.js.map +0 -1
  442. package/dist/tempo/session/Chain.d.ts.map +0 -1
  443. package/dist/tempo/session/Chain.js.map +0 -1
  444. package/dist/tempo/session/Channel.d.ts.map +0 -1
  445. package/dist/tempo/session/Channel.js.map +0 -1
  446. package/dist/tempo/session/ChannelStore.d.ts +0 -117
  447. package/dist/tempo/session/ChannelStore.d.ts.map +0 -1
  448. package/dist/tempo/session/ChannelStore.js +0 -172
  449. package/dist/tempo/session/ChannelStore.js.map +0 -1
  450. package/dist/tempo/session/Receipt.d.ts +0 -22
  451. package/dist/tempo/session/Receipt.d.ts.map +0 -1
  452. package/dist/tempo/session/Receipt.js +0 -34
  453. package/dist/tempo/session/Receipt.js.map +0 -1
  454. package/dist/tempo/session/Sse.d.ts.map +0 -1
  455. package/dist/tempo/session/Sse.js +0 -363
  456. package/dist/tempo/session/Sse.js.map +0 -1
  457. package/dist/tempo/session/Types.d.ts +0 -78
  458. package/dist/tempo/session/Types.d.ts.map +0 -1
  459. package/dist/tempo/session/Types.js.map +0 -1
  460. package/dist/tempo/session/Voucher.d.ts.map +0 -1
  461. package/dist/tempo/session/Voucher.js.map +0 -1
  462. package/dist/tempo/session/Ws.d.ts +0 -87
  463. package/dist/tempo/session/Ws.d.ts.map +0 -1
  464. package/dist/tempo/session/Ws.js +0 -443
  465. package/dist/tempo/session/Ws.js.map +0 -1
  466. package/dist/tempo/session/escrow.abi.js.map +0 -1
  467. package/src/tempo/session/ChannelStore.ts +0 -308
  468. package/src/tempo/session/Receipt.test.ts +0 -89
  469. package/src/tempo/session/Receipt.ts +0 -46
  470. package/src/tempo/session/Sse.ts +0 -462
  471. package/src/tempo/session/Types.ts +0 -86
  472. package/src/tempo/session/Ws.ts +0 -576
  473. /package/dist/tempo/{session → legacy/session}/Channel.js +0 -0
  474. /package/dist/tempo/{session → legacy/session}/Types.js +0 -0
  475. /package/src/tempo/{session → legacy/session}/Channel.test.ts +0 -0
  476. /package/src/tempo/{session → legacy/session}/Voucher.test.ts +0 -0
  477. /package/src/tempo/session/{Sse.fuzz.test.ts → server/Sse.fuzz.test.ts} +0 -0
@@ -0,0 +1,986 @@
1
+ import { parseUnits, type Hex } from 'viem'
2
+
3
+ import type {
4
+ ChannelDescriptor,
5
+ NeedVoucherEvent,
6
+ RawAmountString,
7
+ SessionCredentialPayload,
8
+ SessionReceipt,
9
+ } from '../precompile/Protocol.js'
10
+ import * as Ws from '../precompile/Protocol.js'
11
+ import type { SessionSnapshot } from '../Snapshot.js'
12
+ import type { ChannelEntry } from './ChannelOps.js'
13
+ import type { SessionContext } from './CredentialState.js'
14
+ import type { TempoSessionChallenge } from './Transports.js'
15
+ import type { ActiveSocketSession } from './Transports.js'
16
+
17
+ export { deserializeSnapshot, serializeSnapshot } from '../Snapshot.js'
18
+ export type { SessionSnapshot } from '../Snapshot.js'
19
+
20
+ /** Initial manager state before a session challenge is observed. */
21
+ export type IdleSessionState = { status: 'idle' }
22
+
23
+ /** State after a tempo/session challenge has been selected but before a credential is created. */
24
+ export type ChallengedSessionState = { status: 'challenged'; challengeId: string }
25
+
26
+ /** State while a server snapshot is being used to hydrate a reusable channel. */
27
+ export type HydratingSessionState = {
28
+ status: 'hydrating'
29
+ challengeId: string
30
+ snapshot: SessionSnapshot
31
+ }
32
+
33
+ /** State while the client is creating or submitting an opening channel credential. */
34
+ export type OpeningSessionState = { status: 'opening'; challengeId: string }
35
+
36
+ /** Active state variant used after a channel is opened, hydrated, or receives a receipt. */
37
+ export type ActiveSessionState = {
38
+ status: 'active'
39
+ challengeId: string
40
+ channelId: Hex
41
+ descriptor: ChannelDescriptor
42
+ /** Highest cumulative voucher amount accepted by the server. */
43
+ acceptedCumulative: RawAmountString
44
+ /** Current channel deposit ceiling, tracked independently from accepted cumulative spend. */
45
+ deposit: RawAmountString
46
+ /** Amount actually consumed by delivered work/content. */
47
+ spent: RawAmountString
48
+ /** Paid units delivered by the server. */
49
+ units: number
50
+ }
51
+
52
+ /** State when the server needs a larger cumulative voucher but no top-up is needed. */
53
+ export type VoucherNeededSessionState = {
54
+ status: 'voucherNeeded'
55
+ challengeId: string
56
+ channelId: Hex
57
+ descriptor: ChannelDescriptor
58
+ requiredCumulative: RawAmountString
59
+ deposit: RawAmountString
60
+ }
61
+
62
+ /** State when the server-required cumulative amount exceeds current channel deposit. */
63
+ export type ToppingUpSessionState = {
64
+ status: 'toppingUp'
65
+ challengeId: string
66
+ channelId: Hex
67
+ descriptor: ChannelDescriptor
68
+ deposit: RawAmountString
69
+ }
70
+
71
+ /** State while the server is settling accepted voucher spend on-chain. */
72
+ export type SettlingSessionState = {
73
+ status: 'settling'
74
+ channelId: Hex
75
+ descriptor: ChannelDescriptor
76
+ deposit: RawAmountString
77
+ }
78
+
79
+ /** State after unilateral close has been requested and withdrawal is not yet available. */
80
+ export type CloseRequestedSessionState = {
81
+ status: 'closeRequested'
82
+ channelId: Hex
83
+ descriptor: ChannelDescriptor
84
+ }
85
+
86
+ /** State after the unilateral close delay has elapsed and funds can be withdrawn. */
87
+ export type WithdrawableSessionState = {
88
+ status: 'withdrawable'
89
+ channelId: Hex
90
+ descriptor: ChannelDescriptor
91
+ }
92
+
93
+ /** State while a cooperative close credential or close transaction is in flight. */
94
+ export type ClosingSessionState = {
95
+ status: 'closing'
96
+ channelId: Hex
97
+ descriptor: ChannelDescriptor
98
+ }
99
+
100
+ /** Terminal state after channel close finalization. */
101
+ export type ClosedSessionState = {
102
+ status: 'closed'
103
+ channelId: Hex
104
+ descriptor: ChannelDescriptor
105
+ }
106
+
107
+ /** Pure state-machine state for a TIP-1034 session. */
108
+ export type SessionState =
109
+ | IdleSessionState
110
+ | ChallengedSessionState
111
+ | HydratingSessionState
112
+ | OpeningSessionState
113
+ | ActiveSessionState
114
+ | VoucherNeededSessionState
115
+ | ToppingUpSessionState
116
+ | SettlingSessionState
117
+ | CloseRequestedSessionState
118
+ | WithdrawableSessionState
119
+ | ClosingSessionState
120
+ | ClosedSessionState
121
+
122
+ /** Data required to construct active session state. */
123
+ export type CreateActiveStateParameters = Omit<ActiveSessionState, 'status'>
124
+
125
+ /** State variants that can follow a need-voucher event. */
126
+ export type NeedVoucherSessionState = VoucherNeededSessionState | ToppingUpSessionState
127
+
128
+ /** Events accepted by the pure session reducer. */
129
+ export type SessionEvent =
130
+ | { type: 'challengeReceived'; challengeId: string }
131
+ | { type: 'challenge'; challengeId: string; snapshot?: SessionSnapshot | undefined }
132
+ | {
133
+ type: 'activated'
134
+ challengeId: string
135
+ entry: ChannelEntry
136
+ spent: RawAmountString
137
+ units?: number | undefined
138
+ }
139
+ | {
140
+ type: 'opened'
141
+ receipt: SessionReceipt
142
+ descriptor: ChannelDescriptor
143
+ deposit: RawAmountString
144
+ }
145
+ | { type: 'hydrated'; snapshot: SessionSnapshot }
146
+ | { type: 'receiptAccepted'; receipt: SessionReceipt; entry: ChannelEntry }
147
+ | { type: 'needVoucher'; event: NeedVoucherEvent; descriptor: ChannelDescriptor }
148
+ | { type: 'topUpStarted' }
149
+ | { type: 'voucherAccepted'; receipt: SessionReceipt; deposit?: string | undefined }
150
+ | { type: 'settleStarted' }
151
+ | { type: 'settled'; receipt: SessionReceipt; deposit?: string | undefined }
152
+ | { type: 'closeRequested' }
153
+ | { type: 'withdrawable' }
154
+ | { type: 'closeStarted' }
155
+ | { type: 'closed'; receipt?: SessionReceipt | undefined }
156
+
157
+ /** IO work requested by the pure reducer. */
158
+ export type SessionEffect =
159
+ | { type: 'hydrate'; snapshot: SessionSnapshot }
160
+ | { type: 'open' }
161
+ | { type: 'topUp'; channelId: Hex; amount: string }
162
+ | { type: 'voucher'; payload?: SessionCredentialPayload | undefined }
163
+ | { type: 'settle'; channelId: Hex }
164
+ | { type: 'requestClose'; channelId: Hex }
165
+ | { type: 'withdraw'; channelId: Hex }
166
+ | { type: 'close'; channelId: Hex }
167
+
168
+ /** Effects emitted by need-voucher transition planning. */
169
+ export type NeedVoucherSessionEffect =
170
+ | Extract<SessionEffect, { type: 'topUp' }>
171
+ | Extract<SessionEffect, { type: 'voucher' }>
172
+
173
+ /** Inputs for deciding whether a need-voucher event needs a voucher or deposit top-up first. */
174
+ export type ResolveNeedVoucherTransitionParameters = {
175
+ /** Current challenge ID retained by the active session state. */
176
+ challengeId: string
177
+ /** Descriptor for the channel requiring more authorization. */
178
+ descriptor: ChannelDescriptor
179
+ /** Server event describing required cumulative authorization and current deposit. */
180
+ event: NeedVoucherEvent
181
+ }
182
+
183
+ /** Result of the need-voucher transition decision. */
184
+ export type NeedVoucherTransition = {
185
+ /** Next machine state. */
186
+ state: NeedVoucherSessionState
187
+ /** Driver effects required to satisfy the server request. */
188
+ effects: NeedVoucherSessionEffect[]
189
+ }
190
+
191
+ /** Return value for every pure state-machine transition. */
192
+ export type SessionTransition = {
193
+ /** State after applying the event. */
194
+ state: SessionState
195
+ /** Declarative IO requested from the transport/precompile driver. */
196
+ effects: SessionEffect[]
197
+ }
198
+
199
+ /** Initial state for a TIP-1034 session state machine. */
200
+ export const initialState = { status: 'idle' } satisfies SessionState
201
+
202
+ /** Constructs the canonical active state shape for the reducer and transport drivers. */
203
+ export function createActiveState(parameters: CreateActiveStateParameters): ActiveSessionState {
204
+ return { status: 'active', ...parameters }
205
+ }
206
+
207
+ /** Applies a state-machine event and returns the next state plus requested effects. */
208
+ export function reduce(state: SessionState, event: SessionEvent): SessionTransition {
209
+ switch (event.type) {
210
+ case 'challengeReceived':
211
+ if (state.status === 'closing' || state.status === 'closed') return invalid(state, event)
212
+ return {
213
+ state: { status: 'challenged', challengeId: event.challengeId },
214
+ effects: [],
215
+ }
216
+ case 'challenge': {
217
+ if (state.status !== 'idle' && state.status !== 'active') return invalid(state, event)
218
+ if (event.snapshot) {
219
+ return {
220
+ state: { status: 'hydrating', challengeId: event.challengeId, snapshot: event.snapshot },
221
+ effects: [{ type: 'hydrate', snapshot: event.snapshot }],
222
+ }
223
+ }
224
+ return {
225
+ state: { status: 'opening', challengeId: event.challengeId },
226
+ effects: [{ type: 'open' }],
227
+ }
228
+ }
229
+ case 'hydrated':
230
+ if (state.status !== 'hydrating') return invalid(state, event)
231
+ return {
232
+ state: activeFromSnapshot(state.challengeId, event.snapshot),
233
+ effects: [],
234
+ }
235
+ case 'activated':
236
+ if (state.status === 'closing' || state.status === 'closed') return invalid(state, event)
237
+ return {
238
+ state: activeStateFromChannel({
239
+ challengeId: event.challengeId,
240
+ entry: event.entry,
241
+ spent: event.spent,
242
+ units: event.units ?? 0,
243
+ }),
244
+ effects: [],
245
+ }
246
+ case 'opened':
247
+ if (state.status !== 'opening') return invalid(state, event)
248
+ return {
249
+ state: activeFromReceipt(state.challengeId, event.receipt, event.descriptor, event.deposit),
250
+ effects: [],
251
+ }
252
+ case 'receiptAccepted':
253
+ if (state.status === 'closing' || state.status === 'closed') return invalid(state, event)
254
+ return {
255
+ state: activeStateFromReceipt(event.receipt, event.entry),
256
+ effects: [],
257
+ }
258
+ case 'needVoucher': {
259
+ if (state.status !== 'active') return invalid(state, event)
260
+ return resolveNeedVoucherTransition({
261
+ challengeId: state.challengeId,
262
+ descriptor: event.descriptor,
263
+ event: event.event,
264
+ })
265
+ }
266
+ case 'topUpStarted':
267
+ if (state.status !== 'voucherNeeded') return invalid(state, event)
268
+ return {
269
+ state: {
270
+ status: 'toppingUp',
271
+ challengeId: state.challengeId,
272
+ channelId: state.channelId,
273
+ descriptor: state.descriptor,
274
+ deposit: state.deposit,
275
+ },
276
+ effects: [],
277
+ }
278
+ case 'voucherAccepted':
279
+ if (state.status !== 'voucherNeeded' && state.status !== 'toppingUp')
280
+ return invalid(state, event)
281
+ return {
282
+ state: activeFromReceipt(
283
+ state.challengeId,
284
+ event.receipt,
285
+ state.descriptor,
286
+ event.deposit ?? state.deposit,
287
+ ),
288
+ effects: [],
289
+ }
290
+ case 'settleStarted':
291
+ if (state.status !== 'active') return invalid(state, event)
292
+ return {
293
+ state: {
294
+ status: 'settling',
295
+ channelId: state.channelId,
296
+ descriptor: state.descriptor,
297
+ deposit: state.deposit,
298
+ },
299
+ effects: [{ type: 'settle', channelId: state.channelId }],
300
+ }
301
+ case 'settled':
302
+ if (state.status !== 'settling') return invalid(state, event)
303
+ return {
304
+ state: activeFromReceipt(
305
+ event.receipt.challengeId,
306
+ event.receipt,
307
+ state.descriptor,
308
+ event.deposit ?? state.deposit,
309
+ ),
310
+ effects: [],
311
+ }
312
+ case 'closeRequested':
313
+ if (state.status !== 'active') return invalid(state, event)
314
+ return {
315
+ state: {
316
+ status: 'closeRequested',
317
+ channelId: state.channelId,
318
+ descriptor: state.descriptor,
319
+ },
320
+ effects: [{ type: 'requestClose', channelId: state.channelId }],
321
+ }
322
+ case 'withdrawable':
323
+ if (state.status !== 'closeRequested') return invalid(state, event)
324
+ return {
325
+ state: { status: 'withdrawable', channelId: state.channelId, descriptor: state.descriptor },
326
+ effects: [{ type: 'withdraw', channelId: state.channelId }],
327
+ }
328
+ case 'closeStarted':
329
+ if (
330
+ state.status !== 'active' &&
331
+ state.status !== 'withdrawable' &&
332
+ state.status !== 'closeRequested'
333
+ )
334
+ return invalid(state, event)
335
+ return {
336
+ state: { status: 'closing', channelId: state.channelId, descriptor: state.descriptor },
337
+ effects: [{ type: 'close', channelId: state.channelId }],
338
+ }
339
+ case 'closed':
340
+ if (state.status !== 'closing' && state.status !== 'withdrawable')
341
+ return invalid(state, event)
342
+ return {
343
+ state: { status: 'closed', channelId: state.channelId, descriptor: state.descriptor },
344
+ effects: [],
345
+ }
346
+ }
347
+ }
348
+
349
+ /** Applies a reducer event to mutable manager runtime state. */
350
+ export function dispatchSessionEvent(
351
+ runtime: Pick<SessionManagerRuntime, 'state'>,
352
+ event: SessionEvent,
353
+ ): SessionTransition {
354
+ const transition = reduce(runtime.state, event)
355
+ runtime.state = transition.state
356
+ return transition
357
+ }
358
+
359
+ /** Decides whether a need-voucher event can be answered by voucher or requires top-up first. */
360
+ export function resolveNeedVoucherTransition(
361
+ parameters: ResolveNeedVoucherTransitionParameters,
362
+ ): NeedVoucherTransition {
363
+ const { challengeId, descriptor, event } = parameters
364
+ const required = BigInt(event.requiredCumulative)
365
+ const deposit = BigInt(event.deposit)
366
+
367
+ if (required > deposit) {
368
+ return {
369
+ state: {
370
+ status: 'toppingUp',
371
+ challengeId,
372
+ channelId: event.channelId,
373
+ descriptor,
374
+ deposit: event.deposit,
375
+ },
376
+ effects: [
377
+ { type: 'topUp', channelId: event.channelId, amount: (required - deposit).toString() },
378
+ ],
379
+ }
380
+ }
381
+
382
+ return {
383
+ state: {
384
+ status: 'voucherNeeded',
385
+ challengeId,
386
+ channelId: event.channelId,
387
+ descriptor,
388
+ requiredCumulative: event.requiredCumulative,
389
+ deposit: event.deposit,
390
+ },
391
+ effects: [{ type: 'voucher' }],
392
+ }
393
+ }
394
+
395
+ function activeFromSnapshot(challengeId: string, snapshot: SessionSnapshot): SessionState {
396
+ return createActiveState({
397
+ challengeId,
398
+ channelId: snapshot.channelId,
399
+ descriptor: snapshot.descriptor,
400
+ acceptedCumulative: snapshot.acceptedCumulative,
401
+ deposit: snapshot.deposit,
402
+ spent: snapshot.spent,
403
+ units: snapshot.units ?? 0,
404
+ })
405
+ }
406
+
407
+ function activeFromReceipt(
408
+ challengeId: string,
409
+ receipt: SessionReceipt,
410
+ descriptor: ChannelDescriptor,
411
+ deposit: RawAmountString,
412
+ ): SessionState {
413
+ return createActiveState({
414
+ challengeId,
415
+ channelId: receipt.channelId,
416
+ descriptor,
417
+ acceptedCumulative: receipt.acceptedCumulative,
418
+ deposit,
419
+ spent: receipt.spent,
420
+ units: receipt.units ?? 0,
421
+ })
422
+ }
423
+
424
+ function invalid(state: SessionState, event: SessionEvent): never {
425
+ throw new Error(`Invalid session transition: ${state.status} + ${event.type}`)
426
+ }
427
+
428
+ /** Inputs for validating a cumulative authorization against the local client cap. */
429
+ export type LocalVoucherLimitParameters = {
430
+ /** Cumulative amount being authorized or accepted. */
431
+ cumulativeAmount: bigint
432
+ /** Optional maximum local authorization boundary. Null means uncapped. */
433
+ maxVoucherCumulative: bigint | null
434
+ }
435
+
436
+ /** Inputs for validating a payment receipt against local client state. */
437
+ export type LocalReceiptValidationParameters = {
438
+ /** Active local channel cache entry. */
439
+ channel: ChannelEntry | null
440
+ /** Optional local authorization cap. Null means uncapped. */
441
+ maxVoucherCumulative: bigint | null
442
+ /** Receipt returned by the server. */
443
+ receipt: SessionReceipt
444
+ }
445
+
446
+ /** Inputs for deriving the next locally observed spend from a receipt. */
447
+ export type NextReceiptSpendParameters = {
448
+ /** Active local channel cache entry. */
449
+ channel: ChannelEntry | null
450
+ /** Optional local authorization cap. Null means uncapped. */
451
+ maxVoucherCumulative: bigint | null
452
+ /** Receipt returned by the server, when present. */
453
+ receipt: SessionReceipt | null | undefined
454
+ /** Current locally observed spend. */
455
+ spent: bigint
456
+ }
457
+
458
+ /** Inputs for resolving the initial channel deposit in automatic client mode. */
459
+ export type ResolveOpeningDepositParameters = {
460
+ /** Caller-provided raw deposit override. */
461
+ contextDepositRaw?: string | undefined
462
+ /** Optional local maximum cumulative deposit/authorization boundary. */
463
+ maxDeposit?: bigint | undefined
464
+ /** Current request amount in raw token units. */
465
+ requestAmount: bigint
466
+ /** Server-suggested opening deposit in raw token units. */
467
+ suggestedDepositRaw?: string | undefined
468
+ }
469
+
470
+ /** Throws when a cumulative voucher amount exceeds the caller's local cap. */
471
+ export function assertVoucherWithinLocalLimit(parameters: LocalVoucherLimitParameters): void {
472
+ const { cumulativeAmount, maxVoucherCumulative } = parameters
473
+ if (maxVoucherCumulative === null) return
474
+ if (cumulativeAmount <= maxVoucherCumulative) return
475
+ throw new Error(
476
+ `requested voucher amount ${cumulativeAmount} exceeds local maxDeposit ${maxVoucherCumulative}`,
477
+ )
478
+ }
479
+
480
+ /** Validates a server receipt without allowing it to increase the local signing boundary. */
481
+ export function assertReceiptWithinLocalState(parameters: LocalReceiptValidationParameters): void {
482
+ const { channel, maxVoucherCumulative, receipt } = parameters
483
+ if (!channel || receipt.channelId !== channel.channelId) return
484
+ const acceptedCumulative = BigInt(receipt.acceptedCumulative)
485
+ const receiptSpent = BigInt(receipt.spent)
486
+ if (receiptSpent > acceptedCumulative) {
487
+ throw new Error('receipt spent exceeds accepted cumulative voucher amount')
488
+ }
489
+ if (acceptedCumulative > channel.cumulativeAmount) {
490
+ throw new Error('receipt accepted cumulative exceeds local voucher state')
491
+ }
492
+ if (receiptSpent > channel.cumulativeAmount) {
493
+ throw new Error('receipt spent exceeds local voucher state')
494
+ }
495
+ assertVoucherWithinLocalLimit({ cumulativeAmount: acceptedCumulative, maxVoucherCumulative })
496
+ assertVoucherWithinLocalLimit({ cumulativeAmount: receiptSpent, maxVoucherCumulative })
497
+ }
498
+
499
+ /** Returns the monotonic next local spend after validating an optional receipt. */
500
+ export function nextSpentFromReceipt(parameters: NextReceiptSpendParameters): bigint {
501
+ const { channel, maxVoucherCumulative, receipt, spent } = parameters
502
+ if (!receipt || receipt.channelId !== channel?.channelId) return spent
503
+ assertReceiptWithinLocalState({ channel, maxVoucherCumulative, receipt })
504
+ const next = BigInt(receipt.spent)
505
+ return spent > next ? spent : next
506
+ }
507
+
508
+ /** Parses a manager amount. Bigints are raw units; strings are parsed using token decimals. */
509
+ export function parseManagerAmount(amount: string | bigint, decimals: number): bigint {
510
+ if (typeof amount === 'bigint') return amount
511
+ return parseUnits(amount, decimals)
512
+ }
513
+
514
+ /** Resolves the opening deposit from explicit context, server hint, request amount, and local cap. */
515
+ export function resolveOpeningDeposit(parameters: ResolveOpeningDepositParameters): bigint {
516
+ const { contextDepositRaw, maxDeposit, requestAmount, suggestedDepositRaw } = parameters
517
+ assertWithinMaxDeposit(requestAmount, maxDeposit)
518
+ if (contextDepositRaw !== undefined) {
519
+ const deposit = BigInt(contextDepositRaw)
520
+ if (deposit < requestAmount) {
521
+ throw new Error(`opening deposit ${deposit} below request amount ${requestAmount}`)
522
+ }
523
+ return deposit
524
+ }
525
+
526
+ const suggestedDeposit =
527
+ suggestedDepositRaw !== undefined ? BigInt(suggestedDepositRaw) : undefined
528
+ const proposed =
529
+ suggestedDeposit !== undefined && suggestedDeposit > requestAmount
530
+ ? suggestedDeposit
531
+ : requestAmount
532
+ if (maxDeposit !== undefined) return proposed < maxDeposit ? proposed : maxDeposit
533
+ return proposed
534
+ }
535
+
536
+ /** Enforces the optional client-side maximum cumulative voucher authorization. */
537
+ export function assertWithinMaxDeposit(
538
+ cumulativeAmount: bigint,
539
+ maxDeposit: bigint | undefined,
540
+ ): void {
541
+ assertVoucherWithinLocalLimit({
542
+ cumulativeAmount,
543
+ maxVoucherCumulative: maxDeposit ?? null,
544
+ })
545
+ }
546
+
547
+ /** Predicate used when waiting for a specific session receipt. */
548
+ export type SessionReceiptPredicate = (receipt: SessionReceipt) => boolean
549
+
550
+ /** Resolved data required to close a locally active session channel. */
551
+ export type CloseTarget = {
552
+ /** Challenge used to bind the close credential. */
553
+ challenge: TempoSessionChallenge
554
+ /** Local channel cache entry being closed. */
555
+ channel: ChannelEntry
556
+ /** Channel ID being closed. */
557
+ channelId: Hex
558
+ }
559
+
560
+ /** Inputs for choosing the active close target. */
561
+ export type ResolveCloseTargetParameters = {
562
+ /** Current active channel cache entry. */
563
+ channel: ChannelEntry | null
564
+ /** Active WebSocket session, when close is happening in-band. */
565
+ currentSocket: ActiveSocketSession | null
566
+ /** Last HTTP/SSE challenge observed by the manager. */
567
+ lastChallenge: TempoSessionChallenge | null
568
+ }
569
+
570
+ /** Inputs for validating socket close-ready spend before signing the final close voucher. */
571
+ export type CloseReadySpendParameters = {
572
+ /** Local cumulative voucher authorization. */
573
+ cumulativeAmount: bigint
574
+ /** Spend reported by the close-ready receipt. */
575
+ readySpent: bigint
576
+ /** Latest receipt-tracked local spend. */
577
+ spent: bigint
578
+ }
579
+
580
+ /** Inputs for matching the expected final close receipt. */
581
+ export type ExpectedCloseReceiptParameters = {
582
+ /** Challenge ID used for the close credential. */
583
+ challengeId: string
584
+ /** Channel ID being closed. */
585
+ channelId: Hex
586
+ /** Expected final cumulative/spent amount. */
587
+ expectedCloseAmount: string
588
+ /** Receipt to test. */
589
+ receipt: SessionReceipt
590
+ }
591
+
592
+ /** Resolves the currently closeable channel and challenge, or undefined when no channel is open. */
593
+ export function resolveCloseTarget(
594
+ parameters: ResolveCloseTargetParameters,
595
+ ): CloseTarget | undefined {
596
+ const { channel, currentSocket, lastChallenge } = parameters
597
+ if (!channel?.opened) return undefined
598
+
599
+ const challenge = currentSocket?.challenge ?? lastChallenge
600
+ const channelId = currentSocket?.channelId ?? channel.channelId
601
+
602
+ if (!challenge) {
603
+ throw new Error(
604
+ 'Cannot close session: no challenge available. This usually means close() was called on a SessionManager instance that was recreated after the session was opened. Use the same SessionManager instance that opened the session, or make a request first to receive a fresh 402 challenge.',
605
+ )
606
+ }
607
+ if (!channelId) {
608
+ throw new Error(
609
+ 'Cannot close session: no channel ID available. The session may not have been fully opened.',
610
+ )
611
+ }
612
+
613
+ return { challenge, channel, channelId }
614
+ }
615
+
616
+ /** Highest spend the client may sign for during close based on local receipts and vouchers. */
617
+ export function localCloseSpendLimit(parameters: Omit<CloseReadySpendParameters, 'readySpent'>) {
618
+ const { cumulativeAmount, spent } = parameters
619
+ return cumulativeAmount > spent ? cumulativeAmount : spent
620
+ }
621
+
622
+ /** Throws when a close-ready receipt asks the client to sign beyond local state. */
623
+ export function assertCloseReadyWithinLocalState(parameters: CloseReadySpendParameters): void {
624
+ const { cumulativeAmount, readySpent, spent } = parameters
625
+ if (readySpent > localCloseSpendLimit({ cumulativeAmount, spent })) {
626
+ throw new Error('close-ready spent exceeds local voucher state')
627
+ }
628
+ }
629
+
630
+ /** Returns whether a receipt is the expected final close settlement receipt. */
631
+ export function isExpectedCloseReceipt(parameters: ExpectedCloseReceiptParameters): boolean {
632
+ const { challengeId, channelId, expectedCloseAmount, receipt } = parameters
633
+ return (
634
+ Boolean(receipt.txHash) &&
635
+ receipt.challengeId === challengeId &&
636
+ receipt.channelId === channelId &&
637
+ receipt.acceptedCumulative === expectedCloseAmount &&
638
+ receipt.spent === expectedCloseAmount
639
+ )
640
+ }
641
+
642
+ /** Parameters used to project cached client channel data into an active machine state. */
643
+ export type ActiveStateFromChannelParameters = {
644
+ /** Challenge ID associated with the active payment flow. */
645
+ challengeId: string
646
+ /** Cached channel entry that owns descriptor, deposit, and cumulative authorization. */
647
+ entry: ChannelEntry
648
+ /** Latest locally observed spend in raw units. */
649
+ spent: string
650
+ /** Paid units observed by the active flow. */
651
+ units: number
652
+ }
653
+
654
+ /** Parameters used to project a closed channel into machine state. */
655
+ export type ClosedStateFromChannelParameters = {
656
+ /** Channel ID that has been closed. */
657
+ channelId: Hex
658
+ /** Cached channel entry that owns the descriptor. */
659
+ entry: ChannelEntry
660
+ }
661
+
662
+ /** Inputs for computing the safest fallback close amount when no fresh close-ready receipt is available. */
663
+ export type FallbackCloseAmountParameters = {
664
+ /** Challenge ID being closed. */
665
+ challengeId: string
666
+ /** Channel ID being closed. */
667
+ channelId: Hex
668
+ /** Last socket close-ready receipt, when one was received. */
669
+ closeReadyReceipt?: SessionReceipt | null | undefined
670
+ /** Current local cumulative voucher authorization. */
671
+ cumulativeAmount: bigint
672
+ /** Number of application chunks delivered over the socket. */
673
+ deliveredChunks?: bigint | undefined
674
+ /** Current socket challenge ID, used to decide whether socket delivery data applies. */
675
+ socketChallengeId?: string | undefined
676
+ /** Current socket channel ID, used to decide whether socket delivery data applies. */
677
+ socketChannelId?: Hex | undefined
678
+ /** Latest locally observed spend from receipts. */
679
+ spent: bigint
680
+ /** Per-message socket charge in raw units. */
681
+ tickCost?: bigint | undefined
682
+ }
683
+
684
+ /** Minimal mutable session runtime state that must be restored when an auto-drive attempt fails. */
685
+ export type RuntimeState = {
686
+ /** Current client channel cache entry, when one is active. */
687
+ channel: ChannelEntry | null
688
+ /** Latest locally observed spend from receipts. */
689
+ spent: bigint
690
+ /** Current public state-machine state. */
691
+ state: SessionState
692
+ }
693
+
694
+ /** Mutable client runtime state owned by one auto-driving `sessionManager()` instance. */
695
+ export type SessionManagerRuntime = RuntimeState & {
696
+ /** Last Tempo session challenge observed by HTTP/SSE/WebSocket bootstrap. */
697
+ lastChallenge: TempoSessionChallenge | null
698
+ /** Last HTTP resource URL usable for management POSTs. */
699
+ lastUrl: RequestInfo | URL | null
700
+ /** Active WebSocket payment session bookkeeping, when a socket is open. */
701
+ socketSession: ActiveSocketSession | null
702
+ }
703
+
704
+ /** Immutable snapshot of mutable runtime fields needed for rollback. */
705
+ export type RuntimeSnapshot = {
706
+ /** Channel fields mutated during optimistic open/top-up/voucher attempts. */
707
+ channel: {
708
+ cumulativeAmount: bigint
709
+ deposit: bigint
710
+ entry: ChannelEntry
711
+ opened: boolean
712
+ } | null
713
+ /** Latest locally observed spend when the snapshot was taken. */
714
+ spent: bigint
715
+ /** State-machine state when the snapshot was taken. */
716
+ state: SessionState
717
+ }
718
+
719
+ /** Inputs for applying a server receipt to manager-local runtime state. */
720
+ export type ApplySessionReceiptToRuntimeParameters = {
721
+ /** Optional local cumulative authorization cap. Null means uncapped. */
722
+ maxVoucherCumulative: bigint | null
723
+ /** Receipt returned by a server transport, when present. */
724
+ receipt: SessionReceipt | null | undefined
725
+ /** Mutable manager runtime state to update. */
726
+ runtime: SessionManagerRuntime
727
+ }
728
+
729
+ /** Inputs for restoring local cumulative authorization after a failed optimistic voucher retry. */
730
+ export type RestoreCumulativeAuthorizationParameters = {
731
+ /** Active local channel entry, when one is available. */
732
+ channel: ChannelEntry | null
733
+ /** Channel ID whose optimistic cumulative amount should be restored. */
734
+ channelId: Hex
735
+ /** Previous cumulative voucher authorization in raw units. */
736
+ cumulativeAmount: bigint
737
+ /** Last challenge ID observed by the manager, when known. */
738
+ challengeId?: string | undefined
739
+ /** Latest locally observed spend in raw units. */
740
+ spent: bigint
741
+ /** Current public state-machine state, used to preserve active unit count. */
742
+ state: SessionState
743
+ }
744
+
745
+ /** Projects cached channel data into an active state-machine state. */
746
+ export function activeStateFromChannel(parameters: ActiveStateFromChannelParameters): SessionState {
747
+ return createActiveState({
748
+ challengeId: parameters.challengeId,
749
+ channelId: parameters.entry.channelId,
750
+ descriptor: parameters.entry.descriptor,
751
+ acceptedCumulative: parameters.entry.cumulativeAmount.toString(),
752
+ deposit: parameters.entry.deposit.toString(),
753
+ spent: parameters.spent,
754
+ units: parameters.units,
755
+ })
756
+ }
757
+
758
+ /** Creates the initial mutable runtime state for an auto-driving session manager. */
759
+ export function createSessionManagerRuntime(): SessionManagerRuntime {
760
+ return {
761
+ channel: null,
762
+ lastChallenge: null,
763
+ lastUrl: null,
764
+ spent: 0n,
765
+ socketSession: null,
766
+ state: initialState,
767
+ }
768
+ }
769
+
770
+ /** Validates a receipt, advances observed spend, and projects matching receipts into public state. */
771
+ export function applySessionReceiptToRuntime(
772
+ parameters: ApplySessionReceiptToRuntimeParameters,
773
+ ): void {
774
+ const { maxVoucherCumulative, receipt, runtime } = parameters
775
+ runtime.spent = nextSpentFromReceipt({
776
+ channel: runtime.channel,
777
+ maxVoucherCumulative,
778
+ receipt,
779
+ spent: runtime.spent,
780
+ })
781
+ if (receipt && runtime.channel?.channelId === receipt.channelId) {
782
+ dispatchSessionEvent(runtime, {
783
+ type: 'receiptAccepted',
784
+ receipt,
785
+ entry: runtime.channel,
786
+ })
787
+ }
788
+ }
789
+
790
+ /** Projects a verified receipt plus local descriptor/deposit data into an active state-machine state. */
791
+ export function activeStateFromReceipt(receipt: SessionReceipt, entry: ChannelEntry): SessionState {
792
+ return createActiveState({
793
+ challengeId: receipt.challengeId,
794
+ channelId: receipt.channelId,
795
+ descriptor: entry.descriptor,
796
+ acceptedCumulative: receipt.acceptedCumulative,
797
+ deposit: entry.deposit.toString(),
798
+ spent: receipt.spent,
799
+ units: receipt.units ?? 0,
800
+ })
801
+ }
802
+
803
+ /** Projects a closed channel into the public closed state-machine state. */
804
+ export function closedStateFromChannel(parameters: ClosedStateFromChannelParameters): SessionState {
805
+ return {
806
+ status: 'closed',
807
+ channelId: parameters.channelId,
808
+ descriptor: parameters.entry.descriptor,
809
+ }
810
+ }
811
+
812
+ /** Projects a final close receipt into the public closed state-machine state. */
813
+ export function closedStateFromReceipt(receipt: SessionReceipt, entry: ChannelEntry): SessionState {
814
+ return closedStateFromChannel({ channelId: receipt.channelId, entry })
815
+ }
816
+
817
+ /**
818
+ * Computes the fallback close amount without authorizing more than the local cumulative voucher.
819
+ *
820
+ * Priority:
821
+ * 1. Matching close-ready receipt spend.
822
+ * 2. Matching socket delivery estimate (`deliveredChunks * tickCost`) clamped by cumulative.
823
+ * 3. Latest receipt-tracked spend for HTTP/SSE.
824
+ */
825
+ export function computeFallbackCloseAmount(parameters: FallbackCloseAmountParameters): bigint {
826
+ const {
827
+ challengeId,
828
+ channelId,
829
+ closeReadyReceipt,
830
+ cumulativeAmount,
831
+ deliveredChunks = 0n,
832
+ socketChallengeId,
833
+ socketChannelId,
834
+ spent,
835
+ tickCost = 0n,
836
+ } = parameters
837
+
838
+ if (
839
+ closeReadyReceipt &&
840
+ closeReadyReceipt.challengeId === challengeId &&
841
+ closeReadyReceipt.channelId === channelId
842
+ ) {
843
+ return BigInt(closeReadyReceipt.spent)
844
+ }
845
+
846
+ if (socketChallengeId === challengeId && socketChannelId === channelId && tickCost > 0n) {
847
+ const deliveryEstimate = deliveredChunks * tickCost
848
+ const bestSpent = spent > deliveryEstimate ? spent : deliveryEstimate
849
+ return bestSpent > cumulativeAmount ? cumulativeAmount : bestSpent
850
+ }
851
+
852
+ return spent
853
+ }
854
+
855
+ /**
856
+ * Restores a channel's cumulative voucher boundary and returns the refreshed active state.
857
+ *
858
+ * Returns `undefined` when the active channel does not match or no challenge is
859
+ * available to label the active state.
860
+ */
861
+ export function restoreCumulativeAuthorization(
862
+ parameters: RestoreCumulativeAuthorizationParameters,
863
+ ): ActiveSessionState | undefined {
864
+ const { channel, channelId, challengeId, cumulativeAmount, spent, state } = parameters
865
+ if (!channel || channel.channelId !== channelId) return undefined
866
+ channel.cumulativeAmount = cumulativeAmount
867
+ if (!challengeId) return undefined
868
+ return reduce(state, {
869
+ type: 'activated',
870
+ challengeId,
871
+ entry: channel,
872
+ spent: spent.toString(),
873
+ units: state.status === 'active' ? state.units : 0,
874
+ }).state as ActiveSessionState
875
+ }
876
+
877
+ /** Captures mutable session runtime fields before an optimistic manager action. */
878
+ export function captureRuntimeSnapshot(runtime: RuntimeState): RuntimeSnapshot {
879
+ return {
880
+ channel:
881
+ runtime.channel === null
882
+ ? null
883
+ : {
884
+ entry: runtime.channel,
885
+ cumulativeAmount: runtime.channel.cumulativeAmount,
886
+ deposit: runtime.channel.deposit,
887
+ opened: runtime.channel.opened,
888
+ },
889
+ spent: runtime.spent,
890
+ state: runtime.state,
891
+ }
892
+ }
893
+
894
+ /** Restores mutable session runtime fields from a previous snapshot. */
895
+ export function restoreRuntimeSnapshot(
896
+ snapshot: RuntimeSnapshot,
897
+ currentChannel: ChannelEntry | null,
898
+ ): RuntimeState {
899
+ if (snapshot.channel) {
900
+ snapshot.channel.entry.cumulativeAmount = snapshot.channel.cumulativeAmount
901
+ snapshot.channel.entry.deposit = snapshot.channel.deposit
902
+ snapshot.channel.entry.opened = snapshot.channel.opened
903
+ return {
904
+ channel: snapshot.channel.entry,
905
+ spent: snapshot.spent,
906
+ state: snapshot.state,
907
+ }
908
+ }
909
+
910
+ if (currentChannel) currentChannel.opened = false
911
+ return {
912
+ channel: null,
913
+ spent: snapshot.spent,
914
+ state: snapshot.state,
915
+ }
916
+ }
917
+
918
+ /** Creates a session credential for the selected challenge/context. */
919
+ export type CreateSocketCloseCredential = (
920
+ challenge: TempoSessionChallenge,
921
+ context: SessionContext,
922
+ ) => Promise<string>
923
+
924
+ /** Inputs for cooperatively closing an active WebSocket session in-band. */
925
+ export type CloseSocketSessionParameters = {
926
+ /** Raw WebSocket used by the active paid stream. */
927
+ activeSocket: WebSocket
928
+ /** Creates the signed close credential. */
929
+ createSessionCredential: CreateSocketCloseCredential
930
+ /** Active WebSocket session state. */
931
+ currentSocket: ActiveSocketSession
932
+ /** Latest locally tracked spend from receipts. */
933
+ spent: bigint
934
+ /** Channel/challenge pair being closed. */
935
+ target: CloseTarget
936
+ /** Waits for the server's close-ready receipt after requesting stream close. */
937
+ waitForCloseReady(): Promise<SessionReceipt>
938
+ /** Waits for the final settlement receipt matching `predicate`. */
939
+ waitForReceipt(predicate: SessionReceiptPredicate): Promise<SessionReceipt>
940
+ }
941
+
942
+ /** Cooperatively closes an active paid WebSocket session and returns the final receipt. */
943
+ export async function closeSocketSession(
944
+ parameters: CloseSocketSessionParameters,
945
+ ): Promise<SessionReceipt> {
946
+ const { activeSocket, currentSocket, target } = parameters
947
+ const ready =
948
+ currentSocket.closeReadyReceipt ??
949
+ (await (async () => {
950
+ activeSocket.send(Ws.formatCloseRequestMessage())
951
+ return parameters.waitForCloseReady()
952
+ })())
953
+ const readySpent = BigInt(ready.spent)
954
+ assertCloseReadyWithinLocalState({
955
+ cumulativeAmount: target.channel.cumulativeAmount,
956
+ readySpent,
957
+ spent: parameters.spent,
958
+ })
959
+
960
+ const credential = await parameters.createSessionCredential(target.challenge, {
961
+ action: 'close',
962
+ channelId: target.channelId,
963
+ descriptor: target.channel.descriptor,
964
+ cumulativeAmountRaw: readySpent.toString(),
965
+ })
966
+
967
+ const expectedCloseAmount = readySpent.toString()
968
+ currentSocket.expectedCloseAmount = expectedCloseAmount
969
+ try {
970
+ const pendingReceipt = parameters.waitForReceipt((receipt) =>
971
+ isExpectedCloseReceipt({
972
+ challengeId: target.challenge.id,
973
+ channelId: target.channelId,
974
+ expectedCloseAmount,
975
+ receipt,
976
+ }),
977
+ )
978
+ activeSocket.send(Ws.formatAuthorizationMessage(credential))
979
+ const receipt = await pendingReceipt
980
+ activeSocket.close()
981
+ currentSocket.closeReadyReceipt = null
982
+ return receipt
983
+ } finally {
984
+ currentSocket.expectedCloseAmount = null
985
+ }
986
+ }