@did-btcr2/method 0.19.0 → 0.22.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 (120) hide show
  1. package/README.md +223 -1
  2. package/dist/browser.js +3496 -4202
  3. package/dist/browser.mjs +3496 -4202
  4. package/dist/cjs/core/beacon/beacon.js +25 -0
  5. package/dist/cjs/core/beacon/beacon.js.map +1 -0
  6. package/dist/cjs/core/beacon/cas-beacon.js +20 -36
  7. package/dist/cjs/core/beacon/cas-beacon.js.map +1 -1
  8. package/dist/cjs/core/beacon/error.js +4 -4
  9. package/dist/cjs/core/beacon/error.js.map +1 -1
  10. package/dist/cjs/core/beacon/factory.js +5 -7
  11. package/dist/cjs/core/beacon/factory.js.map +1 -1
  12. package/dist/cjs/core/beacon/interfaces.js +1 -31
  13. package/dist/cjs/core/beacon/interfaces.js.map +1 -1
  14. package/dist/cjs/core/beacon/signal-discovery.js +183 -0
  15. package/dist/cjs/core/beacon/signal-discovery.js.map +1 -0
  16. package/dist/cjs/core/beacon/singleton.js +56 -86
  17. package/dist/cjs/core/beacon/singleton.js.map +1 -1
  18. package/dist/cjs/core/beacon/smt-beacon.js +22 -39
  19. package/dist/cjs/core/beacon/smt-beacon.js.map +1 -1
  20. package/dist/cjs/core/beacon/utils.js +4 -9
  21. package/dist/cjs/core/beacon/utils.js.map +1 -1
  22. package/dist/cjs/core/resolve.js +121 -307
  23. package/dist/cjs/core/resolve.js.map +1 -1
  24. package/dist/cjs/core/update.js +62 -154
  25. package/dist/cjs/core/update.js.map +1 -1
  26. package/dist/cjs/did-btcr2.js +100 -91
  27. package/dist/cjs/did-btcr2.js.map +1 -1
  28. package/dist/cjs/index.js +3 -1
  29. package/dist/cjs/index.js.map +1 -1
  30. package/dist/cjs/utils/appendix.js +6 -15
  31. package/dist/cjs/utils/appendix.js.map +1 -1
  32. package/dist/cjs/utils/did-document-builder.js +5 -6
  33. package/dist/cjs/utils/did-document-builder.js.map +1 -1
  34. package/dist/cjs/utils/did-document.js +42 -38
  35. package/dist/cjs/utils/did-document.js.map +1 -1
  36. package/dist/esm/core/beacon/beacon.js +25 -0
  37. package/dist/esm/core/beacon/beacon.js.map +1 -0
  38. package/dist/esm/core/beacon/cas-beacon.js +20 -36
  39. package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
  40. package/dist/esm/core/beacon/error.js +4 -4
  41. package/dist/esm/core/beacon/error.js.map +1 -1
  42. package/dist/esm/core/beacon/factory.js +5 -7
  43. package/dist/esm/core/beacon/factory.js.map +1 -1
  44. package/dist/esm/core/beacon/interfaces.js +1 -31
  45. package/dist/esm/core/beacon/interfaces.js.map +1 -1
  46. package/dist/esm/core/beacon/signal-discovery.js +183 -0
  47. package/dist/esm/core/beacon/signal-discovery.js.map +1 -0
  48. package/dist/esm/core/beacon/singleton.js +56 -86
  49. package/dist/esm/core/beacon/singleton.js.map +1 -1
  50. package/dist/esm/core/beacon/smt-beacon.js +22 -39
  51. package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
  52. package/dist/esm/core/beacon/utils.js +4 -9
  53. package/dist/esm/core/beacon/utils.js.map +1 -1
  54. package/dist/esm/core/resolve.js +121 -307
  55. package/dist/esm/core/resolve.js.map +1 -1
  56. package/dist/esm/core/update.js +62 -154
  57. package/dist/esm/core/update.js.map +1 -1
  58. package/dist/esm/did-btcr2.js +100 -91
  59. package/dist/esm/did-btcr2.js.map +1 -1
  60. package/dist/esm/index.js +3 -1
  61. package/dist/esm/index.js.map +1 -1
  62. package/dist/esm/utils/appendix.js +6 -15
  63. package/dist/esm/utils/appendix.js.map +1 -1
  64. package/dist/esm/utils/did-document-builder.js +5 -6
  65. package/dist/esm/utils/did-document-builder.js.map +1 -1
  66. package/dist/esm/utils/did-document.js +42 -38
  67. package/dist/esm/utils/did-document.js.map +1 -1
  68. package/dist/types/core/beacon/beacon.d.ts +44 -0
  69. package/dist/types/core/beacon/beacon.d.ts.map +1 -0
  70. package/dist/types/core/beacon/cas-beacon.d.ts +19 -30
  71. package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
  72. package/dist/types/core/beacon/error.d.ts +2 -2
  73. package/dist/types/core/beacon/error.d.ts.map +1 -1
  74. package/dist/types/core/beacon/factory.d.ts +4 -6
  75. package/dist/types/core/beacon/factory.d.ts.map +1 -1
  76. package/dist/types/core/beacon/interfaces.d.ts +7 -46
  77. package/dist/types/core/beacon/interfaces.d.ts.map +1 -1
  78. package/dist/types/core/beacon/signal-discovery.d.ts +25 -0
  79. package/dist/types/core/beacon/signal-discovery.d.ts.map +1 -0
  80. package/dist/types/core/beacon/singleton.d.ts +17 -30
  81. package/dist/types/core/beacon/singleton.d.ts.map +1 -1
  82. package/dist/types/core/beacon/smt-beacon.d.ts +21 -33
  83. package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
  84. package/dist/types/core/beacon/utils.d.ts.map +1 -1
  85. package/dist/types/core/interfaces.d.ts +1 -8
  86. package/dist/types/core/interfaces.d.ts.map +1 -1
  87. package/dist/types/core/resolve.d.ts +34 -47
  88. package/dist/types/core/resolve.d.ts.map +1 -1
  89. package/dist/types/core/types.d.ts +21 -8
  90. package/dist/types/core/types.d.ts.map +1 -1
  91. package/dist/types/core/update.d.ts +30 -73
  92. package/dist/types/core/update.d.ts.map +1 -1
  93. package/dist/types/did-btcr2.d.ts +44 -47
  94. package/dist/types/did-btcr2.d.ts.map +1 -1
  95. package/dist/types/index.d.ts +3 -1
  96. package/dist/types/index.d.ts.map +1 -1
  97. package/dist/types/utils/appendix.d.ts.map +1 -1
  98. package/dist/types/utils/did-document-builder.d.ts +5 -1
  99. package/dist/types/utils/did-document-builder.d.ts.map +1 -1
  100. package/dist/types/utils/did-document.d.ts +26 -21
  101. package/dist/types/utils/did-document.d.ts.map +1 -1
  102. package/package.json +8 -7
  103. package/src/core/beacon/beacon.ts +58 -0
  104. package/src/core/beacon/cas-beacon.ts +30 -44
  105. package/src/core/beacon/error.ts +5 -6
  106. package/src/core/beacon/factory.ts +7 -9
  107. package/src/core/beacon/interfaces.ts +7 -64
  108. package/src/core/beacon/signal-discovery.ts +237 -0
  109. package/src/core/beacon/singleton.ts +78 -100
  110. package/src/core/beacon/smt-beacon.ts +32 -49
  111. package/src/core/beacon/utils.ts +16 -13
  112. package/src/core/interfaces.ts +1 -9
  113. package/src/core/resolve.ts +163 -395
  114. package/src/core/types.ts +25 -8
  115. package/src/core/update.ts +91 -236
  116. package/src/did-btcr2.ts +154 -116
  117. package/src/index.ts +8 -1
  118. package/src/utils/appendix.ts +8 -22
  119. package/src/utils/did-document-builder.ts +5 -7
  120. package/src/utils/did-document.ts +80 -73
