@did-btcr2/method 0.13.1

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 (310) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +7 -0
  3. package/dist/browser.js +2364 -0
  4. package/dist/browser.js.map +7 -0
  5. package/dist/browser.mjs +2364 -0
  6. package/dist/browser.mjs.map +7 -0
  7. package/dist/cjs/bitcoin/constants.js +20 -0
  8. package/dist/cjs/bitcoin/constants.js.map +1 -0
  9. package/dist/cjs/bitcoin/errors.js +11 -0
  10. package/dist/cjs/bitcoin/errors.js.map +1 -0
  11. package/dist/cjs/bitcoin/index.js +95 -0
  12. package/dist/cjs/bitcoin/index.js.map +1 -0
  13. package/dist/cjs/bitcoin/interface.js +2 -0
  14. package/dist/cjs/bitcoin/interface.js.map +1 -0
  15. package/dist/cjs/bitcoin/network.js +17 -0
  16. package/dist/cjs/bitcoin/network.js.map +1 -0
  17. package/dist/cjs/bitcoin/rest-client.js +289 -0
  18. package/dist/cjs/bitcoin/rest-client.js.map +1 -0
  19. package/dist/cjs/bitcoin/rpc-client.js +722 -0
  20. package/dist/cjs/bitcoin/rpc-client.js.map +1 -0
  21. package/dist/cjs/bitcoin/taproot.js +219 -0
  22. package/dist/cjs/bitcoin/taproot.js.map +1 -0
  23. package/dist/cjs/btcr2/beacon/aggregation/coordinator.js +120 -0
  24. package/dist/cjs/btcr2/beacon/aggregation/coordinator.js.map +1 -0
  25. package/dist/cjs/btcr2/beacon/aggregation/messages/advert.js +24 -0
  26. package/dist/cjs/btcr2/beacon/aggregation/messages/advert.js.map +1 -0
  27. package/dist/cjs/btcr2/beacon/aggregation/messages/base.js +37 -0
  28. package/dist/cjs/btcr2/beacon/aggregation/messages/base.js.map +1 -0
  29. package/dist/cjs/btcr2/beacon/aggregation/messages/cohort-set.js +25 -0
  30. package/dist/cjs/btcr2/beacon/aggregation/messages/cohort-set.js.map +1 -0
  31. package/dist/cjs/btcr2/beacon/aggregation/messages/keygen.js +8 -0
  32. package/dist/cjs/btcr2/beacon/aggregation/messages/keygen.js.map +1 -0
  33. package/dist/cjs/btcr2/beacon/aggregation/messages/opt-in.js +23 -0
  34. package/dist/cjs/btcr2/beacon/aggregation/messages/opt-in.js.map +1 -0
  35. package/dist/cjs/btcr2/beacon/aggregation/messages/sign.js +7 -0
  36. package/dist/cjs/btcr2/beacon/aggregation/messages/sign.js.map +1 -0
  37. package/dist/cjs/btcr2/beacon/aggregation/models/cohort/index.js +92 -0
  38. package/dist/cjs/btcr2/beacon/aggregation/models/cohort/index.js.map +1 -0
  39. package/dist/cjs/btcr2/beacon/aggregation/models/cohort/status.js +8 -0
  40. package/dist/cjs/btcr2/beacon/aggregation/models/cohort/status.js.map +1 -0
  41. package/dist/cjs/btcr2/beacon/aggregation/participant.js +2 -0
  42. package/dist/cjs/btcr2/beacon/aggregation/participant.js.map +1 -0
  43. package/dist/cjs/btcr2/beacon/aggregation/protocol/nostr.js +57 -0
  44. package/dist/cjs/btcr2/beacon/aggregation/protocol/nostr.js.map +1 -0
  45. package/dist/cjs/btcr2/beacon/aggregation/protocol/service.js +2 -0
  46. package/dist/cjs/btcr2/beacon/aggregation/protocol/service.js.map +1 -0
  47. package/dist/cjs/btcr2/beacon/cid-aggregate.js +116 -0
  48. package/dist/cjs/btcr2/beacon/cid-aggregate.js.map +1 -0
  49. package/dist/cjs/btcr2/beacon/factory.js +30 -0
  50. package/dist/cjs/btcr2/beacon/factory.js.map +1 -0
  51. package/dist/cjs/btcr2/beacon/singleton.js +220 -0
  52. package/dist/cjs/btcr2/beacon/singleton.js.map +1 -0
  53. package/dist/cjs/btcr2/beacon/smt-aggregate.js +126 -0
  54. package/dist/cjs/btcr2/beacon/smt-aggregate.js.map +1 -0
  55. package/dist/cjs/btcr2/crud/create.js +102 -0
  56. package/dist/cjs/btcr2/crud/create.js.map +1 -0
  57. package/dist/cjs/btcr2/crud/deactivate.js +14 -0
  58. package/dist/cjs/btcr2/crud/deactivate.js.map +1 -0
  59. package/dist/cjs/btcr2/crud/read.js +686 -0
  60. package/dist/cjs/btcr2/crud/read.js.map +1 -0
  61. package/dist/cjs/btcr2/crud/update.js +195 -0
  62. package/dist/cjs/btcr2/crud/update.js.map +1 -0
  63. package/dist/cjs/btcr2/key-manager/index.js +290 -0
  64. package/dist/cjs/btcr2/key-manager/index.js.map +1 -0
  65. package/dist/cjs/btcr2/key-manager/interface.js +2 -0
  66. package/dist/cjs/btcr2/key-manager/interface.js.map +1 -0
  67. package/dist/cjs/did-btcr2.js +222 -0
  68. package/dist/cjs/did-btcr2.js.map +1 -0
  69. package/dist/cjs/index.js +27 -0
  70. package/dist/cjs/index.js.map +1 -0
  71. package/dist/cjs/interfaces/beacon.js +41 -0
  72. package/dist/cjs/interfaces/beacon.js.map +1 -0
  73. package/dist/cjs/interfaces/crud.js +2 -0
  74. package/dist/cjs/interfaces/crud.js.map +1 -0
  75. package/dist/cjs/interfaces/ibeacon.js +2 -0
  76. package/dist/cjs/interfaces/ibeacon.js.map +1 -0
  77. package/dist/cjs/package.json +1 -0
  78. package/dist/cjs/types/bitcoin.js +62 -0
  79. package/dist/cjs/types/bitcoin.js.map +1 -0
  80. package/dist/cjs/types/crud.js +2 -0
  81. package/dist/cjs/types/crud.js.map +1 -0
  82. package/dist/cjs/utils/appendix.js +221 -0
  83. package/dist/cjs/utils/appendix.js.map +1 -0
  84. package/dist/cjs/utils/beacons.js +206 -0
  85. package/dist/cjs/utils/beacons.js.map +1 -0
  86. package/dist/cjs/utils/did-document-builder.js +61 -0
  87. package/dist/cjs/utils/did-document-builder.js.map +1 -0
  88. package/dist/cjs/utils/did-document.js +380 -0
  89. package/dist/cjs/utils/did-document.js.map +1 -0
  90. package/dist/cjs/utils/general.js +195 -0
  91. package/dist/cjs/utils/general.js.map +1 -0
  92. package/dist/cjs/utils/identifier.js +238 -0
  93. package/dist/cjs/utils/identifier.js.map +1 -0
  94. package/dist/esm/bitcoin/constants.js +20 -0
  95. package/dist/esm/bitcoin/constants.js.map +1 -0
  96. package/dist/esm/bitcoin/errors.js +11 -0
  97. package/dist/esm/bitcoin/errors.js.map +1 -0
  98. package/dist/esm/bitcoin/index.js +95 -0
  99. package/dist/esm/bitcoin/index.js.map +1 -0
  100. package/dist/esm/bitcoin/interface.js +2 -0
  101. package/dist/esm/bitcoin/interface.js.map +1 -0
  102. package/dist/esm/bitcoin/network.js +17 -0
  103. package/dist/esm/bitcoin/network.js.map +1 -0
  104. package/dist/esm/bitcoin/rest-client.js +289 -0
  105. package/dist/esm/bitcoin/rest-client.js.map +1 -0
  106. package/dist/esm/bitcoin/rpc-client.js +722 -0
  107. package/dist/esm/bitcoin/rpc-client.js.map +1 -0
  108. package/dist/esm/bitcoin/taproot.js +219 -0
  109. package/dist/esm/bitcoin/taproot.js.map +1 -0
  110. package/dist/esm/btcr2/beacon/aggregation/coordinator.js +120 -0
  111. package/dist/esm/btcr2/beacon/aggregation/coordinator.js.map +1 -0
  112. package/dist/esm/btcr2/beacon/aggregation/messages/advert.js +24 -0
  113. package/dist/esm/btcr2/beacon/aggregation/messages/advert.js.map +1 -0
  114. package/dist/esm/btcr2/beacon/aggregation/messages/base.js +37 -0
  115. package/dist/esm/btcr2/beacon/aggregation/messages/base.js.map +1 -0
  116. package/dist/esm/btcr2/beacon/aggregation/messages/cohort-set.js +25 -0
  117. package/dist/esm/btcr2/beacon/aggregation/messages/cohort-set.js.map +1 -0
  118. package/dist/esm/btcr2/beacon/aggregation/messages/keygen.js +8 -0
  119. package/dist/esm/btcr2/beacon/aggregation/messages/keygen.js.map +1 -0
  120. package/dist/esm/btcr2/beacon/aggregation/messages/opt-in.js +23 -0
  121. package/dist/esm/btcr2/beacon/aggregation/messages/opt-in.js.map +1 -0
  122. package/dist/esm/btcr2/beacon/aggregation/messages/sign.js +7 -0
  123. package/dist/esm/btcr2/beacon/aggregation/messages/sign.js.map +1 -0
  124. package/dist/esm/btcr2/beacon/aggregation/models/cohort/index.js +92 -0
  125. package/dist/esm/btcr2/beacon/aggregation/models/cohort/index.js.map +1 -0
  126. package/dist/esm/btcr2/beacon/aggregation/models/cohort/status.js +8 -0
  127. package/dist/esm/btcr2/beacon/aggregation/models/cohort/status.js.map +1 -0
  128. package/dist/esm/btcr2/beacon/aggregation/participant.js +2 -0
  129. package/dist/esm/btcr2/beacon/aggregation/participant.js.map +1 -0
  130. package/dist/esm/btcr2/beacon/aggregation/protocol/nostr.js +57 -0
  131. package/dist/esm/btcr2/beacon/aggregation/protocol/nostr.js.map +1 -0
  132. package/dist/esm/btcr2/beacon/aggregation/protocol/service.js +2 -0
  133. package/dist/esm/btcr2/beacon/aggregation/protocol/service.js.map +1 -0
  134. package/dist/esm/btcr2/beacon/cid-aggregate.js +116 -0
  135. package/dist/esm/btcr2/beacon/cid-aggregate.js.map +1 -0
  136. package/dist/esm/btcr2/beacon/factory.js +30 -0
  137. package/dist/esm/btcr2/beacon/factory.js.map +1 -0
  138. package/dist/esm/btcr2/beacon/singleton.js +220 -0
  139. package/dist/esm/btcr2/beacon/singleton.js.map +1 -0
  140. package/dist/esm/btcr2/beacon/smt-aggregate.js +126 -0
  141. package/dist/esm/btcr2/beacon/smt-aggregate.js.map +1 -0
  142. package/dist/esm/btcr2/crud/create.js +102 -0
  143. package/dist/esm/btcr2/crud/create.js.map +1 -0
  144. package/dist/esm/btcr2/crud/deactivate.js +14 -0
  145. package/dist/esm/btcr2/crud/deactivate.js.map +1 -0
  146. package/dist/esm/btcr2/crud/read.js +686 -0
  147. package/dist/esm/btcr2/crud/read.js.map +1 -0
  148. package/dist/esm/btcr2/crud/update.js +195 -0
  149. package/dist/esm/btcr2/crud/update.js.map +1 -0
  150. package/dist/esm/btcr2/key-manager/index.js +290 -0
  151. package/dist/esm/btcr2/key-manager/index.js.map +1 -0
  152. package/dist/esm/btcr2/key-manager/interface.js +2 -0
  153. package/dist/esm/btcr2/key-manager/interface.js.map +1 -0
  154. package/dist/esm/did-btcr2.js +222 -0
  155. package/dist/esm/did-btcr2.js.map +1 -0
  156. package/dist/esm/index.js +27 -0
  157. package/dist/esm/index.js.map +1 -0
  158. package/dist/esm/interfaces/beacon.js +41 -0
  159. package/dist/esm/interfaces/beacon.js.map +1 -0
  160. package/dist/esm/interfaces/crud.js +2 -0
  161. package/dist/esm/interfaces/crud.js.map +1 -0
  162. package/dist/esm/interfaces/ibeacon.js +2 -0
  163. package/dist/esm/interfaces/ibeacon.js.map +1 -0
  164. package/dist/esm/types/bitcoin.js +62 -0
  165. package/dist/esm/types/bitcoin.js.map +1 -0
  166. package/dist/esm/types/crud.js +2 -0
  167. package/dist/esm/types/crud.js.map +1 -0
  168. package/dist/esm/utils/appendix.js +221 -0
  169. package/dist/esm/utils/appendix.js.map +1 -0
  170. package/dist/esm/utils/beacons.js +206 -0
  171. package/dist/esm/utils/beacons.js.map +1 -0
  172. package/dist/esm/utils/did-document-builder.js +61 -0
  173. package/dist/esm/utils/did-document-builder.js.map +1 -0
  174. package/dist/esm/utils/did-document.js +380 -0
  175. package/dist/esm/utils/did-document.js.map +1 -0
  176. package/dist/esm/utils/general.js +195 -0
  177. package/dist/esm/utils/general.js.map +1 -0
  178. package/dist/esm/utils/identifier.js +238 -0
  179. package/dist/esm/utils/identifier.js.map +1 -0
  180. package/dist/types/bitcoin/constants.d.ts +19 -0
  181. package/dist/types/bitcoin/constants.d.ts.map +1 -0
  182. package/dist/types/bitcoin/errors.d.ts +5 -0
  183. package/dist/types/bitcoin/errors.d.ts.map +1 -0
  184. package/dist/types/bitcoin/index.d.ts +75 -0
  185. package/dist/types/bitcoin/index.d.ts.map +1 -0
  186. package/dist/types/bitcoin/interface.d.ts +86 -0
  187. package/dist/types/bitcoin/interface.d.ts.map +1 -0
  188. package/dist/types/bitcoin/network.d.ts +2 -0
  189. package/dist/types/bitcoin/network.d.ts.map +1 -0
  190. package/dist/types/bitcoin/rest-client.d.ts +268 -0
  191. package/dist/types/bitcoin/rest-client.d.ts.map +1 -0
  192. package/dist/types/bitcoin/rpc-client.d.ts +506 -0
  193. package/dist/types/bitcoin/rpc-client.d.ts.map +1 -0
  194. package/dist/types/bitcoin/taproot.d.ts +34 -0
  195. package/dist/types/bitcoin/taproot.d.ts.map +1 -0
  196. package/dist/types/btcr2/beacon/aggregation/coordinator.d.ts +74 -0
  197. package/dist/types/btcr2/beacon/aggregation/coordinator.d.ts.map +1 -0
  198. package/dist/types/btcr2/beacon/aggregation/messages/advert.d.ts +22 -0
  199. package/dist/types/btcr2/beacon/aggregation/messages/advert.d.ts.map +1 -0
  200. package/dist/types/btcr2/beacon/aggregation/messages/base.d.ts +36 -0
  201. package/dist/types/btcr2/beacon/aggregation/messages/base.d.ts.map +1 -0
  202. package/dist/types/btcr2/beacon/aggregation/messages/cohort-set.d.ts +23 -0
  203. package/dist/types/btcr2/beacon/aggregation/messages/cohort-set.d.ts.map +1 -0
  204. package/dist/types/btcr2/beacon/aggregation/messages/keygen.d.ts +6 -0
  205. package/dist/types/btcr2/beacon/aggregation/messages/keygen.d.ts.map +1 -0
  206. package/dist/types/btcr2/beacon/aggregation/messages/opt-in.d.ts +22 -0
  207. package/dist/types/btcr2/beacon/aggregation/messages/opt-in.d.ts.map +1 -0
  208. package/dist/types/btcr2/beacon/aggregation/messages/sign.d.ts +5 -0
  209. package/dist/types/btcr2/beacon/aggregation/messages/sign.d.ts.map +1 -0
  210. package/dist/types/btcr2/beacon/aggregation/models/cohort/index.d.ts +77 -0
  211. package/dist/types/btcr2/beacon/aggregation/models/cohort/index.d.ts.map +1 -0
  212. package/dist/types/btcr2/beacon/aggregation/models/cohort/status.d.ts +7 -0
  213. package/dist/types/btcr2/beacon/aggregation/models/cohort/status.d.ts.map +1 -0
  214. package/dist/types/btcr2/beacon/aggregation/participant.d.ts +1 -0
  215. package/dist/types/btcr2/beacon/aggregation/participant.d.ts.map +1 -0
  216. package/dist/types/btcr2/beacon/aggregation/protocol/nostr.d.ts +36 -0
  217. package/dist/types/btcr2/beacon/aggregation/protocol/nostr.d.ts.map +1 -0
  218. package/dist/types/btcr2/beacon/aggregation/protocol/service.d.ts +6 -0
  219. package/dist/types/btcr2/beacon/aggregation/protocol/service.d.ts.map +1 -0
  220. package/dist/types/btcr2/beacon/cid-aggregate.d.ts +103 -0
  221. package/dist/types/btcr2/beacon/cid-aggregate.d.ts.map +1 -0
  222. package/dist/types/btcr2/beacon/factory.d.ts +17 -0
  223. package/dist/types/btcr2/beacon/factory.d.ts.map +1 -0
  224. package/dist/types/btcr2/beacon/singleton.d.ts +93 -0
  225. package/dist/types/btcr2/beacon/singleton.d.ts.map +1 -0
  226. package/dist/types/btcr2/beacon/smt-aggregate.d.ts +112 -0
  227. package/dist/types/btcr2/beacon/smt-aggregate.d.ts.map +1 -0
  228. package/dist/types/btcr2/crud/create.d.ts +92 -0
  229. package/dist/types/btcr2/crud/create.d.ts.map +1 -0
  230. package/dist/types/btcr2/crud/deactivate.d.ts +13 -0
  231. package/dist/types/btcr2/crud/deactivate.d.ts.map +1 -0
  232. package/dist/types/btcr2/crud/read.d.ts +341 -0
  233. package/dist/types/btcr2/crud/read.d.ts.map +1 -0
  234. package/dist/types/btcr2/crud/update.d.ts +83 -0
  235. package/dist/types/btcr2/crud/update.d.ts.map +1 -0
  236. package/dist/types/btcr2/key-manager/index.d.ts +145 -0
  237. package/dist/types/btcr2/key-manager/index.d.ts.map +1 -0
  238. package/dist/types/btcr2/key-manager/interface.d.ts +113 -0
  239. package/dist/types/btcr2/key-manager/interface.d.ts.map +1 -0
  240. package/dist/types/did-btcr2.d.ts +117 -0
  241. package/dist/types/did-btcr2.d.ts.map +1 -0
  242. package/dist/types/index.d.ts +26 -0
  243. package/dist/types/index.d.ts.map +1 -0
  244. package/dist/types/interfaces/beacon.d.ts +57 -0
  245. package/dist/types/interfaces/beacon.d.ts.map +1 -0
  246. package/dist/types/interfaces/crud.d.ts +35 -0
  247. package/dist/types/interfaces/crud.d.ts.map +1 -0
  248. package/dist/types/interfaces/ibeacon.d.ts +66 -0
  249. package/dist/types/interfaces/ibeacon.d.ts.map +1 -0
  250. package/dist/types/types/bitcoin.d.ts +827 -0
  251. package/dist/types/types/bitcoin.d.ts.map +1 -0
  252. package/dist/types/types/crud.d.ts +38 -0
  253. package/dist/types/types/crud.d.ts.map +1 -0
  254. package/dist/types/utils/appendix.d.ts +118 -0
  255. package/dist/types/utils/appendix.d.ts.map +1 -0
  256. package/dist/types/utils/beacons.d.ts +156 -0
  257. package/dist/types/utils/beacons.d.ts.map +1 -0
  258. package/dist/types/utils/did-document-builder.d.ts +13 -0
  259. package/dist/types/utils/did-document-builder.d.ts.map +1 -0
  260. package/dist/types/utils/did-document.d.ts +211 -0
  261. package/dist/types/utils/did-document.d.ts.map +1 -0
  262. package/dist/types/utils/general.d.ts +85 -0
  263. package/dist/types/utils/general.d.ts.map +1 -0
  264. package/dist/types/utils/identifier.d.ts +59 -0
  265. package/dist/types/utils/identifier.d.ts.map +1 -0
  266. package/package.json +137 -0
  267. package/src/bitcoin/constants.ts +19 -0
  268. package/src/bitcoin/errors.ts +10 -0
  269. package/src/bitcoin/index.ts +154 -0
  270. package/src/bitcoin/interface.ts +160 -0
  271. package/src/bitcoin/network.ts +17 -0
  272. package/src/bitcoin/rest-client.ts +415 -0
  273. package/src/bitcoin/rpc-client.ts +888 -0
  274. package/src/bitcoin/taproot.ts +237 -0
  275. package/src/btcr2/beacon/aggregation/coordinator.ts +135 -0
  276. package/src/btcr2/beacon/aggregation/messages/advert.ts +36 -0
  277. package/src/btcr2/beacon/aggregation/messages/base.ts +59 -0
  278. package/src/btcr2/beacon/aggregation/messages/cohort-set.ts +37 -0
  279. package/src/btcr2/beacon/aggregation/messages/keygen.ts +8 -0
  280. package/src/btcr2/beacon/aggregation/messages/opt-in.ts +35 -0
  281. package/src/btcr2/beacon/aggregation/messages/sign.ts +7 -0
  282. package/src/btcr2/beacon/aggregation/models/cohort/index.ts +112 -0
  283. package/src/btcr2/beacon/aggregation/models/cohort/status.ts +7 -0
  284. package/src/btcr2/beacon/aggregation/participant.ts +0 -0
  285. package/src/btcr2/beacon/aggregation/protocol/nostr.ts +81 -0
  286. package/src/btcr2/beacon/aggregation/protocol/service.ts +6 -0
  287. package/src/btcr2/beacon/cid-aggregate.ts +154 -0
  288. package/src/btcr2/beacon/factory.ts +36 -0
  289. package/src/btcr2/beacon/singleton.ts +257 -0
  290. package/src/btcr2/beacon/smt-aggregate.ts +136 -0
  291. package/src/btcr2/crud/create.ts +160 -0
  292. package/src/btcr2/crud/deactivate.ts +13 -0
  293. package/src/btcr2/crud/read.ts +946 -0
  294. package/src/btcr2/crud/update.ts +277 -0
  295. package/src/btcr2/key-manager/index.ts +364 -0
  296. package/src/btcr2/key-manager/interface.ts +129 -0
  297. package/src/canonicalize.d.ts +6 -0
  298. package/src/did-btcr2.ts +288 -0
  299. package/src/index.ts +34 -0
  300. package/src/interfaces/beacon.ts +68 -0
  301. package/src/interfaces/crud.ts +36 -0
  302. package/src/interfaces/ibeacon.ts +76 -0
  303. package/src/types/bitcoin.ts +1028 -0
  304. package/src/types/crud.ts +41 -0
  305. package/src/utils/appendix.ts +257 -0
  306. package/src/utils/beacons.ts +276 -0
  307. package/src/utils/did-document-builder.ts +73 -0
  308. package/src/utils/did-document.ts +474 -0
  309. package/src/utils/general.ts +204 -0
  310. package/src/utils/identifier.ts +276 -0
