@theqrl/wallet.js 0.2.2 → 1.0.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.
@@ -305,15 +305,17 @@ class ExtendedSeed {
305
305
  /**
306
306
  * Layout: [3 bytes descriptor] || [48 bytes seed].
307
307
  * @param {Uint8Array} bytes Exactly 51 bytes.
308
+ * @param {{ skipValidation?: boolean }} [options]
308
309
  * @throws {Error} If size mismatch.
309
310
  */
310
- constructor(bytes) {
311
+ constructor(bytes, options = {}) {
311
312
  if (!bytes || bytes.length !== EXTENDED_SEED_SIZE) {
312
313
  throw new Error(`ExtendedSeed must be ${EXTENDED_SEED_SIZE} bytes`);
313
314
  }
315
+ const { skipValidation = false } = options;
314
316
  /** @private @type {Uint8Array} */
315
317
  this.bytes = Uint8Array.from(bytes);
316
- if (!isValidWalletType(this.bytes[0])) {
318
+ if (!skipValidation && !isValidWalletType(this.bytes[0])) {
317
319
  throw new Error('Invalid wallet type in descriptor');
318
320
  }
319
321
  }
@@ -375,6 +377,17 @@ class ExtendedSeed {
375
377
  static from(input) {
376
378
  return new ExtendedSeed(toFixedU8(input, EXTENDED_SEED_SIZE, 'ExtendedSeed'));
377
379
  }
380
+
381
+ /**
382
+ * Internal helper: construct without wallet type validation.
383
+ * @param {string|Uint8Array|Buffer|number[]} input
384
+ * @returns {ExtendedSeed}
385
+ */
386
+ static fromUnchecked(input) {
387
+ return new ExtendedSeed(toFixedU8(input, EXTENDED_SEED_SIZE, 'ExtendedSeed'), {
388
+ skipValidation: true,
389
+ });
390
+ }
378
391
  }
379
392
 
380
393
  /**
@@ -4526,12 +4539,10 @@ function binToMnemonic(input) {
4526
4539
  for (let nibble = 0; nibble < input.length * 2; nibble += 3) {
4527
4540
  const p = nibble >> 1;
4528
4541
  const b1 = input[p];
4542
+ /* c8 ignore next -- fallback unreachable for valid (multiple of 3) input */
4529
4543
  const b2 = p + 1 < input.length ? input[p + 1] : 0;
4530
4544
  const idx = nibble % 2 === 0 ? (b1 << 4) + (b2 >> 4) : ((b1 & 0x0f) << 8) + b2;
4531
4545
 
4532
- if (idx >= WordList.length) {
4533
- throw new Error('mnemonic index out of range');
4534
- }
4535
4546
  words.push(WordList[idx]);
4536
4547
  }
4537
4548
 
@@ -4732,17 +4743,22 @@ class Wallet {
4732
4743
 
4733
4744
  /** @returns {Descriptor} */
4734
4745
  getDescriptor() {
4735
- return this.descriptor;
4746
+ return new Descriptor(this.descriptor.toBytes());
4736
4747
  }
4737
4748
 
4738
4749
  /** @returns {ExtendedSeed} */
4739
4750
  getExtendedSeed() {
4740
- return this.extendedSeed;
4751
+ const bytes = this.extendedSeed.toBytes();
4752
+ try {
4753
+ return ExtendedSeed.from(bytes);
4754
+ } catch {
4755
+ return ExtendedSeed.fromUnchecked(bytes);
4756
+ }
4741
4757
  }
4742
4758
 
4743
4759
  /** @returns {Seed} */
4744
4760
  getSeed() {
4745
- return this.seed;
4761
+ return new Seed(this.seed.toBytes());
4746
4762
  }
4747
4763
 
4748
4764
  /** @returns {string} hex(ExtendedSeed) */
@@ -4835,6 +4851,7 @@ function newWalletFromExtendedSeed(extendedSeed) {
4835
4851
  return Wallet.newWalletFromExtendedSeed(ext);
4836
4852
  // case WalletType.SPHINCSPLUS_256S:
4837
4853
  // Not yet implemented - reserved for future use
4854
+ /* c8 ignore next 2 */
4838
4855
  default:
4839
4856
  throw new Error(`Unsupported wallet type: ${desc.type()}`);
4840
4857
  }
@@ -303,15 +303,17 @@ class ExtendedSeed {
303
303
  /**
304
304
  * Layout: [3 bytes descriptor] || [48 bytes seed].
305
305
  * @param {Uint8Array} bytes Exactly 51 bytes.
306
+ * @param {{ skipValidation?: boolean }} [options]
306
307
  * @throws {Error} If size mismatch.
307
308
  */
308
- constructor(bytes) {
309
+ constructor(bytes, options = {}) {
309
310
  if (!bytes || bytes.length !== EXTENDED_SEED_SIZE) {
310
311
  throw new Error(`ExtendedSeed must be ${EXTENDED_SEED_SIZE} bytes`);
311
312
  }
313
+ const { skipValidation = false } = options;
312
314
  /** @private @type {Uint8Array} */
313
315
  this.bytes = Uint8Array.from(bytes);
314
- if (!isValidWalletType(this.bytes[0])) {
316
+ if (!skipValidation && !isValidWalletType(this.bytes[0])) {
315
317
  throw new Error('Invalid wallet type in descriptor');
316
318
  }
317
319
  }
@@ -373,6 +375,17 @@ class ExtendedSeed {
373
375
  static from(input) {
374
376
  return new ExtendedSeed(toFixedU8(input, EXTENDED_SEED_SIZE, 'ExtendedSeed'));
375
377
  }
378
+
379
+ /**
380
+ * Internal helper: construct without wallet type validation.
381
+ * @param {string|Uint8Array|Buffer|number[]} input
382
+ * @returns {ExtendedSeed}
383
+ */
384
+ static fromUnchecked(input) {
385
+ return new ExtendedSeed(toFixedU8(input, EXTENDED_SEED_SIZE, 'ExtendedSeed'), {
386
+ skipValidation: true,
387
+ });
388
+ }
376
389
  }
377
390
 
378
391
  /**
@@ -4524,12 +4537,10 @@ function binToMnemonic(input) {
4524
4537
  for (let nibble = 0; nibble < input.length * 2; nibble += 3) {
4525
4538
  const p = nibble >> 1;
4526
4539
  const b1 = input[p];
4540
+ /* c8 ignore next -- fallback unreachable for valid (multiple of 3) input */
4527
4541
  const b2 = p + 1 < input.length ? input[p + 1] : 0;
4528
4542
  const idx = nibble % 2 === 0 ? (b1 << 4) + (b2 >> 4) : ((b1 & 0x0f) << 8) + b2;
4529
4543
 
4530
- if (idx >= WordList.length) {
4531
- throw new Error('mnemonic index out of range');
4532
- }
4533
4544
  words.push(WordList[idx]);
4534
4545
  }
4535
4546
 
@@ -4730,17 +4741,22 @@ class Wallet {
4730
4741
 
4731
4742
  /** @returns {Descriptor} */
4732
4743
  getDescriptor() {
4733
- return this.descriptor;
4744
+ return new Descriptor(this.descriptor.toBytes());
4734
4745
  }
4735
4746
 
4736
4747
  /** @returns {ExtendedSeed} */
4737
4748
  getExtendedSeed() {
4738
- return this.extendedSeed;
4749
+ const bytes = this.extendedSeed.toBytes();
4750
+ try {
4751
+ return ExtendedSeed.from(bytes);
4752
+ } catch {
4753
+ return ExtendedSeed.fromUnchecked(bytes);
4754
+ }
4739
4755
  }
4740
4756
 
4741
4757
  /** @returns {Seed} */
4742
4758
  getSeed() {
4743
- return this.seed;
4759
+ return new Seed(this.seed.toBytes());
4744
4760
  }
4745
4761
 
4746
4762
  /** @returns {string} hex(ExtendedSeed) */
@@ -4833,6 +4849,7 @@ function newWalletFromExtendedSeed(extendedSeed) {
4833
4849
  return Wallet.newWalletFromExtendedSeed(ext);
4834
4850
  // case WalletType.SPHINCSPLUS_256S:
4835
4851
  // Not yet implemented - reserved for future use
4852
+ /* c8 ignore next 2 */
4836
4853
  default:
4837
4854
  throw new Error(`Unsupported wallet type: ${desc.type()}`);
4838
4855
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theqrl/wallet.js",
3
- "version": "0.2.2",
3
+ "version": "1.0.1",
4
4
  "description": "Quantum-resistant wallet library for The QRL using ML-DSA-87 (FIPS 204)",
5
5
  "type": "module",
6
6
  "main": "dist/cjs/wallet.js",
@@ -49,6 +49,7 @@
49
49
  "@types/node": "^20.14.12",
50
50
  "c8": "^7.13.0",
51
51
  "chai": "^4.3.7",
52
+ "conventional-changelog-conventionalcommits": "^9.1.0",
52
53
  "eslint": "^8.37.0",
53
54
  "eslint-config-airbnb": "^19.0.4",
54
55
  "eslint-config-prettier": "^8.8.0",
@@ -48,15 +48,17 @@ class ExtendedSeed {
48
48
  /**
49
49
  * Layout: [3 bytes descriptor] || [48 bytes seed].
50
50
  * @param {Uint8Array} bytes Exactly 51 bytes.
51
+ * @param {{ skipValidation?: boolean }} [options]
51
52
  * @throws {Error} If size mismatch.
52
53
  */
53
- constructor(bytes) {
54
+ constructor(bytes, options = {}) {
54
55
  if (!bytes || bytes.length !== EXTENDED_SEED_SIZE) {
55
56
  throw new Error(`ExtendedSeed must be ${EXTENDED_SEED_SIZE} bytes`);
56
57
  }
58
+ const { skipValidation = false } = options;
57
59
  /** @private @type {Uint8Array} */
58
60
  this.bytes = Uint8Array.from(bytes);
59
- if (!isValidWalletType(this.bytes[0])) {
61
+ if (!skipValidation && !isValidWalletType(this.bytes[0])) {
60
62
  throw new Error('Invalid wallet type in descriptor');
61
63
  }
62
64
  }
@@ -118,6 +120,17 @@ class ExtendedSeed {
118
120
  static from(input) {
119
121
  return new ExtendedSeed(toFixedU8(input, EXTENDED_SEED_SIZE, 'ExtendedSeed'));
120
122
  }
123
+
124
+ /**
125
+ * Internal helper: construct without wallet type validation.
126
+ * @param {string|Uint8Array|Buffer|number[]} input
127
+ * @returns {ExtendedSeed}
128
+ */
129
+ static fromUnchecked(input) {
130
+ return new ExtendedSeed(toFixedU8(input, EXTENDED_SEED_SIZE, 'ExtendedSeed'), {
131
+ skipValidation: true,
132
+ });
133
+ }
121
134
  }
122
135
 
123
136
  export { Seed, ExtendedSeed };
@@ -31,6 +31,7 @@ function newWalletFromExtendedSeed(extendedSeed) {
31
31
  return MLDSA87.newWalletFromExtendedSeed(ext);
32
32
  // case WalletType.SPHINCSPLUS_256S:
33
33
  // Not yet implemented - reserved for future use
34
+ /* c8 ignore next 2 */
34
35
  default:
35
36
  throw new Error(`Unsupported wallet type: ${desc.type()}`);
36
37
  }
@@ -24,12 +24,10 @@ function binToMnemonic(input) {
24
24
  for (let nibble = 0; nibble < input.length * 2; nibble += 3) {
25
25
  const p = nibble >> 1;
26
26
  const b1 = input[p];
27
+ /* c8 ignore next -- fallback unreachable for valid (multiple of 3) input */
27
28
  const b2 = p + 1 < input.length ? input[p + 1] : 0;
28
29
  const idx = nibble % 2 === 0 ? (b1 << 4) + (b2 >> 4) : ((b1 & 0x0f) << 8) + b2;
29
30
 
30
- if (idx >= WordList.length) {
31
- throw new Error('mnemonic index out of range');
32
- }
33
31
  words.push(WordList[idx]);
34
32
  }
35
33
 
@@ -8,6 +8,7 @@ import randomBytes from 'randombytes';
8
8
  import { bytesToHex } from '@noble/hashes/utils.js';
9
9
  import { mnemonicToBin, binToMnemonic } from '../misc/mnemonic.js';
10
10
  import { getAddressFromPKAndDescriptor, addressToString } from '../common/address.js';
11
+ import { Descriptor } from '../common/descriptor.js';
11
12
  import { Seed, ExtendedSeed } from '../common/seed.js';
12
13
  import { newMLDSA87Descriptor } from './descriptor.js';
13
14
  import { keygen, sign, verify } from './crypto.js';
@@ -81,17 +82,22 @@ class Wallet {
81
82
 
82
83
  /** @returns {Descriptor} */
83
84
  getDescriptor() {
84
- return this.descriptor;
85
+ return new Descriptor(this.descriptor.toBytes());
85
86
  }
86
87
 
87
88
  /** @returns {ExtendedSeed} */
88
89
  getExtendedSeed() {
89
- return this.extendedSeed;
90
+ const bytes = this.extendedSeed.toBytes();
91
+ try {
92
+ return ExtendedSeed.from(bytes);
93
+ } catch {
94
+ return ExtendedSeed.fromUnchecked(bytes);
95
+ }
90
96
  }
91
97
 
92
98
  /** @returns {Seed} */
93
99
  getSeed() {
94
- return this.seed;
100
+ return new Seed(this.seed.toBytes());
95
101
  }
96
102
 
97
103
  /** @returns {string} hex(ExtendedSeed) */