@did-btcr2/method 0.20.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 (45) hide show
  1. package/README.md +223 -1
  2. package/dist/browser.js +3316 -3292
  3. package/dist/browser.mjs +3316 -3292
  4. package/dist/cjs/core/beacon/singleton.js +6 -9
  5. package/dist/cjs/core/beacon/singleton.js.map +1 -1
  6. package/dist/cjs/core/resolve.js +41 -37
  7. package/dist/cjs/core/resolve.js.map +1 -1
  8. package/dist/cjs/core/update.js +3 -4
  9. package/dist/cjs/core/update.js.map +1 -1
  10. package/dist/cjs/did-btcr2.js +32 -28
  11. package/dist/cjs/did-btcr2.js.map +1 -1
  12. package/dist/cjs/utils/did-document-builder.js +0 -6
  13. package/dist/cjs/utils/did-document-builder.js.map +1 -1
  14. package/dist/cjs/utils/did-document.js +31 -24
  15. package/dist/cjs/utils/did-document.js.map +1 -1
  16. package/dist/esm/core/beacon/singleton.js +6 -9
  17. package/dist/esm/core/beacon/singleton.js.map +1 -1
  18. package/dist/esm/core/resolve.js +41 -37
  19. package/dist/esm/core/resolve.js.map +1 -1
  20. package/dist/esm/core/update.js +3 -4
  21. package/dist/esm/core/update.js.map +1 -1
  22. package/dist/esm/did-btcr2.js +32 -28
  23. package/dist/esm/did-btcr2.js.map +1 -1
  24. package/dist/esm/utils/did-document-builder.js +0 -6
  25. package/dist/esm/utils/did-document-builder.js.map +1 -1
  26. package/dist/esm/utils/did-document.js +31 -24
  27. package/dist/esm/utils/did-document.js.map +1 -1
  28. package/dist/types/core/beacon/singleton.d.ts +1 -1
  29. package/dist/types/core/beacon/singleton.d.ts.map +1 -1
  30. package/dist/types/core/resolve.d.ts +7 -4
  31. package/dist/types/core/resolve.d.ts.map +1 -1
  32. package/dist/types/core/update.d.ts.map +1 -1
  33. package/dist/types/did-btcr2.d.ts +8 -4
  34. package/dist/types/did-btcr2.d.ts.map +1 -1
  35. package/dist/types/utils/did-document-builder.d.ts +0 -1
  36. package/dist/types/utils/did-document-builder.d.ts.map +1 -1
  37. package/dist/types/utils/did-document.d.ts +12 -9
  38. package/dist/types/utils/did-document.d.ts.map +1 -1
  39. package/package.json +7 -6
  40. package/src/core/beacon/singleton.ts +7 -9
  41. package/src/core/resolve.ts +59 -47
  42. package/src/core/update.ts +3 -3
  43. package/src/did-btcr2.ts +34 -32
  44. package/src/utils/did-document-builder.ts +0 -7
  45. package/src/utils/did-document.ts +41 -30
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@did-btcr2/method",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "type": "module",
5
- "description": "Javascript/TypeScript reference implementation of did:btcr2 method, a censorship resistant DID Method using the Bitcoin blockchain as a Verifiable Data Registry to announce changes to the DID document. Core package of the did-btcr2-js monorepo.",
5
+ "description": "Reference implementation for the did:btcr2 DID method written in TypeScript and JavaScript. did:btcr2 is a censorship resistant DID Method using the Bitcoin blockchain as a Verifiable Data Registry to announce changes to the DID document. This is the core method implementation for the did-btcr2-js monorepo.",
6
6
  "main": "./dist/cjs/index.js",
7
7
  "module": "./dist/esm/index.js",
8
8
  "types": "./dist/types/index.d.ts",
@@ -83,11 +83,11 @@
83
83
  "multiformats": "^13.3.1",
84
84
  "nostr-tools": "^2.15.0",
85
85
  "tiny-secp256k1": "^2.2.3",