package/src/core/types.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { HexString } from '@did-btcr2/common';
2
- import { BTCR2SignedUpdate } from '@did-btcr2/cryptosuite';
2
+ import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
3
3
  import { SMTProof } from './interfaces.js';
4
4
 
5
5
  /**
@@ -41,7 +41,7 @@ export type Sidecar = {
41
41
  * Optional array of BTCR2 Signed Updates. Required if the DID being resolved
42
42
  * has ever had a published BTCR2 Update.
43
43
  */
44
- updates?: Array<BTCR2SignedUpdate>
44
+ updates?: Array<SignedBTCR2Update>
45
45
 
46
46
  /**
47
47
  * Optional array of CAS Announcements. Required if the DID being reslved has
@@ -56,23 +56,40 @@ export type Sidecar = {
56
56
  smtProofs?: Array<SMTProof>;
57
57
  };
58
58
 
59
+ /**
60
+ * The Sidecar data structure used for Singleton Beacons.
61
+ */
62
+ export type SingletonBeaconSidecarData = Map<HexString, SignedBTCR2Update>;
63
+ /**
64
+ * The Sidecar data structure used for CAS Beacons.
65
+ */
66
+ export type CASBeaconSidecarData = Map<HexString, CASAnnouncement>;
67
+ /**
68
+ * The Sidecar data structure used for SMT Beacons.
69
+ */
70
+ export type SMTBeaconSidecarData = Map<string, SMTProof>;
71
+
59
72
  /**
60
73
  * The Sidecar data structure post-processing used for resolution.
61
74
  */