@@ -0,0 +1,81 @@
1
+ import { SchnorrKeyPair, SecretKey } from '@did-btcr2/keypair';
2
+ import { Filter } from 'nostr-tools';
3
+ import { SimplePool, } from 'nostr-tools/pool';
4
+ import { Btc1Identifier } from '../../../../utils/identifier.js';
5
+ import { ProtocolService } from './service.js';
6
+
7
+ export interface NostrAdapterConfig {
8
+ keys: {
9
+ secret?: Uint8Array;
10
+ public?: Uint8Array;
11
+ };
12
+ did?: string;
13
+ components: {
14
+ idType?: string;
15
+ version?: number;
16
+ network?: string;
17
+ };
18
+ relays: string[];
19
+ [key: string]: any;
20
+ }
21
+
22
+ export class NostrAdapter implements ProtocolService {
23
+ public name: string = 'nostr';
24
+ private config: NostrAdapterConfig;
25
+ private handlers: Map<string, (msg: any) => Promise<void>> = new Map();
26
+
27
+ constructor(config: NostrAdapterConfig = { keys: {}, components: {}, relays: ['wss://relay.damus.io'] }) {
28
+ this.config = config;
29
+ this.config.keys = this.config.keys || SchnorrKeyPair.generate().raw;
30
+ this.config.did = config.did || Btc1Identifier.encode({
31
+ idType : config.components.idType || 'KEY',
32
+ version : config.components.version || 1,
33
+ network : config.components.network || 'signet',
34
+ genesisBytes : this.config.keys.public!
35
+ });
36
+ }
37
+
38
+ async start(): Promise<void> {
39
+ const pool = new SimplePool();
40
+ pool.subscribe(this.config.relays, { pubkey: this.config.did, kinds: [1059] } as Filter, {
41
+ onclose : (reasons: string[]) => console.log('Subscription closed for reasons:', reasons),
42
+ onevent : async (event: any) => {
43
+ console.log('Received event:', event);
44
+ }
45
+ });
46
+ }
47
+
48
+ registerMessageHandler(messageType: string, handler: (msg: any) => Promise<void>): void {
49
+ this.handlers.set(messageType, handler);
50
+ }
51
+
52
+ /**
53
+ * Sends a message to a recipient using the Nostr protocol.
54
+ * This method is a placeholder and should be implemented with actual Nostr message sending logic.
55
+ * @param message
56
+ * @param recipient
57
+ * @param sender
58
+ */
59
+ async sendMessage(message: object, recipient: string, sender: string): Promise<void> {
60
+ // TODO: Implement message sending logic via Nostr
61
+ console.log(`Sending message to ${recipient} from ${sender}:`, message);
62
+ }
63
+
64
+ /**
65
+ * Generates a Nostr identity using the SecretKey and Btc1Identifier classes.
66
+ * @returns {string} A BTCR2 DID used for communication over the nostr protocol
67
+ */
68
+ public generateIdentity(): string {
69
+ this.config.keys.secret = SecretKey.random();
70
+ this.config.keys.public = SecretKey.getPublicKey(this.config.keys.secret);
71
+ this.config.did = Btc1Identifier.encode(
72
+ {
73
+ idType : this.config.components.idType || 'KEY',
74
+ version : this.config.components.version || 1,
75
+ network : this.config.components.network || 'signet',
76
+ genesisBytes : this.config.keys.public
77
+ }
78
+ );
79
+ return this.config.did;
80
+ }
81
+ }
@@ -0,0 +1,6 @@
1
+ export interface ProtocolService {
2
+ start(): Promise<void>;
3
+ registerMessageHandler(messageType: string, handler: (msg: any) => Promise<void>): void;
4
+ sendMessage(message: object, recipient: string, sender: string): Promise<void>;
5
+ generateIdentity(): string;
6
+ }
@@ -0,0 +1,154 @@
1
+ import { Btcr2Error, DidUpdateInvocation, DidUpdatePayload } from '@did-btcr2/common';
2
+ import { DidServiceEndpoint } from '@web5/dids';
3
+ import { Beacon } from '../../interfaces/beacon.js';
4
+ import { BeaconService, BeaconSignal } from '../../interfaces/ibeacon.js';
5
+ import { RawTransactionV2 } from '../../types/bitcoin.js';
6
+ import { BeaconSidecarData, CIDAggregateSidecar, SignalsMetadata } from '../../types/crud.js';
7
+
8
+ /**
9
+ * Implements {@link https://dcdpr.github.io/did-btcr2/#cidaggregate-beacon | 5.2 CIDAggregate Beacon}.
10
+ *
11
+ * A Beacon of the type CIDAggregatoBeacon is a Beacon that publishes Bitcoin transactions containing a Content
12
+ * Identifier (CID) announcing an Aggregated DID Update Bundle. An Aggregated DID Update Bundle is a JSON object that
13
+ * maps did:btcr2 identifiers to CID values for the individual DID Update Payloads. The Aggregated DID Update Bundle CID
14
+ * (bundleCID) SHOULD be resolvable against a Content Addressable Storage (CAS) system such as IPFS, while the CID for
15
+ * the DID Update Payload (payloadCID) MAY be resolvable against a CAS or provided through a Sidecar mechanism. It is
16
+ * RECOMMENDED that this type of Beacon is only included in a DID document if the DID controller is REQUIRED to
17
+ * participate in authorizing Bitcoin transactions from this Beacon. In other words, this Beacon SHOULD identify an
18
+ * n-of-n P2TR Bitcoin address where n is the number of unique DID controllers submitting updates through the Beacon.
19
+ *
20
+ * @class CIDAggregateBeacon
21
+ * @type {CIDAggregateBeacon}
22
+ * @extends {Beacon}
23
+ */
24
+ export class CIDAggregateBeacon extends Beacon {
25
+ /**
26
+ * Creates an instance of CIDAggregateBeacon.
27
+ * @param {BeaconService} service The service of the Beacon.
28
+ * @param {?BeaconSidecarData} [sidecar] The sidecar data of the Beacon.
29
+ */
30
+ constructor(service: BeaconService, sidecar?: BeaconSidecarData<CIDAggregateSidecar>) {
31
+ super({ ...service, type: 'CIDAggregateBeacon' }, sidecar);
32
+ }
33
+ get service(): BeaconService {
34
+ return {
35
+ type : this.type,
36
+ id : this.id,
37
+ serviceEndpoint : this.serviceEndpoint
38
+ };
39
+ }
40
+
41
+
42
+ /**
43
+ * TODO: Finish implementation
44
+ *
45
+ * Implements {@link https://dcdpr.github.io/did-btcr2/#establish-cidaggregate-beacon | 5.2.1 Establish CIDAggregate Beacon}.
46
+ *
47
+ * To establish a CIDAggregatorBeacon, a cohort of cooperating parties SHOULD generate an n-of-n P2TR Bitcoin address
48
+ * where each party contributes a public key. Furthermore, each party SHOULD verify that their key is part of the
49
+ * address and all other keys that are part of the address are keys with controllers able to produce valid signatures.
50
+ * To establish a Beacon there are two roles. One is the cohort participant, they want to join a Beacon cohort and
51
+ * submit a request to do so with a key and proof of control over that key. The other is the Beacon coordinator, they
52
+ * advertise and curate Beacon cohorts by combining Beacon participants into cohorts, verifying proofs of control, and
53
+ * producing Beacon addresses.
54
+ *
55
+ * @param {string} id The identifier of the Beacon.
56
+ * @param {string} type The type of the Beacon.
57
+ * @param {DidServiceEndpoint} serviceEndpoint The service endpoint of the Beacon.
58
+ * @returns {CIDAggregateBeacon} The established CIDAggregate Beacon.
59
+ */
60
+ static establish(id: string, type: string, serviceEndpoint: DidServiceEndpoint): CIDAggregateBeacon {
61
+ return new CIDAggregateBeacon({ id, type, serviceEndpoint });
62
+ }
63
+
64
+
65
+ /**
66
+ * TODO: Figure out if this is necessary or not.
67
+ * @param {string} didUpdatePayload The DID Update Payload to generate the signal for.
68
+ * @returns {BeaconSignal} The generated signal.
69
+ * @throws {Btcr2Error} if the signal is invalid.
70
+ */
71
+ generateSignal(didUpdatePayload: string): BeaconSignal {
72
+ throw new Btcr2Error('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {didUpdatePayload});
73
+ }
74
+
75
+
76
+ /**
77
+ * TODO: Finish implementation
78
+ *
79
+ * Implements {@link https://dcdpr.github.io/did-btcr2/#process-cidaggregate-beacon-signal | 5.2.3 Process CIDAggregate Beacon Signal}.
80
+ *
81
+ * A Beacon Signal from a CIDAggregate Beacon is a Bitcoin transaction that contains the hashBytes of a DID Update
82
+ * Bundle in its first transaction output. The corresponding DID Update Bundle MUST either be provided through Sidecar
83
+ * Data or by converting hashBytes into a IPFS v1 Content Identifier and attempting to retrieve it from Content
84
+ * Addressable Storage. The DID Update Bundle maps from did:btcr2 identifiers to hashes of DID Update payloads
85
+ * applicable for that identifier. Again this algorithm attempts to retrieve and validate the DID Update Payload
86
+ * identified for the identifier being resolved. If successful, the DID Update Payload is returned.
87
+ *
88
+ * The Process CIDAggregate Beacon Signal algorithm is called by the Process Beacon Signals algorithm as part of the
89
+ * Read operation.
90
+ *
91
+ * It takes as inputs a did:btcr2 identifier, btc1Identifier, a Beacon Signal, tx, and a optional
92
+ * object, signalSidecarData, containing any sidecar data provided to the resolver for the Beacon Signal identified by
93
+ * the Bitcoin transaction identifier.
94
+ *
95
+ * It returns the DID Update payload announced by the Beacon Signal for the
96
+ * did:btcr2 identifier being resolved or throws an error.
97
+ *
98
+ * @param {RawTransactionV2} signal Bitcoin transaction representing a Beacon Signal.
99
+ * @param {SignalsMetadata} signalsMetadata Optional sidecar data for the Beacon Signal.
100
+ * @returns {Promise<DidUpdatePayload | undefined>} The DID Update payload announced by the Beacon Signal.
101
+ * @throws {DidError} if the signalTx is invalid or the signalsMetadata is invalid.
102
+ */
103
+ processSignal(signal: RawTransactionV2, signalsMetadata: SignalsMetadata): Promise<DidUpdateInvocation | undefined> {
104
+ throw new Btcr2Error('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {signal, signalsMetadata});
105
+ }
106
+
107
+ /**
108
+ * TODO: Finish implementation
109
+ *
110
+ * Implements {@link https://dcdpr.github.io/did-btcr2/#broadcast-cidaggregate-beacon-signal | 5.2.2 Broadcast CIDAggregate Beacon Signal}.
111
+ *
112
+ * The Broadcast CIDAggregate Beacon Signal algorithm involving two roles: a set of cohort participants and a Beacon
113
+ * coordinator. The Beacon coordinator collects individual DID Update Payload Content Identifiers (CIDs) for specific
114
+ * did:btc1s and aggregates them into a DID Update Bundle, which is then published to a Content Addressable Storage
115
+ * (CAS). The CID for the DID Update Bundle is included in a Partially Signed Bitcoin Transaction (PSBT) transaction
116
+ * output spent from the Beacon’s n-of-n address. Each of the n cohort participants in the Beacon MUST sign the
117
+ * transaction before it can be broadcast to the network. It is RECOMMENDED that cohort participants keep a copy of
118
+ * the DID Update Bundle and separately pin it to the CAS.
119
+ *
120
+ * @param {DidUpdatePayload} didUpdatePayload The verificationMethod object to be used for signing.
121
+ * @returns {SignalsMetadata} Successful output of a bitcoin transaction.
122
+ * @throws {SingletonBeaconError} if the bitcoin address is invalid or unfunded.
123
+ */
124
+ broadcastSignal(didUpdatePayload: DidUpdatePayload): Promise<SignalsMetadata> {
125
+ throw new Btcr2Error('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, didUpdatePayload);
126
+ }
127
+
128
+ /**
129
+ * TODO: Finish implementation
130
+ *
131
+ * 5.2.1.1 Create CIDAggregate Beacon Advertisement
132
+ * Any entity MAY act in the role of Beacon coordinator, creating a Beacon advertisement that they can broadcast across any medium. A Beacon advertisement specifies the properties of the Beacon that
133
+ * the coordinator intends to establish, including the Beacon Type, cohort size, update frequency, and response latency. Once the advertisement has been created and broadcast, the coordinator waits
134
+ * for enough participants to opt in before establishing the Beacon.
135
+ *
136
+ * 5.2.1.2 CIDAggregate Beacon Opt-in
137
+ * DID controllers who wish to participate in a Beacon cohort first find potential Beacon advertisements that meet their needs. This includes checking the Beacon terms and update frequency, etc. If
138
+ * satisfied, they create a secp256k1 cohort keypair and send an Opt-In request to the endpoint specified in the advertisement.
139
+ *
140
+ * 5.2.1.3 Cohort Set
141
+ * Once a Beacon Aggregator has received enough opt-in responses from participants to satisfy the Beacon properties, they generate the n-of-n P2TR Bitcoin address for the Beacon. The address and all
142
+ * the cohort public keys the address is constructed from are then sent to all participants in a CohortSet message.
143
+ *
144
+ * 5.2.1.4 Add Beacon Service Endpoint to DID Document
145
+ * A participant receiving a CohortSet message first verifies their cohort key is included in the cohort, then calculates the P2TR Beacon address for themselves and verifies it matches the address
146
+ * provided. They MAY wait until the Beacon address is funded before adding the Beacon as a service in the DID document. The following is an example of the Beacon service endpoint the DID controller
147
+ * adds into their DID document, the Beacon address is converted into a URI following BIP21:
148
+ * {
149
+ * "id": "#cidAggregateBeacon",
150
+ * "type": "CIDAggregateBeacon",
151
+ * "serviceEndpoint": "bitcoin:tb1pfdnyc8vxeca2zpsg365sn308dmrpka4e0n9c5axmp2nptdf7j6ts7eqhr8"
152
+ * }
153
+ */
154
+ }
@@ -0,0 +1,36 @@
1
+ import { Btcr2Error } from '@did-btcr2/common';
2
+ import { Beacon } from '../../interfaces/beacon.js';
3
+ import { BeaconService } from '../../interfaces/ibeacon.js';
4
+ import { CIDAggregateSidecar, SidecarData, SMTAggregateSidecar } from '../../types/crud.js';
5
+ import { CIDAggregateBeacon } from './cid-aggregate.js';
6
+ import { SingletonBeacon } from './singleton.js';
7
+ import { SMTAggregateBeacon } from './smt-aggregate.js';
8
+
9
+ /**
10
+ * Beacon Factory pattern to create Beacon instances.
11
+ * @class BeaconFactory
12
+ * @type {BeaconFactory}
13
+ */
14
+ export class BeaconFactory {
15
+ /**
16
+ * Establish a Beacon instance based on the provided service and optional sidecar data.
17
+ * @param {BeaconService} service - The beacon service configuration.
18
+ * @param {SidecarData} [sidecar] - The optional sidecar data.
19
+ * @returns {Beacon} The established Beacon instance.
20
+ */
21
+ static establish(service: BeaconService, sidecar?: SidecarData): Beacon {
22
+ switch (service.type) {
23
+ case 'SingletonBeacon':
24
+ return new SingletonBeacon(service, sidecar);
25
+ case 'CIDAggregateBeacon':
26
+ return new CIDAggregateBeacon(service, sidecar as CIDAggregateSidecar);
27
+ case 'SMTAggregateBeacon':
28
+ return new SMTAggregateBeacon(service, sidecar as SMTAggregateSidecar);
29
+ default:
30
+ throw new Btcr2Error(
31
+ 'Invalid Beacon Type',
32
+ 'INVALID_BEACON_ERROR', { service, sidecar }
33
+ );
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,257 @@
1
+ import { DidUpdatePayload, INVALID_SIDECAR_DATA, LATE_PUBLISHING_ERROR, SingletonBeaconError } from '@did-btcr2/common';
2
+ import { opcodes, Psbt, script } from 'bitcoinjs-lib';
3
+ import { base58btc } from 'multiformats/bases/base58';
4
+ import bitcoinNetwork, { Bitcoin } from '../../bitcoin/index.js';
5
+ import { AddressUtxo, RawTransactionRest, Vout } from '../../bitcoin/rest-client.js';
6
+ import { Beacon } from '../../interfaces/beacon.js';
7
+ import { BeaconService, BeaconSignal } from '../../interfaces/ibeacon.js';
8
+ import { RawTransactionV2, TxOut } from '../../types/bitcoin.js';
9
+ import { BeaconSidecarData, Metadata, SignalsMetadata, SingletonSidecar } from '../../types/crud.js';
10
+ import { Btc1Appendix } from '../../utils/appendix.js';
11
+ import { Btc1KeyManager, Signer } from '../key-manager/index.js';
12
+
13
+ /**
14
+ * Implements {@link https://dcdpr.github.io/did-btcr2/#singleton-beacon | 5.1 Singleton Beacon}.
15
+ *
16
+ * A Singleton Beacon enables a single entity to independently post a DID Update Payload in a Beacon Signal. Its is a
17
+ * Beacon that can be used to publish a single DID Update Payload targeting a single DID document. The serviceEndpoint
18
+ * for this Beacon Type is a Bitcoin address represented as a URI following the BIP21 scheme. It is recommended that
19
+ * this Bitcoin address be under the sole control of the DID controller. How the Bitcoin address and the cryptographic
20
+ * material that controls it are generated is left to the implementation.
21
+ *
22
+ * @class SingletonBeacon
23
+ * @type {SingletonBeacon}
24
+ * @extends {Beacon}
25
+ */
26
+ export class SingletonBeacon extends Beacon {
27
+
28
+ /**
29
+ * Creates an instance of SingletonBeacon.
30
+ * @param {BeaconService} service The Beacon service.
31
+ * @param {?BeaconSidecarData} [sidecar] Optional sidecar data.
32
+ */
33
+ constructor(service: BeaconService, sidecar?: BeaconSidecarData<SingletonSidecar>) {
34
+ super({ ...service, type: 'SingletonBeacon' }, sidecar);
35
+ }
36
+
37
+ /**
38
+ * Get the Beacon service.
39
+ * @readonly
40
+ * @type {BeaconService} The Beacon service.
41
+ */
42
+ get service(): BeaconService {
43
+ return {
44
+ type : this.type,
45
+ id : this.id,
46
+ serviceEndpoint : this.serviceEndpoint
47
+ };
48
+ }
49
+
50
+ /**
51
+ * Implements {@link https://dcdpr.github.io/did-btcr2/#establish-singleton-beacon | 5.1.1 Establish Singleton Beacon}.
52
+ *
53
+ * Static, convenience method for establishing a Beacon object.
54
+ *
55
+ * A Singleton Beacon is a Beacon that can be used to publish a single DID Update Payload targeting a single DID
56
+ * document. The serviceEndpoint for this Beacon Type is a Bitcoin address represented as a URI following the BIP21
57
+ * scheme. It is RECOMMENDED that this Bitcoin address be under the sole control of the DID controller. How the
58
+ * Bitcoin address and the cryptographic material that controls it are generated is left to the implementation.
59
+ * The Establish Singleton Beacon algorithm takes in a Bitcoin address and a serviceId and returns a Singleton Beacon service.
60
+ * It returns a SignletonBeacon object with the given id, type, and serviceEndpoint.
61
+ *
62
+ * @param {string} service The Beacon service.
63
+ * @param {BeaconSidecarData<SingletonSidecar>} sidecar The sidecar data.
64
+ * @returns {SingletonBeacon} The Singleton Beacon.
65
+ */
66
+ public static establish(service: BeaconService, sidecar: BeaconSidecarData<SingletonSidecar>): SingletonBeacon {
67
+ return new SingletonBeacon(service, sidecar);
68
+ }
69
+
70
+ /**
71
+ * TODO: Figure out if this is necessary or not.
72
+ * @param {string} didUpdatePayload The DID Update Payload to generate the signal for.
73
+ * @returns {BeaconSignal} The generated signal.
74
+ * @throws {Btcr2Error} if the signal is invalid.
75
+ */
76
+ public generateSignal(didUpdatePayload: string): BeaconSignal {
77
+ throw new Error('Method not implemented.' + didUpdatePayload);
78
+ }
79
+
80
+ /**
81
+ * TODO: Finish implementation per spec
82
+ *
83
+ * Implements {@link https://dcdpr.github.io/did-btcr2/#process-singleton-beacon-signal | 5.1.3 Process Singleton Beacon Signal}.
84
+ * See {@link Beacon.processSignal | Abstract Beacon Interface Method processSignal} for more details.
85
+ *
86
+ * The Process Singleton Beacon Signal algorithm is called by the Process Beacon Signals algorithm as part of the Read
87
+ * operation. It takes a Bitcoin transaction representing a Beacon Signal and optional signalSidecarData containing
88
+ * any sidecar data provided to the resolver for the Beacon Signal identified by the Bitcoin transaction identifier.
89
+ * It returns the DID Update payload announced by the Beacon Signal or throws an error.
90
+ *
91
+ * @param {RawTransactionV2} signal Bitcoin transaction representing a Beacon Signal.
92
+ * @param {SignalsMetadata} signalsMetadata: SignalsMetadata Optional sidecar data for the Beacon Signal.
93
+ * @returns {Promise<DidUpdatePayload | undefined>} The DID Update payload announced by the Beacon Signal.
94
+ * @throws {DidError} if the signalTx is invalid or the signalSidecarData is invalid.
95
+ */
96
+ public async processSignal(signal: RawTransactionV2 | RawTransactionRest, signalsMetadata: SignalsMetadata): Promise<DidUpdatePayload | undefined> {
97
+ // 1. Initialize a txOut variable to the 0th transaction output of the tx.
98
+ const output = signal.vout.filter((vout) => ((vout as Vout)['scriptpubkey_asm'] as string || (vout as TxOut)['scriptPubKey'].asm as string).includes('OP_RETURN'))?.[0];
99
+ if(!output) {
100
+ throw new SingletonBeaconError('No OP_RETURN output found in transaction outputs.', 'NO_OP_RETURN', { signal });
101
+ }
102
+ const outputMap = new Map(Object.entries(output));
103
+
104
+ // 2. Set didUpdatePayload to null.
105
+ let didUpdatePayload: DidUpdatePayload | undefined = undefined;
106
+
107
+ // 3. Check txout is of the format [OP_RETURN, OP_PUSH32, <32bytes>], if not, then return didUpdatePayload.
108
+ // The Bitcoin transaction is not a Beacon Signal.
109
+ const UPDATE_PAYLOAD_HASH = (outputMap.get('scriptpubkey_asm') ?? outputMap.get('scriptPubKey').asm).split(' ').last() as string;
110
+ if(!UPDATE_PAYLOAD_HASH) {
111
+ return undefined;
112
+ }
113
+ // 4. Set hashBytes to the 32 bytes in the txout.
114
+ const hashBytes = JSON.canonicalization.encode(Buffer.fromHex(UPDATE_PAYLOAD_HASH), 'base58');
115
+
116
+ // Convert signalsMetadata to a Map for easier access
117
+ const signalsMetadataMap = new Map<string, Metadata>(Object.entries(signalsMetadata));
118
+
119
+ // 5. If signalsMetadata:
120
+ if (signalsMetadata) {
121
+ // 5.1 Set didUpdatePayload to signalsMetadata.updatePayload
122
+ didUpdatePayload = signalsMetadataMap.get(signal.txid)?.btc1Update;
123
+
124
+ if(!didUpdatePayload) {
125
+ throw new SingletonBeaconError('Update Payload not found in signal metadata.', 'PROCESS_SIGNAL_ERROR');
126
+ }
127
+
128
+ // 5.2 Set updateHashBytes to the result of passing didUpdatePayload to the JSON Canonicalization and Hash algorithm.
129
+ const updateHashBytes = await JSON.canonicalization.process(didUpdatePayload, 'base58');
130
+
131
+ // 5.3 If updateHashBytes does not equal hashBytes, MUST throw an invalidSidecarData error.
132
+ if (updateHashBytes !== hashBytes) {
133
+ throw new SingletonBeaconError(
134
+ `Hash mismatch: updateHashBytes ${updateHashBytes} !== hashBytes ${hashBytes}.`,
135
+ INVALID_SIDECAR_DATA,
136
+ { UPDATE_PAYLOAD_HASH, didUpdatePayload }
137
+ );
138
+ }
139
+ // 7. Return didUpdatePayload.
140
+ return didUpdatePayload;
141
+ }
142
+
143
+ // 6. Else:
144
+ // 6.1 Set didUpdatePayload to the result of passing hashBytes into the Fetch Content from Addressable Storage algorithm.
145
+ const didUpdatePayloadString = await Btc1Appendix.fetchFromCas(base58btc.decode(hashBytes));
146
+ if(!didUpdatePayloadString || !JSON.parse(didUpdatePayloadString)) {
147
+ throw new SingletonBeaconError('Update payload not found in addressable storage.', INVALID_SIDECAR_DATA);
148
+ }
149
+ didUpdatePayload = JSON.parse(didUpdatePayloadString) as DidUpdatePayload;
150
+
151
+ // 6.2 If didUpdatePayload is null, MUST raise a latePublishingError. MAY identify Beacon Signal to resolver and request additional Sidecar data be provided.
152
+ if (!didUpdatePayload) {
153
+ throw new SingletonBeaconError('Update payload hash does not match transaction hash.', LATE_PUBLISHING_ERROR);
154
+ }
155
+
156
+ // 7. Return didUpdatePayload.
157
+ return didUpdatePayload;
158
+ }
159
+
160
+
161
+ /**
162
+ * Implements {@link https://dcdpr.github.io/did-btcr2/#broadcast-singleton-beacon-signal | 5.1.2 Broadcast Singleton Beacon Signal}.
163
+ *
164
+ * The Broadcast Singleton Beacon Signal algorithm is called by the Announce DID Update algorithm as part of the
165
+ * Update operation, if the Beacon being used is of the type SingletonBeacon. It takes as input a Beacon service and a
166
+ * secured didUpdatePayload. The algorithm constructs a Bitcoin transaction that spends from the Beacon address
167
+ * identified in the service and contains a transaction output of the format [OP_RETURN, OP_PUSH32, <hashBytes>],
168
+ * where hashBytes is the SHA256 hash of the canonical didUpdatePayload. The Bitcoin transaction is then signed and
169
+ * broadcast to the Bitcoin network, thereby publicly announcing a DID update in a Beacon Signal. It returns a
170
+ * signalMetadata object mapping the Bitcoin transaction identifier of the Beacon Signal to the necessary data needed
171
+ * to verify the signal announces a specific DID Update Payload.
172
+ *
173
+ * TODO: Design and implement a way to construct, sign and send via RPC
174
+ *
175
+ * @param {DidUpdatePayload} didUpdatePayload The verificationMethod object to be used for signing.
176
+ * @returns {SignedRawTx} Successful output of a bitcoin transaction.
177
+ * @throws {SingletonBeaconError} if the bitcoin address is invalid or unfunded.
178
+ */
179
+ public async broadcastSignal(didUpdatePayload: DidUpdatePayload): Promise<SignalsMetadata> {
180
+ // Grab the connection configuration from the environment variable or default to the rpc config
181
+ const bitcoin = bitcoinNetwork ?? new Bitcoin();
182
+
183
+ // 1. Initialize an addressURI variable to beacon.serviceEndpoint.
184
+ // 2. Set bitcoinAddress to the decoding of addressURI following BIP21.
185
+ const bitcoinAddress = this.service.serviceEndpoint.replace('bitcoin:', '');
186
+
187
+ // 3. Ensure bitcoinAddress is funded, if not, fund this address.
188
+ // let inputs: Array<CreateRawTxInputs> = [];
189
+
190
+ const utxos = await bitcoin.rest.address.getUtxos(bitcoinAddress);
191
+ if(!utxos.length) {
192
+ // TODO: Discuss what to do here because sending to a beacon address does not allow you to spend from it immediately.
193
+ throw new SingletonBeaconError('No UTXOs found, please fund address!', 'UNFUNDED_BEACON_ADDRESS', { bitcoinAddress });
194
+ }
195
+
196
+ const utxo: AddressUtxo = utxos.sort((a, b) => b.status.block_height - a.status.block_height)[0];
197
+ if(!utxo) {
198
+ throw new SingletonBeaconError(
199
+ 'Beacon bitcoin address unfunded or utxos unconfirmed.',
200
+ 'UNFUNDED_BEACON_ADDRESS', { bitcoinAddress });
201
+ }
202
+
203
+ // 4. Set hashBytes to the result of passing didUpdatePayload to the JSON Canonicalization and Hash algorithm.
204
+ const hashBytes = Buffer.fromHex(await JSON.canonicalization.process(didUpdatePayload));
205
+ if (hashBytes.length !== 32) throw new SingletonBeaconError('Hash must be 32 bytes');
206
+
207
+ // 5. Initialize spendTx to a Bitcoin transaction that spends a transaction controlled by the bitcoinAddress and
208
+ // contains at least one transaction output. This output MUST have the following format
209
+ // [OP_RETURN, OP_PUSH32, hashBytes]
210
+ const {txid, vout} = utxo;
211
+ const prevTx = await bitcoin.rest.transaction.getHex(txid);
212
+ const input = {
213
+ hash : txid,
214
+ index : vout,
215
+ nonWitnessUtxo : Buffer.fromHex(prevTx)
216
+ };
217
+ // TODO: Figure out a good way to estimate fees
218
+ const spendTx = new Psbt({ network: bitcoin.network.data })
219
+ .addInput(input)
220
+ .addOutput({ address: bitcoinAddress, value: BigInt(utxo.value) - BigInt(500) })
221
+ .addOutput({ script: script.compile([opcodes.OP_RETURN, hashBytes]), value: 0n });
222
+
223
+ // 6. Retrieve the cryptographic material, e.g private key or signing capability, associated with the bitcoinAddress
224
+ // or service. How this is done is left to the implementer.
225
+ // TODO: Determine how we want to handle this. Currently, this code uses the RPC to handle signing.
226
+ console.log('Btc1KeyManager', Btc1KeyManager.instance);
227
+ console.log('this.service.id', this.service.id);
228
+ const multikey = await Btc1KeyManager.getKeyPair(this.service.id);
229
+ console.log('multikey', multikey);
230
+ if (!multikey) {
231
+ throw new Error('Key pair not found.');
232
+ }
233
+
234
+ const signer = new Signer({ multikey, network: bitcoin.network.name });
235
+
236
+ // 7. Sign the spendTx.
237
+ const signedTx = spendTx.signInput(0, signer)
238
+ .finalizeAllInputs()
239
+ .extractTransaction()
240
+ .toHex();
241
+ if(!spendTx) {
242
+ throw new SingletonBeaconError('Failed to sign raw transaction.', 'RAW_TX_SIGN_FAILED', { spendTx });
243
+ }
244
+
245
+ // 8. Broadcast spendTx to the Bitcoin network.
246
+ const spentTx = await bitcoin.rest.transaction.send(signedTx);
247
+ if(!spentTx) {
248
+ throw new SingletonBeaconError('Failed to send raw transaction.', 'SEND_FAILED', { spentTx });
249
+ }
250
+
251
+ // 9. Set signalId to the Bitcoin transaction identifier of spendTx.
252
+ // 10. Initialize signalMetadata to an empty object.
253
+ // 11. Set signalMetadata.updatePayload to didUpdatePayload.
254
+ // 12. Return the object {<signalId>: { updatePayload: DidUpdatePayload; proofs?: any; }}.
255
+ return { [spentTx]: { btc1Update: didUpdatePayload } };
256
+ }
257
+ }