@did-btcr2/aggregation 0.1.0 → 0.3.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 (342) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/browser.js +18107 -18096
  3. package/dist/browser.mjs +18107 -18096
  4. package/dist/cjs/core/index.js +2423 -0
  5. package/dist/cjs/index.js +3513 -3521
  6. package/dist/cjs/participant/index.js +2425 -0
  7. package/dist/cjs/service/index.js +3199 -0
  8. package/dist/esm/{runner/aggregation-runner.js → aggregation-runner.js} +4 -4
  9. package/dist/esm/aggregation-runner.js.map +1 -0
  10. package/dist/esm/core/beacon-strategy.js.map +1 -0
  11. package/dist/esm/core/cohort.js.map +1 -0
  12. package/dist/esm/core/conditions.js.map +1 -0
  13. package/dist/esm/core/errors.js.map +1 -0
  14. package/dist/esm/core/fallback-spend.js.map +1 -0
  15. package/dist/esm/core/index.js +23 -0
  16. package/dist/esm/core/index.js.map +1 -0
  17. package/dist/esm/core/logger.js.map +1 -0
  18. package/dist/esm/core/messages/base.js.map +1 -0
  19. package/dist/esm/core/messages/bodies.js.map +1 -0
  20. package/dist/esm/core/messages/constants.js.map +1 -0
  21. package/dist/esm/core/messages/factories.js.map +1 -0
  22. package/dist/esm/core/messages/guards.js.map +1 -0
  23. package/dist/esm/core/messages/index.js.map +1 -0
  24. package/dist/esm/core/phases.js.map +1 -0
  25. package/dist/esm/core/recovery-policy.js.map +1 -0
  26. package/dist/esm/core/recovery-spend.js.map +1 -0
  27. package/dist/esm/core/signer.js.map +1 -0
  28. package/dist/esm/core/signing-session.js.map +1 -0
  29. package/dist/esm/core/transport/didcomm.js.map +1 -0
  30. package/dist/esm/core/transport/error.js.map +1 -0
  31. package/dist/esm/core/transport/http/envelope.js.map +1 -0
  32. package/dist/esm/core/transport/http/errors.js.map +1 -0
  33. package/dist/esm/core/transport/http/index.js +9 -0
  34. package/dist/esm/core/transport/http/index.js.map +1 -0
  35. package/dist/esm/core/transport/http/protocol.js.map +1 -0
  36. package/dist/esm/core/transport/http/request-auth.js.map +1 -0
  37. package/dist/esm/core/transport/in-memory.js.map +1 -0
  38. package/dist/esm/core/transport/index.js +12 -0
  39. package/dist/esm/core/transport/index.js.map +1 -0
  40. package/dist/esm/core/transport/nostr.js.map +1 -0
  41. package/dist/esm/core/transport/transport.js.map +1 -0
  42. package/dist/esm/core/typed-emitter.js.map +1 -0
  43. package/dist/esm/index.js +13 -20
  44. package/dist/esm/index.js.map +1 -1
  45. package/dist/esm/participant/events.js.map +1 -0
  46. package/dist/esm/{transport/http/client.js → participant/http-client.js} +6 -6
  47. package/dist/esm/participant/http-client.js.map +1 -0
  48. package/dist/esm/participant/index.js +13 -0
  49. package/dist/esm/participant/index.js.map +1 -0
  50. package/dist/esm/{runner → participant}/participant-runner.js +5 -5
  51. package/dist/esm/participant/participant-runner.js.map +1 -0
  52. package/dist/esm/{participant.js → participant/participant.js} +11 -11
  53. package/dist/esm/participant/participant.js.map +1 -0
  54. package/dist/esm/participant/sse-stream.js.map +1 -0
  55. package/dist/esm/service/events.js +2 -0
  56. package/dist/esm/{runner → service}/events.js.map +1 -1
  57. package/dist/esm/{transport/http/server.js → service/http-server.js} +6 -6
  58. package/dist/esm/service/http-server.js.map +1 -0
  59. package/dist/esm/service/inbox-buffer.js.map +1 -0
  60. package/dist/esm/service/index.js +16 -0
  61. package/dist/esm/service/index.js.map +1 -0
  62. package/dist/esm/service/nonce-cache.js.map +1 -0
  63. package/dist/esm/service/rate-limiter.js.map +1 -0
  64. package/dist/esm/{runner → service}/service-runner.js +5 -5
  65. package/dist/esm/service/service-runner.js.map +1 -0
  66. package/dist/esm/{service.js → service/service.js} +12 -12
  67. package/dist/esm/service/service.js.map +1 -0
  68. package/dist/esm/service/sse-writer.js.map +1 -0
  69. package/dist/esm/{transport/factory.js → transport-factory.js} +5 -5
  70. package/dist/esm/transport-factory.js.map +1 -0
  71. package/dist/types/{runner/aggregation-runner.d.ts → aggregation-runner.d.ts} +3 -3
  72. package/dist/types/aggregation-runner.d.ts.map +1 -0
  73. package/dist/types/{beacon-strategy.d.ts → core/beacon-strategy.d.ts} +2 -2
  74. package/dist/types/core/beacon-strategy.d.ts.map +1 -0
  75. package/dist/types/{cohort.d.ts → core/cohort.d.ts} +3 -3
  76. package/dist/types/core/cohort.d.ts.map +1 -0
  77. package/dist/types/core/conditions.d.ts.map +1 -0
  78. package/dist/types/core/errors.d.ts.map +1 -0
  79. package/dist/types/core/fallback-spend.d.ts.map +1 -0
  80. package/dist/types/core/index.d.ts +15 -0
  81. package/dist/types/core/index.d.ts.map +1 -0
  82. package/dist/types/core/logger.d.ts.map +1 -0
  83. package/dist/types/core/messages/base.d.ts.map +1 -0
  84. package/dist/types/core/messages/bodies.d.ts.map +1 -0
  85. package/dist/types/core/messages/constants.d.ts.map +1 -0
  86. package/dist/types/core/messages/factories.d.ts.map +1 -0
  87. package/dist/types/core/messages/guards.d.ts.map +1 -0
  88. package/dist/types/core/messages/index.d.ts.map +1 -0
  89. package/dist/types/core/phases.d.ts.map +1 -0
  90. package/dist/types/core/recovery-policy.d.ts.map +1 -0
  91. package/dist/types/core/recovery-spend.d.ts.map +1 -0
  92. package/dist/types/core/signer.d.ts.map +1 -0
  93. package/dist/types/core/signing-session.d.ts.map +1 -0
  94. package/dist/types/core/transport/didcomm.d.ts.map +1 -0
  95. package/dist/types/core/transport/error.d.ts.map +1 -0
  96. package/dist/types/core/transport/http/envelope.d.ts.map +1 -0
  97. package/dist/types/core/transport/http/errors.d.ts.map +1 -0
  98. package/dist/types/core/transport/http/index.d.ts +5 -0
  99. package/dist/types/core/transport/http/index.d.ts.map +1 -0
  100. package/dist/types/core/transport/http/protocol.d.ts.map +1 -0
  101. package/dist/types/core/transport/http/request-auth.d.ts.map +1 -0
  102. package/dist/types/core/transport/in-memory.d.ts.map +1 -0
  103. package/{src/transport/index.ts → dist/types/core/transport/index.d.ts} +1 -1
  104. package/dist/types/core/transport/index.d.ts.map +1 -0
  105. package/dist/types/core/transport/nostr.d.ts.map +1 -0
  106. package/dist/types/core/transport/transport.d.ts.map +1 -0
  107. package/dist/types/core/typed-emitter.d.ts.map +1 -0
  108. package/dist/types/index.d.ts +5 -16
  109. package/dist/types/index.d.ts.map +1 -1
  110. package/dist/types/{runner → participant}/events.d.ts +1 -76
  111. package/dist/types/participant/events.d.ts.map +1 -0
  112. package/dist/types/{transport/http/client.d.ts → participant/http-client.d.ts} +4 -4
  113. package/dist/types/participant/http-client.d.ts.map +1 -0
  114. package/dist/types/participant/index.d.ts +6 -0
  115. package/dist/types/participant/index.d.ts.map +1 -0
  116. package/dist/types/{runner → participant}/participant-runner.d.ts +6 -6
  117. package/dist/types/participant/participant-runner.d.ts.map +1 -0
  118. package/dist/types/{participant.d.ts → participant/participant.d.ts} +6 -6
  119. package/dist/types/participant/participant.d.ts.map +1 -0
  120. package/dist/types/participant/sse-stream.d.ts.map +1 -0
  121. package/dist/types/service/events.d.ts +76 -0
  122. package/dist/types/service/events.d.ts.map +1 -0
  123. package/dist/types/{transport/http/server.d.ts → service/http-server.d.ts} +4 -4
  124. package/dist/types/{transport/http/server.d.ts.map → service/http-server.d.ts.map} +1 -1
  125. package/dist/types/service/inbox-buffer.d.ts.map +1 -0
  126. package/dist/types/service/index.d.ts +9 -0
  127. package/dist/types/service/index.d.ts.map +1 -0
  128. package/dist/types/service/nonce-cache.d.ts.map +1 -0
  129. package/dist/types/service/rate-limiter.d.ts.map +1 -0
  130. package/dist/types/{runner → service}/service-runner.d.ts +4 -4
  131. package/dist/types/service/service-runner.d.ts.map +1 -0
  132. package/dist/types/{service.d.ts → service/service.d.ts} +6 -6
  133. package/dist/types/service/service.d.ts.map +1 -0
  134. package/dist/types/service/sse-writer.d.ts.map +1 -0
  135. package/dist/types/{transport/factory.d.ts → transport-factory.d.ts} +5 -5
  136. package/dist/types/transport-factory.d.ts.map +1 -0
  137. package/package.json +23 -6
  138. package/src/{runner/aggregation-runner.ts → aggregation-runner.ts} +7 -7
  139. package/src/{beacon-strategy.ts → core/beacon-strategy.ts} +2 -2
  140. package/src/{cohort.ts → core/cohort.ts} +3 -3
  141. package/src/core/index.ts +22 -0
  142. package/src/core/transport/http/index.ts +8 -0
  143. package/src/core/transport/index.ts +11 -0
  144. package/src/index.ts +13 -23
  145. package/src/{runner → participant}/events.ts +1 -59
  146. package/src/{transport/http/client.ts → participant/http-client.ts} +8 -8
  147. package/src/participant/index.ts +12 -0
  148. package/src/{runner → participant}/participant-runner.ts +10 -10
  149. package/src/{participant.ts → participant/participant.ts} +18 -18
  150. package/src/service/events.ts +58 -0
  151. package/src/{transport/http/server.ts → service/http-server.ts} +8 -8
  152. package/src/service/index.ts +15 -0
  153. package/src/{runner → service}/service-runner.ts +9 -9
  154. package/src/{service.ts → service/service.ts} +19 -19
  155. package/src/{transport/factory.ts → transport-factory.ts} +8 -8
  156. package/dist/esm/beacon-strategy.js.map +0 -1
  157. package/dist/esm/cohort.js.map +0 -1
  158. package/dist/esm/conditions.js.map +0 -1
  159. package/dist/esm/errors.js.map +0 -1
  160. package/dist/esm/fallback-spend.js.map +0 -1
  161. package/dist/esm/logger.js.map +0 -1
  162. package/dist/esm/messages/base.js.map +0 -1
  163. package/dist/esm/messages/bodies.js.map +0 -1
  164. package/dist/esm/messages/constants.js.map +0 -1
  165. package/dist/esm/messages/factories.js.map +0 -1
  166. package/dist/esm/messages/guards.js.map +0 -1
  167. package/dist/esm/messages/index.js.map +0 -1
  168. package/dist/esm/participant.js.map +0 -1
  169. package/dist/esm/phases.js.map +0 -1
  170. package/dist/esm/recovery-policy.js.map +0 -1
  171. package/dist/esm/recovery-spend.js.map +0 -1
  172. package/dist/esm/runner/aggregation-runner.js.map +0 -1
  173. package/dist/esm/runner/index.js +0 -6
  174. package/dist/esm/runner/index.js.map +0 -1
  175. package/dist/esm/runner/participant-runner.js.map +0 -1
  176. package/dist/esm/runner/service-runner.js.map +0 -1
  177. package/dist/esm/runner/typed-emitter.js.map +0 -1
  178. package/dist/esm/service.js.map +0 -1
  179. package/dist/esm/signer.js.map +0 -1
  180. package/dist/esm/signing-session.js.map +0 -1
  181. package/dist/esm/transport/didcomm.js.map +0 -1
  182. package/dist/esm/transport/error.js.map +0 -1
  183. package/dist/esm/transport/factory.js.map +0 -1
  184. package/dist/esm/transport/http/client.js.map +0 -1
  185. package/dist/esm/transport/http/envelope.js.map +0 -1
  186. package/dist/esm/transport/http/errors.js.map +0 -1
  187. package/dist/esm/transport/http/inbox-buffer.js.map +0 -1
  188. package/dist/esm/transport/http/index.js +0 -12
  189. package/dist/esm/transport/http/index.js.map +0 -1
  190. package/dist/esm/transport/http/nonce-cache.js.map +0 -1
  191. package/dist/esm/transport/http/protocol.js.map +0 -1
  192. package/dist/esm/transport/http/rate-limiter.js.map +0 -1
  193. package/dist/esm/transport/http/request-auth.js.map +0 -1
  194. package/dist/esm/transport/http/server.js.map +0 -1
  195. package/dist/esm/transport/http/sse-stream.js.map +0 -1
  196. package/dist/esm/transport/http/sse-writer.js.map +0 -1
  197. package/dist/esm/transport/in-memory.js.map +0 -1
  198. package/dist/esm/transport/index.js +0 -8
  199. package/dist/esm/transport/index.js.map +0 -1
  200. package/dist/esm/transport/nostr.js.map +0 -1
  201. package/dist/esm/transport/transport.js.map +0 -1
  202. package/dist/types/beacon-strategy.d.ts.map +0 -1
  203. package/dist/types/cohort.d.ts.map +0 -1
  204. package/dist/types/conditions.d.ts.map +0 -1
  205. package/dist/types/errors.d.ts.map +0 -1
  206. package/dist/types/fallback-spend.d.ts.map +0 -1
  207. package/dist/types/logger.d.ts.map +0 -1
  208. package/dist/types/messages/base.d.ts.map +0 -1
  209. package/dist/types/messages/bodies.d.ts.map +0 -1
  210. package/dist/types/messages/constants.d.ts.map +0 -1
  211. package/dist/types/messages/factories.d.ts.map +0 -1
  212. package/dist/types/messages/guards.d.ts.map +0 -1
  213. package/dist/types/messages/index.d.ts.map +0 -1
  214. package/dist/types/participant.d.ts.map +0 -1
  215. package/dist/types/phases.d.ts.map +0 -1
  216. package/dist/types/recovery-policy.d.ts.map +0 -1
  217. package/dist/types/recovery-spend.d.ts.map +0 -1
  218. package/dist/types/runner/aggregation-runner.d.ts.map +0 -1
  219. package/dist/types/runner/events.d.ts.map +0 -1
  220. package/dist/types/runner/index.d.ts +0 -6
  221. package/dist/types/runner/index.d.ts.map +0 -1
  222. package/dist/types/runner/participant-runner.d.ts.map +0 -1
  223. package/dist/types/runner/service-runner.d.ts.map +0 -1
  224. package/dist/types/runner/typed-emitter.d.ts.map +0 -1
  225. package/dist/types/service.d.ts.map +0 -1
  226. package/dist/types/signer.d.ts.map +0 -1
  227. package/dist/types/signing-session.d.ts.map +0 -1
  228. package/dist/types/transport/didcomm.d.ts.map +0 -1
  229. package/dist/types/transport/error.d.ts.map +0 -1
  230. package/dist/types/transport/factory.d.ts.map +0 -1
  231. package/dist/types/transport/http/client.d.ts.map +0 -1
  232. package/dist/types/transport/http/envelope.d.ts.map +0 -1
  233. package/dist/types/transport/http/errors.d.ts.map +0 -1
  234. package/dist/types/transport/http/inbox-buffer.d.ts.map +0 -1
  235. package/dist/types/transport/http/index.d.ts +0 -12
  236. package/dist/types/transport/http/index.d.ts.map +0 -1
  237. package/dist/types/transport/http/nonce-cache.d.ts.map +0 -1
  238. package/dist/types/transport/http/protocol.d.ts.map +0 -1
  239. package/dist/types/transport/http/rate-limiter.d.ts.map +0 -1
  240. package/dist/types/transport/http/request-auth.d.ts.map +0 -1
  241. package/dist/types/transport/http/sse-stream.d.ts.map +0 -1
  242. package/dist/types/transport/http/sse-writer.d.ts.map +0 -1
  243. package/dist/types/transport/in-memory.d.ts.map +0 -1
  244. package/dist/types/transport/index.d.ts +0 -8
  245. package/dist/types/transport/index.d.ts.map +0 -1
  246. package/dist/types/transport/nostr.d.ts.map +0 -1
  247. package/dist/types/transport/transport.d.ts.map +0 -1
  248. package/src/runner/index.ts +0 -5
  249. package/src/transport/http/index.ts +0 -11
  250. /package/dist/esm/{beacon-strategy.js → core/beacon-strategy.js} +0 -0
  251. /package/dist/esm/{cohort.js → core/cohort.js} +0 -0
  252. /package/dist/esm/{conditions.js → core/conditions.js} +0 -0
  253. /package/dist/esm/{errors.js → core/errors.js} +0 -0
  254. /package/dist/esm/{fallback-spend.js → core/fallback-spend.js} +0 -0
  255. /package/dist/esm/{logger.js → core/logger.js} +0 -0
  256. /package/dist/esm/{messages → core/messages}/base.js +0 -0
  257. /package/dist/esm/{messages → core/messages}/bodies.js +0 -0
  258. /package/dist/esm/{messages → core/messages}/constants.js +0 -0
  259. /package/dist/esm/{messages → core/messages}/factories.js +0 -0
  260. /package/dist/esm/{messages → core/messages}/guards.js +0 -0
  261. /package/dist/esm/{messages → core/messages}/index.js +0 -0
  262. /package/dist/esm/{phases.js → core/phases.js} +0 -0
  263. /package/dist/esm/{recovery-policy.js → core/recovery-policy.js} +0 -0
  264. /package/dist/esm/{recovery-spend.js → core/recovery-spend.js} +0 -0
  265. /package/dist/esm/{signer.js → core/signer.js} +0 -0
  266. /package/dist/esm/{signing-session.js → core/signing-session.js} +0 -0
  267. /package/dist/esm/{transport → core/transport}/didcomm.js +0 -0
  268. /package/dist/esm/{transport → core/transport}/error.js +0 -0
  269. /package/dist/esm/{transport → core/transport}/http/envelope.js +0 -0
  270. /package/dist/esm/{transport → core/transport}/http/errors.js +0 -0
  271. /package/dist/esm/{transport → core/transport}/http/protocol.js +0 -0
  272. /package/dist/esm/{transport → core/transport}/http/request-auth.js +0 -0
  273. /package/dist/esm/{transport → core/transport}/in-memory.js +0 -0
  274. /package/dist/esm/{transport → core/transport}/nostr.js +0 -0
  275. /package/dist/esm/{transport → core/transport}/transport.js +0 -0
  276. /package/dist/esm/{runner → core}/typed-emitter.js +0 -0
  277. /package/dist/esm/{runner → participant}/events.js +0 -0
  278. /package/dist/esm/{transport/http → participant}/sse-stream.js +0 -0
  279. /package/dist/esm/{transport/http → service}/inbox-buffer.js +0 -0
  280. /package/dist/esm/{transport/http → service}/nonce-cache.js +0 -0
  281. /package/dist/esm/{transport/http → service}/rate-limiter.js +0 -0
  282. /package/dist/esm/{transport/http → service}/sse-writer.js +0 -0
  283. /package/dist/types/{conditions.d.ts → core/conditions.d.ts} +0 -0
  284. /package/dist/types/{errors.d.ts → core/errors.d.ts} +0 -0
  285. /package/dist/types/{fallback-spend.d.ts → core/fallback-spend.d.ts} +0 -0
  286. /package/dist/types/{logger.d.ts → core/logger.d.ts} +0 -0
  287. /package/dist/types/{messages → core/messages}/base.d.ts +0 -0
  288. /package/dist/types/{messages → core/messages}/bodies.d.ts +0 -0
  289. /package/dist/types/{messages → core/messages}/constants.d.ts +0 -0
  290. /package/dist/types/{messages → core/messages}/factories.d.ts +0 -0
  291. /package/dist/types/{messages → core/messages}/guards.d.ts +0 -0
  292. /package/dist/types/{messages → core/messages}/index.d.ts +0 -0
  293. /package/dist/types/{phases.d.ts → core/phases.d.ts} +0 -0
  294. /package/dist/types/{recovery-policy.d.ts → core/recovery-policy.d.ts} +0 -0
  295. /package/dist/types/{recovery-spend.d.ts → core/recovery-spend.d.ts} +0 -0
  296. /package/dist/types/{signer.d.ts → core/signer.d.ts} +0 -0
  297. /package/dist/types/{signing-session.d.ts → core/signing-session.d.ts} +0 -0
  298. /package/dist/types/{transport → core/transport}/didcomm.d.ts +0 -0
  299. /package/dist/types/{transport → core/transport}/error.d.ts +0 -0
  300. /package/dist/types/{transport → core/transport}/http/envelope.d.ts +0 -0
  301. /package/dist/types/{transport → core/transport}/http/errors.d.ts +0 -0
  302. /package/dist/types/{transport → core/transport}/http/protocol.d.ts +0 -0
  303. /package/dist/types/{transport → core/transport}/http/request-auth.d.ts +0 -0
  304. /package/dist/types/{transport → core/transport}/in-memory.d.ts +0 -0
  305. /package/dist/types/{transport → core/transport}/nostr.d.ts +0 -0
  306. /package/dist/types/{transport → core/transport}/transport.d.ts +0 -0
  307. /package/dist/types/{runner → core}/typed-emitter.d.ts +0 -0
  308. /package/dist/types/{transport/http → participant}/sse-stream.d.ts +0 -0
  309. /package/dist/types/{transport/http → service}/inbox-buffer.d.ts +0 -0
  310. /package/dist/types/{transport/http → service}/nonce-cache.d.ts +0 -0
  311. /package/dist/types/{transport/http → service}/rate-limiter.d.ts +0 -0
  312. /package/dist/types/{transport/http → service}/sse-writer.d.ts +0 -0
  313. /package/src/{conditions.ts → core/conditions.ts} +0 -0
  314. /package/src/{errors.ts → core/errors.ts} +0 -0
  315. /package/src/{fallback-spend.ts → core/fallback-spend.ts} +0 -0
  316. /package/src/{logger.ts → core/logger.ts} +0 -0
  317. /package/src/{messages → core/messages}/base.ts +0 -0
  318. /package/src/{messages → core/messages}/bodies.ts +0 -0
  319. /package/src/{messages → core/messages}/constants.ts +0 -0
  320. /package/src/{messages → core/messages}/factories.ts +0 -0
  321. /package/src/{messages → core/messages}/guards.ts +0 -0
  322. /package/src/{messages → core/messages}/index.ts +0 -0
  323. /package/src/{phases.ts → core/phases.ts} +0 -0
  324. /package/src/{recovery-policy.ts → core/recovery-policy.ts} +0 -0
  325. /package/src/{recovery-spend.ts → core/recovery-spend.ts} +0 -0
  326. /package/src/{signer.ts → core/signer.ts} +0 -0
  327. /package/src/{signing-session.ts → core/signing-session.ts} +0 -0
  328. /package/src/{transport → core/transport}/didcomm.ts +0 -0
  329. /package/src/{transport → core/transport}/error.ts +0 -0
  330. /package/src/{transport → core/transport}/http/envelope.ts +0 -0
  331. /package/src/{transport → core/transport}/http/errors.ts +0 -0
  332. /package/src/{transport → core/transport}/http/protocol.ts +0 -0
  333. /package/src/{transport → core/transport}/http/request-auth.ts +0 -0
  334. /package/src/{transport → core/transport}/in-memory.ts +0 -0
  335. /package/src/{transport → core/transport}/nostr.ts +0 -0
  336. /package/src/{transport → core/transport}/transport.ts +0 -0
  337. /package/src/{runner → core}/typed-emitter.ts +0 -0
  338. /package/src/{transport/http → participant}/sse-stream.ts +0 -0
  339. /package/src/{transport/http → service}/inbox-buffer.ts +0 -0
  340. /package/src/{transport/http → service}/nonce-cache.ts +0 -0
  341. /package/src/{transport/http → service}/rate-limiter.ts +0 -0
  342. /package/src/{transport/http → service}/sse-writer.ts +0 -0