62
75
  export type SidecarData = {
63
76
  /**
64
77
  * Map of BTCR2 Signed Updates by their hash bytes.
65
- * @type {Map<HexString, BTCR2SignedUpdate>}
66
78
  */
67
- updateMap: Map<HexString, BTCR2SignedUpdate>;
79
+ updateMap: SingletonBeaconSidecarData;
80
+
68
81
  /**
69
82
  * Map of CAS Announcements by their hash bytes.
70
- * @type {Map<HexString, CASAnnouncement>}
71
83
  */
72
- casMap: Map<HexString, CASAnnouncement>;
84
+ casMap: CASBeaconSidecarData;
85
+
73
86
  /**
74
87
  * Map of SMT Proofs by their ID.
75
- * @type {Map<string, SMTProof>}
76
88
  */
77
- smtMap: Map<string, SMTProof>;
89
+ smtMap: SMTBeaconSidecarData;
78
90
  }
91
+
92
+ /**
93
+ * Union type for all Beacon Sidecar data structures.
94
+ */
95
+ export type BeaconSidecarData = SingletonBeaconSidecarData | CASBeaconSidecarData | SMTBeaconSidecarData;
@@ -1,44 +1,24 @@
1
1
  import {
2
- INVALID_DID_DOCUMENT,
2
+ Canonicalization,
3
3
  INVALID_DID_UPDATE,
4
- INVALID_PUBLIC_KEY_TYPE,
5
4
  JSONPatch,
6
- MethodError,
7
- NOT_FOUND,
5
+ KeyBytes,
8
6
  PatchOperation,
9
7
  UpdateError
10
8
  } from '@did-btcr2/common';
11
- import { BTCR2SignedUpdate, BTCR2UnsignedUpdate, DataIntegrityConfig, SchnorrMultikey } from '@did-btcr2/cryptosuite';
12
- import { CompressedSecp256k1PublicKey, SchnorrKeyPair, Secp256k1SecretKey } from '@did-btcr2/keypair';
13
- import { Kms } from '@did-btcr2/kms';
14
- import type { DidService } from '@web5/dids';
15
- import { canonicalization } from '../did-btcr2.js';
16
- import { Appendix } from '../utils/appendix.js';
17
- import { DidDocument, DidVerificationMethod } from '../utils/did-document.js';
9
+ import {
10
+ DataIntegrityConfig,
11
+ SchnorrMultikey,
12
+ SignedBTCR2Update,
13
+ UnsignedBTCR2Update
14
+ } from '@did-btcr2/cryptosuite';
15
+ import { Btcr2DidDocument, DidDocument, DidVerificationMethod } from '../utils/did-document.js';
16
+ import { BeaconFactory } from './beacon/factory.js';
18
17
  import { BeaconService } from './beacon/interfaces.js';
