@did-btcr2/common 3.1.0 → 5.0.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.
@@ -1,36 +1,24 @@
1
1
  import { sha256 } from '@noble/hashes/sha2';
2
- import { bytesToHex } from '@noble/hashes/utils';
2
+ import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
3
3
  import { canonicalize as jcsa } from 'json-canonicalize';
4
4
  import { base58btc } from 'multiformats/bases/base58';
5
5
  import { CanonicalizationError } from './errors.js';
6
- import { CanonicalizationAlgorithm, CanonicalizationEncoding, HashBytes } from './types.js';
6
+ import { CanonicalizationAlgorithm, CanonicalizationEncoding, HashBytes, HexString } from './types.js';
7
+ import { base64url } from 'multiformats/bases/base64';
8
+
9
+ export interface CanonicalizationOptions {
10
+ algorithm?: CanonicalizationAlgorithm;
11
+ encoding?: CanonicalizationEncoding;
12
+ }
7
13
 
8
14
  /**
9
15
  * Canonicalization class provides methods for canonicalizing JSON objects
10
16
  * and hashing them using SHA-256. It supports different canonicalization
11
- * algorithms and encoding formats (hex and base58).
17
+ * algorithms and encoding formats (hex and base58btc).
12
18
  * @class Canonicalization
13
19
  * @type {Canonicalization}
14
20
  */