@@ -0,0 +1,2423 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/core/index.ts
31
+ var core_exports = {};
32
+ __export(core_exports, {
33
+ AGGREGATED_NONCE: () => AGGREGATED_NONCE,
34
+ AGGREGATION_MESSAGE_PREFIX: () => AGGREGATION_MESSAGE_PREFIX,
35
+ AGGREGATION_WIRE_VERSION: () => AGGREGATION_WIRE_VERSION,
36
+ AUTHORIZATION_REQUEST: () => AUTHORIZATION_REQUEST,
37
+ AggregationCohort: () => AggregationCohort,
38
+ AggregationCohortError: () => AggregationCohortError,
39
+ AggregationParticipantError: () => AggregationParticipantError,
40
+ AggregationServiceError: () => AggregationServiceError,
41
+ BaseMessage: () => BaseMessage,
42
+ BeaconSigningSession: () => BeaconSigningSession,
43
+ COHORT_ADVERT: () => COHORT_ADVERT,
44
+ COHORT_OPT_IN: () => COHORT_OPT_IN,
45
+ COHORT_OPT_IN_ACCEPT: () => COHORT_OPT_IN_ACCEPT,
46
+ COHORT_READY: () => COHORT_READY,
47
+ CONSOLE_LOGGER: () => CONSOLE_LOGGER,
48
+ DEFAULT_BROADCAST_LOOKBACK_MS: () => DEFAULT_BROADCAST_LOOKBACK_MS,
49
+ DEFAULT_CLOCK_SKEW_SEC: () => DEFAULT_CLOCK_SKEW_SEC,
50
+ DEFAULT_FUNDING_MODEL: () => DEFAULT_FUNDING_MODEL,
51
+ DEFAULT_NONCE_LEN_BYTES: () => DEFAULT_NONCE_LEN_BYTES,
52
+ DEFAULT_NOSTR_RELAYS: () => DEFAULT_NOSTR_RELAYS,
53
+ DEFAULT_RECOVERY_SEQUENCE: () => DEFAULT_RECOVERY_SEQUENCE,
54
+ DISTRIBUTE_AGGREGATED_DATA: () => DISTRIBUTE_AGGREGATED_DATA,
55
+ DidCommTransport: () => DidCommTransport,
56
+ FALLBACK_AUTHORIZATION_REQUEST: () => FALLBACK_AUTHORIZATION_REQUEST,
57
+ FALLBACK_SIGNATURE: () => FALLBACK_SIGNATURE,
58
+ HTTP_ENVELOPE_VERSION: () => HTTP_ENVELOPE_VERSION,
59
+ HTTP_ROUTE: () => HTTP_ROUTE,
60
+ HttpTransportError: () => HttpTransportError,
61
+ InMemoryBus: () => InMemoryBus,
62
+ InMemoryTransport: () => InMemoryTransport,
63
+ KNOWN_BEACON_TYPES: () => KNOWN_BEACON_TYPES,
64
+ KNOWN_FUNDING_MODELS: () => KNOWN_FUNDING_MODELS,
65
+ KeyPairAggregationSigner: () => KeyPairAggregationSigner,
66
+ MAX_RECOVERY_SEQUENCE: () => MAX_RECOVERY_SEQUENCE,
67
+ NONCE_CONTRIBUTION: () => NONCE_CONTRIBUTION,
68
+ NostrTransport: () => NostrTransport,
69
+ ParticipantCohortPhase: () => ParticipantCohortPhase,
70
+ REQUEST_AUTH_SCHEME: () => REQUEST_AUTH_SCHEME,
71
+ SIGNATURE_AUTHORIZATION: () => SIGNATURE_AUTHORIZATION,
72
+ SILENT_LOGGER: () => SILENT_LOGGER,
73
+ SSE_EVENT: () => SSE_EVENT,
74
+ SUBMIT_NONINCLUDED: () => SUBMIT_NONINCLUDED,
75
+ SUBMIT_UPDATE: () => SUBMIT_UPDATE,
76
+ ServiceCohortPhase: () => ServiceCohortPhase,
77
+ SigningSessionError: () => SigningSessionError,
78
+ SigningSessionPhase: () => SigningSessionPhase,
79
+ TAPROOT_LEAF_VERSION: () => TAPROOT_LEAF_VERSION,
80
+ TransportAdapterError: () => TransportAdapterError,
81
+ TransportError: () => TransportError,
82
+ TypedEventEmitter: () => TypedEventEmitter,
83
+ VALIDATION_ACK: () => VALIDATION_ACK,
84
+ buildFallbackLeaf: () => buildFallbackLeaf,
85
+ buildFallbackSpend: () => buildFallbackSpend,
86
+ buildRecoveryLeaves: () => buildRecoveryLeaves,
87
+ buildRecoveryScript: () => buildRecoveryScript,
88
+ buildRecoverySpend: () => buildRecoverySpend,
89
+ buildRequestAuth: () => buildRequestAuth,
90
+ createAggregatedNonceMessage: () => createAggregatedNonceMessage,
91
+ createAuthorizationRequestMessage: () => createAuthorizationRequestMessage,
92
+ createCohortAdvertMessage: () => createCohortAdvertMessage,
93
+ createCohortOptInAcceptMessage: () => createCohortOptInAcceptMessage,
94
+ createCohortOptInMessage: () => createCohortOptInMessage,
95
+ createCohortReadyMessage: () => createCohortReadyMessage,
96
+ createDistributeAggregatedDataMessage: () => createDistributeAggregatedDataMessage,
97
+ createFallbackAuthorizationRequestMessage: () => createFallbackAuthorizationRequestMessage,
98
+ createFallbackSignatureMessage: () => createFallbackSignatureMessage,
99
+ createNonceContributionMessage: () => createNonceContributionMessage,
100
+ createSignatureAuthorizationMessage: () => createSignatureAuthorizationMessage,
101
+ createSubmitNonIncludedMessage: () => createSubmitNonIncludedMessage,
102
+ createSubmitUpdateMessage: () => createSubmitUpdateMessage,
103
+ createValidationAckMessage: () => createValidationAckMessage,
104
+ fallbackSighash: () => fallbackSighash,
105
+ getBeaconStrategy: () => getBeaconStrategy,
106
+ isAggregatedNonceMessage: () => isAggregatedNonceMessage,
107
+ isAggregationMessageType: () => isAggregationMessageType,
108
+ isAuthorizationRequestMessage: () => isAuthorizationRequestMessage,
109
+ isCohortAdvertMessage: () => isCohortAdvertMessage,
110
+ isCohortOptInAcceptMessage: () => isCohortOptInAcceptMessage,
111
+ isCohortOptInMessage: () => isCohortOptInMessage,
112
+ isCohortReadyMessage: () => isCohortReadyMessage,
113
+ isDistributeAggregatedDataMessage: () => isDistributeAggregatedDataMessage,
114
+ isFallbackAuthorizationRequestMessage: () => isFallbackAuthorizationRequestMessage,
115
+ isFallbackSignatureMessage: () => isFallbackSignatureMessage,
116
+ isKeygenMessageType: () => isKeygenMessageType,
117
+ isNonceContributionMessage: () => isNonceContributionMessage,
118
+ isSignMessageType: () => isSignMessageType,
119
+ isSignatureAuthorizationMessage: () => isSignatureAuthorizationMessage,
120
+ isSubmitNonIncludedMessage: () => isSubmitNonIncludedMessage,
121
+ isSubmitUpdateMessage: () => isSubmitUpdateMessage,
122
+ isUpdateMessageType: () => isUpdateMessageType,
123
+ isValidationAckMessage: () => isValidationAckMessage,
124
+ normalizeForWire: () => normalizeForWire,
125
+ parseRequestAuth: () => parseRequestAuth,
126
+ registerBeaconStrategy: () => registerBeaconStrategy,
127
+ resolveFallbackThreshold: () => resolveFallbackThreshold,
128
+ reviveFromWire: () => reviveFromWire,
129
+ signEnvelope: () => signEnvelope,
130
+ tapLeafHash: () => tapLeafHash,
131
+ validateCohortConditions: () => validateCohortConditions,
132
+ verifyEnvelope: () => verifyEnvelope,
133
+ verifyRequestAuth: () => verifyRequestAuth
134
+ });
135
+ module.exports = __toCommonJS(core_exports);
136
+
137
+ // src/core/errors.ts
138
+ var import_common = require("@did-btcr2/common");
139
+ var AggregationServiceError = class extends import_common.MethodError {
140
+ constructor(message, type = "AggregationServiceError", data) {
141
+ super(message, type, data);
142
+ }
143
+ };
144
+ var AggregationParticipantError = class extends import_common.MethodError {
145
+ constructor(message, type = "AggregationParticipantError", data) {
146
+ super(message, type, data);
147
+ }
148
+ };
149
+ var AggregationCohortError = class extends import_common.MethodError {
150
+ constructor(message, type = "AggregationCohortError", data) {
151
+ super(message, type, data);
152
+ }
153
+ };
154
+ var SigningSessionError = class extends import_common.MethodError {
155
+ constructor(message, type = "SigningSessionError", data) {
156
+ super(message, type, data);
157
+ }
158
+ };
159
+
160
+ // src/core/logger.ts
161
+ var CONSOLE_LOGGER = {
162
+ debug: (msg, ...args) => console.debug(msg, ...args),
163
+ info: (msg, ...args) => console.info(msg, ...args),
164
+ warn: (msg, ...args) => console.warn(msg, ...args),
165
+ error: (msg, ...args) => console.error(msg, ...args)
166
+ };
167
+ var SILENT_LOGGER = {
168
+ debug: () => {
169
+ },
170
+ info: () => {
171
+ },
172
+ warn: () => {
173
+ },
174
+ error: () => {
175
+ }
176
+ };
177
+
178
+ // src/core/recovery-policy.ts
179
+ var import_secp256k1 = require("@noble/curves/secp256k1.js");
180
+ var import_utils = require("@noble/hashes/utils");
181
+ var import_btc_signer = require("@scure/btc-signer");
182
+ var import_musig2 = require("@scure/btc-signer/musig2");
183
+ var DEFAULT_FUNDING_MODEL = "operator-funded";
184
+ var DEFAULT_RECOVERY_SEQUENCE = 144;
185
+ var MAX_RECOVERY_SEQUENCE = 65535;
186
+ var TAPROOT_LEAF_VERSION = 192;
187
+ function compactSize(n) {
188
+ if (n < 253) return new Uint8Array([n]);
189
+ if (n <= 65535) return new Uint8Array([253, n & 255, n >> 8 & 255]);
190
+ return new Uint8Array([254, n & 255, n >> 8 & 255, n >> 16 & 255, n >> 24 & 255]);
191
+ }
192
+ function tapLeafHash(script, leafVersion = TAPROOT_LEAF_VERSION) {
193
+ return import_secp256k1.schnorr.utils.taggedHash(
194
+ "TapLeaf",
195
+ (0, import_utils.concatBytes)(new Uint8Array([leafVersion]), compactSize(script.length), script)
196
+ );
197
+ }
198
+ function resolveFallbackThreshold(advertised, n) {
199
+ return advertised ?? Math.max(1, n - 1);
200
+ }
201
+ function assertFallbackParams({ cohortKeys, fallbackThreshold }) {
202
+ const n = cohortKeys.length;
203
+ if (n === 0) {
204
+ throw new AggregationCohortError(
205
+ "Cannot build fallback leaf: no cohort keys.",
206
+ "NO_COHORT_KEYS"
207
+ );
208
+ }
209
+ for (const key of cohortKeys) {
210
+ if (key.length !== 33) {
211
+ throw new AggregationCohortError(
212
+ `Cohort key must be a 33-byte compressed public key, got ${key.length} bytes.`,
213
+ "INVALID_COHORT_KEY",
214
+ { length: key.length }
215
+ );
216
+ }
217
+ }
218
+ if (!Number.isInteger(fallbackThreshold) || fallbackThreshold < 1 || fallbackThreshold > n) {
219
+ throw new AggregationCohortError(
220
+ `Fallback threshold must be an integer in [1, ${n}] (k-of-n), got ${fallbackThreshold}.`,
221
+ "INVALID_FALLBACK_THRESHOLD",
222
+ { fallbackThreshold, n }
223
+ );
224
+ }
225
+ }
226
+ function buildFallbackLeaf(params) {
227
+ assertFallbackParams(params);
228
+ const xOnlyKeys = (0, import_musig2.sortKeys)(params.cohortKeys).map((k) => k.slice(1));
229
+ return (0, import_btc_signer.p2tr_ms)(params.fallbackThreshold, xOnlyKeys).script;
230
+ }
231
+ function assertRecoveryParams({ recoveryKey, recoverySequence }) {
232
+ if (recoveryKey.length !== 32) {
233
+ throw new AggregationCohortError(
234
+ `Recovery key must be a 32-byte x-only public key, got ${recoveryKey.length} bytes.`,
235
+ "INVALID_RECOVERY_KEY"
236
+ );
237
+ }
238
+ if (!Number.isInteger(recoverySequence) || recoverySequence < 1 || recoverySequence > MAX_RECOVERY_SEQUENCE) {
239
+ throw new AggregationCohortError(
240
+ `Recovery sequence must be a block-based BIP-68 relative timelock in [1, ${MAX_RECOVERY_SEQUENCE}], got ${recoverySequence}.`,
241
+ "INVALID_RECOVERY_SEQUENCE"
242
+ );
243
+ }
244
+ }
245
+ function buildRecoveryScript(params) {
246
+ assertRecoveryParams(params);
247
+ return import_btc_signer.Script.encode([
248
+ params.recoverySequence,
249
+ "CHECKSEQUENCEVERIFY",
250
+ "DROP",
251
+ params.recoveryKey,
252
+ "CHECKSIG"
253
+ ]);
254
+ }
255
+ function buildRecoveryLeaves(fundingModel, params) {
256
+ switch (fundingModel) {
257
+ case "operator-funded":
258
+ return [
259
+ { script: buildFallbackLeaf(params) },
260
+ { script: buildRecoveryScript(params) }
261
+ ];
262
+ case "participant-funded":
263
+ throw new AggregationCohortError(
264
+ "Funding model 'participant-funded' is reserved and not yet implemented.",
265
+ "UNSUPPORTED_FUNDING_MODEL",
266
+ { fundingModel }
267
+ );
268
+ default:
269
+ throw new AggregationCohortError(
270
+ `Unknown funding model: ${fundingModel}.`,
271
+ "UNKNOWN_FUNDING_MODEL",
272
+ { fundingModel }
273
+ );
274
+ }
275
+ }
276
+
277
+ // src/core/conditions.ts
278
+ var KNOWN_BEACON_TYPES = ["CASBeacon", "SMTBeacon"];
279
+ var KNOWN_FUNDING_MODELS = ["operator-funded", "participant-funded"];
280
+ function checkPair(problems, label, min, max) {
281
+ if (min !== void 0 && (!Number.isInteger(min) || min < 0)) {
282
+ problems.push(`min${label} must be an integer >= 0`);
283
+ }
284
+ if (max !== void 0 && (!Number.isInteger(max) || max < 0)) {
285
+ problems.push(`max${label} must be an integer >= 0`);
286
+ }
287
+ if (min !== void 0 && max !== void 0 && Number.isInteger(min) && Number.isInteger(max) && max < min) {
288
+ problems.push(`max${label} must be >= min${label}`);
289
+ }
290
+ }
291
+ function checkCost(problems, label, cost) {
292
+ if (cost === void 0) return;
293
+ if (typeof cost.amount !== "number" || !Number.isFinite(cost.amount) || cost.amount < 0) {
294
+ problems.push(`${label}.amount must be a finite number >= 0`);
295
+ }
296
+ if (typeof cost.unit !== "string" || cost.unit.length === 0) {
297
+ problems.push(`${label}.unit must be a non-empty string`);
298
+ }
299
+ if (cost.basis !== void 0 && cost.basis !== "per-did" && cost.basis !== "per-participant") {
300
+ problems.push(`${label}.basis must be 'per-did' or 'per-participant'`);
301
+ }
302
+ }
303
+ function validateCohortConditions(c) {
304
+ const problems = [];
305
+ if (!KNOWN_BEACON_TYPES.includes(c.beaconType)) {
306
+ problems.push(`beaconType must be one of ${KNOWN_BEACON_TYPES.join(", ")}`);
307
+ }
308
+ if (!Number.isInteger(c.minParticipants) || c.minParticipants < 1) {
309
+ problems.push("minParticipants must be an integer >= 1");
310
+ }
311
+ if (c.maxParticipants !== void 0) {
312
+ if (!Number.isInteger(c.maxParticipants) || c.maxParticipants < 1) {
313
+ problems.push("maxParticipants must be an integer >= 1");
314
+ } else if (Number.isInteger(c.minParticipants) && c.maxParticipants < c.minParticipants) {
315
+ problems.push("maxParticipants must be >= minParticipants");
316
+ }
317
+ }
318
+ checkPair(problems, "DidsPerParticipant", c.minDidsPerParticipant, c.maxDidsPerParticipant);
319
+ checkPair(problems, "SecondsBetweenAnnouncements", c.minSecondsBetweenAnnouncements, c.maxSecondsBetweenAnnouncements);
320
+ if (c.pendingUpdateTrigger !== void 0 && (!Number.isInteger(c.pendingUpdateTrigger) || c.pendingUpdateTrigger < 1)) {
321
+ problems.push("pendingUpdateTrigger must be an integer >= 1");
322
+ }
323
+ if (c.fallbackThreshold !== void 0) {
324
+ if (!Number.isInteger(c.fallbackThreshold) || c.fallbackThreshold < 1) {
325
+ problems.push("fallbackThreshold must be an integer >= 1");
326
+ } else if (c.maxParticipants !== void 0 && Number.isInteger(c.maxParticipants) && c.fallbackThreshold > c.maxParticipants) {
327
+ problems.push("fallbackThreshold must be <= maxParticipants");
328
+ }
329
+ }
330
+ checkCost(problems, "costOfEnrollment", c.costOfEnrollment);
331
+ checkCost(problems, "costPerAnnouncement", c.costPerAnnouncement);
332
+ if (typeof c.recoveryKey !== "string" || !/^[0-9a-fA-F]{64}$/.test(c.recoveryKey)) {
333
+ problems.push("recoveryKey must be a 64-character hex string (x-only public key)");
334
+ }
335
+ if (!Number.isInteger(c.recoverySequence) || c.recoverySequence < 1 || c.recoverySequence > MAX_RECOVERY_SEQUENCE) {
336
+ problems.push(`recoverySequence must be a block-based BIP-68 relative timelock in [1, ${MAX_RECOVERY_SEQUENCE}]`);
337
+ }
338
+ if (c.fundingModel !== void 0 && !KNOWN_FUNDING_MODELS.includes(c.fundingModel)) {
339
+ problems.push(`fundingModel must be one of ${KNOWN_FUNDING_MODELS.join(", ")}`);
340
+ }
341
+ return problems;
342
+ }
343
+
344
+ // src/core/phases.ts
345
+ var ServiceCohortPhase = /* @__PURE__ */ ((ServiceCohortPhase2) => {
346
+ ServiceCohortPhase2["Created"] = "Created";
347
+ ServiceCohortPhase2["Advertised"] = "Advertised";
348
+ ServiceCohortPhase2["CohortSet"] = "CohortSet";
349
+ ServiceCohortPhase2["CollectingUpdates"] = "CollectingUpdates";
350
+ ServiceCohortPhase2["UpdatesCollected"] = "UpdatesCollected";
351
+ ServiceCohortPhase2["DataDistributed"] = "DataDistributed";
352
+ ServiceCohortPhase2["Validated"] = "Validated";
353
+ ServiceCohortPhase2["SigningStarted"] = "SigningStarted";
354
+ ServiceCohortPhase2["NoncesCollected"] = "NoncesCollected";
355
+ ServiceCohortPhase2["AwaitingPartialSigs"] = "AwaitingPartialSigs";
356
+ ServiceCohortPhase2["FallbackRequested"] = "FallbackRequested";
357
+ ServiceCohortPhase2["Complete"] = "Complete";
358
+ ServiceCohortPhase2["Failed"] = "Failed";
359
+ return ServiceCohortPhase2;
360
+ })(ServiceCohortPhase || {});
361
+ var ParticipantCohortPhase = /* @__PURE__ */ ((ParticipantCohortPhase2) => {
362
+ ParticipantCohortPhase2["Discovered"] = "Discovered";
363
+ ParticipantCohortPhase2["OptedIn"] = "OptedIn";
364
+ ParticipantCohortPhase2["CohortReady"] = "CohortReady";
365
+ ParticipantCohortPhase2["UpdateSubmitted"] = "UpdateSubmitted";
366
+ ParticipantCohortPhase2["NonIncluded"] = "NonIncluded";
367
+ ParticipantCohortPhase2["AwaitingValidation"] = "AwaitingValidation";
368
+ ParticipantCohortPhase2["ValidationSent"] = "ValidationSent";
369
+ ParticipantCohortPhase2["AwaitingSigning"] = "AwaitingSigning";
370
+ ParticipantCohortPhase2["NonceSent"] = "NonceSent";
371
+ ParticipantCohortPhase2["AwaitingPartialSig"] = "AwaitingPartialSig";
372
+ ParticipantCohortPhase2["AwaitingFallbackSig"] = "AwaitingFallbackSig";
373
+ ParticipantCohortPhase2["Complete"] = "Complete";
374
+ ParticipantCohortPhase2["Failed"] = "Failed";
375
+ return ParticipantCohortPhase2;
376
+ })(ParticipantCohortPhase || {});
377
+ var SigningSessionPhase = /* @__PURE__ */ ((SigningSessionPhase2) => {
378
+ SigningSessionPhase2["AwaitingNonceContributions"] = "AwaitingNonceContributions";
379
+ SigningSessionPhase2["NonceContributionsReceived"] = "NonceContributionsReceived";
380
+ SigningSessionPhase2["AwaitingPartialSignatures"] = "AwaitingPartialSignatures";
381
+ SigningSessionPhase2["PartialSignaturesReceived"] = "PartialSignaturesReceived";
382
+ SigningSessionPhase2["Complete"] = "Complete";
383
+ SigningSessionPhase2["Failed"] = "Failed";
384
+ return SigningSessionPhase2;
385
+ })(SigningSessionPhase || {});
386
+
387
+ // src/core/cohort.ts
388
+ var import_bitcoin = require("@did-btcr2/bitcoin");
389
+ var import_common2 = require("@did-btcr2/common");
390
+ var import_smt = require("@did-btcr2/smt");
391
+ var import_secp256k12 = require("@noble/curves/secp256k1.js");
392
+ var import_utils2 = require("@noble/hashes/utils");
393
+ var import_btc_signer2 = require("@scure/btc-signer");
394
+ var import_musig22 = require("@scure/btc-signer/musig2");
395
+ var AggregationCohort = class {
396
+ /** Unique identifier for the cohort. */
397
+ id;
398
+ /** DID of the Aggregation Service managing this cohort. */
399
+ serviceDid;
400
+ /** Minimum number of participants required to finalize the cohort. */
401
+ minParticipants;
402
+ /** Network on which the cohort operates (mainnet, mutinynet, etc.). */
403
+ network;
404
+ /** Type of beacon used in the cohort: 'CASBeacon' or 'SMTBeacon'. */
405
+ beaconType;
406
+ /** List of participant DIDs that have been accepted into the cohort. */
407
+ participants = [];
408
+ /**
409
+ * Mapping from participant DID to their compressed secp256k1 public key.
410
+ * Distinct from {@link cohortKeys} (which is sorted per BIP-327): this lets
411
+ * callers look up a participant's key without knowing their position in the
412
+ * sorted array. Populated by the service at `acceptParticipant` time.
413
+ */
414
+ participantKeys = /* @__PURE__ */ new Map();
415
+ /** Sorted list of cohort participants' compressed public keys. */
416
+ #cohortKeys = [];
417
+ /**
418
+ * BIP-341 TapTweak scalar: `taggedHash("TapTweak", internalPubkey || tapMerkleRoot)`.
419
+ * The beacon output is an internal key (the MuSig2 aggregate) plus a script
420
+ * tree (the recovery leaves), so the tweak commits to the tree's Merkle root.
421
+ * The MuSig2 signing session applies this as an x-only tweak; a value that does
422
+ * not match the root the funded address was derived from silently yields an
423
+ * invalid key-path signature.
424
+ */
425
+ tapTweak = new Uint8Array();
426
+ /** The n-of-n MuSig2 aggregate internal key, x-only (32 bytes), set by computeBeaconAddress(). */
427
+ internalKey = new Uint8Array();
428
+ /** BIP-341 Taproot Merkle root of the recovery script tree, set by computeBeaconAddress(). */
429
+ tapMerkleRoot = new Uint8Array();
430
+ /** Operator recovery key, x-only (32 bytes). Used to build the CSV recovery leaf. */
431
+ recoveryKey;
432
+ /** Relative-timelock (BIP-68 nSequence) before the recovery leaf is spendable. */
433
+ recoverySequence;
434
+ /** Funding model governing the recovery leaves (default 'operator-funded'). */
435
+ fundingModel;
436
+ /**
437
+ * Advertised k of the k-of-n fallback leaf, or undefined to default to n-1 at
438
+ * address computation. Read the resolved value via {@link effectiveFallbackThreshold}.
439
+ */
440
+ fallbackThreshold;
441
+ /** The Taproot beacon address: key path is the MuSig2 aggregate, script path is fallback + recovery. */
442
+ beaconAddress = "";
443
+ /** Pending DID updates submitted by participants, keyed by DID. */
444
+ pendingUpdates = /* @__PURE__ */ new Map();
445
+ /**
446
+ * Participant DIDs that explicitly declined to submit an update this round
447
+ * (cooperative non-inclusion). A decliner is absent from the CAS Announcement
448
+ * Map and carries a non-inclusion leaf in the SMT, yet still signs. Kept
449
+ * disjoint from {@link pendingUpdates} so CAS correctness holds by construction.
450
+ */
451
+ nonIncluded = /* @__PURE__ */ new Set();
452
+ /** CAS Beacon Announcement Map (DID to updateHash), set by buildCASAnnouncement(). */
453
+ casAnnouncement;
454
+ /** Per-participant SMT proofs, set by buildSMTTree(). */
455
+ smtProofs;
456
+ /** Signal bytes (32 bytes) for OP_RETURN: SHA-256 of CAS announcement OR SMT root. */
457
+ signalBytes;
458
+ /** Set of participant DIDs that have approved the aggregated data. */
459
+ validationAcks = /* @__PURE__ */ new Set();
460
+ /** Set of participant DIDs that have rejected the aggregated data. */
461
+ validationRejections = /* @__PURE__ */ new Set();
462
+ constructor({ id, minParticipants, serviceDid, network, beaconType, recoveryKey, recoverySequence, fundingModel, fallbackThreshold }) {
463
+ this.id = id || crypto.randomUUID();
464
+ this.minParticipants = minParticipants ?? 2;
465
+ this.serviceDid = serviceDid || "";
466
+ this.network = network;
467
+ this.beaconType = beaconType || "CASBeacon";
468
+ this.recoveryKey = recoveryKey;
469
+ this.recoverySequence = recoverySequence;
470
+ this.fundingModel = fundingModel ?? DEFAULT_FUNDING_MODEL;
471
+ this.fallbackThreshold = fallbackThreshold;
472
+ }
473
+ /** Sorted cohort keys (sorted on assignment per BIP-327). */
474
+ get cohortKeys() {
475
+ return this.#cohortKeys;
476
+ }
477
+ set cohortKeys(keys) {
478
+ this.#cohortKeys = (0, import_musig22.sortKeys)(keys);
479
+ }
480
+ /**
481
+ * The resolved k of the k-of-n fallback leaf: the advertised
482
+ * {@link fallbackThreshold}, or n-1 (floored at 1) when unadvertised, where n is
483
+ * the current cohort size. This is the value the beacon address commits to and
484
+ * the spend builders must reproduce. Returns 0 before any cohort keys are set.
485
+ */
486
+ get effectiveFallbackThreshold() {
487
+ if (this.#cohortKeys.length === 0) return 0;
488
+ return resolveFallbackThreshold(this.fallbackThreshold, this.#cohortKeys.length);
489
+ }
490
+ /**
491
+ * Computes the Taproot beacon address from the cohort keys and recovery params.
492
+ *
493
+ * The output's key path is the n-of-n MuSig2 aggregate of the cohort keys; its
494
+ * script path is the recovery tree (a CSV recovery leaf so a missing signer
495
+ * cannot permanently lock the UTXO). Sets `internalKey`, `tapMerkleRoot`, and
496
+ * the `tapTweak` the MuSig2 session must apply for the key-path spend.
497
+ *
498
+ * The tweak is derived from the Merkle root the address was built with (read
499
+ * back from the payment), never recomputed by hand, so the MuSig2 key-path
500
+ * signature is guaranteed to validate against the funded address.
501
+ */
502
+ computeBeaconAddress() {
503
+ if (this.#cohortKeys.length === 0) {
504
+ throw new AggregationCohortError(
505
+ "Cannot compute beacon address: no cohort keys.",
506
+ "NO_COHORT_KEYS",
507
+ { cohortId: this.id }
508
+ );
509
+ }
510
+ if (!this.recoveryKey || this.recoveryKey.length === 0 || this.recoverySequence === void 0) {
511
+ throw new AggregationCohortError(
512
+ "Cannot compute beacon address: missing recovery key or sequence.",
513
+ "NO_RECOVERY_PARAMS",
514
+ { cohortId: this.id }
515
+ );
516
+ }
517
+ const keyAggContext = (0, import_musig22.keyAggregate)(this.#cohortKeys);
518
+ const aggPubkey = (0, import_musig22.keyAggExport)(keyAggContext);
519
+ const leaves = buildRecoveryLeaves(this.fundingModel, {
520
+ recoveryKey: this.recoveryKey,
521
+ recoverySequence: this.recoverySequence,
522
+ cohortKeys: this.#cohortKeys,
523
+ fallbackThreshold: resolveFallbackThreshold(this.fallbackThreshold, this.#cohortKeys.length)
524
+ });
525
+ const payment = (0, import_btc_signer2.p2tr)(aggPubkey, leaves, (0, import_bitcoin.getNetwork)(this.network), true);
526
+ this.internalKey = aggPubkey;
527
+ this.tapMerkleRoot = payment.tapMerkleRoot;
528
+ this.tapTweak = import_secp256k12.schnorr.utils.taggedHash("TapTweak", (0, import_utils2.concatBytes)(aggPubkey, payment.tapMerkleRoot));
529
+ if (!payment.address) {
530
+ throw new AggregationCohortError(
531
+ "Failed to compute Taproot address",
532
+ "BEACON_ADDRESS_ERROR",
533
+ { cohortId: this.id }
534
+ );
535
+ }
536
+ this.beaconAddress = payment.address;
537
+ return payment.address;
538
+ }
539
+ /**
540
+ * Validates that the participant's key is in the cohort and the beacon address
541
+ * matches the locally-computed one. Used by participants to verify cohort ready
542
+ * messages from the service.
543
+ */
544
+ validateMembership(participantPkHex, cohortKeysHex, expectedBeaconAddress) {
545
+ if (!cohortKeysHex.includes(participantPkHex)) {
546
+ throw new AggregationCohortError(
547
+ `Participant key not found in cohort ${this.id}.`,
548
+ "COHORT_VALIDATION_ERROR",
549
+ { cohortId: this.id, participantPkHex }
550
+ );
551
+ }
552
+ this.cohortKeys = cohortKeysHex.map((k) => (0, import_utils2.hexToBytes)(k));
553
+ const computed = this.computeBeaconAddress();
554
+ if (computed !== expectedBeaconAddress) {
555
+ throw new AggregationCohortError(
556
+ `Computed beacon address ${computed} does not match expected ${expectedBeaconAddress}.`,
557
+ "BEACON_ADDRESS_MISMATCH",
558
+ { cohortId: this.id, computed, expected: expectedBeaconAddress }
559
+ );
560
+ }
561
+ }
562
+ /**
563
+ * Returns the position of a participant's public key in the sorted
564
+ * {@link cohortKeys} array, or -1 if the participant is not in the cohort.
565
+ * Required by MuSig2 partial-sig verification which indexes by signer position.
566
+ */
567
+ indexOfParticipant(did) {
568
+ const pk = this.participantKeys.get(did);
569
+ if (!pk) return -1;
570
+ return this.#cohortKeys.findIndex(
571
+ (k) => k.length === pk.length && k.every((b, i) => b === pk[i])
572
+ );
573
+ }
574
+ addUpdate(participantDid, signedUpdate) {
575
+ if (!this.participants.includes(participantDid)) {
576
+ throw new AggregationCohortError(
577
+ `Participant ${participantDid} is not in cohort ${this.id}.`,
578
+ "UNKNOWN_PARTICIPANT",
579
+ { cohortId: this.id, participantDid }
580
+ );
581
+ }
582
+ this.pendingUpdates.set(participantDid, signedUpdate);
583
+ }
584
+ /**
585
+ * Record that a participant declined to submit an update this round
586
+ * (cooperative non-inclusion). The member stays in the cohort and still signs.
587
+ */
588
+ addNonInclusion(participantDid) {
589
+ if (!this.participants.includes(participantDid)) {
590
+ throw new AggregationCohortError(
591
+ `Participant ${participantDid} is not in cohort ${this.id}.`,
592
+ "UNKNOWN_PARTICIPANT",
593
+ { cohortId: this.id, participantDid }
594
+ );
595
+ }
596
+ if (this.pendingUpdates.has(participantDid)) {
597
+ throw new AggregationCohortError(
598
+ `Participant ${participantDid} already submitted an update; cannot also decline.`,
599
+ "CONFLICTING_RESPONSE",
600
+ { cohortId: this.id, participantDid }
601
+ );
602
+ }
603
+ this.nonIncluded.add(participantDid);
604
+ }
605
+ hasAllUpdates() {
606
+ return this.pendingUpdates.size === this.participants.length;
607
+ }
608
+ /**
609
+ * True when every participant has responded for this round, either with an
610
+ * update or with an explicit non-inclusion. This is the aggregation gate when
611
+ * non-inclusion is in play; it generalizes {@link hasAllUpdates} the same way
612
+ * {@link hasAllValidationResponses} generalizes a unanimous ack.
613
+ */
614
+ hasAllResponses() {
615
+ return this.pendingUpdates.size + this.nonIncluded.size === this.participants.length;
616
+ }
617
+ /**
618
+ * Builds a CAS Announcement Map from collected updates.
619
+ * Maps each participant DID to base64url canonical hash of their signed update.
620
+ * Computes signal bytes as SHA-256 of canonicalized announcement.
621
+ *
622
+ * Members who declined (cooperative non-inclusion) are naturally absent from
623
+ * the map: the body iterates {@link pendingUpdates}, which never holds a
624
+ * decliner. Absence from the map is exactly the CAS non-inclusion signal.
625
+ */
626
+ buildCASAnnouncement() {
627
+ if (!this.hasAllResponses()) {
628
+ throw new AggregationCohortError(
629
+ "Cannot build CAS Announcement: not all participants have responded.",
630
+ "INCOMPLETE_RESPONSES",
631
+ { cohortId: this.id, updates: this.pendingUpdates.size, declined: this.nonIncluded.size, total: this.participants.length }
632
+ );
633
+ }
634
+ const announcement = {};
635
+ for (const [did, signedUpdate] of this.pendingUpdates) {
636
+ announcement[did] = (0, import_common2.canonicalHash)(signedUpdate);
637
+ }
638
+ this.casAnnouncement = announcement;
639
+ this.signalBytes = (0, import_common2.hash)((0, import_common2.canonicalize)(announcement));
640
+ return announcement;
641
+ }
642
+ /**
643
+ * Builds an SMT tree with one leaf per participant.
644
+ *
645
+ * A member who submitted an update gets an inclusion leaf
646
+ * (SHA-256(SHA-256(nonce) || SHA-256(update))); a member who declined gets a
647
+ * non-inclusion leaf (SHA-256(SHA-256(nonce)), the `signedUpdate` entry field
648
+ * omitted). The cohort mints each member's nonce and returns it inside that
649
+ * member's serialized proof, so a decliner can self-validate its own
650
+ * non-inclusion slot and the resolver can recompute the leaf. Stores
651
+ * per-participant proofs and the SMT root as signalBytes.
652
+ */
653
+ buildSMTTree() {
654
+ if (!this.hasAllResponses()) {
655
+ throw new AggregationCohortError(
656
+ "Cannot build SMT tree: not all participants have responded.",
657
+ "INCOMPLETE_RESPONSES",
658
+ { cohortId: this.id, updates: this.pendingUpdates.size, declined: this.nonIncluded.size, total: this.participants.length }
659
+ );
660
+ }
661
+ const tree = new import_smt.BTCR2MerkleTree();
662
+ const entries = [];
663
+ const encoder = new TextEncoder();
664
+ for (const did of this.participants) {
665
+ const nonce = (0, import_utils2.randomBytes)(32);
666
+ const signedUpdate = this.pendingUpdates.get(did);
667
+ if (signedUpdate) {
668
+ entries.push({ did, nonce, signedUpdate: encoder.encode((0, import_common2.canonicalize)(signedUpdate)) });
669
+ } else {
670
+ entries.push({ did, nonce });
671
+ }
672
+ }
673
+ tree.addEntries(entries);
674
+ tree.finalize();
675
+ this.signalBytes = tree.rootHash;
676
+ this.smtProofs = /* @__PURE__ */ new Map();
677
+ for (const did of this.participants) {
678
+ this.smtProofs.set(did, tree.proof(did));
679
+ }
680
+ return this.smtProofs;
681
+ }
682
+ addValidation(participantDid, approved) {
683
+ if (!this.participants.includes(participantDid)) {
684
+ throw new AggregationCohortError(
685
+ `Unknown participant ${participantDid} in cohort ${this.id}.`,
686
+ "UNKNOWN_PARTICIPANT",
687
+ { cohortId: this.id, participantDid }
688
+ );
689
+ }
690
+ if (approved) {
691
+ this.validationAcks.add(participantDid);
692
+ } else {
693
+ this.validationRejections.add(participantDid);
694
+ }
695
+ }
696
+ /**
697
+ * True when every participant has either approved or rejected the aggregated data.
698
+ */
699
+ hasAllValidationResponses() {
700
+ return this.validationAcks.size + this.validationRejections.size === this.participants.length;
701
+ }
702
+ /**
703
+ * True when all participants approved. Note: differs from {@link hasAllValidationResponses},
704
+ * this returns false if any participant rejected, even if all responses are in.
705
+ */
706
+ isFullyValidated() {
707
+ return this.validationRejections.size === 0 && this.validationAcks.size === this.participants.length;
708
+ }
709
+ };
710
+
711
+ // src/core/signing-session.ts
712
+ var import_keypair = require("@did-btcr2/keypair");
713
+ var import_btc_signer3 = require("@scure/btc-signer");
714
+ var musig2 = __toESM(require("@scure/btc-signer/musig2"), 1);
715
+ var BeaconSigningSession = class {
716
+ /** Unique identifier for this signing session. */
717
+ id;
718
+ /** The cohort this session signs for. */
719
+ cohort;
720
+ /** The Bitcoin transaction being signed. */
721
+ pendingTx;
722
+ /** Previous output scripts for Taproot sighash computation (BIP-341). */
723
+ prevOutScripts;
724
+ /** Previous output values for Taproot sighash computation. */
725
+ prevOutValues;
726
+ /** Map of participant publicKey-hex to public nonce contribution. */
727
+ nonceContributions = /* @__PURE__ */ new Map();
728
+ /** Aggregated MuSig2 nonce (66 bytes). */
729
+ aggregatedNonce;
730
+ /** Map of participant DID to partial signature. */
731
+ partialSignatures = /* @__PURE__ */ new Map();
732
+ /** Final 64-byte Schnorr signature. */
733
+ signature;
734
+ /** Current signing session phase. */
735
+ phase;
736
+ /**
737
+ * Participant's MuSig2 secret nonce, held only on the participant side
738
+ * between {@link generateNonceContribution} and {@link generatePartialSignature}.
739
+ * Private and cleared on every terminal path (success, failure, or teardown
740
+ * via {@link clearSecrets}) so a spent or abandoned nonce cannot be reused or
741
+ * serialized.
742
+ */
743
+ #secretNonce;
744
+ constructor({ id, cohort, pendingTx, prevOutScripts, prevOutValues }) {
745
+ this.id = id || crypto.randomUUID();
746
+ this.cohort = cohort;
747
+ this.pendingTx = pendingTx;
748
+ this.prevOutScripts = prevOutScripts || [];
749
+ this.prevOutValues = prevOutValues || [];
750
+ this.phase = "AwaitingNonceContributions" /* AwaitingNonceContributions */;
751
+ }
752
+ /**
753
+ * Computes the Taproot sighash (BIP-341) for the first input.
754
+ */
755
+ get sigHash() {
756
+ if (!this.prevOutScripts.length || !this.prevOutValues.length) {
757
+ throw new SigningSessionError(
758
+ "Cannot compute sighash: missing prevOutScripts or prevOutValues.",
759
+ "SIGHASH_ERROR"
760
+ );
761
+ }
762
+ return this.pendingTx.preimageWitnessV1(
763
+ 0,
764
+ this.prevOutScripts,
765
+ import_btc_signer3.SigHash.DEFAULT,
766
+ this.prevOutValues
767
+ );
768
+ }
769
+ addNonceContribution(participantDid, nonceContribution) {
770
+ if (this.phase !== "AwaitingNonceContributions" /* AwaitingNonceContributions */) {
771
+ throw new SigningSessionError(
772
+ `Nonce contributions not expected. Current phase: ${this.phase}`,
773
+ "INVALID_PHASE",
774
+ { phase: this.phase }
775
+ );
776
+ }
777
+ if (!this.cohort.participants.includes(participantDid)) {
778
+ throw new SigningSessionError(
779
+ `Participant ${participantDid} is not a member of cohort ${this.cohort.id}.`,
780
+ "UNKNOWN_PARTICIPANT",
781
+ { cohortId: this.cohort.id, participantDid }
782
+ );
783
+ }
784
+ if (nonceContribution.length !== 66) {
785
+ throw new SigningSessionError(
786
+ `Invalid nonce contribution: expected 66 bytes, got ${nonceContribution.length}.`,
787
+ "INVALID_NONCE_LENGTH"
788
+ );
789
+ }
790
+ if (this.nonceContributions.has(participantDid)) {
791
+ throw new SigningSessionError(
792
+ `Duplicate nonce contribution from ${participantDid}.`,
793
+ "DUPLICATE_NONCE"
794
+ );
795
+ }
796
+ this.nonceContributions.set(participantDid, nonceContribution);
797
+ if (this.nonceContributions.size === this.cohort.participants.length) {
798
+ this.phase = "NonceContributionsReceived" /* NonceContributionsReceived */;
799
+ }
800
+ }
801
+ generateAggregatedNonce() {
802
+ if (this.phase !== "NonceContributionsReceived" /* NonceContributionsReceived */) {
803
+ throw new SigningSessionError(
804
+ `Cannot aggregate nonces: phase is ${this.phase}, expected NonceContributionsReceived.`,
805
+ "INVALID_PHASE"
806
+ );
807
+ }
808
+ this.aggregatedNonce = musig2.nonceAggregate([...this.nonceContributions.values()]);
809
+ this.phase = "AwaitingPartialSignatures" /* AwaitingPartialSignatures */;
810
+ return this.aggregatedNonce;
811
+ }
812
+ addPartialSignature(participantDid, partialSig) {
813
+ if (this.phase !== "AwaitingPartialSignatures" /* AwaitingPartialSignatures */) {
814
+ throw new SigningSessionError(
815
+ `Partial signatures not expected. Current phase: ${this.phase}`,
816
+ "INVALID_PHASE"
817
+ );
818
+ }
819
+ if (!this.cohort.participants.includes(participantDid)) {
820
+ throw new SigningSessionError(
821
+ `Participant ${participantDid} is not a member of cohort ${this.cohort.id}.`,
822
+ "UNKNOWN_PARTICIPANT",
823
+ { cohortId: this.cohort.id, participantDid }
824
+ );
825
+ }
826
+ if (this.partialSignatures.has(participantDid)) {
827
+ throw new SigningSessionError(
828
+ `Duplicate partial signature from ${participantDid}.`,
829
+ "DUPLICATE_PARTIAL_SIG"
830
+ );
831
+ }
832
+ this.partialSignatures.set(participantDid, partialSig);
833
+ if (this.partialSignatures.size === this.cohort.participants.length) {
834
+ this.phase = "PartialSignaturesReceived" /* PartialSignaturesReceived */;
835
+ }
836
+ }
837
+ generateFinalSignature() {
838
+ if (this.phase !== "PartialSignaturesReceived" /* PartialSignaturesReceived */) {
839
+ throw new SigningSessionError(
840
+ `Cannot generate final signature: phase is ${this.phase}.`,
841
+ "INVALID_PHASE"
842
+ );
843
+ }
844
+ if (!this.aggregatedNonce) {
845
+ throw new SigningSessionError("Aggregated nonce missing.", "MISSING_AGGREGATED_NONCE");
846
+ }
847
+ const session = new musig2.Session(
848
+ this.aggregatedNonce,
849
+ this.cohort.cohortKeys,
850
+ this.sigHash,
851
+ [this.cohort.tapTweak],
852
+ [true]
853
+ );
854
+ const pubNoncesByIndex = new Array(this.cohort.cohortKeys.length);
855
+ for (const [did, nonce] of this.nonceContributions) {
856
+ const idx = this.cohort.indexOfParticipant(did);
857
+ if (idx < 0) {
858
+ throw new SigningSessionError(
859
+ `Cannot verify nonce from ${did}: participant key missing from cohort.`,
860
+ "UNKNOWN_PARTICIPANT_KEY",
861
+ { participantDid: did }
862
+ );
863
+ }
864
+ pubNoncesByIndex[idx] = nonce;
865
+ }
866
+ for (const [did, partialSig] of this.partialSignatures) {
867
+ const idx = this.cohort.indexOfParticipant(did);
868
+ if (idx < 0) {
869
+ throw new SigningSessionError(
870
+ `Cannot verify partial signature from ${did}: participant key missing from cohort.`,
871
+ "UNKNOWN_PARTICIPANT_KEY",
872
+ { participantDid: did }
873
+ );
874
+ }
875
+ const ok = session.partialSigVerify(partialSig, pubNoncesByIndex, idx);
876
+ if (!ok) {
877
+ throw new SigningSessionError(
878
+ `Bad partial signature from ${did}.`,
879
+ "BAD_PARTIAL_SIG",
880
+ { participantDid: did, index: idx }
881
+ );
882
+ }
883
+ }
884
+ this.signature = session.partialSigAgg([...this.partialSignatures.values()]);
885
+ this.phase = "Complete" /* Complete */;
886
+ return this.signature;
887
+ }
888
+ /**
889
+ * Generates a fresh MuSig2 nonce contribution for the participant.
890
+ * Stores the secret nonce internally for use in `generatePartialSignature()`.
891
+ */
892
+ generateNonceContribution(participantPublicKey, participantSecretKey) {
893
+ const aggPublicKey = musig2.keyAggExport(musig2.keyAggregate(this.cohort.cohortKeys));
894
+ const nonces = musig2.nonceGen(participantPublicKey, participantSecretKey, aggPublicKey);
895
+ this.#secretNonce = nonces.secret;
896
+ return nonces.public;
897
+ }
898
+ /**
899
+ * Generates a partial signature using the participant's secret key + secret nonce.
900
+ * Requires the aggregated nonce to have been set first (via the service).
901
+ *
902
+ * Clears the stored secret nonce after use on every path (success or throw)
903
+ * via {@link clearSecrets}. JS cannot truly erase memory (GC may relocate
904
+ * buffers), but overwriting the bytes shortens the exposure window and
905
+ * prevents accidental reuse or serialization of a spent nonce - reuse of a
906
+ * MuSig2 nonce leaks the secret key.
907
+ */
908
+ generatePartialSignature(participantSecretKey) {
909
+ if (!this.aggregatedNonce) {
910
+ throw new SigningSessionError("Aggregated nonce not available.", "MISSING_AGGREGATED_NONCE");
911
+ }
912
+ if (!this.#secretNonce) {
913
+ throw new SigningSessionError("Secret nonce not available - generateNonceContribution() must be called first.", "MISSING_SECRET_NONCE");
914
+ }
915
+ const session = new musig2.Session(
916
+ this.aggregatedNonce,
917
+ this.cohort.cohortKeys,
918
+ this.sigHash,
919
+ [this.cohort.tapTweak],
920
+ [true]
921
+ );
922
+ try {
923
+ return session.sign(this.#secretNonce, participantSecretKey);
924
+ } finally {
925
+ this.clearSecrets();
926
+ }
927
+ }
928
+ /**
929
+ * Zeroize any retained secret nonce. Safe to call repeatedly and on any path
930
+ * (completion, failure, or teardown of an abandoned session). Callers that
931
+ * drop a session before it reaches a partial signature should invoke this so
932
+ * the secret nonce does not linger on the live object.
933
+ */
934
+ clearSecrets() {
935
+ if (this.#secretNonce) {
936
+ (0, import_keypair.wipe)(this.#secretNonce);
937
+ this.#secretNonce = void 0;
938
+ }
939
+ }
940
+ isComplete() {
941
+ return this.phase === "Complete" /* Complete */;
942
+ }
943
+ isFailed() {
944
+ return this.phase === "Failed" /* Failed */;
945
+ }
946
+ };
947
+
948
+ // src/core/signer.ts
949
+ var import_keypair2 = require("@did-btcr2/keypair");
950
+ var KeyPairAggregationSigner = class {
951
+ publicKey;
952
+ #keys;
953
+ /** @param {SchnorrKeyPair} keys The keypair whose secret backs this signer. */
954
+ constructor(keys) {
955
+ this.#keys = keys;
956
+ this.publicKey = keys.publicKey.compressed;
957
+ }
958
+ withSecret(fn) {
959
+ const secretKey = this.#keys.secretKey.bytes;
960
+ try {
961
+ return fn(secretKey);
962
+ } finally {
963
+ (0, import_keypair2.wipe)(secretKey);
964
+ }
965
+ }
966
+ };
967
+
968
+ // src/core/beacon-strategy.ts
969
+ var import_common3 = require("@did-btcr2/common");
970
+ var import_smt2 = require("@did-btcr2/smt");
971
+ var CAS_STRATEGY = {
972
+ type: "CASBeacon",
973
+ buildAggregatedData(cohort) {
974
+ cohort.buildCASAnnouncement();
975
+ },
976
+ getDistributePayload(cohort) {
977
+ return { casAnnouncement: cohort.casAnnouncement };
978
+ },
979
+ validateParticipantView({ participantDid, included, expectedHash, body }) {
980
+ const casAnnouncement = body.casAnnouncement;
981
+ if (!casAnnouncement) return { matches: false };
982
+ if (!included) {
983
+ return { matches: !(participantDid in casAnnouncement), casAnnouncement };
984
+ }
985
+ return {
986
+ matches: casAnnouncement[participantDid] === expectedHash,
987
+ casAnnouncement
988
+ };
989
+ }
990
+ };
991
+ var SMT_STRATEGY = {
992
+ type: "SMTBeacon",
993
+ buildAggregatedData(cohort) {
994
+ cohort.buildSMTTree();
995
+ },
996
+ getDistributePayload(cohort, participantDid) {
997
+ const proof = cohort.smtProofs?.get(participantDid);
998
+ return { smtProof: proof };
999
+ },
1000
+ validateParticipantView({ participantDid, included, submittedUpdate, body }) {
1001
+ const smtProof = body.smtProof;
1002
+ const index = (0, import_smt2.didToIndex)(participantDid);
1003
+ if (!included) {
1004
+ if (!smtProof?.nonce || smtProof?.updateId) return { matches: false, smtProof };
1005
+ const candidateHash2 = (0, import_smt2.blockHash)((0, import_smt2.blockHash)((0, import_smt2.base64UrlToHash)(smtProof.nonce)));
1006
+ return { matches: (0, import_smt2.verifySerializedProof)(smtProof, index, candidateHash2), smtProof };
1007
+ }
1008
+ if (!smtProof?.updateId || !smtProof?.nonce || !submittedUpdate) return { matches: false, smtProof };
1009
+ const canonicalBytes = new TextEncoder().encode((0, import_common3.canonicalize)(submittedUpdate));
1010
+ const expectedUpdateId = (0, import_smt2.hashToBase64Url)((0, import_smt2.blockHash)(canonicalBytes));
1011
+ if (smtProof.updateId !== expectedUpdateId) {
1012
+ return { matches: false, smtProof };
1013
+ }
1014
+ const candidateHash = (0, import_smt2.blockHash)((0, import_smt2.blockHash)((0, import_smt2.base64UrlToHash)(smtProof.nonce)), (0, import_smt2.base64UrlToHash)(smtProof.updateId));
1015
+ return {
1016
+ matches: (0, import_smt2.verifySerializedProof)(smtProof, index, candidateHash),
1017
+ smtProof
1018
+ };
1019
+ }
1020
+ };
1021
+ var STRATEGIES = /* @__PURE__ */ new Map([
1022
+ [CAS_STRATEGY.type, CAS_STRATEGY],
1023
+ [SMT_STRATEGY.type, SMT_STRATEGY]
1024
+ ]);
1025
+ function registerBeaconStrategy(strategy) {
1026
+ STRATEGIES.set(strategy.type, strategy);
1027
+ }
1028
+ function getBeaconStrategy(type) {
1029
+ return STRATEGIES.get(type);
1030
+ }
1031
+
1032
+ // src/core/recovery-spend.ts
1033
+ var import_bitcoin2 = require("@did-btcr2/bitcoin");
1034
+ var import_secp256k13 = require("@noble/curves/secp256k1.js");
1035
+ var import_btc_signer4 = require("@scure/btc-signer");
1036
+ var import_musig23 = require("@scure/btc-signer/musig2");
1037
+ var DUST_LIMIT_SATS = 546n;
1038
+ function bytesEqual(a, b) {
1039
+ return a.length === b.length && a.every((x, i) => x === b[i]);
1040
+ }
1041
+ function buildRecoverySpend(params) {
1042
+ const {
1043
+ cohortKeys,
1044
+ recoverySecretKey,
1045
+ recoveryKey,
1046
+ recoverySequence,
1047
+ fallbackThreshold,
1048
+ fundingModel,
1049
+ network,
1050
+ utxo,
1051
+ destinationAddress,
1052
+ fee,
1053
+ beaconAddress
1054
+ } = params;
1055
+ if (cohortKeys.length === 0) {
1056
+ throw new AggregationCohortError(
1057
+ "Cannot build recovery spend: no cohort keys.",
1058
+ "NO_COHORT_KEYS"
1059
+ );
1060
+ }
1061
+ const derivedPub = import_secp256k13.schnorr.getPublicKey(recoverySecretKey);
1062
+ if (!bytesEqual(derivedPub, recoveryKey)) {
1063
+ throw new AggregationCohortError(
1064
+ "Recovery secret key does not correspond to the committed recovery key.",
1065
+ "RECOVERY_KEY_MISMATCH"
1066
+ );
1067
+ }
1068
+ const out = utxo.value - fee;
1069
+ if (out <= 0n) {
1070
+ throw new AggregationCohortError(
1071
+ `Recovery fee ${fee} exceeds UTXO value ${utxo.value}.`,
1072
+ "FEE_EXCEEDS_VALUE",
1073
+ { fee: fee.toString(), value: utxo.value.toString() }
1074
+ );
1075
+ }
1076
+ if (out < DUST_LIMIT_SATS) {
1077
+ throw new AggregationCohortError(
1078
+ `Recovered output ${out} is below the dust limit ${DUST_LIMIT_SATS}; the spend would not relay.`,
1079
+ "DUST_OUTPUT",
1080
+ { output: out.toString(), dustLimit: DUST_LIMIT_SATS.toString() }
1081
+ );
1082
+ }
1083
+ const internalKey = (0, import_musig23.keyAggExport)((0, import_musig23.keyAggregate)((0, import_musig23.sortKeys)(cohortKeys)));
1084
+ const leaves = buildRecoveryLeaves(fundingModel ?? DEFAULT_FUNDING_MODEL, {
1085
+ recoveryKey,
1086
+ recoverySequence,
1087
+ cohortKeys,
1088
+ fallbackThreshold: resolveFallbackThreshold(fallbackThreshold, cohortKeys.length)
1089
+ });
1090
+ const net = (0, import_bitcoin2.getNetwork)(network);
1091
+ const payment = (0, import_btc_signer4.p2tr)(internalKey, leaves, net, true);
1092
+ if (beaconAddress !== void 0 && payment.address !== beaconAddress) {
1093
+ throw new AggregationCohortError(
1094
+ `Reconstructed beacon address ${payment.address} does not match the cohort's funded address ${beaconAddress}.`,
1095
+ "BEACON_ADDRESS_MISMATCH",
1096
+ { reconstructed: payment.address, expected: beaconAddress }
1097
+ );
1098
+ }
1099
+ const tx = new import_btc_signer4.Transaction({ version: 2, allowUnknownInputs: true });
1100
+ tx.addInput({
1101
+ txid: utxo.txid,
1102
+ index: utxo.vout,
1103
+ witnessUtxo: { script: payment.script, amount: utxo.value },
1104
+ tapLeafScript: payment.tapLeafScript,
1105
+ sequence: recoverySequence
1106
+ });
1107
+ tx.addOutputAddress(destinationAddress, out, net);
1108
+ tx.signIdx(recoverySecretKey, 0);
1109
+ tx.finalize();
1110
+ return tx;
1111
+ }
1112
+
1113
+ // src/core/fallback-spend.ts
1114
+ var import_bitcoin3 = require("@did-btcr2/bitcoin");
1115
+ var import_secp256k14 = require("@noble/curves/secp256k1.js");
1116
+ var import_btc_signer5 = require("@scure/btc-signer");
1117
+ var import_musig24 = require("@scure/btc-signer/musig2");
1118
+ function bytesEqual2(a, b) {
1119
+ return a.length === b.length && a.every((x, i) => x === b[i]);
1120
+ }
1121
+ function fallbackSighash(tx, inputIndex, prevOutScript, prevOutValue, fallbackLeafScript) {
1122
+ return tx.preimageWitnessV1(
1123
+ inputIndex,
1124
+ [prevOutScript],
1125
+ import_btc_signer5.SigHash.DEFAULT,
1126
+ [prevOutValue],
1127
+ void 0,
1128
+ fallbackLeafScript,
1129
+ TAPROOT_LEAF_VERSION
1130
+ );
1131
+ }
1132
+ function buildFallbackSpend(params) {
1133
+ const {
1134
+ pendingTx,
1135
+ cohortKeys,
1136
+ recoveryKey,
1137
+ recoverySequence,
1138
+ fundingModel,
1139
+ network,
1140
+ prevOutScript,
1141
+ prevOutValue,
1142
+ signatures
1143
+ } = params;
1144
+ const inputIndex = params.inputIndex ?? 0;
1145
+ if (cohortKeys.length === 0) {
1146
+ throw new AggregationCohortError(
1147
+ "Cannot build fallback spend: no cohort keys.",
1148
+ "NO_COHORT_KEYS"
1149
+ );
1150
+ }
1151
+ const fallbackThreshold = resolveFallbackThreshold(params.fallbackThreshold, cohortKeys.length);
1152
+ const internalKey = (0, import_musig24.keyAggExport)((0, import_musig24.keyAggregate)((0, import_musig24.sortKeys)(cohortKeys)));
1153
+ const leaves = buildRecoveryLeaves(fundingModel ?? DEFAULT_FUNDING_MODEL, {
1154
+ recoveryKey,
1155
+ recoverySequence,
1156
+ cohortKeys,
1157
+ fallbackThreshold
1158
+ });
1159
+ const net = (0, import_bitcoin3.getNetwork)(network);
1160
+ const payment = (0, import_btc_signer5.p2tr)(internalKey, leaves, net, true);
1161
+ if (!bytesEqual2(payment.script, prevOutScript)) {
1162
+ throw new AggregationCohortError(
1163
+ "Reconstructed beacon output script does not match the spent prevout script.",
1164
+ "PREVOUT_SCRIPT_MISMATCH"
1165
+ );
1166
+ }
1167
+ const fallbackLeaf = buildFallbackLeaf({ cohortKeys, fallbackThreshold });
1168
+ const leafEntry = payment.tapLeafScript?.find(([, scriptVer]) => {
1169
+ const script = scriptVer.slice(0, scriptVer.length - 1);
1170
+ return bytesEqual2(script, fallbackLeaf);
1171
+ });
1172
+ if (!leafEntry) {
1173
+ throw new AggregationCohortError(
1174
+ "Could not locate the fallback leaf in the reconstructed beacon output.",
1175
+ "FALLBACK_LEAF_NOT_FOUND"
1176
+ );
1177
+ }
1178
+ const cohortXOnly = (0, import_musig24.sortKeys)(cohortKeys).map((k) => k.slice(1));
1179
+ const tx = pendingTx;
1180
+ const sighash = fallbackSighash(tx, inputIndex, prevOutScript, prevOutValue, fallbackLeaf);
1181
+ const leafHash = tapLeafHash(fallbackLeaf);
1182
+ const accepted = /* @__PURE__ */ new Map();
1183
+ for (const { pubKey, signature } of signatures) {
1184
+ if (pubKey.length !== 32 || signature.length !== 64) continue;
1185
+ const isCohortKey = cohortXOnly.some((k) => bytesEqual2(k, pubKey));
1186
+ if (!isCohortKey) continue;
1187
+ const hex = Array.from(pubKey, (b) => b.toString(16).padStart(2, "0")).join("");
1188
+ if (accepted.has(hex)) continue;
1189
+ let ok = false;
1190
+ try {
1191
+ ok = import_secp256k14.schnorr.verify(signature, sighash, pubKey);
1192
+ } catch {
1193
+ ok = false;
1194
+ }
1195
+ if (ok) accepted.set(hex, signature);
1196
+ }
1197
+ if (accepted.size < fallbackThreshold) {
1198
+ throw new AggregationCohortError(
1199
+ `Not enough valid fallback signatures: have ${accepted.size}, need ${fallbackThreshold}.`,
1200
+ "NOT_ENOUGH_FALLBACK_SIGNATURES",
1201
+ { have: accepted.size, need: fallbackThreshold }
1202
+ );
1203
+ }
1204
+ const chosen = cohortXOnly.filter((k) => accepted.has(Array.from(k, (b) => b.toString(16).padStart(2, "0")).join(""))).slice(0, fallbackThreshold);
1205
+ tx.updateInput(inputIndex, {
1206
+ tapLeafScript: [leafEntry],
1207
+ tapScriptSig: chosen.map((pubKey) => {
1208
+ const hex = Array.from(pubKey, (b) => b.toString(16).padStart(2, "0")).join("");
1209
+ return [{ pubKey, leafHash }, accepted.get(hex)];
1210
+ })
1211
+ });
1212
+ tx.finalize();
1213
+ return tx;
1214
+ }
1215
+
1216
+ // src/core/typed-emitter.ts
1217
+ var TypedEventEmitter = class {
1218
+ #listeners = /* @__PURE__ */ new Map();
1219
+ /** Subscribe to an event. */
1220
+ on(event, listener) {
1221
+ let set = this.#listeners.get(event);
1222
+ if (!set) {
1223
+ set = /* @__PURE__ */ new Set();
1224
+ this.#listeners.set(event, set);
1225
+ }
1226
+ set.add(listener);
1227
+ return this;
1228
+ }
1229
+ /** Subscribe to an event, automatically unsubscribing after the first call. */
1230
+ once(event, listener) {
1231
+ const wrapped = ((...args) => {
1232
+ this.off(event, wrapped);
1233
+ listener(...args);
1234
+ });
1235
+ return this.on(event, wrapped);
1236
+ }
1237
+ /** Unsubscribe a specific listener. */
1238
+ off(event, listener) {
1239
+ this.#listeners.get(event)?.delete(listener);
1240
+ return this;
1241
+ }
1242
+ /** Emit an event to all subscribed listeners. */
1243
+ emit(event, ...args) {
1244
+ const set = this.#listeners.get(event);
1245
+ if (!set || set.size === 0) return false;
1246
+ for (const listener of set) {
1247
+ try {
1248
+ listener(...args);
1249
+ } catch (err) {
1250
+ console.error(`Listener for event "${String(event)}" threw:`, err);
1251
+ }
1252
+ }
1253
+ return true;
1254
+ }
1255
+ /** Remove all listeners (optionally for a specific event). */
1256
+ removeAllListeners(event) {
1257
+ if (event === void 0) {
1258
+ this.#listeners.clear();
1259
+ } else {
1260
+ this.#listeners.delete(event);
1261
+ }
1262
+ return this;
1263
+ }
1264
+ /** Number of listeners for an event. */
1265
+ listenerCount(event) {
1266
+ return this.#listeners.get(event)?.size ?? 0;
1267
+ }
1268
+ };
1269
+
1270
+ // src/core/messages/base.ts
1271
+ var AGGREGATION_WIRE_VERSION = 1;
1272
+ var BaseMessage = class {
1273
+ type;
1274
+ version;
1275
+ to;
1276
+ from;
1277
+ body;
1278
+ constructor({ type, version, to, from, body }) {
1279
+ this.type = type;
1280
+ this.version = version ?? AGGREGATION_WIRE_VERSION;
1281
+ this.to = to;
1282
+ this.from = from;
1283
+ this.body = body;
1284
+ }
1285
+ /**
1286
+ * Converts a BaseMessage to a JSON object.
1287
+ * @returns {Base} The JSON representation of the BaseMessage.
1288
+ */
1289
+ toJSON() {
1290
+ return {
1291
+ type: this.type,
1292
+ version: this.version,
1293
+ to: this.to,
1294
+ from: this.from,
1295
+ body: this.body
1296
+ };
1297
+ }
1298
+ };
1299
+
1300
+ // src/core/messages/constants.ts
1301
+ var AGGREGATION_MESSAGE_PREFIX = "https://btcr2.dev/aggregation";
1302
+ var COHORT_ADVERT = `${AGGREGATION_MESSAGE_PREFIX}/keygen/cohort_advert`;
1303
+ var COHORT_OPT_IN = `${AGGREGATION_MESSAGE_PREFIX}/keygen/cohort_opt_in`;
1304
+ var COHORT_OPT_IN_ACCEPT = `${AGGREGATION_MESSAGE_PREFIX}/keygen/cohort_opt_in_accept`;
1305
+ var COHORT_READY = `${AGGREGATION_MESSAGE_PREFIX}/keygen/cohort_ready`;
1306
+ var SUBMIT_UPDATE = `${AGGREGATION_MESSAGE_PREFIX}/update/submit_update`;
1307
+ var SUBMIT_NONINCLUDED = `${AGGREGATION_MESSAGE_PREFIX}/update/submit_nonincluded`;
1308
+ var DISTRIBUTE_AGGREGATED_DATA = `${AGGREGATION_MESSAGE_PREFIX}/update/distribute_aggregated_data`;
1309
+ var VALIDATION_ACK = `${AGGREGATION_MESSAGE_PREFIX}/update/validation_ack`;
1310
+ var AUTHORIZATION_REQUEST = `${AGGREGATION_MESSAGE_PREFIX}/sign/authorization_request`;
1311
+ var NONCE_CONTRIBUTION = `${AGGREGATION_MESSAGE_PREFIX}/sign/nonce_contribution`;
1312
+ var AGGREGATED_NONCE = `${AGGREGATION_MESSAGE_PREFIX}/sign/aggregated_nonce`;
1313
+ var SIGNATURE_AUTHORIZATION = `${AGGREGATION_MESSAGE_PREFIX}/sign/signature_authorization`;
1314
+ var FALLBACK_AUTHORIZATION_REQUEST = `${AGGREGATION_MESSAGE_PREFIX}/sign/fallback_authorization_request`;
1315
+ var FALLBACK_SIGNATURE = `${AGGREGATION_MESSAGE_PREFIX}/sign/fallback_signature`;
1316
+
1317
+ // src/core/messages/bodies.ts
1318
+ var hasStr = (b, k) => !!b && typeof b[k] === "string";
1319
+ var hasIntMin = (b, k, min) => {
1320
+ const v = b ? b[k] : void 0;
1321
+ return typeof v === "number" && Number.isInteger(v) && v >= min;
1322
+ };
1323
+ var optIntMin = (b, k, min) => {
1324
+ const v = b ? b[k] : void 0;
1325
+ return v === void 0 || typeof v === "number" && Number.isInteger(v) && v >= min;
1326
+ };
1327
+ var intInRange = (b, k, min, max) => {
1328
+ const v = b ? b[k] : void 0;
1329
+ return typeof v === "number" && Number.isInteger(v) && v >= min && v <= max;
1330
+ };
1331
+ var optStrOneOf = (b, k, allowed) => {
1332
+ const v = b ? b[k] : void 0;
1333
+ return v === void 0 || typeof v === "string" && allowed.includes(v);
1334
+ };
1335
+ var hasBool = (b, k) => !!b && typeof b[k] === "boolean";
1336
+ var hasBytes = (b, k) => !!b && b[k] instanceof Uint8Array;
1337
+ var hasBytesArray = (b, k) => {
1338
+ const v = b ? b[k] : void 0;
1339
+ return Array.isArray(v) && v.every((x) => x instanceof Uint8Array);
1340
+ };
1341
+ function isCohortAdvertMessage(m) {
1342
+ return m.type === COHORT_ADVERT && hasStr(m.body, "cohortId") && hasIntMin(m.body, "minParticipants", 1) && optIntMin(m.body, "maxParticipants", 1) && hasStr(m.body, "beaconType") && hasStr(m.body, "network") && hasStr(m.body, "recoveryKey") && intInRange(m.body, "recoverySequence", 1, MAX_RECOVERY_SEQUENCE) && optStrOneOf(m.body, "fundingModel", KNOWN_FUNDING_MODELS) && optIntMin(m.body, "fallbackThreshold", 1) && hasBytes(m.body, "communicationPk");
1343
+ }
1344
+ function isCohortOptInMessage(m) {
1345
+ return m.type === COHORT_OPT_IN && hasStr(m.body, "cohortId") && hasBytes(m.body, "participantPk") && hasBytes(m.body, "communicationPk");
1346
+ }
1347
+ function isCohortOptInAcceptMessage(m) {
1348
+ return m.type === COHORT_OPT_IN_ACCEPT && hasStr(m.body, "cohortId");
1349
+ }
1350
+ function isCohortReadyMessage(m) {
1351
+ return m.type === COHORT_READY && hasStr(m.body, "cohortId") && hasStr(m.body, "beaconAddress") && hasBytesArray(m.body, "cohortKeys");
1352
+ }
1353
+ function isSubmitUpdateMessage(m) {
1354
+ return m.type === SUBMIT_UPDATE && hasStr(m.body, "cohortId") && !!m.body && typeof m.body.signedUpdate === "object";
1355
+ }
1356
+ function isSubmitNonIncludedMessage(m) {
1357
+ return m.type === SUBMIT_NONINCLUDED && hasStr(m.body, "cohortId");
1358
+ }
1359
+ function isDistributeAggregatedDataMessage(m) {
1360
+ return m.type === DISTRIBUTE_AGGREGATED_DATA && hasStr(m.body, "cohortId") && hasStr(m.body, "beaconType") && hasStr(m.body, "signalBytesHex");
1361
+ }
1362
+ function isValidationAckMessage(m) {
1363
+ return m.type === VALIDATION_ACK && hasStr(m.body, "cohortId") && hasBool(m.body, "approved");
1364
+ }
1365
+ function isAuthorizationRequestMessage(m) {
1366
+ return m.type === AUTHORIZATION_REQUEST && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasStr(m.body, "pendingTx") && hasStr(m.body, "prevOutScriptHex") && hasStr(m.body, "prevOutValue");
1367
+ }
1368
+ function isNonceContributionMessage(m) {
1369
+ return m.type === NONCE_CONTRIBUTION && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "nonceContribution");
1370
+ }
1371
+ function isAggregatedNonceMessage(m) {
1372
+ return m.type === AGGREGATED_NONCE && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "aggregatedNonce");
1373
+ }
1374
+ function isSignatureAuthorizationMessage(m) {
1375
+ return m.type === SIGNATURE_AUTHORIZATION && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "partialSignature");
1376
+ }
1377
+ function isFallbackAuthorizationRequestMessage(m) {
1378
+ return m.type === FALLBACK_AUTHORIZATION_REQUEST && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasStr(m.body, "pendingTx") && hasStr(m.body, "prevOutScriptHex") && hasStr(m.body, "prevOutValue") && hasStr(m.body, "fallbackLeafScriptHex");
1379
+ }
1380
+ function isFallbackSignatureMessage(m) {
1381
+ return m.type === FALLBACK_SIGNATURE && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "signerPk") && hasBytes(m.body, "fallbackSignature");
1382
+ }
1383
+
1384
+ // src/core/messages/factories.ts
1385
+ function createCohortAdvertMessage(fields) {
1386
+ const { from, ...body } = fields;
1387
+ return new BaseMessage({ type: COHORT_ADVERT, from, body });
1388
+ }
1389
+ function createCohortOptInMessage(fields) {
1390
+ const { from, to, ...body } = fields;
1391
+ return new BaseMessage({ type: COHORT_OPT_IN, from, to, body });
1392
+ }
1393
+ function createCohortOptInAcceptMessage(fields) {
1394
+ const { from, to, ...body } = fields;
1395
+ return new BaseMessage({ type: COHORT_OPT_IN_ACCEPT, from, to, body });
1396
+ }
1397
+ function createCohortReadyMessage(fields) {
1398
+ const { from, to, ...body } = fields;
1399
+ return new BaseMessage({ type: COHORT_READY, from, to, body });
1400
+ }
1401
+ function createSubmitUpdateMessage(fields) {
1402
+ const { from, to, ...body } = fields;
1403
+ return new BaseMessage({ type: SUBMIT_UPDATE, from, to, body });
1404
+ }
1405
+ function createSubmitNonIncludedMessage(fields) {
1406
+ const { from, to, ...body } = fields;
1407
+ return new BaseMessage({ type: SUBMIT_NONINCLUDED, from, to, body });
1408
+ }
1409
+ function createDistributeAggregatedDataMessage(fields) {
1410
+ const { from, to, ...body } = fields;
1411
+ return new BaseMessage({ type: DISTRIBUTE_AGGREGATED_DATA, from, to, body });
1412
+ }
1413
+ function createValidationAckMessage(fields) {
1414
+ const { from, to, ...body } = fields;
1415
+ return new BaseMessage({ type: VALIDATION_ACK, from, to, body });
1416
+ }
1417
+ function createAuthorizationRequestMessage(fields) {
1418
+ const { from, to, ...body } = fields;
1419
+ return new BaseMessage({ type: AUTHORIZATION_REQUEST, from, to, body });
1420
+ }
1421
+ function createNonceContributionMessage(fields) {
1422
+ const { from, to, ...body } = fields;
1423
+ return new BaseMessage({ type: NONCE_CONTRIBUTION, from, to, body });
1424
+ }
1425
+ function createAggregatedNonceMessage(fields) {
1426
+ const { from, to, ...body } = fields;
1427
+ return new BaseMessage({ type: AGGREGATED_NONCE, from, to, body });
1428
+ }
1429
+ function createSignatureAuthorizationMessage(fields) {
1430
+ const { from, to, ...body } = fields;
1431
+ return new BaseMessage({ type: SIGNATURE_AUTHORIZATION, from, to, body });
1432
+ }
1433
+ function createFallbackAuthorizationRequestMessage(fields) {
1434
+ const { from, to, ...body } = fields;
1435
+ return new BaseMessage({ type: FALLBACK_AUTHORIZATION_REQUEST, from, to, body });
1436
+ }
1437
+ function createFallbackSignatureMessage(fields) {
1438
+ const { from, to, ...body } = fields;
1439
+ return new BaseMessage({ type: FALLBACK_SIGNATURE, from, to, body });
1440
+ }
1441
+
1442
+ // src/core/messages/guards.ts
1443
+ var KEYGEN_VALUES = /* @__PURE__ */ new Set([
1444
+ COHORT_ADVERT,
1445
+ COHORT_OPT_IN,
1446
+ COHORT_OPT_IN_ACCEPT,
1447
+ COHORT_READY
1448
+ ]);
1449
+ var UPDATE_VALUES = /* @__PURE__ */ new Set([
1450
+ SUBMIT_UPDATE,
1451
+ SUBMIT_NONINCLUDED,
1452
+ DISTRIBUTE_AGGREGATED_DATA,
1453
+ VALIDATION_ACK
1454
+ ]);
1455
+ var SIGN_VALUES = /* @__PURE__ */ new Set([
1456
+ AUTHORIZATION_REQUEST,
1457
+ NONCE_CONTRIBUTION,
1458
+ AGGREGATED_NONCE,
1459
+ SIGNATURE_AUTHORIZATION,
1460
+ FALLBACK_AUTHORIZATION_REQUEST,
1461
+ FALLBACK_SIGNATURE
1462
+ ]);
1463
+ function isAggregationMessageType(type) {
1464
+ return KEYGEN_VALUES.has(type) || UPDATE_VALUES.has(type) || SIGN_VALUES.has(type);
1465
+ }
1466
+ function isKeygenMessageType(type) {
1467
+ return KEYGEN_VALUES.has(type);
1468
+ }
1469
+ function isUpdateMessageType(type) {
1470
+ return UPDATE_VALUES.has(type);
1471
+ }
1472
+ function isSignMessageType(type) {
1473
+ return SIGN_VALUES.has(type);
1474
+ }
1475
+
1476
+ // src/core/transport/error.ts
1477
+ var import_common4 = require("@did-btcr2/common");
1478
+ var TransportError = class extends import_common4.MethodError {
1479
+ constructor(message, type = "TransportError", data) {
1480
+ super(message, type, data);
1481
+ }
1482
+ };
1483
+ var TransportAdapterError = class extends import_common4.MethodError {
1484
+ constructor(message, type = "TransportAdapterError", data) {
1485
+ super(message, type, data);
1486
+ }
1487
+ };
1488
+
1489
+ // src/core/transport/in-memory.ts
1490
+ var import_utils3 = require("@noble/hashes/utils");
1491
+ var InMemoryBus = class {
1492
+ #transports = /* @__PURE__ */ new Set();
1493
+ /** Attach a transport to this bus. Called by the transport's constructor. */
1494
+ register(transport) {
1495
+ this.#transports.add(transport);
1496
+ }
1497
+ /** Detach a transport from this bus. */
1498
+ unregister(transport) {
1499
+ this.#transports.delete(transport);
1500
+ }
1501
+ /**
1502
+ * Deliver a message. With no `recipient` the message is broadcast to every
1503
+ * actor on the bus; otherwise it is routed to the single transport that owns
1504
+ * the recipient DID.
1505
+ */
1506
+ async deliver(message, _sender, recipient) {
1507
+ const type = message.type;
1508
+ if (!type) return;
1509
+ const replacer = (_k, v) => v instanceof Uint8Array ? { __bytes: (0, import_utils3.bytesToHex)(v) } : v;
1510
+ const reviver = (_k, v) => v && typeof v === "object" && "__bytes" in v ? (0, import_utils3.hexToBytes)(v.__bytes) : v;
1511
+ const raw = JSON.parse(JSON.stringify(message, replacer), reviver);
1512
+ const serialized = { ...raw, ...raw.body ?? {} };
1513
+ if (!recipient) {
1514
+ for (const t of this.#transports) {
1515
+ await t.dispatchBroadcast(type, serialized);
1516
+ }
1517
+ return;
1518
+ }
1519
+ for (const t of this.#transports) {
1520
+ if (t.hasActor(recipient)) {
1521
+ await t.dispatchDirected(recipient, type, serialized);
1522
+ return;
1523
+ }
1524
+ }
1525
+ }
1526
+ };
1527
+ var InMemoryTransport = class {
1528
+ name = "in-memory";
1529
+ bus;
1530
+ #actors = /* @__PURE__ */ new Map();
1531
+ #peers = /* @__PURE__ */ new Map();
1532
+ /** @param bus Shared bus. Pass the same bus to connect multiple transports. */
1533
+ constructor(bus = new InMemoryBus()) {
1534
+ this.bus = bus;
1535
+ this.bus.register(this);
1536
+ }
1537
+ start() {
1538
+ }
1539
+ registerActor(did, keys) {
1540
+ this.#actors.set(did, { publicKey: keys.publicKey.compressed, handlers: /* @__PURE__ */ new Map() });
1541
+ }
1542
+ getActorPk(did) {
1543
+ return this.#actors.get(did)?.publicKey;
1544
+ }
1545
+ /** True if `did` is registered on this transport. Used by the bus for routing. */
1546
+ hasActor(did) {
1547
+ return this.#actors.has(did);
1548
+ }
1549
+ registerPeer(did, communicationPk) {
1550
+ this.#peers.set(did, communicationPk);
1551
+ }
1552
+ getPeerPk(did) {
1553
+ return this.#peers.get(did);
1554
+ }
1555
+ registerMessageHandler(actorDid, messageType, handler) {
1556
+ const actor = this.#actors.get(actorDid);
1557
+ if (actor) actor.handlers.set(messageType, handler);
1558
+ }
1559
+ unregisterMessageHandler(actorDid, messageType) {
1560
+ const actor = this.#actors.get(actorDid);
1561
+ if (actor) actor.handlers.delete(messageType);
1562
+ }
1563
+ unregisterActor(did) {
1564
+ const actor = this.#actors.get(did);
1565
+ if (!actor) return;
1566
+ actor.handlers.clear();
1567
+ this.#actors.delete(did);
1568
+ this.#peers.delete(did);
1569
+ }
1570
+ async sendMessage(message, sender, recipient) {
1571
+ await this.bus.deliver(message, sender, recipient);
1572
+ }
1573
+ publishRepeating(message, sender, intervalMs, recipient) {
1574
+ let stopped = false;
1575
+ void this.sendMessage(message, sender, recipient).catch(() => {
1576
+ });
1577
+ const timer = setInterval(() => {
1578
+ if (stopped) return;
1579
+ void this.sendMessage(message, sender, recipient).catch(() => {
1580
+ });
1581
+ }, intervalMs);
1582
+ return () => {
1583
+ if (stopped) return;
1584
+ stopped = true;
1585
+ clearInterval(timer);
1586
+ };
1587
+ }
1588
+ /** Deliver a broadcast message to every actor on this transport that handles `type`. */
1589
+ async dispatchBroadcast(type, message) {
1590
+ for (const actor of this.#actors.values()) {
1591
+ const handler = actor.handlers.get(type);
1592
+ if (handler) await handler(message);
1593
+ }
1594
+ }
1595
+ /** Deliver a directed message to the recipient actor's handler for `type`. */
1596
+ async dispatchDirected(recipientDid, type, message) {
1597
+ const handler = this.#actors.get(recipientDid)?.handlers.get(type);
1598
+ if (handler) await handler(message);
1599
+ }
1600
+ };
1601
+
1602
+ // src/core/transport/nostr.ts
1603
+ var import_keypair3 = require("@did-btcr2/keypair");
1604
+ var import_utils4 = require("@noble/hashes/utils");
1605
+ var import_nostr_tools = require("nostr-tools");
1606
+ var import_pool = require("nostr-tools/pool");
1607
+ var DEFAULT_NOSTR_RELAYS = [
1608
+ "wss://relay.damus.io",
1609
+ "wss://nos.lol",
1610
+ "wss://relay.snort.social",
1611
+ "wss://nostr-pub.wellorder.net"
1612
+ ];
1613
+ var DEFAULT_BROADCAST_LOOKBACK_MS = 5 * 60 * 1e3;
1614
+ var NostrTransport = class _NostrTransport {
1615
+ name = "nostr";
1616
+ pool;
1617
+ #relays;
1618
+ #actors = /* @__PURE__ */ new Map();
1619
+ #peerRegistry = /* @__PURE__ */ new Map();
1620
+ #started = false;
1621
+ #logger;
1622
+ #broadcastLookbackMs;
1623
+ constructor(config) {
1624
+ this.#relays = config?.relays ?? DEFAULT_NOSTR_RELAYS;
1625
+ this.#logger = config?.logger ?? CONSOLE_LOGGER;
1626
+ this.#broadcastLookbackMs = config?.broadcastLookbackMs ?? DEFAULT_BROADCAST_LOOKBACK_MS;
1627
+ }
1628
+ /**
1629
+ * Registers an actor (DID + keys) to send/receive messages with.
1630
+ * Must be called before start() to ensure subscriptions are created for the actor.
1631
+ * @param {string} did - The DID of the actor.
1632
+ * @param {SchnorrKeyPair} keys - The Schnorr key pair for the actor.
1633
+ * @throws {TransportAdapterError} If the actor is already registered or if the transport has already started.
1634
+ * @example
1635
+ * const transport = new NostrTransport();
1636
+ * const keys = SchnorrKeyPair.generate();
1637
+ * const did = DidBtcr2.create(keys.publicKey.compressed, { idType: 'KEY', network: 'mutinynet' });
1638
+ * transport.registerActor(did, keys);
1639
+ * transport.start();
1640
+ */
1641
+ registerActor(did, keys) {
1642
+ const entry = { keys, handlers: /* @__PURE__ */ new Map(), subscriptions: [] };
1643
+ this.#actors.set(did, entry);
1644
+ if (this.#started && this.pool) {
1645
+ this.#subscribeDirected(did, entry);
1646
+ }
1647
+ }
1648
+ /**
1649
+ * Detach an actor: drop its handlers, close its relay subscriptions, and remove its keys + peer
1650
+ * mapping. Idempotent.
1651
+ * @param {string} did - The DID of the actor to unregister.
1652
+ * @returns {void}
1653
+ * @throws {TransportAdapterError} If the transport is not started or if the pool is unavailable.
1654
+ * @example
1655
+ * transport.unregisterActor(did);
1656
+ */
1657
+ unregisterActor(did) {
1658
+ const entry = this.#actors.get(did);
1659
+ if (!entry) return;
1660
+ for (const sub of entry.subscriptions) {
1661
+ try {
1662
+ sub.close();
1663
+ } catch (err) {
1664
+ this.#logger.debug(`Error closing subscription for ${did}:`, err);
1665
+ }
1666
+ }
1667
+ entry.subscriptions.length = 0;
1668
+ entry.handlers.clear();
1669
+ this.#actors.delete(did);
1670
+ this.#peerRegistry.delete(did);
1671
+ }
1672
+ /**
1673
+ * Remove a single (actor, messageType) handler. Idempotent.
1674
+ * @param {string} actorDid - The DID of the actor.
1675
+ * @param {string} messageType - The type of message to unregister the handler for.
1676
+ * @returns {void}
1677
+ * @example
1678
+ * transport.unregisterMessageHandler(actorDid, messageType);
1679
+ */
1680
+ unregisterMessageHandler(actorDid, messageType) {
1681
+ const actor = this.#actors.get(actorDid);
1682
+ if (!actor) return;
1683
+ actor.handlers.delete(messageType);
1684
+ }
1685
+ /**
1686
+ * Gets the public key for a registered actor by their DID.
1687
+ * @param {string} did - The DID of the registered actor to get the public key for.
1688
+ * @returns {Uint8Array | undefined} The compressed public key bytes for the actor's DID, or
1689
+ * undefined if the DID is not registered.
1690
+ */
1691
+ getActorPk(did) {
1692
+ return this.#actors.get(did)?.keys.publicKey.compressed;
1693
+ }
1694
+ /**
1695
+ * Registers a peer's communication public key for encrypted messages.
1696
+ * @param {string} did - The DID of the peer to register.
1697
+ * @param {Uint8Array} communicationPk - The compressed secp256k1 public key bytes for the peer.
1698
+ */
1699
+ registerPeer(did, communicationPk) {
1700
+ try {
1701
+ new import_keypair3.CompressedSecp256k1PublicKey(communicationPk);
1702
+ } catch {
1703
+ throw new TransportAdapterError(
1704
+ `Invalid communication public key for peer ${did}: expected a 33-byte compressed secp256k1 key.`,
1705
+ "INVALID_PEER_KEY",
1706
+ { adapter: this.name, did, keyLength: communicationPk.length }
1707
+ );
1708
+ }
1709
+ this.#peerRegistry.set(did, communicationPk);
1710
+ }
1711
+ /**
1712
+ * Gets the registered communication public key for a peer by their DID.
1713
+ * @param {string} did - The DID of the peer to get the communication public key for.
1714
+ * @returns {Uint8Array | undefined} The compressed secp256k1 public key bytes for the peer, or
1715
+ * undefined if the peer is not registered.
1716
+ */
1717
+ getPeerPk(did) {
1718
+ return this.#peerRegistry.get(did);
1719
+ }
1720
+ /**
1721
+ * Registers a message handler function for a specific actor and message type. The handler will be called
1722
+ * when a message of the specified type is received for the actor's DID. The transport must have been
1723
+ * started for handlers to be invoked. If the transport is already started, the handler will be registered
1724
+ * immediately; otherwise, it will be registered when the transport starts and the actor's subscription is created.
1725
+ * @param {string} actorDid - The DID of the actor to register the message handler for.
1726
+ * @param {string} messageType - The type of message to handle.
1727
+ * @param {MessageHandler} handler - The function to handle incoming messages of the specified type.
1728
+ * @throws {TransportAdapterError} If the actor DID is not registered or if the handler is invalid.
1729
+ */
1730
+ registerMessageHandler(actorDid, messageType, handler) {
1731
+ const actor = this.#actors.get(actorDid);
1732
+ if (!actor) {
1733
+ throw new TransportAdapterError(
1734
+ `Cannot register handler: actor ${actorDid} not registered. Call registerActor() first.`,
1735
+ "UNKNOWN_ACTOR_ERROR",
1736
+ { adapter: this.name, did: actorDid }
1737
+ );
1738
+ }
1739
+ actor.handlers.set(messageType, handler);
1740
+ }
1741
+ /**
1742
+ * Starts the transport by connecting to the configured Nostr relays and setting up subscriptions
1743
+ * for all registered actors. This method must be called after registering actors via registerActor()
1744
+ * and before sending or receiving messages. The transport will subscribe to broadcast events (kind 1)
1745
+ * for cohort adverts and directed events (kinds 1 and 1059) for each registered actor based on their
1746
+ * public keys. Incoming events are processed and dispatched to the appropriate handlers based on
1747
+ * message type. If the transport is already started, this method has no effect.
1748
+ * @returns {NostrTransport}
1749
+ */
1750
+ start() {
1751
+ if (this.#started) return this;
1752
+ this.#started = true;
1753
+ this.pool = new import_pool.SimplePool();
1754
+ const broadcastFilter = {
1755
+ kinds: [1],
1756
+ "#t": [COHORT_ADVERT]
1757
+ };
1758
+ if (this.#broadcastLookbackMs > 0) {
1759
+ broadcastFilter.since = Math.floor((Date.now() - this.#broadcastLookbackMs) / 1e3);
1760
+ }
1761
+ this.pool.subscribeMany(this.#relays, broadcastFilter, {
1762
+ onclose: (reasons) => this.#logger.debug("Nostr broadcast subscription closed", reasons),
1763
+ onevent: this.#handleBroadcastEvent.bind(this)
1764
+ });
1765
+ for (const [did, entry] of this.#actors) {
1766
+ this.#subscribeDirected(did, entry);
1767
+ }
1768
+ this.#logger.info(`NostrTransport started, listening on ${this.#relays.length} relay(s)`);
1769
+ return this;
1770
+ }
1771
+ /**
1772
+ * Sends a message by publishing a Nostr event to the configured relays. The message is serialized
1773
+ * as JSON and included in the event content.
1774
+ * @param {BaseMessage} message - The aggregation message to send. Must include a valid `type` property.
1775
+ * @param {Did} sender - The DID of the registered actor sending the message. Must have been
1776
+ * registered via registerActor().
1777
+ * @param {Did} [to] - Optional recipient DID for directed messages. Required for encrypted message
1778
+ * types. If provided, must have been registered via registerPeer().
1779
+ * @returns {Promise<void>} Resolves when the message has been published to the relays. Note that
1780
+ * publication is best-effort: the method will resolve as long as at least one relay accepts the
1781
+ * event, even if others reject it.
1782
+ */
1783
+ async sendMessage(message, sender, to) {
1784
+ const type = message.type;
1785
+ if (!type) {
1786
+ throw new TransportAdapterError(
1787
+ "Message type is undefined",
1788
+ "SEND_MESSAGE_ERROR",
1789
+ { adapter: this.name, type }
1790
+ );
1791
+ }
1792
+ const actor = this.#actors.get(sender);
1793
+ if (!actor) {
1794
+ throw new TransportAdapterError(
1795
+ `Unknown sender: ${sender}. Call registerActor() before sending messages.`,
1796
+ "UNKNOWN_ACTOR_ERROR",
1797
+ { adapter: this.name, did: sender }
1798
+ );
1799
+ }
1800
+ const senderKeys = actor.keys;
1801
+ const tags = [
1802
+ ["p", (0, import_utils4.bytesToHex)(senderKeys.publicKey.x)],
1803
+ ["t", type]
1804
+ ];
1805
+ if (to) {
1806
+ const recipientPkBytes = this.#peerRegistry.get(to);
1807
+ if (recipientPkBytes) {
1808
+ const recipientPk = new import_keypair3.CompressedSecp256k1PublicKey(recipientPkBytes);
1809
+ tags.push(["p", (0, import_utils4.bytesToHex)(recipientPk.x)]);
1810
+ }
1811
+ }
1812
+ if (isKeygenMessageType(type)) {
1813
+ const event = (0, import_nostr_tools.finalizeEvent)({
1814
+ kind: 1,
1815
+ created_at: Math.floor(Date.now() / 1e3),
1816
+ tags,
1817
+ content: JSON.stringify(message, _NostrTransport.#jsonReplacer)
1818
+ }, senderKeys.secretKey.bytes);
1819
+ this.#logger.debug(`Publishing kind 1 [${type}]`);
1820
+ await this.#publishToRelays(event);
1821
+ return;
1822
+ }
1823
+ if (isUpdateMessageType(type) || isSignMessageType(type)) {
1824
+ if (!to) {
1825
+ throw new TransportAdapterError(
1826
+ `Encrypted messages require a recipient DID, got undefined for type: ${type}`,
1827
+ "SEND_MESSAGE_ERROR",
1828
+ { adapter: this.name }
1829
+ );
1830
+ }
1831
+ const recipientPkBytes = this.#peerRegistry.get(to);
1832
+ if (!recipientPkBytes) {
1833
+ throw new TransportAdapterError(
1834
+ `Unknown peer DID: ${to}. Register peer via registerPeer() before sending encrypted messages.`,
1835
+ "UNKNOWN_PEER_ERROR",
1836
+ { adapter: this.name, did: to }
1837
+ );
1838
+ }
1839
+ const recipientPk = new import_keypair3.CompressedSecp256k1PublicKey(recipientPkBytes);
1840
+ const conversationKey = import_nostr_tools.nip44.v2.utils.getConversationKey(
1841
+ senderKeys.secretKey.bytes,
1842
+ (0, import_utils4.bytesToHex)(recipientPk.x)
1843
+ );
1844
+ const content = import_nostr_tools.nip44.v2.encrypt(JSON.stringify(message, _NostrTransport.#jsonReplacer), conversationKey);
1845
+ const event = (0, import_nostr_tools.finalizeEvent)({
1846
+ kind: 1059,
1847
+ created_at: Math.floor(Date.now() / 1e3),
1848
+ tags,
1849
+ content
1850
+ }, senderKeys.secretKey.bytes);
1851
+ this.#logger.debug(`Publishing kind 1059 [${type}]`);
1852
+ await this.#publishToRelays(event);
1853
+ return;
1854
+ }
1855
+ this.#logger.warn(`Unsupported message type: ${type}`);
1856
+ }
1857
+ /**
1858
+ * Publish the message once immediately and then re-publish on an interval
1859
+ * until the returned stop function is invoked.
1860
+ *
1861
+ * Useful for broadcast messages (COHORT_ADVERT) on relays that don't
1862
+ * backfill historical events to late subscribers: republishing gives late
1863
+ * joiners a window to discover the message without requiring protocol
1864
+ * changes. Relay rate-limit / publish failures inside the interval are
1865
+ * caught and logged rather than propagated - the caller should stop the
1866
+ * repeater once the protocol condition is satisfied.
1867
+ */
1868
+ publishRepeating(message, sender, intervalMs, recipient) {
1869
+ let stopped = false;
1870
+ void this.sendMessage(message, sender, recipient).catch((err) => {
1871
+ this.#logger.debug("publishRepeating first send failed:", err);
1872
+ });
1873
+ const timer = setInterval(() => {
1874
+ if (stopped) return;
1875
+ void this.sendMessage(message, sender, recipient).catch((err) => {
1876
+ this.#logger.debug("publishRepeating retry failed:", err);
1877
+ });
1878
+ }, intervalMs);
1879
+ return () => {
1880
+ if (stopped) return;
1881
+ stopped = true;
1882
+ clearInterval(timer);
1883
+ };
1884
+ }
1885
+ /**
1886
+ * Creates a directed subscription for the given actor, filtering for messages that match the
1887
+ * actor's public key. Messages received on this subscription are dispatched to the actor's
1888
+ * registered handlers based on message type.
1889
+ * @param {string} did - The DID of the actor to create the subscription for.
1890
+ * @param {ActorEntry} entry - The actor's registration entry containing keys and handlers.
1891
+ * @returns {void}
1892
+ * @throws {TransportAdapterError} If the transport is not started or if the pool is unavailable.
1893
+ */
1894
+ #subscribeDirected(did, entry) {
1895
+ if (!this.pool) return;
1896
+ const pkHex = (0, import_utils4.bytesToHex)(entry.keys.publicKey.x);
1897
+ const sub = this.pool.subscribeMany(this.#relays, { kinds: [1, 1059], "#p": [pkHex] }, {
1898
+ onclose: (reasons) => this.#logger.debug(`Nostr directed subscription closed for ${did}`, reasons),
1899
+ onevent: this.#makeActorEventHandler(did)
1900
+ });
1901
+ entry.subscriptions.push(sub);
1902
+ }
1903
+ /**
1904
+ * Creates an event handler function for a specific actor that processes incoming events, decrypts
1905
+ * if necessary, and dispatches messages to the actor's registered handlers based on message type.
1906
+ * @param {string} actorDid - The DID of the actor to create the event handler for.
1907
+ * @returns {(event: Event) => Promise<void>} An asynchronous event handler function that
1908
+ * processes incoming events for the specified actor.
1909
+ */
1910
+ #makeActorEventHandler(actorDid) {
1911
+ return async (event) => {
1912
+ const actor = this.#actors.get(actorDid);
1913
+ if (!actor) return;
1914
+ if (event.pubkey === (0, import_utils4.bytesToHex)(actor.keys.publicKey.x)) return;
1915
+ let message;
1916
+ try {
1917
+ if (event.kind === 1) {
1918
+ message = JSON.parse(event.content, _NostrTransport.#jsonReviver);
1919
+ } else if (event.kind === 1059) {
1920
+ const conversationKey = import_nostr_tools.nip44.v2.utils.getConversationKey(
1921
+ actor.keys.secretKey.bytes,
1922
+ event.pubkey
1923
+ );
1924
+ const plaintext = import_nostr_tools.nip44.v2.decrypt(event.content, conversationKey);
1925
+ message = JSON.parse(plaintext, _NostrTransport.#jsonReviver);
1926
+ } else {
1927
+ return;
1928
+ }
1929
+ } catch (err) {
1930
+ this.#logger.debug(`Failed to parse event ${event.id} for ${actorDid}:`, err);
1931
+ return;
1932
+ }
1933
+ this.#dispatchMessage(message, actor);
1934
+ };
1935
+ }
1936
+ /**
1937
+ * Handles incoming broadcast events (kind 1) by parsing the event content, validating it as an
1938
+ * aggregation message, and dispatching it to all registered actors that have handlers for the
1939
+ * message type. This is used for COHORT_ADVERT messages that need to be received by all actors
1940
+ * regardless of DID.
1941
+ * @param {Event} event - The Nostr event to handle, expected to be a kind 1 broadcast containing
1942
+ * a COHORT_ADVERT message. The event content is parsed and dispatched to all registered actors
1943
+ * that have handlers for the
1944
+ * @returns
1945
+ */
1946
+ async #handleBroadcastEvent(event) {
1947
+ if (event.kind !== 1) return;
1948
+ let message;
1949
+ try {
1950
+ message = JSON.parse(event.content, _NostrTransport.#jsonReviver);
1951
+ } catch (err) {
1952
+ this.#logger.debug(`Failed to parse broadcast event ${event.id}:`, err);
1953
+ return;
1954
+ }
1955
+ if (message.body && typeof message.body === "object") {
1956
+ message = { ...message, ...message.body };
1957
+ }
1958
+ const messageType = message.type;
1959
+ if (!messageType || !isAggregationMessageType(messageType)) return;
1960
+ for (const actor of this.#actors.values()) {
1961
+ const handler = actor.handlers.get(messageType);
1962
+ if (handler) await handler(message);
1963
+ }
1964
+ }
1965
+ /**
1966
+ * Dispatches a parsed message to the appropriate handler of a registered actor based on message type.
1967
+ * The message is expected to have already been parsed from the Nostr event content and validated as
1968
+ * an aggregation message. If the message has a body, its properties are merged into the top-level
1969
+ * message object for easier handler access. The message is then dispatched to the handler registered
1970
+ * for its type, if one exists.
1971
+ * @param {Record<string, unknown>} message - The message object parsed from a Nostr event, expected to
1972
+ * @param {ActorEntry} actor - The registered actor entry containing keys and handlers to dispatch the message to.
1973
+ * @returns {void}
1974
+ * @throws {TransportAdapterError} If the message type is unsupported or if no handler is registered
1975
+ * for the message type.
1976
+ */
1977
+ #dispatchMessage(message, actor) {
1978
+ if (message.body && typeof message.body === "object") {
1979
+ message = { ...message, ...message.body };
1980
+ }
1981
+ const messageType = message.type;
1982
+ if (!messageType || !isAggregationMessageType(messageType)) return;
1983
+ const handler = actor.handlers.get(messageType);
1984
+ if (handler) handler(message);
1985
+ }
1986
+ /**
1987
+ * Publishes a Nostr event to the configured relays and handles the results. The method waits for all
1988
+ * relay promises to settle and checks how many accepted or rejected the event. If all relays reject the event,
1989
+ * an error is thrown. Otherwise, the method completes successfully even if some relays rejected the event,
1990
+ * as long as at least one relay accepted it. Relay rejections are logged for debugging purposes.
1991
+ * @param {Event} event - The Nostr event to publish to the configured relays. The event should already
1992
+ * @returns {Promise<void>} A promise that resolves if the event was accepted by at least one relay, or rejects
1993
+ * with a TransportAdapterError if all relays rejected the event.
1994
+ * @throws {TransportAdapterError} If the pool is not initialized or if all relays reject the event.
1995
+ */
1996
+ async #publishToRelays(event) {
1997
+ const relayPromises = this.pool?.publish(this.#relays, event);
1998
+ if (!relayPromises?.length) return;
1999
+ const results = await Promise.allSettled(relayPromises);
2000
+ const accepted = results.filter((r) => r.status === "fulfilled").length;
2001
+ const rejected = results.filter((r) => r.status === "rejected");
2002
+ for (const r of rejected) {
2003
+ this.#logger.debug(`Relay rejected event ${event.id}: ${r.reason}`);
2004
+ }
2005
+ if (accepted === 0) {
2006
+ throw new TransportAdapterError(
2007
+ `All ${results.length} relay(s) rejected event ${event.id}`,
2008
+ "PUBLISH_ERROR",
2009
+ { adapter: this.name, reasons: rejected.map((r) => String(r.reason)) }
2010
+ );
2011
+ }
2012
+ }
2013
+ /**
2014
+ * Custom JSON replacer to handle serialization of Uint8Array values as hex strings in message
2015
+ * content. This allows messages containing binary data (e.g. public keys, signatures) to be correctly
2016
+ * serialized to JSON for Nostr event content. The replacer checks if a value is a Uint8Array and, if so,
2017
+ * converts it to a hex string wrapped in an object with a __bytes property. The corresponding reviver
2018
+ * can then convert this back to a Uint8Array when parsing the message content from the event.
2019
+ * @param {string} _key - The key of the property being processed.
2020
+ * @param {unknown} value - The value to check if the message type is valid.
2021
+ * @returns {unknown} The transformed value for JSON serialization. If the value is a Uint8Array,
2022
+ * it returns an object with a __bytes property containing the hex string. Otherwise, it returns
2023
+ * the value unchanged.
2024
+ */
2025
+ static #jsonReplacer(_key, value) {
2026
+ if (value instanceof Uint8Array) {
2027
+ return { __bytes: (0, import_utils4.bytesToHex)(value) };
2028
+ }
2029
+ return value;
2030
+ }
2031
+ /**
2032
+ * Custom JSON reviver to handle deserialization of hex strings back into Uint8Array values in message
2033
+ * content. This complements the custom replacer used during serialization, allowing messages that contain
2034
+ * binary data (e.g. public keys, signatures) to be correctly reconstructed when parsing JSON from
2035
+ * Nostr event content. The reviver checks if a value is an object with a __bytes property and,
2036
+ * if so, converts the hex string back into a Uint8Array. Otherwise, it returns the value unchanged.
2037
+ * @param {string} _key - The key of the property being processed.
2038
+ * @param {unknown} value - The value to check if it is an object containing a __bytes property for
2039
+ * hex string conversion.
2040
+ * @returns {unknown} The transformed value for JSON deserialization. If the value is an object
2041
+ * with a __bytes property, it returns a Uint8Array. Otherwise, it returns the value unchanged.
2042
+ */
2043
+ static #jsonReviver(_key, value) {
2044
+ if (value && typeof value === "object" && "__bytes" in value) {
2045
+ return (0, import_utils4.hexToBytes)(value.__bytes);
2046
+ }
2047
+ return value;
2048
+ }
2049
+ };
2050
+
2051
+ // src/core/transport/didcomm.ts
2052
+ var import_common5 = require("@did-btcr2/common");
2053
+ var DidCommTransport = class {
2054
+ name = "didcomm";
2055
+ start() {
2056
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented. Use NostrTransport instead.");
2057
+ }
2058
+ registerActor(_did, _keys) {
2059
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented.");
2060
+ }
2061
+ getActorPk(_did) {
2062
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented.");
2063
+ }
2064
+ registerPeer(_did, _communicationPk) {
2065
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented.");
2066
+ }
2067
+ getPeerPk(_did) {
2068
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented.");
2069
+ }
2070
+ registerMessageHandler(_actorDid, _messageType, _handler) {
2071
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented.");
2072
+ }
2073
+ unregisterMessageHandler(_actorDid, _messageType) {
2074
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented.");
2075
+ }
2076
+ unregisterActor(_did) {
2077
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented.");
2078
+ }
2079
+ async sendMessage(_message, _sender, _recipient) {
2080
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented.");
2081
+ }
2082
+ publishRepeating(_message, _sender, _intervalMs, _recipient) {
2083
+ throw new import_common5.NotImplementedError("DidCommTransport not implemented.");
2084
+ }
2085
+ };
2086
+
2087
+ // src/core/transport/http/envelope.ts
2088
+ var import_common6 = require("@did-btcr2/common");
2089
+ var import_utils5 = require("@noble/hashes/utils");
2090
+
2091
+ // src/core/transport/http/errors.ts
2092
+ var HttpTransportError = class extends TransportAdapterError {
2093
+ constructor(message, type = "HttpTransportError", data) {
2094
+ super(message, type, { adapter: "http", ...data ?? {} });
2095
+ }
2096
+ };
2097
+
2098
+ // src/core/transport/http/protocol.ts
2099
+ var HTTP_ENVELOPE_VERSION = 1;
2100
+ var HTTP_ROUTE = {
2101
+ ADVERTS: "/v1/adverts",
2102
+ MESSAGES: "/v1/messages",
2103
+ ACTOR_INBOX: "/v1/actors/{did}/inbox",
2104
+ WELL_KNOWN: "/v1/.well-known/aggregation"
2105
+ };
2106
+ var SSE_EVENT = {
2107
+ ADVERT: "advert",
2108
+ MESSAGE: "message",
2109
+ HEARTBEAT: "heartbeat"
2110
+ };
2111
+ var DEFAULT_CLOCK_SKEW_SEC = 60;
2112
+ var DEFAULT_NONCE_LEN_BYTES = 16;
2113
+
2114
+ // src/core/transport/http/envelope.ts
2115
+ function signEnvelope(message, sender, opts = {}) {
2116
+ const timestamp = opts.timestamp ?? Math.floor(Date.now() / 1e3);
2117
+ const nonce = opts.nonce ?? (0, import_utils5.bytesToHex)((0, import_utils5.randomBytes)(DEFAULT_NONCE_LEN_BYTES));
2118
+ const messageJson = normalizeForWire(normalizeMessage(message));
2119
+ const unsigned = {
2120
+ v: HTTP_ENVELOPE_VERSION,
2121
+ from: sender.did,
2122
+ ...opts.to !== void 0 ? { to: opts.to } : {},
2123
+ timestamp,
2124
+ nonce,
2125
+ message: messageJson
2126
+ };
2127
+ const digest = (0, import_common6.canonicalHashBytes)(unsigned);
2128
+ const sig = sender.keys.secretKey.sign(digest, { scheme: "schnorr" });
2129
+ return { ...unsigned, sig: (0, import_utils5.bytesToHex)(sig) };
2130
+ }
2131
+ function verifyEnvelope(envelope, senderPk, opts = {}) {
2132
+ if (envelope.v !== HTTP_ENVELOPE_VERSION) {
2133
+ throw new HttpTransportError(
2134
+ `Unsupported envelope version: ${envelope.v}`,
2135
+ "ENVELOPE_VERSION_MISMATCH",
2136
+ { version: envelope.v, expected: HTTP_ENVELOPE_VERSION }
2137
+ );
2138
+ }
2139
+ if (opts.expectedFrom !== void 0 && envelope.from !== opts.expectedFrom) {
2140
+ throw new HttpTransportError(
2141
+ `Envelope from mismatch: expected ${opts.expectedFrom}, got ${envelope.from}`,
2142
+ "ENVELOPE_FROM_MISMATCH",
2143
+ { expected: opts.expectedFrom, got: envelope.from }
2144
+ );
2145
+ }
2146
+ if ("expectedTo" in opts && envelope.to !== opts.expectedTo) {
2147
+ throw new HttpTransportError(
2148
+ `Envelope to mismatch: expected ${opts.expectedTo ?? "<broadcast>"}, got ${envelope.to ?? "<broadcast>"}`,
2149
+ "ENVELOPE_TO_MISMATCH",
2150
+ { expected: opts.expectedTo, got: envelope.to }
2151
+ );
2152
+ }
2153
+ const skewSec = opts.clockSkewSec ?? DEFAULT_CLOCK_SKEW_SEC;
2154
+ const nowMs = opts.now ? opts.now() : Date.now();
2155
+ const nowSec = Math.floor(nowMs / 1e3);
2156
+ const diff = Math.abs(nowSec - envelope.timestamp);
2157
+ if (diff > skewSec) {
2158
+ throw new HttpTransportError(
2159
+ `Envelope timestamp out of skew: ${diff}s > ${skewSec}s`,
2160
+ "ENVELOPE_TIMESTAMP_SKEW",
2161
+ { diff, skewSec, timestamp: envelope.timestamp, now: nowSec }
2162
+ );
2163
+ }
2164
+ let sigBytes;
2165
+ try {
2166
+ sigBytes = (0, import_utils5.hexToBytes)(envelope.sig);
2167
+ } catch {
2168
+ throw new HttpTransportError(
2169
+ "Envelope signature is not valid hex",
2170
+ "ENVELOPE_SIG_HEX"
2171
+ );
2172
+ }
2173
+ if (sigBytes.length !== 64) {
2174
+ throw new HttpTransportError(
2175
+ `Invalid signature length: ${sigBytes.length} (expected 64)`,
2176
+ "ENVELOPE_SIG_LENGTH",
2177
+ { length: sigBytes.length }
2178
+ );
2179
+ }
2180
+ const { sig: _sig, ...unsigned } = envelope;
2181
+ const digest = (0, import_common6.canonicalHashBytes)(unsigned);
2182
+ const ok = senderPk.verify(sigBytes, digest, { scheme: "schnorr" });
2183
+ if (!ok) {
2184
+ throw new HttpTransportError(
2185
+ "Envelope signature verification failed",
2186
+ "ENVELOPE_SIG_INVALID"
2187
+ );
2188
+ }
2189
+ }
2190
+ function normalizeMessage(message) {
2191
+ const maybeToJSON = message.toJSON;
2192
+ if (typeof maybeToJSON === "function") {
2193
+ return maybeToJSON.call(message);
2194
+ }
2195
+ return message;
2196
+ }
2197
+ function normalizeForWire(value) {
2198
+ if (value instanceof Uint8Array) {
2199
+ return { __bytes: (0, import_utils5.bytesToHex)(value) };
2200
+ }
2201
+ if (Array.isArray(value)) {
2202
+ return value.map((v) => normalizeForWire(v));
2203
+ }
2204
+ if (value && typeof value === "object") {
2205
+ const out = {};
2206
+ for (const [k, v] of Object.entries(value)) {
2207
+ out[k] = normalizeForWire(v);
2208
+ }
2209
+ return out;
2210
+ }
2211
+ return value;
2212
+ }
2213
+ function reviveFromWire(value) {
2214
+ if (value && typeof value === "object" && !Array.isArray(value)) {
2215
+ const rec = value;
2216
+ const keys = Object.keys(rec);
2217
+ if (keys.length === 1 && keys[0] === "__bytes" && typeof rec.__bytes === "string") {
2218
+ return (0, import_utils5.hexToBytes)(rec.__bytes);
2219
+ }
2220
+ const out = {};
2221
+ for (const [k, v] of Object.entries(rec)) out[k] = reviveFromWire(v);
2222
+ return out;
2223
+ }
2224
+ if (Array.isArray(value)) {
2225
+ return value.map((v) => reviveFromWire(v));
2226
+ }
2227
+ return value;
2228
+ }
2229
+
2230
+ // src/core/transport/http/request-auth.ts
2231
+ var import_common7 = require("@did-btcr2/common");
2232
+ var import_utils6 = require("@noble/hashes/utils");
2233
+ var REQUEST_AUTH_SCHEME = "BTCR2-Sig";
2234
+ function buildRequestAuth(did, keys, path, opts = {}) {
2235
+ const ts = opts.timestamp ?? Math.floor(Date.now() / 1e3);
2236
+ const nonce = opts.nonce ?? (0, import_utils6.bytesToHex)((0, import_utils6.randomBytes)(DEFAULT_NONCE_LEN_BYTES));
2237
+ const digest = (0, import_common7.canonicalHashBytes)({
2238
+ v: HTTP_ENVELOPE_VERSION,
2239
+ did,
2240
+ ts,
2241
+ nonce,
2242
+ path
2243
+ });
2244
+ const sig = keys.secretKey.sign(digest, { scheme: "schnorr" });
2245
+ return `${REQUEST_AUTH_SCHEME} v=${HTTP_ENVELOPE_VERSION},did=${did},ts=${ts},nonce=${nonce},sig=${(0, import_utils6.bytesToHex)(sig)}`;
2246
+ }
2247
+ function parseRequestAuth(headerValue) {
2248
+ const prefix = `${REQUEST_AUTH_SCHEME} `;
2249
+ if (!headerValue.startsWith(prefix)) {
2250
+ throw new HttpTransportError(
2251
+ `Unexpected auth scheme (want ${REQUEST_AUTH_SCHEME})`,
2252
+ "REQUEST_AUTH_SCHEME"
2253
+ );
2254
+ }
2255
+ const params = {};
2256
+ for (const piece of headerValue.slice(prefix.length).split(",")) {
2257
+ const eq = piece.indexOf("=");
2258
+ if (eq === -1) continue;
2259
+ const key = piece.slice(0, eq).trim();
2260
+ const val = piece.slice(eq + 1).trim();
2261
+ if (key.length > 0) params[key] = val;
2262
+ }
2263
+ const v = Number(params.v);
2264
+ const ts = Number(params.ts);
2265
+ if (!Number.isInteger(v) || !Number.isInteger(ts) || !params.did || !params.nonce || !params.sig) {
2266
+ throw new HttpTransportError(
2267
+ "Malformed auth header (missing or invalid field)",
2268
+ "REQUEST_AUTH_MALFORMED",
2269
+ { received: Object.keys(params) }
2270
+ );
2271
+ }
2272
+ return { v, did: params.did, ts, nonce: params.nonce, sig: params.sig };
2273
+ }
2274
+ function verifyRequestAuth(headerValue, expectedPath, senderPk, opts = {}) {
2275
+ const parsed = parseRequestAuth(headerValue);
2276
+ if (parsed.v !== HTTP_ENVELOPE_VERSION) {
2277
+ throw new HttpTransportError(
2278
+ `Unsupported auth version: ${parsed.v}`,
2279
+ "REQUEST_AUTH_VERSION_MISMATCH",
2280
+ { version: parsed.v, expected: HTTP_ENVELOPE_VERSION }
2281
+ );
2282
+ }
2283
+ const skewSec = opts.clockSkewSec ?? DEFAULT_CLOCK_SKEW_SEC;
2284
+ const nowMs = opts.now ? opts.now() : Date.now();
2285
+ const nowSec = Math.floor(nowMs / 1e3);
2286
+ const diff = Math.abs(nowSec - parsed.ts);
2287
+ if (diff > skewSec) {
2288
+ throw new HttpTransportError(
2289
+ `Auth timestamp out of skew: ${diff}s > ${skewSec}s`,
2290
+ "REQUEST_AUTH_TIMESTAMP_SKEW",
2291
+ { diff, skewSec }
2292
+ );
2293
+ }
2294
+ let sigBytes;
2295
+ try {
2296
+ sigBytes = (0, import_utils6.hexToBytes)(parsed.sig);
2297
+ } catch {
2298
+ throw new HttpTransportError("Auth signature is not valid hex", "REQUEST_AUTH_SIG_HEX");
2299
+ }
2300
+ if (sigBytes.length !== 64) {
2301
+ throw new HttpTransportError(
2302
+ `Invalid auth signature length: ${sigBytes.length}`,
2303
+ "REQUEST_AUTH_SIG_LENGTH",
2304
+ { length: sigBytes.length }
2305
+ );
2306
+ }
2307
+ const digest = (0, import_common7.canonicalHashBytes)({
2308
+ v: parsed.v,
2309
+ did: parsed.did,
2310
+ ts: parsed.ts,
2311
+ nonce: parsed.nonce,
2312
+ path: expectedPath
2313
+ });
2314
+ const ok = senderPk.verify(sigBytes, digest, { scheme: "schnorr" });
2315
+ if (!ok) {
2316
+ throw new HttpTransportError("Auth signature verification failed", "REQUEST_AUTH_SIG_INVALID");
2317
+ }
2318
+ return parsed;
2319
+ }
2320
+ // Annotate the CommonJS export names for ESM import in node:
2321
+ 0 && (module.exports = {
2322
+ AGGREGATED_NONCE,
2323
+ AGGREGATION_MESSAGE_PREFIX,
2324
+ AGGREGATION_WIRE_VERSION,
2325
+ AUTHORIZATION_REQUEST,
2326
+ AggregationCohort,
2327
+ AggregationCohortError,
2328
+ AggregationParticipantError,
2329
+ AggregationServiceError,
2330
+ BaseMessage,
2331
+ BeaconSigningSession,
2332
+ COHORT_ADVERT,
2333
+ COHORT_OPT_IN,
2334
+ COHORT_OPT_IN_ACCEPT,
2335
+ COHORT_READY,
2336
+ CONSOLE_LOGGER,
2337
+ DEFAULT_BROADCAST_LOOKBACK_MS,
2338
+ DEFAULT_CLOCK_SKEW_SEC,
2339
+ DEFAULT_FUNDING_MODEL,
2340
+ DEFAULT_NONCE_LEN_BYTES,
2341
+ DEFAULT_NOSTR_RELAYS,
2342
+ DEFAULT_RECOVERY_SEQUENCE,
2343
+ DISTRIBUTE_AGGREGATED_DATA,
2344
+ DidCommTransport,
2345
+ FALLBACK_AUTHORIZATION_REQUEST,
2346
+ FALLBACK_SIGNATURE,
2347
+ HTTP_ENVELOPE_VERSION,
2348
+ HTTP_ROUTE,
2349
+ HttpTransportError,
2350
+ InMemoryBus,
2351
+ InMemoryTransport,
2352
+ KNOWN_BEACON_TYPES,
2353
+ KNOWN_FUNDING_MODELS,
2354
+ KeyPairAggregationSigner,
2355
+ MAX_RECOVERY_SEQUENCE,
2356
+ NONCE_CONTRIBUTION,
2357
+ NostrTransport,
2358
+ ParticipantCohortPhase,
2359
+ REQUEST_AUTH_SCHEME,
2360
+ SIGNATURE_AUTHORIZATION,
2361
+ SILENT_LOGGER,
2362
+ SSE_EVENT,
2363
+ SUBMIT_NONINCLUDED,
2364
+ SUBMIT_UPDATE,
2365
+ ServiceCohortPhase,
2366
+ SigningSessionError,
2367
+ SigningSessionPhase,
2368
+ TAPROOT_LEAF_VERSION,
2369
+ TransportAdapterError,
2370
+ TransportError,
2371
+ TypedEventEmitter,
2372
+ VALIDATION_ACK,
2373
+ buildFallbackLeaf,
2374
+ buildFallbackSpend,
2375
+ buildRecoveryLeaves,
2376
+ buildRecoveryScript,
2377
+ buildRecoverySpend,
2378
+ buildRequestAuth,
2379
+ createAggregatedNonceMessage,
2380
+ createAuthorizationRequestMessage,
2381
+ createCohortAdvertMessage,
2382
+ createCohortOptInAcceptMessage,
2383
+ createCohortOptInMessage,
2384
+ createCohortReadyMessage,
2385
+ createDistributeAggregatedDataMessage,
2386
+ createFallbackAuthorizationRequestMessage,
2387
+ createFallbackSignatureMessage,
2388
+ createNonceContributionMessage,
2389
+ createSignatureAuthorizationMessage,
2390
+ createSubmitNonIncludedMessage,
2391
+ createSubmitUpdateMessage,
2392
+ createValidationAckMessage,
2393
+ fallbackSighash,
2394
+ getBeaconStrategy,
2395
+ isAggregatedNonceMessage,
2396
+ isAggregationMessageType,
2397
+ isAuthorizationRequestMessage,
2398
+ isCohortAdvertMessage,
2399
+ isCohortOptInAcceptMessage,
2400
+ isCohortOptInMessage,
2401
+ isCohortReadyMessage,
2402
+ isDistributeAggregatedDataMessage,
2403
+ isFallbackAuthorizationRequestMessage,
2404
+ isFallbackSignatureMessage,
2405
+ isKeygenMessageType,
2406
+ isNonceContributionMessage,
2407
+ isSignMessageType,
2408
+ isSignatureAuthorizationMessage,
2409
+ isSubmitNonIncludedMessage,
2410
+ isSubmitUpdateMessage,
2411
+ isUpdateMessageType,
2412
+ isValidationAckMessage,
2413
+ normalizeForWire,
2414
+ parseRequestAuth,
2415
+ registerBeaconStrategy,
2416
+ resolveFallbackThreshold,
2417
+ reviveFromWire,
2418
+ signEnvelope,
2419
+ tapLeafHash,
2420
+ validateCohortConditions,
2421
+ verifyEnvelope,
2422
+ verifyRequestAuth
2423
+ });