19
- import { Identifier } from './identifier.js';
20
- import { SidecarData } from './types.js';
21
-
22
- export interface ConstructUpdateParams {
23
- identifier: string;
24
- sourceDocument: DidDocument;
25
- sourceVersionId: number;
26
- patch: PatchOperation[];
27
- }
28
-
29
- export interface UpdateParams extends ConstructUpdateParams {
30
- verificationMethodId: string;
31
- beaconIds: string[];
32
- }
33
-
34
- export type InvokePayloadParams = {
35
- identifier: string;
36
- BTCR2SignedUpdate: BTCR2SignedUpdate;
37
- verificationMethod: DidVerificationMethod;
38
- }
18
+ import { BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
39
19
 
40
20
  /**
41
- * Implements {@link https://dcdpr.github.io/did-btcr2/#update | 4.3 Update}.
21
+ * Implements {@link https://dcdpr.github.io/did-btcr2/operations/update.html | 7.3 Update}.
42
22
  *
43
23
  * An update to a did:btcr2 document is an invoked capability using the ZCAP-LD
44
24
  * data format, signed by a verificationMethod that has the authority to make
@@ -51,154 +31,80 @@ export type InvokePayloadParams = {
51
31
  */
52
32
  export class Update {
53
33
  /**
54
- * Implements {@link https://dcdpr.github.io/did-btcr2/#construct-did-update-payload | 4.3.1 Construct DID Update Payload}.
55
- *
56
- * The Construct DID Update Payload algorithm applies the documentPatch to the sourceDocument and verifies the
57
- * resulting targetDocument is a conformant DID document. It takes in a Identifier, sourceDocument,
58
- * sourceVersionId, and documentPatch objects. It returns an unsigned DID Update Payload.
34
+ * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/update.html#construct-btcr2-unsigned-update | 7.3.b Construct BTCR2 Unsigned Update}.
35
+ * This process constructs a BTCR2 Unsigned Update conformant to the spec template.
59
36
  *
60
- * @param {ConstructPayloadParams} params See {@link ConstructPayloadParams} for more details.
61
- * @param {string} params.identifier The did-btcr2 identifier to use for verification.
62
- * @param {DidDocument} params.sourceDocument The source document to be updated.
63
- * @param {string} params.sourceVersionId The versionId of the source document.
64
- * @param {DidDocumentPatch} params.patch The JSON patch to be applied to the source document.
65
- * @returns {Promise<BTCR2SignedUpdate>} The constructed BTCR2SignedUpdate object.
66
- * @throws {MethodError} InvalidDid if sourceDocument.id does not match identifier.
37
+ * @param {Btcr2DidDocument} sourceDocument The source DID document to be updated.
38
+ * @param {PatchOperation[]} patches The array of JSON Patch operations to apply to the sourceDocument.
39
+ * @param {number} sourceVersionId The version ID of the source document.
40
+ * @returns {Promise<SignedBTCR2Update>} The constructed SignedBTCR2Update object.
41
+ * @throws {UpdateError} InvalidDid if sourceDocument.id does not match identifier.
67
42
  */
68
- public static async construct({
69
- identifier,
70
- sourceDocument,
71
- sourceVersionId,
72
- patch,
73
- }: {
74
- identifier: string;
75
- sourceDocument: DidDocument;
76
- sourceVersionId: number;
77
- patch: PatchOperation[];
78
- }): Promise<BTCR2UnsignedUpdate> {
79
-
80
- // 1. Check that sourceDocument.id equals identifier else MUST raise invalidDIDUpdate error.
81
- if (sourceDocument.id !== identifier) {
82
- throw new UpdateError(
83
- 'Identifier mismatch: sourceDocument.id !== identifier',
84
- INVALID_DID_UPDATE, { sourceDocument, identifier }
85
- );
86
- }
87
-
88
- // 2. Initialize an unsigned update.
89
- const unsignedUpdate: BTCR2UnsignedUpdate = {
90
- // 3. Set BTCR2SignedUpdate.@context to the following list
43
+ static async construct(
44
+ sourceDocument: Btcr2DidDocument,
45
+ patches: PatchOperation[],
46
+ sourceVersionId: number,
47
+ ): Promise<UnsignedBTCR2Update> {
48
+ // Initialize an unsigned update conformant to btcr2 spec.
49
+ const unsignedUpdate: UnsignedBTCR2Update = {
91
50
  '@context' : [
92
51
  'https://w3id.org/security/v2',
93
52
  'https://w3id.org/zcap/v1',
94
53
  'https://w3id.org/json-ld-patch/v1',
95
54
  'https://btcr2.dev/context/v1'
96
55
  ],
97
- // 4. Set BTCR2SignedUpdate.patch to documentPatch.
98
- patch,
56
+ patch : patches,
99
57
  targetHash : '',
100
- targetVersionId : 0,
101
- sourceHash : '',
58
+ targetVersionId : sourceVersionId + 1,
59
+ sourceHash : Canonicalization.process(sourceDocument, { encoding: 'base58' }),
102
60
  };
103
61
 
104
- // 5. Set targetDocument to the result of applying the documentPatch to the sourceDocument, following the JSON Patch
105
- // specification.
106
- const targetDocument = JSONPatch.apply(sourceDocument, patch) as DidDocument;
62
+ // Apply all JSON patches to sourceDocument.
63
+ const targetDocument = JSONPatch.apply(sourceDocument, patches);
107
64
 
108
- // 6. Validate targetDocument is a conformant DID document, else MUST raise invalidDIDUpdate error.
109
- DidDocument.validate(targetDocument);
110
-
111
- // 7. Set sourceHashBytes to the result of passing sourceDocument into the JSON Canonicalization and Hash algorithm.
112
- // 8. Set BTCR2SignedUpdate.sourceHash to the base58-btc Multibase encoding of sourceHashBytes.
113
- unsignedUpdate.sourceHash = (canonicalization.process(sourceDocument, { encoding: 'base58' })).slice(1);
114
- // TODO: Question - is base58btc the correct encoding scheme?
115
-
116
- // 9. Set targetHashBytes to the result of passing targetDocument into the JSON Canonicalization and Hash algorithm.
117
- // 10. Set BTCR2SignedUpdate.targetHash to the base58-btc Multibase encoding of targetHashBytes.
118
- unsignedUpdate.targetHash = (canonicalization.process(targetDocument, { encoding: 'base58' })).slice(1);
65
+ try {
66
+ // Ensure the targetDocument is conformant to DID Core v1.1.
67
+ DidDocument.isValid(targetDocument);
68
+ } catch (error) {
69
+ // If validation fails, throw an UpdateError with INVALID_DID_UPDATE.
70
+ throw new UpdateError(
71
+ 'Error validating targetDocument: ' + (error instanceof Error ? error.message : String(error)),
72
+ INVALID_DID_UPDATE, targetDocument
73
+ );
74
+ }
119
75
 
120
- // 11. Set BTCR2SignedUpdate.targetVersionId to sourceVersionId + 1.
121
- unsignedUpdate.targetVersionId = sourceVersionId + 1;
76
+ // Set the targetHash by canonicalizing the targetDocument and encoding it in base58.
77
+ unsignedUpdate.targetHash = Canonicalization.process(targetDocument, { encoding: 'base58' });
122
78
 
123
- // 12. Return updatePayload.
79
+ // Return unsignedUpdate.
124
80
  return unsignedUpdate;
125
81
  }
126
82
 
127
83
  /**
128
- * {@link https://dcdpr.github.io/did-btcr2/#invoke-did-update-payload | 4.3.2 Invoke DID Update Payload}.
84
+ * Implements subsection {@link http://dcdpr.github.io/did-btcr2/operations/update.html#construct-btcr2-signed-update | 7.3.c Construct BTCR2 Signed Update }.
85
+ * This process constructs a BTCR2 Signed Update from a BTCR2 Unsigned Update.
129
86
  *
130
- * The Invoke DID Update Payload algorithm takes in a Identifier, an unsigned BTCR2SignedUpdate, and a
131
- * verificationMethod. It retrieves the privateKeyBytes for the verificationMethod and adds a capability invocation in
132
- * the form of a Data Integrity proof following the Authorization Capabilities (ZCAP-LD) and VC Data Integrity
133
- * specifications. It returns the invoked DID Update Payload.
134
- *
135
- * @param {InvokePayloadParams} params Required params for calling the invokePayload method
136
- * @param {string} params.identifier The did-btcr2 identifier to derive the root capability from
137
- * @param {BTCR2SignedUpdate} params.BTCR2SignedUpdate The updatePayload object to be signed
138
- * @param {DidVerificationMethod} params.verificationMethod The verificationMethod object to be used for signing
139
- * @returns {BTCR2SignedUpdate} Did update payload secured with a proof => BTCR2SignedUpdate
140
- * @throws {MethodError} if the privateKeyBytes are invalid
87
+ * @param {string} did The did-btcr2 identifier to derive the root capability from
88
+ * @param {UnsignedBTCR2Update} unsignedUpdate The updatePayload object to be signed
89
+ * @param {DidVerificationMethod} verificationMethod The verificationMethod object to be used for signing
90
+ * @returns {SignedBTCR2Update} Did update payload secured with a proof => SignedBTCR2Update
91
+ * @throws {UpdateError} if the privateKeyBytes are invalid
141
92
  */
142
- public static async invoke({
143
- identifier,
144
- unsignedUpdate,
145
- verificationMethod
146
- }: {
147
- identifier: string;
148
- unsignedUpdate: BTCR2UnsignedUpdate;
149
- verificationMethod: DidVerificationMethod;
150
- }): Promise<BTCR2SignedUpdate> {
151
- // Deconstruct the verificationMethod
152
- const { id: fullId, controller, publicKeyMultibase, secretKeyMultibase } = verificationMethod;
153
-
154
- // Validate the verificationMethod
155
- if(!publicKeyMultibase) {
156
- throw new MethodError(
157
- 'Invalid publicKeyMultibase: cannot be undefined',
158
- INVALID_PUBLIC_KEY_TYPE, verificationMethod
159
- );
160
- }
161
-
162
- // 1. Set privateKeyBytes to the result of retrieving the private key bytes
163
- // associated with the verificationMethod value.
164
- // 1.1 Let id be the fragment portion of verificationMethod.id.
165
- const id = fullId.slice(fullId.indexOf('#'));
166
-
167
- // 1.2 Retrieve the key pair from the KMS or from the secretKeyMultibase
168
- const components = Identifier.decode(id);
169
- const keyUri = new CompressedSecp256k1PublicKey(components.genesisBytes).hex;
170
- const keys = secretKeyMultibase
171
- ? new SchnorrKeyPair({ secretKey: Secp256k1SecretKey.decode(secretKeyMultibase) })
172
- : Kms.getKey(keyUri as string);
173
- if (!keys) {
174
- throw new MethodError(
175
- 'No privateKey found in kms or vm',
176
- NOT_FOUND, verificationMethod
177
- );
178
- }
179
-
180
- // 1.3 Set multikey to the result of passing verificationMethod and privateKeyBytes into the Multikey Creation algorithm.
181
- const multikey = SchnorrMultikey.create({ id, controller, keys });
182
-
183
- // 1.4 If the privateKey is not found, throw an error
184
- if (!multikey) {
185
- throw new MethodError(
186
- 'Failed to create multikey from verification method',
187
- 'MULTKEY_CREATE_FAILED', verificationMethod
188
- );
189
- }
190
-
191
- // 2. Set rootCapability to the result of passing Identifier into the Derive Root Capability from did:btcr2
192
- // Identifier algorithm.
193
- const rootCapability = Appendix.deriveRootCapability(identifier);
194
- const cryptosuite = 'bip340-jcs-2025';
195
- // 3. Initialize proofOptions to an empty object.
196
- // 4. Set proofOptions.type to DataIntegrityProof.
197
- // 5. Set proofOptions.cryptosuite to schnorr-secp256k1-jcs-2025.
198
- // 6. Set proofOptions.verificationMethod to verificationMethod.id.
199
- // 7. Set proofOptions.proofPurpose to capabilityInvocation.
200
- // 8. Set proofOptions.capability to rootCapability.id.
201
- // 9. Set proofOptions.capabilityAction to Write.
93
+ static async sign(
94
+ did: string,
95
+ unsignedUpdate: UnsignedBTCR2Update,
96
+ verificationMethod: DidVerificationMethod,
97
+ secretKey: KeyBytes,
98
+ ): Promise<SignedBTCR2Update> {
99
+ // Parse the controller from the verificationMethod
100
+ const controller = verificationMethod.controller;
101
+ // Parse the fragment from the vmId
102
+ const id = verificationMethod.id.slice(verificationMethod.id.indexOf('#'));
103
+
104
+ // Construct a Schnorr Multikey
105
+ const multikey = SchnorrMultikey.fromSecretKey(id, controller, secretKey);
106
+
107
+ // Define the Data Integrity proof config
202
108
  const config: DataIntegrityConfig = {
203
109
  '@context' : [
204
110
  'https://w3id.org/security/v2',
@@ -206,94 +112,43 @@ export class Update {
206
112
  'https://w3id.org/json-ld-patch/v1',
207
113
  'https://btcr2.dev/context/v1'
208
114
  ],
209
- cryptosuite,
115
+ cryptosuite : 'bip340-jcs-2025',
210
116
  type : 'DataIntegrityProof',
211
- verificationMethod : fullId,
117
+ verificationMethod : verificationMethod.id,
212
118
  proofPurpose : 'capabilityInvocation',
213
- capability : rootCapability.id,
119
+ capability : `urn:zcap:root:${encodeURIComponent(did)}`,
214
120
  capabilityAction : 'Write',
215
121
  };
216
122
 
217
- // 10. Set cryptosuite to the result of executing the Cryptosuite Instantiation algorithm from the BIP340 Data
218
- // Integrity specification passing in proofOptions.
123
+ // Go from multikey => cryptosuite => diproof
219
124
  const diproof = multikey.toCryptosuite().toDataIntegrityProof();
220
125
 
221
- // 12. Set BTCR2SignedUpdate to the result of executing the Add Proof algorithm from VC Data Integrity passing
222
- // BTCR2SignedUpdate as the input document, cryptosuite, and the set of proofOptions.
223
- // 13. Return BTCR2SignedUpdate.
224
- return await diproof.addProof(unsignedUpdate, config);
126
+ // Use the config to add a proof to the unsigned update
127
+ return diproof.addProof(unsignedUpdate, config);
225
128
  }
226
129
 
227
130
  /**
228
- * Implements {@link https://dcdpr.github.io/did-btcr2/#announce-did-update | 4.3.3 Announce DID Update}.
229
- *
230
- * The Announce DID Update algorithm retrieves beaconServices from the sourceDocument and calls the Broadcast DID
231
- * Update algorithm corresponding to the type of the Beacon. It takes in a Identifier, sourceDocument, an array of
232
- * beaconIds, and a BTCR2SignedUpdate. It returns an array of signalsMetadata, containing the necessary
233
- * data to validate the Beacon Signal against the BTCR2SignedUpdate.
234
- *
235
- * @param {AnnounceUpdatePayloadParams} params Required params for calling the announcePayload method
236
- * @param {DidDocument} params.sourceDocument The did-btcr2 did document to derive the root capability from
237
- * @param {string[]} params.beaconIds The BTCR2SignedUpdate object to be signed
238
- * @param {BTCR2SignedUpdate} params.BTCR2SignedUpdate The verificationMethod object to be used for signing
239
- * @returns {BTCR2SignedUpdate} The BTCR2SignedUpdate object containing data to validate the Beacon Signal
240
- * @throws {MethodError} if the beaconService type is invalid
131
+ * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/update.html#announce-did-update | 7.3.d Announce DID Update}.
132
+ * BTCR2 Signed Updates are announced to the Bitcoin blockchain depending on the Beacon Type.
133
+ * @param {BeaconService} beaconService The BeaconService object representing the funded beacon to announce the update to.
134
+ * @param {SignedBTCR2Update} update The signed update object to be announced.
135
+ * @param {KeyBytes} secretKey The private key used to sign the update for announcement.
136
+ * @returns {SignedBTCR2Update} The SignedBTCR2Update object containing data to validate the Beacon Signal
137
+ * @throws {UpdateError} if the beaconService type is invalid
241
138
  */
242
- public static async announce({
243
- sourceDocument,
244
- beaconIds,
245
- signedUpdate
246
- }: {
247
- sourceDocument: DidDocument;
248
- beaconIds: string[];
249
- signedUpdate: BTCR2SignedUpdate;
250
- }): Promise<SidecarData> {
251
- // 1. Set beaconServices to an empty array.
252
- const beaconServices: BeaconService[] = [];
253
-
254
- // 2. sidecarData to an empty array.
255
- let sidecarData: SidecarData | undefined;
256
-
257
- // 3. For beaconId in beaconIds:
258
- for (const beaconId of beaconIds) {
259
- // 3.1 Find the beacon services in the sourceDocument
260
- const beaconService = sourceDocument.service.find((s: DidService) => s.id === beaconId);
261
-
262
- // 3.2 If no beaconService MUST throw beaconNotFound error.
263
- if (!beaconService) {
264
- throw new MethodError('Not found: sourceDocument does not contain beaconId', INVALID_DID_DOCUMENT, { beaconId });
265
- }
266
-
267
- // 3.3 Push beaconService to beaconServices.
268
- beaconServices.push(beaconService);
269
- }
270
-
271
- // 4. For beaconService in beaconServices:
272
- for (const beaconService of beaconServices) {
273
- // 4.1 Set signalMetadata to null.
274
- // 4.2 If beaconService.type == SingletonBeacon:
275
- // 4.2.1 Set signalMetadata to the result of passing beaconService and BTCR2SignedUpdate to the Broadcast
276
- // Singleton Beacon Signal algorithm.
277
- // 4.3 Else If beaconService.type == CASBeacon:
278
- // 4.3.1 Set signalMetadata to the result of passing Identifier, beaconService and BTCR2SignedUpdate to
279
- // the Broadcast CIDAggregate Beacon Signal algorithm.
280
- // 4.4 Else If beaconService.type == SMTBeacon:
281
- // 4.4.1 Set signalMetadata to the result of passing Identifier, beaconService and BTCR2SignedUpdate to
282
- // the Broadcast SMTAggregate Beacon Signal algorithm.
283
- // 4.5 Else:
284
- // 4.5.1 MUST throw invalidBeacon error.
285
- // const beacon = BeaconFactory.establish(beaconService);
286
- // sidecarData = await beacon.broadcastSignal(signedUpdate);
287
- console.log('TODO: refactor this code', signedUpdate, beaconService);
288
- }
289
- if(!sidecarData) {
290
- throw new MethodError(
291
- 'Invalid beacon: no sidecarData found',
292
- INVALID_DID_DOCUMENT, { beaconServices }
293
- );
294
- }
139
+ static async announce(
140
+ beaconService: BeaconService,
141
+ update: SignedBTCR2Update,
142
+ secretKey: KeyBytes,
143
+ bitcoin: BitcoinNetworkConnection
144
+ ): Promise<SignedBTCR2Update> {
145
+ // Establish a beacon object
146
+ const beacon = BeaconFactory.establish(beaconService);
147
+
148
+ // Broadcast the update
149
+ const result = await beacon.broadcastSignal(update, secretKey, bitcoin);
295
150
 
296
151
  // Return the sidecarData
297
- return sidecarData;
152
+ return result;
298
153
  }
299
154
  }