15
21
  export class Canonicalization {
16
- private readonly _defaultAlgorithm: CanonicalizationAlgorithm;
17
-
18
- /**
19
- * Initializes the Canonicalization class with the specified algorithm.
20
- * @param {CanonicalizationAlgorithm} algorithm The canonicalization algorithm to use ('jcs').
21
- */
22
- constructor(algorithm: CanonicalizationAlgorithm = 'jcs') {
23
- this._defaultAlgorithm = Canonicalization.normalizeAlgorithm(algorithm);
24
- }
25
-
26
- /**
27
- * Gets the canonicalization algorithm.
28
- * @returns {CanonicalizationAlgorithm} The current canonicalization algorithm.
29
- */
30
- get algorithm(): CanonicalizationAlgorithm {
31
- return this._defaultAlgorithm;
32
- }
33
-
34
22
  /**
35
23
  * Normalizes the canonicalization algorithm.
36
24
  * @param {CanonicalizationAlgorithm} algorithm
@@ -53,7 +41,7 @@ export class Canonicalization {
53
41
  */
54
42
  static normalizeEncoding(encoding: CanonicalizationEncoding): CanonicalizationEncoding {
55
43
  const normalized = encoding.toLowerCase() as CanonicalizationEncoding;
56
- if (normalized !== 'hex' && normalized !== 'base58') {
44
+ if (!['hex', 'base58btc', 'base64url'].includes(normalized)) {
57
45
  throw new CanonicalizationError(`Unsupported encoding: ${encoding}`, 'ENCODING_ERROR');
58
46
  }
59
47
  return normalized;
@@ -70,24 +58,22 @@ export class Canonicalization {
70
58
  *
71
59
  * @param {Record<any, any>} object The object to process.
72
60
  * @param {Object} [options] Options for processing.
73
- * @param {CanonicalizationEncoding} [options.encoding='hex'] The encoding format ('hex' or 'base58').
61
+ * @param {CanonicalizationEncoding} [options.encoding='hex'] The encoding format ('hex' or 'base58btc').
74
62
  * @param {CanonicalizationAlgorithm} [options.algorithm] The canonicalization algorithm to use.
75
63
  * @returns {string} The final SHA-256 hash bytes as a hex string.
76
64
  */
77
- process(object: Record<any, any>, options: {
78
- encoding?: CanonicalizationEncoding;
79
- algorithm?: CanonicalizationAlgorithm;
80
- multibase?: boolean;
81
- } = {}): string {
82
- const algorithm = Canonicalization.normalizeAlgorithm(options.algorithm ?? this._defaultAlgorithm);
83
- const encoding = Canonicalization.normalizeEncoding(options.encoding ?? 'hex');
65
+ static process(object: Record<any, any>, options?: CanonicalizationOptions): string {
66
+ // Normalize the algorithm
67
+ const algorithm = Canonicalization.normalizeAlgorithm(options?.algorithm ?? 'jcs');
68
+ // Normalize the encoding
69
+ const encoding = Canonicalization.normalizeEncoding(options?.encoding ?? 'hex');
84
70
 
85
71
  // Step 1: Canonicalize
86
72
  const canonicalized = this.canonicalize(object, algorithm);
87
73
  // Step 2: Hash
88
- const hashed = this.hash(canonicalized);
74
+ const hashed = this.toHash(canonicalized);
89
75
  // Step 3: Encode
90
- const encoded = this.encode(hashed, encoding, options.multibase ?? false);
76
+ const encoded = this.encode(hashed, encoding);
91
77
  // Return the encoded string
92
78
  return encoded;
93
79
  }
@@ -98,7 +84,7 @@ export class Canonicalization {
98
84
  * @param {CanonicalizationAlgorithm} [algorithm] The algorithm to use.
99
85
  * @returns {string} The canonicalized object.
100
86
  */
101
- canonicalize(object: Record<any, any>, algorithm: CanonicalizationAlgorithm = this._defaultAlgorithm): string {
87
+ static canonicalize(object: Record<any, any>, algorithm: CanonicalizationAlgorithm = 'jcs'): string {
102
88
  switch (Canonicalization.normalizeAlgorithm(algorithm)) {
103
89
  case 'jcs':
104
90
  return this.jcs(object);
@@ -112,7 +98,7 @@ export class Canonicalization {
112
98
  * @param {Record<any, any>} object The object to canonicalize.
113
99
  * @returns {string} The canonicalized object.
114
100
  */
115
- jcs(object: Record<any, any>): string {
101
+ static jcs(object: Record<any, any>): string {
116
102
  return jcsa(object);
117
103
  }
118
104
 
@@ -121,44 +107,121 @@ export class Canonicalization {
121
107
  * @param {string} canonicalized The canonicalized object.
122
108
  * @returns {HashBytes} The SHA-256 HashBytes (Uint8Array).
123
109
  */
124
- hash(canonicalized: string): HashBytes {
110
+ static toHash(canonicalized: string): HashBytes {
125
111
  return sha256(canonicalized);
126
112
  }
127
113
 
128
114
  /**
129
- * Step 3: Encodes SHA-256 hashed, canonicalized object as a hex or base58 string.
115
+ * Step 3: Encodes SHA-256 hashed, canonicalized object as a hex or base58btc string.
130
116
  * @param {string} canonicalizedhash The canonicalized object to encode.
131
- * @param {CanonicalizationEncoding} encoding The encoding format ('hex' or 'base58').
117
+ * @param {CanonicalizationEncoding} encoding The encoding format ('hex' or 'base58btc').
132
118
  * @throws {CanonicalizationError} If the encoding format is not supported.
133
119
  * @returns {string} The encoded string.
134
120
  */
135
- encode(canonicalizedhash: HashBytes, encoding: CanonicalizationEncoding = 'hex', multibase: boolean = false): string {
121
+ static encode(canonicalizedhash: HashBytes, encoding: CanonicalizationEncoding = 'hex'): string {
122
+ // Normalize encoding
136
123
  const normalized = Canonicalization.normalizeEncoding(encoding);
137
- if (normalized === 'hex') return this.hex(canonicalizedhash);
138
- if (normalized === 'base58') {
139
- const encoded = this.base58(canonicalizedhash);
140
- return multibase ? `z${encoded}` : encoded;
124
+
125
+ // If encoding is hex, encode to hex
126
+ if (normalized === 'hex') {
127
+ return this.toHex(canonicalizedhash);
141
128
  }
129
+
130
+ // If encoding is base58btc, encode to base58btc
131
+ if (normalized === 'base58btc') {
132
+ return this.toBase58(canonicalizedhash);
133
+ }
134
+
135
+ // If encoding is base64url, encode to base64url
136
+ if (normalized === 'base64url') {
137
+ return this.toBase64Url(canonicalizedhash);
138
+ }
139
+
140
+ // Throw error if encoding is unsupported
142
141
  throw new CanonicalizationError(`Unsupported encoding: ${encoding}`, 'ENCODING_ERROR');
143
142
  }
144
143
 
144
+ /**
145
+ * Decodes SHA-256 hashed, canonicalized object as a hex or base58btc string.
146
+ * @param {string} canonicalizedhash The canonicalized object to encode.
147
+ * @param {CanonicalizationEncoding} encoding The encoding format ('hex' or 'base58btc').
148
+ * @throws {CanonicalizationError} If the encoding format is not supported.
149
+ * @returns {string} The encoded string.
150
+ */
151
+ static decode(canonicalizedhash: string, encoding: CanonicalizationEncoding = 'hex'): HashBytes {
152
+ // Normalize encoding
153
+ const normalized = Canonicalization.normalizeEncoding(encoding);
154
+
155
+ // If encoding is hex, decode from hex
156
+ if (normalized === 'hex') {
157
+ return this.fromHex(canonicalizedhash);
158
+ }
159
+
160
+ // If encoding is base58btc, decode from base58btc
161
+ if (normalized === 'base58btc') {
162
+ return this.fromBase58(canonicalizedhash);
163
+ }
164
+
165
+ if(normalized === 'base64url') {
166
+ return this.fromBase64Url(canonicalizedhash);
167
+ }
168
+
169
+ // Throw error if encoding is unsupported
170
+ throw new CanonicalizationError(`Unsupported encoding: ${encoding}`, 'DECODING_ERROR');
171
+ }
172
+
145
173
  /**
146
174
  * Step 3.1: Encodes HashBytes (Uint8Array) to a hex string.
147
175
  * @param {HashBytes} hashBytes The hash as a Uint8Array.
148
176
  * @returns {string} The hash as a hex string.
149
177
  */
150
- hex(hashBytes: HashBytes): string {
178
+ static toHex(hashBytes: HashBytes): string {
151
179
  return bytesToHex(hashBytes);
152
180
  }
153
181
 
182
+ /**
183
+ * Decodes a hex string to HashBytes (Uint8Array).
184
+ * @param {HexString} hexString The hash as a hex string.
185
+ * @returns {HashBytes} The hash bytes.
186
+ */
187
+ static fromHex(hexString: HexString): HashBytes {
188
+ return hexToBytes(hexString);
189
+ }
190
+
154
191
  /**
155
192
  * Step 3.2: Encodes HashBytes (Uint8Array) to a base58btc string.
156
193
  * @param {HashBytes} hashBytes The hash as a Uint8Array.
157
194
  * @returns {string} The hash as a hex string.
158
195
  */
159
- base58(hashBytes: HashBytes): string {
160
- const encoded = base58btc.encode(hashBytes);
161
- return encoded.startsWith('z') ? encoded.slice(1) : encoded;
196
+ static toBase58(hashBytes: HashBytes): string {
197
+ return base58btc.encode(hashBytes);
198
+ }
199
+
200
+ /**
201
+ * Decodes a base58btc string to HashBytes (Uint8Array).
202
+ * @param {string} b58str The hash as a base58btc string.
203
+ * @returns {HashBytes} The hash bytes.
204
+ */
205
+ static fromBase58(b58str: string): HashBytes {
206
+ return base58btc.decode(b58str);
207
+ }
208
+
209
+ /**
210
+ * Step 3.2: Encodes HashBytes (Uint8Array) to a base64url string.
211
+ * @param {HashBytes} hashBytes The hash as a Uint8Array.
212
+ * @returns {string} The hash as a base64url string.
213
+ */
214
+ static toBase64Url(hashBytes: HashBytes): string {
215
+ return base64url.encode(hashBytes);
216
+ }
217
+
218
+ /**
219
+ * Decodes a base64url string to HashBytes (Uint8Array).
220
+ * @param {string} b64urlstr The hash as a base64url string.
221
+ * @returns {HashBytes} The hash bytes.
222
+ */
223
+ static fromBase64Url(b64urlstr: string): HashBytes {
224
+ return base64url.decode(b64urlstr);
162
225
  }
163
226
 
164
227
  /**
@@ -167,12 +230,16 @@ export class Canonicalization {
167
230
  * @param {Record<any, any>} object The object to process.
168
231
  * @returns {Promise<HashBytes>} The final SHA-256 hash bytes.
169
232
  */
170
- canonicalhash(
233
+ static andHash(
171
234
  object: Record<any, any>,
172
- algorithm: CanonicalizationAlgorithm = this._defaultAlgorithm
235
+ algorithm: CanonicalizationAlgorithm = 'jcs'
173
236
  ): HashBytes {
237
+ // Step 1: Canonicalize
174
238
  const canonicalized = this.canonicalize(object, algorithm);
175
- return this.hash(canonicalized);
239
+ // Step 2: Hash
240
+ const hashed = this.toHash(canonicalized);
241
+ // Return canonicalized hash bytes
242
+ return hashed;
176
243
  }
177
244
 
178
245
  /**
@@ -181,17 +248,32 @@ export class Canonicalization {
181
248
  * @param {string} canonicalized The canonicalized object to hash.
182
249
  * @returns {string} The SHA-256 hash as a hex string.
183
250
  */
184
- hashhex(canonicalized: string): string {
185
- return this.encode(this.hash(canonicalized), 'hex');
251
+ static andHashToHex(canonicalized: string): string {
252
+ // Step 2: Hash
253
+ const hashed = this.toHash(canonicalized);
254
+ // Step 3: Encode (Hex)
255
+ const hexed = this.toHex(hashed);
256
+ // Return the hashed encoded string
257
+ return hexed;
258
+ }
259
+
260
+ /**
261
+ * Computes the SHA-256 hashes of canonicalized object and encodes it as a base58btc string.
262
+ * Step 2-3: Hash → Encode(base58btc).
263
+ * @param {string} canonicalized The canonicalized object to hash.
264
+ * @returns {string} The SHA-256 hash as a base58btc string.
265
+ */
266
+ static andHashToBase58(canonicalized: string): string {
267
+ return this.encode(this.toHash(canonicalized), 'base58btc');
186
268
  }
187
269
 
188
270
  /**
189
- * Computes the SHA-256 hashes of canonicalized object and encodes it as a base58 string.
190
- * Step 2-3: Hash → Encode(base58).
271
+ * Computes the SHA-256 hashes of canonicalized object and encodes it as a base64url string.
272
+ * Step 2-3: Hash → Encode(base64url).
191
273
  * @param {string} canonicalized The canonicalized object to hash.
192
- * @returns {string} The SHA-256 hash as a base58 string.
274
+ * @returns {string} The SHA-256 hash as a base64url string.
193
275
  */
194
- hashbase58(canonicalized: string): string {
195
- return this.encode(this.hash(canonicalized), 'base58', false);
276
+ static andHashToBase64Url(canonicalized: string): string {
277
+ return this.toBase64Url(this.toHash(canonicalized));
196
278
  }
197
279
  }
package/src/errors.ts CHANGED
@@ -82,7 +82,10 @@ export enum MethodErrorCode {
82
82
  INVALID_UPDATE = 'INVALID_UPDATE',
83
83
 
84
84
  /** The proof is missing or has a malformed domain field. */
85
- INVALID_DOMAIN_ERROR = 'INVALID_DOMAIN_ERROR'
85
+ INVALID_DOMAIN_ERROR = 'INVALID_DOMAIN_ERROR',
86
+
87
+ /** Options required for resolution are missing. */
88
+ MISSING_RESOLUTION_OPTIONS = 'MISSING_RESOLUTION_OPTIONS'
86
89
  }
87
90
 
88
91
  export const {
@@ -111,7 +114,8 @@ export const {
111
114
  INVALID_SIDECAR_DATA,
112
115
  MISSING_UPDATE_DATA,
113
116
  INVALID_UPDATE,
114
- INVALID_DOMAIN_ERROR
117
+ INVALID_DOMAIN_ERROR,
118
+ MISSING_RESOLUTION_OPTIONS
115
119
  } = MethodErrorCode;
116
120
 
117
121
  export type ErrorOptions = {
package/src/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export * from './canonicalization.js';
2
2
  export * from './constants.js';
3
3
  export * from './errors.js';
4
- export * from './interfaces.js';
5
4
  export * from './json-patch.js';
6
5
  export * from './logger.js';
7
6
  export * from './types.js';
package/src/json-patch.ts CHANGED
@@ -1,10 +1,20 @@
1
1
  import jsonPatch, { Operation } from 'fast-json-patch';
2
2
  import { MethodError } from './errors.js';
3
- import { PatchOperation } from './interfaces.js';
4
3
  import { JSONObject } from './types.js';
5
4
 
6
5
  const { applyPatch, compare, deepClone } = jsonPatch;
7
6
 
7
+ export type PatchOpCode = 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test' | (string & {});
8
+ /**
9
+ * A JSON Patch operation, as defined in {@link https://datatracker.ietf.org/doc/html/rfc6902 | RFC 6902}.
10
+ */
11
+ export interface PatchOperation {
12
+ op: PatchOpCode;
13
+ path: string;
14
+ value?: unknown; // Required for add, replace, test
15
+ from?: string; // Required for move, copy
16
+ }
17
+
8
18
  /**
9
19
  * Thin wrapper around fast-json-patch to keep a stable API within this package.
10
20
  * @class JSONPatch
package/src/types.ts CHANGED
@@ -26,13 +26,13 @@ export type Point = {
26
26
  }
27
27
  export type PublicKeyObject = {
28
28
  point: Point;
29
- hex: Hex;
29
+ hex: HexString;
30
30
  multibase: MultibaseObject;
31
31
  };
32
32
  export type SecretKeyObject = {
33
33
  bytes: Array<number>;
34
34
  seed?: string;
35
- hex?: Hex;
35
+ hex?: HexString;
36
36
  };
37
37
  export type SchnorrKeyPair = {
38
38
  secretKey: KeyBytes;
@@ -70,7 +70,6 @@ export enum BitcoinNetworkNames {
70
70
  export type DecentralizedIdentifier = string;
71
71
  export type Did = DecentralizedIdentifier;
72
72
  export type BeaconUri = string;
73
- export type DidPlaceholder = 'did:btcr2:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
74
73
  export type CanonicalizedProofConfig = string;
75
74
  export type CryptosuiteName = 'bip340-jcs-2025' | 'bip340-rdfc-2025';
76
75
  export type JsonPrimitive = string | number | boolean | null;
@@ -98,5 +97,5 @@ export type TzOffset = `${Hours}:${Minutes}`;
98
97
  export type DateTimestamp = `${UtcTimestamp}Z` | `${UtcTimestamp}-${TzOffset}`;
99
98
  export type CanonicalizableObject = Record<string, any>;
100
99
  export type CanonicalizationAlgorithm = 'jcs' | 'rdfc';
101
- export type CanonicalizationEncoding = 'hex' | 'base58';
100
+ export type CanonicalizationEncoding = 'hex' | 'base58btc' | 'base64url';
102
101
  export type UnixTimestamp = number;
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=interfaces.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=interfaces.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":""}
@@ -1,11 +0,0 @@
1
- export type JsonPatch = Array<PatchOperation>;
2
- export type PatchOpCode = 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test' | (string & {});
3
- /**
4
- * A JSON Patch operation, as defined in {@link https://datatracker.ietf.org/doc/html/rfc6902 | RFC 6902}.
5
- */
6
- export interface PatchOperation {
7
- op: PatchOpCode;
8
- path: string;
9
- value?: unknown;
10
- from?: string;
11
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;AAC9C,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAClG;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,WAAW,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
package/src/interfaces.ts DELETED
@@ -1,11 +0,0 @@
1
- export type JsonPatch = Array<PatchOperation>;
2
- export type PatchOpCode = 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test' | (string & {});
3
- /**
4
- * A JSON Patch operation, as defined in {@link https://datatracker.ietf.org/doc/html/rfc6902 | RFC 6902}.
5
- */
6
- export interface PatchOperation {
7
- op: PatchOpCode;
8
- path: string;
9
- value?: unknown; // Required for add, replace, test
10
- from?: string; // Required for move, copy
11
- }