@did-btcr2/api 0.2.2 → 0.3.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 (73) hide show
  1. package/dist/browser.js +56457 -104900
  2. package/dist/browser.mjs +56442 -104885
  3. package/dist/cjs/api.js +31 -934
  4. package/dist/cjs/api.js.map +1 -1
  5. package/dist/cjs/bitcoin.js +110 -0
  6. package/dist/cjs/bitcoin.js.map +1 -0
  7. package/dist/cjs/cas.js +90 -0
  8. package/dist/cjs/cas.js.map +1 -0
  9. package/dist/cjs/crypto.js +425 -0
  10. package/dist/cjs/crypto.js.map +1 -0
  11. package/dist/cjs/did.js +70 -0
  12. package/dist/cjs/did.js.map +1 -0
  13. package/dist/cjs/helpers.js +28 -0
  14. package/dist/cjs/helpers.js.map +1 -0
  15. package/dist/cjs/index.js +12 -0
  16. package/dist/cjs/index.js.map +1 -1
  17. package/dist/cjs/kms.js +73 -0
  18. package/dist/cjs/kms.js.map +1 -0
  19. package/dist/cjs/method.js +262 -0
  20. package/dist/cjs/method.js.map +1 -0
  21. package/dist/cjs/types.js +2 -0
  22. package/dist/cjs/types.js.map +1 -0
  23. package/dist/esm/api.js +31 -934
  24. package/dist/esm/api.js.map +1 -1
  25. package/dist/esm/bitcoin.js +110 -0
  26. package/dist/esm/bitcoin.js.map +1 -0
  27. package/dist/esm/cas.js +90 -0
  28. package/dist/esm/cas.js.map +1 -0
  29. package/dist/esm/crypto.js +425 -0
  30. package/dist/esm/crypto.js.map +1 -0
  31. package/dist/esm/did.js +70 -0
  32. package/dist/esm/did.js.map +1 -0
  33. package/dist/esm/helpers.js +28 -0
  34. package/dist/esm/helpers.js.map +1 -0
  35. package/dist/esm/index.js +12 -0
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/kms.js +73 -0
  38. package/dist/esm/kms.js.map +1 -0
  39. package/dist/esm/method.js +262 -0
  40. package/dist/esm/method.js.map +1 -0
  41. package/dist/esm/types.js +2 -0
  42. package/dist/esm/types.js.map +1 -0
  43. package/dist/types/api.d.ts +19 -693
  44. package/dist/types/api.d.ts.map +1 -1
  45. package/dist/types/bitcoin.d.ts +64 -0
  46. package/dist/types/bitcoin.d.ts.map +1 -0
  47. package/dist/types/cas.d.ts +70 -0
  48. package/dist/types/cas.d.ts.map +1 -0
  49. package/dist/types/crypto.d.ts +310 -0
  50. package/dist/types/crypto.d.ts.map +1 -0
  51. package/dist/types/did.d.ts +51 -0
  52. package/dist/types/did.d.ts.map +1 -0
  53. package/dist/types/helpers.d.ts +10 -0
  54. package/dist/types/helpers.d.ts.map +1 -0
  55. package/dist/types/index.d.ts +14 -0
  56. package/dist/types/index.d.ts.map +1 -1
  57. package/dist/types/kms.d.ts +49 -0
  58. package/dist/types/kms.d.ts.map +1 -0
  59. package/dist/types/method.d.ts +117 -0
  60. package/dist/types/method.d.ts.map +1 -0
  61. package/dist/types/types.d.ts +128 -0
  62. package/dist/types/types.d.ts.map +1 -0
  63. package/package.json +7 -7
  64. package/src/api.ts +40 -1317
  65. package/src/bitcoin.ts +129 -0
  66. package/src/cas.ts +121 -0
  67. package/src/crypto.ts +525 -0
  68. package/src/did.ts +75 -0
  69. package/src/helpers.ts +35 -0
  70. package/src/index.ts +37 -1
  71. package/src/kms.ts +95 -0
  72. package/src/method.ts +331 -0
  73. package/src/types.ts +122 -0