86
- "@did-btcr2/cryptosuite": "5.0.0",
87
86
  "@did-btcr2/bitcoin": "0.3.4",
87
+ "@did-btcr2/cryptosuite": "5.1.0",
88
88
  "@did-btcr2/kms": "0.2.0",
89
- "@did-btcr2/common": "3.1.0",
90
- "@did-btcr2/keypair": "0.9.0"
89
+ "@did-btcr2/keypair": "0.9.1",
90
+ "@did-btcr2/common": "4.0.1"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@eslint/js": "^9.22.0",
@@ -95,7 +95,7 @@
95
95
  "@types/chai-as-promised": "^8.0.1",
96
96
  "@types/eslint": "^9.6.1",
97
97
  "@types/mocha": "^10.0.9",
98
- "@types/node": "^22.5.4",
98
+ "@types/node": "^25.3.0",
99
99
  "@typescript-eslint/eslint-plugin": "^8.5.0",
100
100
  "@typescript-eslint/parser": "^8.5.0",
101
101
  "c8": "^10.1.2",
@@ -138,6 +138,7 @@
138
138
  "build:test": "pnpm build && pnpm build:tests && pnpm c8 mocha",
139
139
  "build:lint:test": "pnpm build && pnpm build:tests && pnpm lint:fix",
140
140
  "prepublish": "pnpm build",
141
+ "generate:vector": "pnpm tsx lib/generate-vector.ts",
141
142
  "do": "pnpm tsx",
142
143
  "do:lib": "${PWD}/lib/run-lib.sh",
143
144
  "pack:local": "pnpm pack && mv *.tgz ./release"