package/src/crypto.ts ADDED
@@ -0,0 +1,525 @@
1
+ import type { Bytes, Entropy, HexString, KeyBytes, SchnorrKeyPairObject, SignatureBytes } from '@did-btcr2/common';
2
+ import {
3
+ BIP340Cryptosuite,
4
+ BIP340DataIntegrityProof,
5
+ BTCR2Update,
6
+ DataIntegrityConfig,
7
+ DataIntegrityProofObject,
8
+ type FromPublicKey,
9
+ type Multikey,
10
+ SchnorrMultikey,
11
+ SignedBTCR2Update,
12
+ UnsignedBTCR2Update,
13
+ VerificationResult
14
+ } from '@did-btcr2/cryptosuite';
15
+ import { CompressedSecp256k1PublicKey, SchnorrKeyPair, Secp256k1SecretKey } from '@did-btcr2/keypair';
16
+ import { KeyIdentifier } from '@did-btcr2/kms';
17
+ import type { DidVerificationMethod } from '@web5/dids';
18
+ import { KeyManagerApi } from './kms.js';
19
+
20
+ /**
21
+ * Schnorr keypair operations.
22
+ * @public
23
+ */
24
+ export class KeyPairApi {
25
+ /**
26
+ * Generate a new Schnorr keypair.
27
+ * @returns The generated Schnorr keypair.
28
+ */
29
+ generate(): SchnorrKeyPair {
30
+ return SchnorrKeyPair.generate();
31
+ }
32
+
33
+ /**
34
+ * Create a Schnorr keypair from secret key bytes or hex string.
35
+ * @param data The secret key bytes or hex string.
36
+ * @returns The created Schnorr keypair.
37
+ */
38
+ fromSecret(data: KeyBytes | HexString): SchnorrKeyPair {
39
+ return SchnorrKeyPair.fromSecret(data);
40
+ }
41
+
42
+ /** Create a secret key from entropy (bytes or bigint). */
43
+ secretKeyFrom(ent: Entropy): Secp256k1SecretKey {
44
+ return new Secp256k1SecretKey(ent);
45
+ }
46
+
47
+ /** Create a compressed public key from bytes. */
48
+ publicKeyFrom(byt: Bytes): CompressedSecp256k1PublicKey {
49
+ return new CompressedSecp256k1PublicKey(byt);
50
+ }
51
+
52
+ /** Deserialize a keypair from a JSON object. */
53
+ fromJSON(obj: SchnorrKeyPairObject): SchnorrKeyPair {
54
+ return SchnorrKeyPair.fromJSON(obj);
55
+ }
56
+
57
+ /** Serialize a keypair to a JSON object. */
58
+ toJSON(kp: SchnorrKeyPair): SchnorrKeyPairObject {
59
+ return kp.exportJSON();
60
+ }
61
+
62
+ /** Compare two keypairs for equality. */
63
+ equals(kp1: SchnorrKeyPair, kp2: SchnorrKeyPair): boolean {
64
+ return SchnorrKeyPair.equals(kp1, kp2);
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Schnorr cryptosuite operations.
70
+ *
71
+ * Optionally stateful: call {@link use} to set a current cryptosuite, then
72
+ * call {@link createProof}, {@link verifyProof}, or {@link toDataIntegrityProof}
73
+ * without passing an explicit instance. Pass an explicit instance to any
74
+ * method to override the current one for that call.
75
+ * @public
76
+ */
77
+ export class CryptosuiteApi {
78
+ #current?: BIP340Cryptosuite;
79
+
80
+ /** The currently active cryptosuite, or `undefined` if none is set. */
81
+ get current(): BIP340Cryptosuite | undefined {
82
+ return this.#current;
83
+ }
84
+
85
+ /**
86
+ * Set the current cryptosuite for subsequent operations.
87
+ * @param cs The cryptosuite to activate.
88
+ * @returns `this` for chaining.
89
+ */
90
+ use(cs: BIP340Cryptosuite): this {
91
+ this.#current = cs;
92
+ return this;
93
+ }
94
+
95
+ /** Clear the current cryptosuite. */
96
+ clear(): void {
97
+ this.#current = undefined;
98
+ }
99
+
100
+ /**
101
+ * Create a new Schnorr cryptosuite from a multikey.
102
+ * @param multikey The Schnorr multikey to use.
103
+ * @returns The created Schnorr cryptosuite.
104
+ */
105
+ create(multikey: SchnorrMultikey): BIP340Cryptosuite {
106
+ return new BIP340Cryptosuite(multikey);
107
+ }
108
+
109
+ /**
110
+ * Convenience: resolve a key from the KMS and create a cryptosuite in one step.
111
+ * @param id The multikey ID (e.g. '#initialKey').
112
+ * @param controller The DID that controls this key.
113
+ * @param keyId The KMS key identifier to resolve.
114
+ * @param kms The KeyManagerApi instance holding the key.
115
+ * @returns The created Schnorr cryptosuite.
116
+ */
117
+ createFromKms(
118
+ id: string,
119
+ controller: string,
120
+ keyId: KeyIdentifier,
121
+ kms: KeyManagerApi
122
+ ): BIP340Cryptosuite {
123
+ const pubBytes = kms.getPublicKey(keyId);
124
+ const mk = SchnorrMultikey.fromPublicKey({ id, controller, publicKeyBytes: pubBytes });
125
+ return new BIP340Cryptosuite(mk as SchnorrMultikey);
126
+ }
127
+
128
+ /**
129
+ * Convert a cryptosuite to a Data Integrity Proof instance.
130
+ * Uses the current cryptosuite when `cryptosuite` is omitted.
131
+ * @param cryptosuite Optional explicit cryptosuite to convert.
132
+ * @returns The Data Integrity Proof instance.
133
+ */
134
+ toDataIntegrityProof(cryptosuite?: BIP340Cryptosuite): BIP340DataIntegrityProof {
135
+ const cs = cryptosuite ?? this.#requireCurrent();
136
+ return cs.toDataIntegrityProof();
137
+ }
138
+
139
+ /**
140
+ * Create a proof for a document.
141
+ * Uses the current cryptosuite when `cryptosuite` is omitted.
142
+ * @param document The document to create the proof for.
143
+ * @param config Configuration for the proof creation.
144
+ * @param cryptosuite Optional explicit cryptosuite; defaults to current.
145
+ * @returns The created proof.
146
+ */
147
+ createProof(
148
+ document: BTCR2Update,
149
+ config: DataIntegrityConfig,
150
+ cryptosuite?: BIP340Cryptosuite
151
+ ): DataIntegrityProofObject {
152
+ const cs = cryptosuite ?? this.#requireCurrent();
153
+ return cs.createProof(document, config);
154
+ }
155
+
156
+ /**
157
+ * Verify a proof for a document.
158
+ * Uses the current cryptosuite when `cryptosuite` is omitted.
159
+ * @param document The document to verify the proof for.
160
+ * @param cryptosuite Optional explicit cryptosuite; defaults to current.
161
+ * @returns The full verification result.
162
+ */
163
+ verifyProof(document: SignedBTCR2Update, cryptosuite?: BIP340Cryptosuite): VerificationResult {
164
+ const cs = cryptosuite ?? this.#requireCurrent();
165
+ return cs.verifyProof(document);
166
+ }
167
+
168
+ #requireCurrent(): BIP340Cryptosuite {
169
+ if (!this.#current) {
170
+ throw new Error(
171
+ 'No current cryptosuite set. Call cryptosuite.use(cs) first, or pass an explicit instance.'
172
+ );
173
+ }
174
+ return this.#current;
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Data Integrity Proof operations.
180
+ *
181
+ * Optionally stateful: call {@link use} to set a current proof instance, then
182
+ * call {@link addProof} or {@link verifyProof} without passing an explicit
183
+ * instance. Pass an explicit instance to override for that call.
184
+ * @public
185
+ */
186
+ export class DataIntegrityProofApi {
187
+ #current?: BIP340DataIntegrityProof;
188
+
189
+ /** The currently active proof instance, or `undefined` if none is set. */
190
+ get current(): BIP340DataIntegrityProof | undefined {
191
+ return this.#current;
192
+ }
193
+
194
+ /**
195
+ * Set the current proof instance for subsequent operations.
196
+ * @param p The proof instance to activate.
197
+ * @returns `this` for chaining.
198
+ */
199
+ use(p: BIP340DataIntegrityProof): this {
200
+ this.#current = p;
201
+ return this;
202
+ }
203
+
204
+ /** Clear the current proof instance. */
205
+ clear(): void {
206
+ this.#current = undefined;
207
+ }
208
+
209
+ /**
210
+ * Create a BIP340DataIntegrityProof instance with the given cryptosuite.
211
+ * @param cryptosuite The cryptosuite to use for proof operations.
212
+ * @returns The created BIP340DataIntegrityProof instance.
213
+ */
214
+ create(cryptosuite: BIP340Cryptosuite): BIP340DataIntegrityProof {
215
+ return new BIP340DataIntegrityProof(cryptosuite);
216
+ }
217
+
218
+ /**
219
+ * Add a proof to a document.
220
+ * Uses the current proof instance when `proof` is omitted.
221
+ * @param document The document to add the proof to.
222
+ * @param config Configuration for adding the proof.
223
+ * @param proof Optional explicit proof instance; defaults to current.
224
+ * @returns A document with a proof added.
225
+ */
226
+ addProof(
227
+ document: UnsignedBTCR2Update,
228
+ config: DataIntegrityConfig,
229
+ proof?: BIP340DataIntegrityProof
230
+ ): SignedBTCR2Update {
231
+ const p = proof ?? this.#requireCurrent();
232
+ return p.addProof(document, config);
233
+ }
234
+
235
+ /**
236
+ * Convenience: create a cryptosuite, proof instance, and sign a document
237
+ * in one call. Requires a multikey with signing capability.
238
+ * @param multikey The Schnorr multikey (must include secret key).
239
+ * @param document The unsigned document to sign.
240
+ * @param config The Data Integrity proof configuration.
241
+ * @returns The signed document with proof attached.
242
+ */
243
+ signDocument(
244
+ multikey: SchnorrMultikey,
245
+ document: UnsignedBTCR2Update,
246
+ config: DataIntegrityConfig
247
+ ): SignedBTCR2Update {
248
+ const cs = new BIP340Cryptosuite(multikey);
249
+ const proofInst = new BIP340DataIntegrityProof(cs);
250
+ return proofInst.addProof(document, config);
251
+ }
252
+
253
+ /**
254
+ * Verify a proof using a BIP340DataIntegrityProof instance.
255
+ * Uses the current proof instance when `proof` is omitted.
256
+ * @param document The document to verify the proof for.
257
+ * @param expectedPurpose The expected proof purpose.
258
+ * @param mediaType The media type of the document.
259
+ * @param expectedDomain The expected domain for the proof.
260
+ * @param expectedChallenge The expected challenge for the proof.
261
+ * @param proof Optional explicit proof instance; defaults to current.
262
+ * @returns The result of verifying the proof.
263
+ */
264
+ verifyProof(
265
+ document: string,
266
+ expectedPurpose: string,
267
+ mediaType?: string,
268
+ expectedDomain?: string,
269
+ expectedChallenge?: string,
270
+ proof?: BIP340DataIntegrityProof,
271
+ ): VerificationResult {
272
+ const p = proof ?? this.#requireCurrent();
273
+ return p.verifyProof(
274
+ document,
275
+ expectedPurpose,
276
+ mediaType,
277
+ expectedDomain,
278
+ expectedChallenge
279
+ );
280
+ }
281
+
282
+ #requireCurrent(): BIP340DataIntegrityProof {
283
+ if (!this.#current) {
284
+ throw new Error(
285
+ 'No current proof instance set. Call proof.use(p) first, or pass an explicit instance.'
286
+ );
287
+ }
288
+ return this.#current;
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Schnorr multikey operations.
294
+ *
295
+ * Optionally stateful: call {@link use} to set a current multikey, then
296
+ * call {@link sign}, {@link verify}, or {@link toVerificationMethod} without
297
+ * passing an explicit instance. Pass an explicit instance to any method to
298
+ * override the current one for that call.
299
+ * @public
300
+ */
301
+ export class MultikeyApi {
302
+ #current?: SchnorrMultikey;
303
+
304
+ /** The currently active multikey, or `undefined` if none is set. */
305
+ get current(): SchnorrMultikey | undefined {
306
+ return this.#current;
307
+ }
308
+
309
+ /**
310
+ * Set the current multikey for subsequent operations.
311
+ * @param mk The multikey to activate.
312
+ * @returns `this` for chaining.
313
+ */
314
+ use(mk: SchnorrMultikey): this {
315
+ this.#current = mk;
316
+ return this;
317
+ }
318
+
319
+ /** Clear the current multikey. */
320
+ clear(): void {
321
+ this.#current = undefined;
322
+ }
323
+
324
+ /**
325
+ * Create a new Schnorr multikey from a keypair.
326
+ * @param id The multikey ID.
327
+ * @param controller The multikey controller.
328
+ * @param keyPair The Schnorr keypair to use.
329
+ * @returns The created Schnorr multikey.
330
+ */
331
+ create(id: string, controller: string, keyPair: SchnorrKeyPair): SchnorrMultikey {
332
+ return new SchnorrMultikey({ id, controller, keyPair });
333
+ }
334
+
335
+ /**
336
+ * Create a Schnorr multikey from raw secret key bytes.
337
+ * @param id The multikey ID.
338
+ * @param controller The multikey controller.
339
+ * @param secretKeyBytes The secret key bytes.
340
+ * @returns The created Schnorr multikey.
341
+ */
342
+ fromSecretKey(id: string, controller: string, secretKeyBytes: Bytes): SchnorrMultikey {
343
+ return SchnorrMultikey.fromSecretKey(id, controller, secretKeyBytes);
344
+ }
345
+
346
+ /**
347
+ * Create a verification-only multikey from public key bytes.
348
+ * @param params The id, controller, and publicKeyBytes.
349
+ * @returns The created Multikey.
350
+ */
351
+ fromPublicKey(params: FromPublicKey): Multikey {
352
+ return SchnorrMultikey.fromPublicKey(params);
353
+ }
354
+
355
+ /**
356
+ * Convenience: resolve a key from the KMS and create a multikey in one step.
357
+ * @param id The multikey ID.
358
+ * @param controller The multikey controller DID.
359
+ * @param keyId The KMS key identifier to resolve.
360
+ * @param kms The KeyManagerApi instance holding the key.
361
+ * @returns The created Multikey (verification-only; public key from KMS).
362
+ */
363
+ fromKms(id: string, controller: string, keyId: KeyIdentifier, kms: KeyManagerApi): Multikey {
364
+ const pubBytes = kms.getPublicKey(keyId);
365
+ return SchnorrMultikey.fromPublicKey({ id, controller, publicKeyBytes: pubBytes });
366
+ }
367
+
368
+ /**
369
+ * Reconstruct a multikey from a DID document's verification method.
370
+ * @param verificationMethod The verification method to convert.
371
+ * @returns The reconstructed multikey.
372
+ */
373
+ fromVerificationMethod(verificationMethod: DidVerificationMethod): SchnorrMultikey {
374
+ return SchnorrMultikey.fromVerificationMethod(verificationMethod);
375
+ }
376
+
377
+ /**
378
+ * Produce a DID Verification Method JSON from a multikey.
379
+ * Uses the current multikey when `mk` is omitted.
380
+ * @param mk Optional explicit multikey; defaults to current.
381
+ */
382
+ toVerificationMethod(mk?: SchnorrMultikey): DidVerificationMethod {
383
+ const m = mk ?? this.#requireCurrent();
384
+ return m.toVerificationMethod();
385
+ }
386
+
387
+ /**
388
+ * Sign bytes via the multikey (requires secret).
389
+ * Uses the current multikey when `mk` is omitted.
390
+ * @param data The data to sign.
391
+ * @param mk Optional explicit multikey; defaults to current.
392
+ */
393
+ sign(data: Bytes, mk?: SchnorrMultikey): SignatureBytes {
394
+ const m = mk ?? this.#requireCurrent();
395
+ return m.sign(data);
396
+ }
397
+
398
+ /**
399
+ * Verify signature via multikey.
400
+ * Uses the current multikey when `mk` is omitted.
401
+ * @param data The data that was signed.
402
+ * @param signature The signature to verify.
403
+ * @param mk Optional explicit multikey; defaults to current.
404
+ */
405
+ verify(data: Bytes, signature: SignatureBytes, mk?: SchnorrMultikey): boolean {
406
+ const m = mk ?? this.#requireCurrent();
407
+ return m.verify(signature, data);
408
+ }
409
+
410
+ #requireCurrent(): SchnorrMultikey {
411
+ if (!this.#current) {
412
+ throw new Error(
413
+ 'No current multikey set. Call multikey.use(mk) first, or pass an explicit instance.'
414
+ );
415
+ }
416
+ return this.#current;
417
+ }
418
+ }
419
+
420
+ /**
421
+ * Aggregated cryptographic operations sub-facade.
422
+ *
423
+ * Provides direct access to the four sub-facades ({@link keypair},
424
+ * {@link multikey}, {@link cryptosuite}, {@link proof}) plus top-level
425
+ * convenience methods that orchestrate the full signing/verification
426
+ * pipeline using their stateful defaults.
427
+ *
428
+ * @example Stateful pipeline
429
+ * ```ts
430
+ * const api = createApi();
431
+ * const kp = api.crypto.keypair.generate();
432
+ * const mk = api.crypto.multikey.create('#key-1', 'did:btcr2:test', kp);
433
+ *
434
+ * // Set the active multikey — flows through to cryptosuite and proof
435
+ * api.crypto.activate(mk);
436
+ *
437
+ * // Now sign without threading instances
438
+ * const signed = api.crypto.signDocument(unsignedDoc, proofConfig);
439
+ * ```
440
+ * @public
441
+ */
442
+ export class CryptoApi {
443
+ /** Schnorr keypair operations. */
444
+ readonly keypair = new KeyPairApi();
445
+
446
+ /** Schnorr Multikey operations (optionally stateful). */
447
+ readonly multikey = new MultikeyApi();
448
+
449
+ /** Schnorr Cryptosuite operations (optionally stateful). */
450
+ readonly cryptosuite = new CryptosuiteApi();
451
+
452
+ /** Data Integrity Proof operations (optionally stateful). */
453
+ readonly proof = new DataIntegrityProofApi();
454
+
455
+ /**
456
+ * Activate a multikey and propagate through the full pipeline.
457
+ * Sets the current multikey, creates a cryptosuite from it, and creates
458
+ * a proof instance from the cryptosuite — all three sub-facades become
459
+ * ready for stateful operations.
460
+ * @param mk The multikey to activate (must include a secret key for signing).
461
+ * @returns `this` for chaining.
462
+ */
463
+ activate(mk: SchnorrMultikey): this {
464
+ this.multikey.use(mk);
465
+ const cs = this.cryptosuite.create(mk);
466
+ this.cryptosuite.use(cs);
467
+ const p = this.proof.create(cs);
468
+ this.proof.use(p);
469
+ return this;
470
+ }
471
+
472
+ /**
473
+ * Clear stateful defaults from all sub-facades.
474
+ */
475
+ deactivate(): void {
476
+ this.multikey.clear();
477
+ this.cryptosuite.clear();
478
+ this.proof.clear();
479
+ }
480
+
481
+ /**
482
+ * Sign data using the current multikey.
483
+ * Shorthand for `crypto.multikey.sign(data)`.
484
+ * @param data The data to sign.
485
+ * @returns The signature bytes.
486
+ */
487
+ sign(data: Bytes): SignatureBytes {
488
+ return this.multikey.sign(data);
489
+ }
490
+
491
+ /**
492
+ * Verify a signature using the current multikey.
493
+ * Shorthand for `crypto.multikey.verify(data, signature)`.
494
+ * @param data The data that was signed.
495
+ * @param signature The signature to verify.
496
+ * @returns `true` if the signature is valid.
497
+ */
498
+ verify(data: Bytes, signature: SignatureBytes): boolean {
499
+ return this.multikey.verify(data, signature);
500
+ }
501
+
502
+ /**
503
+ * Sign a BTCR2 update document using the current proof instance.
504
+ * Shorthand for `crypto.proof.addProof(document, config)`.
505
+ *
506
+ * Requires {@link activate} to have been called first, or the three
507
+ * sub-facades to have been configured individually.
508
+ * @param document The unsigned BTCR2 update document.
509
+ * @param config The Data Integrity proof configuration.
510
+ * @returns The signed document with proof attached.
511
+ */
512
+ signDocument(document: UnsignedBTCR2Update, config: DataIntegrityConfig): SignedBTCR2Update {
513
+ return this.proof.addProof(document, config);
514
+ }
515
+
516
+ /**
517
+ * Verify a signed BTCR2 update document using the current cryptosuite.
518
+ * Shorthand for `crypto.cryptosuite.verifyProof(document)`.
519
+ * @param document The signed document to verify.
520
+ * @returns The full verification result.
521
+ */
522
+ verifyDocument(document: SignedBTCR2Update): VerificationResult {
523
+ return this.cryptosuite.verifyProof(document);
524
+ }
525
+ }
package/src/did.ts ADDED
@@ -0,0 +1,75 @@
1
+ import type { NetworkName } from '@did-btcr2/bitcoin';
2
+ import type { DocumentBytes } from '@did-btcr2/common';
3
+ import { IdentifierTypes } from '@did-btcr2/common';
4
+ import { SchnorrKeyPair } from '@did-btcr2/keypair';
5
+ import type { SchnorrKeyPairObject } from '@did-btcr2/common';
6
+ import type { DidCreateOptions } from '@did-btcr2/method';
7
+ import { Identifier, IdentifierComponents } from '@did-btcr2/method';
8
+ import { Did } from '@web5/dids';
9
+ import { assertBytes, assertString } from './helpers.js';
10
+
11
+ /**
12
+ * DID identifier operations sub-facade (encode, decode, generate, parse).
13
+ * @public
14
+ */
15
+ export class DidApi {
16
+ /**
17
+ * Encode a DID from genesis bytes and options.
18
+ * @param genesisBytes The genesis document bytes.
19
+ * @param options The creation options.
20
+ * @returns The encoded DID string.
21
+ */
22
+ encode(genesisBytes: DocumentBytes, options: DidCreateOptions): string {
23
+ assertBytes(genesisBytes, 'genesisBytes');
24
+ return Identifier.encode(genesisBytes, options);
25
+ }
26
+
27
+ /**
28
+ * Decode a DID into its components.
29
+ * @param did The DID string to decode.
30
+ * @returns The decoded identifier components.
31
+ */
32
+ decode(did: string): IdentifierComponents {
33
+ assertString(did, 'did');
34
+ return Identifier.decode(did);
35
+ }
36
+
37
+ /**
38
+ * Generate a new DID along with its keypair.
39
+ *
40
+ * When no `network` is given, defaults to `'regtest'` (upstream default).
41
+ * Pass an explicit network to generate DIDs for other networks.
42
+ *
43
+ * @param network Optional network to generate the DID for.
44
+ * @returns The generated keypair and DID string.
45
+ */
46
+ generate(network?: NetworkName): { keyPair: SchnorrKeyPairObject; did: string } {
47
+ if (!network) return Identifier.generate();
48
+ const kp = SchnorrKeyPair.generate();
49
+ const did = Identifier.encode(kp.publicKey.compressed, {
50
+ idType : IdentifierTypes.KEY,
51
+ network,
52
+ });
53
+ return { keyPair: kp.exportJSON(), did };
54
+ }
55
+
56
+ /**
57
+ * Check if a DID string is valid.
58
+ * @param did The DID string to validate.
59
+ * @returns `true` if valid, `false` otherwise.
60
+ */
61
+ isValid(did: string): boolean {
62
+ if (typeof did !== 'string' || did.length === 0) return false;
63
+ return Identifier.isValid(did);
64
+ }
65
+
66
+ /**
67
+ * Parse a DID string into a Did instance.
68
+ * @param did The DID string to parse.
69
+ * @returns The parsed Did instance, or `null` if parsing failed.
70
+ */
71
+ parse(did: string): Did | null {
72
+ if (typeof did !== 'string' || did.length === 0) return null;
73
+ return Did.parse(did);
74
+ }
75
+ }
package/src/helpers.ts ADDED
@@ -0,0 +1,35 @@
1
+ import type { Logger } from './types.js';
2
+
3
+ const noopFn = () => {};
4
+
5
+ /** @internal */
6
+ export const NOOP_LOGGER: Logger = {
7
+ debug : noopFn,
8
+ info : noopFn,
9
+ warn : noopFn,
10
+ error : noopFn,
11
+ };
12
+
13
+ /** @internal */
14
+ export function assertString(value: unknown, name: string): asserts value is string {
15
+ if (typeof value !== 'string' || value.length === 0) {
16
+ throw new Error(`${name} must be a non-empty string.`);
17
+ }
18
+ }
19
+
20
+ /** @internal */
21
+ export function assertBytes(value: unknown, name: string): asserts value is Uint8Array {
22
+ if (!(value instanceof Uint8Array) || value.length === 0) {
23
+ throw new Error(`${name} must be a non-empty Uint8Array.`);
24
+ }
25
+ }
26
+
27
+ /** @internal */
28
+ export function assertCompressedPubkey(value: unknown, name: string): asserts value is Uint8Array {
29
+ assertBytes(value, name);
30
+ if (value.length !== 33) {
31
+ throw new Error(
32
+ `${name} must be a 33-byte compressed public key, got ${value.length} bytes.`
33
+ );
34
+ }
35
+ }
package/src/index.ts CHANGED
@@ -1 +1,37 @@
1
- export * from './api.js';
1
+ // Upstream re-exports
2
+ export { DidDocument, DidDocumentBuilder, Identifier } from '@did-btcr2/method';
3
+ export { IdentifierTypes } from '@did-btcr2/common';
4
+ export type {
5
+ BlockV3,
6
+ HttpExecutor,
7
+ NetworkName,
8
+ RawTransactionV2,
9
+ RestConfig,
10
+ RpcConfig
11
+ } from '@did-btcr2/bitcoin';
12
+ export type {
13
+ Bytes,
14
+ CryptosuiteName,
15
+ DocumentBytes,
16
+ HashBytes,
17
+ Hex,
18
+ JSONObject,
19
+ KeyBytes,
20
+ PatchOperation,
21
+ ProofBytes,
22
+ SchnorrKeyPairObject,
23
+ SignatureBytes
24
+ } from '@did-btcr2/common';
25
+ export type { MultikeyObject } from '@did-btcr2/cryptosuite';
26
+ export type { DidResolutionResult, DidService, DidVerificationMethod } from '@web5/dids';
27
+
28
+ // Local modules
29
+ export * from './types.js';
30
+ export * from './helpers.js';
31
+ export * from './bitcoin.js';
32
+ export * from './cas.js';
33
+ export * from './kms.js';
34
+ export * from './crypto.js';
35
+ export * from './did.js';
36
+ export * from './method.js';
37
+ export * from './api.js';