@@ -1,11 +1,10 @@
1
1
  import { AddressUtxo, BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
2
- import { INVALID_SIDECAR_DATA, KeyBytes, MISSING_UPDATE_DATA } from '@did-btcr2/common';
2
+ import { Canonicalization, INVALID_SIDECAR_DATA, KeyBytes, MISSING_UPDATE_DATA } from '@did-btcr2/common';
3
3
  import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
4
4
  import { SchnorrKeyPair } from '@did-btcr2/keypair';
5
5
  import { Signer } from '@did-btcr2/kms';
6
6
  import { opcodes, Psbt, script } from 'bitcoinjs-lib';
7
7
  import { base58btc } from 'multiformats/bases/base58';
8
- import { canonicalization } from '../../did-btcr2.js';
9
8
  import { SidecarData } from '../types.js';
10
9
  import { Beacon } from './beacon.js';
11
10
  import { SingletonBeaconError } from './error.js';
@@ -15,7 +14,7 @@ import { BeaconService, BeaconSignal, BlockMetadata } from './interfaces.js';
15
14
  * Implements {@link https://dcdpr.github.io/did-btcr2/terminology.html#singleton-beacon | Singleton Beacon}.
16
15
  * @class SingletonBeacon
17
16
  * @type {SingletonBeacon}
18
- * @extends {AggregateBeacon}
17
+ * @extends {Beacon}
19
18
  */
20
19
  export class SingletonBeacon extends Beacon {
21
20
 
@@ -57,7 +56,7 @@ export class SingletonBeacon extends Beacon {
57
56
  }
58
57
 
59
58
  // Canonicalize, hash and encode to base58 the signed update object found in sidecar or CAS
60
- const encodedUpdate = canonicalization.process(signedUpdate, { encoding: 'base58' });
59
+ const encodedUpdate = Canonicalization.process(signedUpdate, { encoding: 'base58' });
61
60
 
62
61
  // Encode the signal bytes hex string to base58
63
62
  const signalBytes = base58btc.encode(Buffer.from(updateHash, 'hex'));
@@ -122,7 +121,7 @@ export class SingletonBeacon extends Beacon {
122
121
  const prevTx = await bitcoin.network.rest.transaction.getHex(utxo.txid);
123
122
 
124
123
  // Canonicalize and hash the signed update for OP_RETURN output
125
- const updateHash = canonicalization.canonicalhash(signedUpdate);
124
+ const updateHash = Canonicalization.andHash(signedUpdate);
126
125
 
127
126
  // Construct a spend transaction
128
127
  const spendTx = new Psbt({ network: bitcoin.network.data })
@@ -140,9 +139,6 @@ export class SingletonBeacon extends Beacon {
140
139
 
141
140
  // Construct a Schnorr key pair from the secret key
142
141
  const keyPair = SchnorrKeyPair.fromSecret(secretKey);
143
- if (!keyPair) {
144
- throw new SingletonBeaconError('Key pair not found.', 'KEY_PAIR_NOT_FOUND', { secretKey });
145
- }
146
142
 
147
143
  // Construct a signer object from the key pair and bitcoin network
148
144
  const signer = new Signer({ keyPair, network: bitcoin.network.name });
@@ -155,7 +151,9 @@ export class SingletonBeacon extends Beacon {
155
151
 
156
152
  // Broadcast spendTx to the Bitcoin network.
157
153
  const txid = await bitcoin.network.rest.transaction.send(signedTx);
158
- console.info(`Broadcasted Singleton Beacon signal with txid ${txid}`);
154
+
155
+ // Log the txid of the broadcasted transaction
156
+ console.info(`Singleton Beacon Signal Broadcasted with txid: ${txid}`);
159
157
 
160
158
  // Return the signed update
161
159
  return signedUpdate;
@@ -3,6 +3,7 @@ import {
3
3
  getNetwork
4
4
  } from '@did-btcr2/bitcoin';
5
5
  import {
6
+ Canonicalization,
6
7
  DateUtils,
7
8
  IdentifierHrp,
8
9
  INVALID_DID,
@@ -23,7 +24,7 @@ import {
23
24
  } from '@did-btcr2/cryptosuite';
24
25
  import { CompressedSecp256k1PublicKey } from '@did-btcr2/keypair';
25
26
  import { bytesToHex } from '@noble/hashes/utils';
26
- import { canonicalization, DidBtcr2 } from '../did-btcr2.js';
27
+ import { DidBtcr2 } from '../did-btcr2.js';
27
28
  import { Appendix } from '../utils/appendix.js';
28
29
  import { DidDocument, ID_PLACEHOLDER_VALUE } from '../utils/did-document.js';
29
30
  import { BeaconFactory } from './beacon/factory.js';
@@ -38,10 +39,13 @@ import { CASAnnouncement, Sidecar, SidecarData } from './types.js';
38
39
  * The response object for DID Resolution.
39
40
  */
40
41
  export interface DidResolutionResponse {
41
- currentDocument: DidDocument;
42
- confirmations: number;
43
- versionId: string;
44
- updated: string;
42
+ didDocument: DidDocument;
43
+ metadata: {
44
+ confirmations?: number;
45
+ versionId: string;
46
+ updated?: string;
47
+ deactivated?: boolean;
48
+ }
45
49
  }
46
50
 
47
51
  /**
@@ -79,7 +83,6 @@ export class Resolve {
79
83
 
80
84
  return new DidDocument({
81
85
  id : did,
82
- controller : [did],
83
86
  verificationMethod : [{
84
87
  id : `${did}#initialKey`,
85
88
  type : 'Multikey',
@@ -102,7 +105,7 @@ export class Resolve {
102
105
  genesisDocument: object,
103
106
  ): Promise<DidDocument> {
104
107
  // Canonicalize and sha256 hash the currentDocument
105
- const hashBytes = canonicalization.process(genesisDocument, { encoding: 'hex' });
108
+ const hashBytes = Canonicalization.process(genesisDocument, { encoding: 'hex' });
106
109
 
107
110
  // Compare the genesisBytes to the hashBytes
108
111
  const genesisBytes = bytesToHex(didComponents.genesisBytes);
@@ -137,14 +140,14 @@ export class Resolve {
137
140
  const updateMap = new Map<string, SignedBTCR2Update>();
138
141
  if(sidecar.updates?.length)
139
142
  for(const update of sidecar.updates) {
140
- updateMap.set(canonicalization.process(update, { encoding: 'hex' }), update);
143
+ updateMap.set(Canonicalization.process(update, { encoding: 'hex' }), update);
141
144
  }
142
145
 
143
146
  // CAS Announcements map
144
147
  const casMap = new Map<string, CASAnnouncement>();
145
148
  if(sidecar.casUpdates?.length)
146
149
  for(const update of sidecar.casUpdates) {
147
- casMap.set(canonicalization.process(update, { encoding: 'hex' }), update);
150
+ casMap.set(Canonicalization.process(update, { encoding: 'hex' }), update);
148
151
  }
149
152
 
150
153
  // SMT Proofs map
@@ -220,16 +223,18 @@ export class Resolve {
220
223
  : await BeaconSignalDiscovery.fullnode(beaconServices, bitcoin);
221
224
 
222
225
  // Process each beacon's signals in parallel
223
- const promises = Array.from(beaconServicesSignals.entries()).map(
224
- async ([service, signals]) => {
225
- // Skip beacons with no signals
226
- if (!signals.length) return [];
227
- // Establish a typed beacon and process its signals
228
- return BeaconFactory.establish(service).processSignals(signals, sidecarData);
229
- }
226
+ const promises = await Promise.all(
227
+ Array.from(beaconServicesSignals.entries()).map(
228
+ async ([service, signals]) => {
229
+ // Skip beacons with no signals
230
+ if (!signals.length) return [];
231
+ // Establish a typed beacon and process its signals
232
+ return BeaconFactory.establish(service).processSignals(signals, sidecarData);
233
+ }
234
+ )
230
235
  );
231
236
 
232
- return (await Promise.all(promises)).flat();
237
+ return promises.flat();
233
238
  }
234
239
 
235
240
  /**
@@ -258,31 +263,36 @@ export class Resolve {
258
263
  );
259
264
 
260
265
  // Create a default response object
261
- const response = {
262
- currentDocument,
263
- versionId : `${currentVersionId}`,
264
- confirmations : 0,
265
- updated : ''
266
+ const response: DidResolutionResponse = {
267
+ didDocument : currentDocument,
268
+ metadata : {
269
+ versionId : `${currentVersionId}`,
270
+ confirmations : 0,
271
+ updated : '',
272
+ deactivated : currentDocument.deactivated || false
273
+ }
266
274
  };
267
275
 
268
276
  // Iterate over each (update block) pair
269
277
  for(const [update, block] of updates) {
270
278
  // Get the hash of the current document
271
- const currentDocumentHash = canonicalization.process(response.currentDocument, { encoding: 'base58' });
279
+ const currentDocumentHash = Canonicalization.process(response.didDocument, { encoding: 'base58' });
272
280
 
273
- // Set confirmations to the block confirmations
274
- response.confirmations = block.confirmations;
281
+ // Safely convert block.time to timestamp
282
+ const blocktime = DateUtils.blocktimeToTimestamp(block.time);
275
283
 
276
- // Safely convert versionTime to timestamp
277
- const vTime = DateUtils.dateStringToTimestamp(versionTime || '');
278
- // Safely convert block.blocktime to timestamp
279
- const bTime = DateUtils.blocktimeToTimestamp(block.time);
280
284
  // Set the updated field to the blocktime of the current update
281
- response.updated = DateUtils.toISOStringNonFractional(bTime);
285
+ response.metadata.updated = DateUtils.toISOStringNonFractional(blocktime);
286
+
287
+ // Set confirmations to the block confirmations
288
+ response.metadata.confirmations = block.confirmations;
282
289
 
283
290
  // if resolutionOptions.versionTime is defined and the blocktime is more recent, return currentDocument
284
- if(vTime < bTime) {
285
- return response;
291
+ if(versionTime) {
292
+ // Safely convert versionTime to timestamp
293
+ if(blocktime > DateUtils.dateStringToTimestamp(versionTime)) {
294
+ return response;
295
+ }
286
296
  }
287
297
 
288
298
  // Check update.targetVersionId against currentVersionId
@@ -294,23 +304,21 @@ export class Resolve {
294
304
 
295
305
  // If update.targetVersionId == currentVersionId + 1, apply the update
296
306
  else if (update.targetVersionId === currentVersionId + 1) {
297
- // Prepend `z` to the sourceHash if it does not start with it
298
- const sourceHash = update.sourceHash.startsWith('z') ? update.sourceHash : `z${update.sourceHash}`;
299
-
300
307
  // Check if update.sourceHash !== currentDocumentHash
301
- if (sourceHash !== currentDocumentHash) {
308
+ if (update.sourceHash !== currentDocumentHash) {
302
309
  // Raise an INVALID_DID_UPDATE error if they do not match
303
310
  throw new ResolveError(
304
311
  `Hash mismatch: update.sourceHash !== currentDocumentHash`,
305
- INVALID_DID_UPDATE, { sourceHash, currentDocumentHash }
312
+ INVALID_DID_UPDATE, { sourceHash: update.sourceHash, currentDocumentHash }
306
313
  );
307
314
  }
308
315
  // Apply the update to the currentDocument and set it in the response
309
- response.currentDocument = await this.applyUpdate(response.currentDocument, update);
316
+ response.didDocument = await this.applyUpdate(response.didDocument, update);
317
+
310
318
  // Create unsigned_update by removing the proof property from update.
311
319
  const unsignedUpdate = JSONUtils.deleteKeys(update, ['proof']) as UnsignedBTCR2Update;
312
320
  // Push the canonicalized unsigned update hash to the updateHashHistory
313
- updateHashHistory.push(canonicalization.process(unsignedUpdate, { encoding: 'base58' }));
321
+ updateHashHistory.push(Canonicalization.process(unsignedUpdate, { encoding: 'base58' }));
314
322
  }
315
323
 
316
324
  // If update.targetVersionId > currentVersionId + 1, throw LATE_PUBLISHING error
@@ -319,15 +327,16 @@ export class Resolve {
319
327
  `Version Id Mismatch: targetVersionId cannot be > currentVersionId + 1`,
320
328
  'LATE_PUBLISHING_ERROR', {
321
329
  targetVersionId : update.targetVersionId,
322
- currentVersionId : String(currentVersionId + 1)
330
+ currentVersionId : currentVersionId + 1
323
331
  }
324
332
  );
325
333
  }
326
334
 
327
335
  // Increment currentVersionId
328
336
  currentVersionId++;
329
- // Set currentVersionId in response
330
- response.versionId = `${currentVersionId}`;
337
+
338
+ // Set response.versionId to be the new currentVersionId
339
+ response.metadata.versionId = `${currentVersionId}`;
331
340
 
332
341
  // If resolutionOptions.versionId is defined and <= currentVersionId, return currentDocument
333
342
  if(currentVersionId >= Number(versionId)) {
@@ -336,6 +345,9 @@ export class Resolve {
336
345
 
337
346
  // Check if the current document is deactivated before further processing
338
347
  if(currentDocument.deactivated) {
348
+ // Set the response deactivated flag to true
349
+ response.metadata.deactivated = currentDocument.deactivated;
350
+ // If deactivated, stop processing further updates and return the response
339
351
  return response;
340
352
  }
341
353
  }
@@ -352,12 +364,12 @@ export class Resolve {
352
364
  */
353
365
  static confirmDuplicate(update: SignedBTCR2Update, updateHashHistory: string[]): void {
354
366
  // Create unsigned_update by removing the proof property from update.
355
- const unsignedUpdate = JSONUtils.deleteKeys(update, ['proof']) as UnsignedBTCR2Update;
367
+ const { proof: _, ...unsignedUpdate } = update;
356
368
 
357
369
  // Hash unsignedUpdate with JSON Document Hashing algorithm
358
- const unsignedUpdateHash = canonicalization.process(unsignedUpdate);
370
+ const unsignedUpdateHash = Canonicalization.process(unsignedUpdate);
359
371
 
360
- // 5. Let historicalUpdateHash equal updateHashHistory[updateHashIndex].
372
+ // Let historicalUpdateHash equal updateHashHistory[updateHashIndex].
361
373
  const historicalUpdateHash = updateHashHistory[update.targetVersionId - 2];
362
374
 
363
375
  // Check if the updateHash matches the historical hash
@@ -420,7 +432,7 @@ export class Resolve {
420
432
  const cryptosuite = new BIP340Cryptosuite(multikey);
421
433
 
422
434
  // Canonicalize the update
423
- const canonicalUpdate = canonicalization.canonicalize(update);
435
+ const canonicalUpdate = Canonicalization.canonicalize(update);
424
436
 
425
437
  // Construct a DataIntegrityProof with the cryptosuite
426
438
  const diProof = new BIP340DataIntegrityProof(cryptosuite);
@@ -443,7 +455,7 @@ export class Resolve {
443
455
  DidDocument.validate(updatedDocument);
444
456
 
445
457
  // Canonicalize and hash the updatedDocument to get the currentDocumentHash.
446
- const currentDocumentHash = canonicalization.process(currentDocument, { encoding: 'base58' });
458
+ const currentDocumentHash = Canonicalization.process(updatedDocument, { encoding: 'base58' });
447
459
 
448
460
  // Prepare the update targetHash for comparison with currentDocumentHash.
449
461
  const updateTargetHash = update.targetHash.startsWith('z') ? update.targetHash : `z${update.targetHash}`;
@@ -1,4 +1,5 @@
1
1
  import {
2
+ Canonicalization,
2
3
  INVALID_DID_UPDATE,
3
4
  JSONPatch,
4
5
  KeyBytes,
@@ -11,7 +12,6 @@ import {
11
12
  SignedBTCR2Update,
12
13
  UnsignedBTCR2Update
13
14
  } from '@did-btcr2/cryptosuite';
14
- import { canonicalization } from '../did-btcr2.js';
15
15
  import { Btcr2DidDocument, DidDocument, DidVerificationMethod } from '../utils/did-document.js';
16
16
  import { BeaconFactory } from './beacon/factory.js';
17
17
  import { BeaconService } from './beacon/interfaces.js';
@@ -56,7 +56,7 @@ export class Update {
56
56
  patch : patches,
57
57
  targetHash : '',
58
58
  targetVersionId : sourceVersionId + 1,
59
- sourceHash : canonicalization.process(sourceDocument, { encoding: 'base58' }),
59
+ sourceHash : Canonicalization.process(sourceDocument, { encoding: 'base58' }),
60
60
  };
61
61
 
62
62
  // Apply all JSON patches to sourceDocument.
@@ -74,7 +74,7 @@ export class Update {
74
74
  }
75
75
 
76
76
  // Set the targetHash by canonicalizing the targetDocument and encoding it in base58.
77
- unsignedUpdate.targetHash = canonicalization.process(targetDocument, { encoding: 'base58' });
77
+ unsignedUpdate.targetHash = Canonicalization.process(targetDocument, { encoding: 'base58' });
78
78
 
79
79
  // Return unsignedUpdate.
80
80
  return unsignedUpdate;
package/src/did-btcr2.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
2
2
  import {
3
- Canonicalization,
4
3
  DocumentBytes,
5
4
  HexString,
6
5
  IdentifierHrp,
@@ -34,9 +33,6 @@ import { Update } from './core/update.js';
34
33
  import { Appendix } from './utils/appendix.js';
35
34
  import { Btcr2DidDocument, DidVerificationMethod } from './utils/did-document.js';
36
35
 
37
- // TODO: convert to API driver?
38
- export const canonicalization = new Canonicalization();
39
-
40
36
  export type Btcr2Identifier = string;
41
37
 
42
38
  export interface DidCreateOptions {
@@ -81,11 +77,16 @@ export class DidBtcr2 implements DidMethod {
81
77
  * @param {string} options.network The Bitcoin network to use for the identifier, e.g. 'bitcoin', 'testnet', etc. Defaults to 'bitcoin'.
82
78
  * @returns {Promise<Btcr2Identifier>} Promise resolving to a Btcr2Identifier string.
83
79
  * @throws {MethodError} if any of the checks fail
80
+ * @example
81
+ * ```ts
82
+ * const genesisBytes = SchnorrKeyPair.generate().publicKey.compressed;
83
+ * const did = DidBtcr2.create(genesisBytes, { idType: 'KEY', network: 'regtest' });
84
+ * ```
84
85
  */
85
- static async create(
86
+ static create(
86
87
  genesisBytes: KeyBytes | DocumentBytes,
87
88
  options?: DidCreateOptions
88
- ): Promise<Btcr2Identifier> {
89
+ ): Btcr2Identifier {
89
90
  // Deconstruct the idType, version and network from the options, setting defaults if not given
90
91
  const { idType, version = 1, network = 'bitcoin' } = options || {};
91
92
 
@@ -117,24 +118,26 @@ export class DidBtcr2 implements DidMethod {
117
118
  * @example
118
119
  * ```ts
119
120
  * const resolution = await DidBtcr2.resolve(
120
- * 'did:btcr2:k1q0dygyp3gz969tp46dychzy4q78c2k3js68kvyr0shanzg67jnuez2cfplh'
121
+ * 'did:btcr2:k1qgpr45cheptyjekl3cex80xfnkwhxnlclecwwf92gvdjrszm2uwhzlcxu5xte'
121
122
  * )
122
123
  * ```
123
124
  */
124
125
  static async resolve(
125
126
  did: string,
126
- resolutionOptions: ResolutionOptions = { drivers: {} }
127
+ resolutionOptions: ResolutionOptions = {}
127
128
  ): Promise<DidResolutionResult> {
128
129
  try {
130
+ // Set versionId from resolutionOptions
131
+ const versionId = resolutionOptions.versionId;
129
132
 
130
133
  // Initialize an empty DID Resolution Result
131
134
  const didResolutionResult: DidResolutionResult = {
132
135
  '@context' : 'https://w3id.org/did-resolution/v1',
133
136
  didResolutionMetadata : { contentType: 'application/ld+json' },
134
137
  didDocumentMetadata : {
138
+ versionId,
135
139
  deactivated : false,
136
140
  updated : undefined,
137
- versionId : resolutionOptions.versionId,
138
141
  confirmations : undefined,
139
142
  },
140
143
  didDocument : null,
@@ -146,25 +149,16 @@ export class DidBtcr2 implements DidMethod {
146
149
  // Process sidecar if provided
147
150
  const sidecarData = Resolve.sidecarData(resolutionOptions.sidecar);
148
151
 
149
- // Check if bitcoin driver provided
150
- if(!resolutionOptions?.drivers?.bitcoin) {
151
- // If not, initialize default drivers
152
- resolutionOptions.drivers = resolutionOptions.drivers || {};
153
- // Set bitcoin driver to default BitcoinNetworkConnection
154
- resolutionOptions.drivers.bitcoin = new BitcoinNetworkConnection();
155
- // Set the network based on the decoded identifier
156
- resolutionOptions.drivers.bitcoin.setActiveNetwork(didComponents.network);
157
- }
158
-
159
152
  // Parse the genesis document from the resolution options if provided
160
153
  const genesisDocument = resolutionOptions.sidecar?.genesisDocument;
154
+
161
155
  // Since genesisDocument is optional, check if it exists
162
156
  if(!genesisDocument) {
163
157
  // If no genesisDocument and x HRP, throw MISSING_UPDATE_DATA error
164
158
  if(didComponents.hrp === IdentifierHrp.x)
165
159
  throw new ResolveError(
166
160
  'External resolution requires genesisDocument',
167
- MISSING_UPDATE_DATA, { resolutionOptions }
161
+ MISSING_UPDATE_DATA, resolutionOptions
168
162
  );
169
163
  }
170
164
 
@@ -176,23 +170,33 @@ export class DidBtcr2 implements DidMethod {
176
170
  .filter(BeaconUtils.isBeaconService)
177
171
  .map(BeaconUtils.parseBeaconServiceEndpoint);
178
172
 
179
- console.log('beaconServices', beaconServices);
173
+ // Check if bitcoin driver provided
174
+ if(!resolutionOptions?.drivers?.bitcoin) {
175
+ // If not, initialize default drivers
176
+ resolutionOptions.drivers = resolutionOptions.drivers || {};
177
+ // Set bitcoin driver to default BitcoinNetworkConnection
178
+ resolutionOptions.drivers.bitcoin = new BitcoinNetworkConnection();
179
+ // Set the network based on the decoded identifier
180
+ resolutionOptions.drivers.bitcoin.setActiveNetwork(didComponents.network);
181
+ }
182
+
183
+ // Get the bitcoin driver from the resolution options
184
+ const bitcoin = resolutionOptions.drivers.bitcoin;
180
185
 
181
186
  // Process the Beacon Signals to get the required updates
182
187
  const unsortedUpdates = await Resolve.beaconSignals(
183
188
  beaconServices,
184
189
  sidecarData,
185
- resolutionOptions.drivers.bitcoin
190
+ bitcoin
186
191
  );
187
- console.log('unsortedUpdates', unsortedUpdates);
188
192
 
189
193
  // If no updates found, return the current document
190
194
  if(!unsortedUpdates.length) {
191
- // Set the current document in the didResolutionResult
195
+ // Set the didDocument in didResolutionResult based on currentDocument
192
196
  didResolutionResult.didDocument = currentDocument;
193
-
194
- // Set the deactivated status in the didDocumentMetadata
197
+ // Set other required fields in the didResolutionResult
195
198
  didResolutionResult.didDocumentMetadata.deactivated = !!currentDocument.deactivated;
199
+ didResolutionResult.didDocumentMetadata.versionId = versionId ?? '1';
196
200
 
197
201
  // Return the didResolutionResult early
198
202
  return didResolutionResult;
@@ -203,14 +207,12 @@ export class DidBtcr2 implements DidMethod {
203
207
  currentDocument,
204
208
  unsortedUpdates,
205
209
  resolutionOptions.versionTime,
206
- resolutionOptions.versionId
210
+ versionId
207
211
  );
208
212
 
209
213
  // Set all of the required fields in the didResolutionResult
210
- didResolutionResult.didDocument = result.currentDocument;
211
- didResolutionResult.didDocumentMetadata.confirmations = result.confirmations;
212
- didResolutionResult.didDocumentMetadata.versionId = result.versionId;
213
- didResolutionResult.didDocumentMetadata.deactivated = !!result.currentDocument.deactivated;
214
+ didResolutionResult.didDocument = result.didDocument;
215
+ didResolutionResult.didDocumentMetadata = result.metadata;
214
216
 
215
217
  // Return didResolutionResult;
216
218
  return didResolutionResult;
@@ -339,7 +341,7 @@ export class DidBtcr2 implements DidMethod {
339
341
  bitcoin ??= new BitcoinNetworkConnection();
340
342
 
341
343
  // Announce the signed update to the blockchain using the specified beacon(s)
342
- // await Update.announce(beaconService, signed, secretKey, bitcoin);
344
+ await Update.announce(beaconService, signed, secretKey, bitcoin);
343
345
 
344
346
  // Return signed update if announced successfully
345
347
  return signed;
@@ -22,13 +22,6 @@ export class DidDocumentBuilder {
22
22
  }
23
23
  }
24
24
 
25
- withController(controller?: Array<string>): this {
26
- if (controller) {
27
- this.document.controller = controller ?? [this.document.id!];
28
- }
29
- return this;
30
- }
31
-
32
25
  withAuthentication(authentication: Array<string | DidVerificationMethod>): this {
33
26
  if (authentication) {
34
27
  this.document.authentication = authentication;