quantumcoin 7.0.9 → 7.0.10

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.
package/README-SDK.md CHANGED
@@ -392,6 +392,7 @@ User-facing wallet class.
392
392
  - `Wallet.fromEncryptedJsonSync(json: string, password: string, provider?: AbstractProvider): Wallet`
393
393
  - `Wallet.fromPhrase(phrase: string | string[], provider?: AbstractProvider): Wallet`
394
394
  - `Wallet.fromKeys(privateKey: Uint8Array | string, publicKey: Uint8Array | string, provider?: AbstractProvider): Wallet`
395
+ - `Wallet.encryptSeedSync(seed: number[] | Uint8Array, password: string | Uint8Array): string` — encrypts raw seed bytes (64/72/96) into a wallet JSON string (version 5 pre-expansion format). The resulting JSON can be opened with `fromEncryptedJsonSync()` or Desktop/Mobile/Web/CLI wallet applications. Password must be at least 12 characters.
395
396
 
396
397
  **Instance methods**
397
398
  - `getAddress(): string`
package/README.md CHANGED
@@ -58,6 +58,23 @@ const restored = Wallet.fromEncryptedJsonSync(encrypted, "mySecurePassword123");
58
58
  console.log(restored.address);
59
59
  ```
60
60
 
61
+ ### Encrypt a raw seed
62
+
63
+ You can encrypt raw seed bytes (pre-expansion) into a portable wallet JSON (version 5 format) without first opening the wallet:
64
+
65
+ ```js
66
+ const { Wallet } = require("quantumcoin");
67
+ const { Initialize } = require("quantumcoin/config");
68
+
69
+ await Initialize(null);
70
+
71
+ // 64-byte seed (keyType 3), 72-byte (keyType 5), or 96-byte (legacy)
72
+ const seed = [51,214,149,165, /* ...remaining bytes... */];
73
+ const json = Wallet.encryptSeedSync(seed, "mySecurePassword123");
74
+ const restored = Wallet.fromEncryptedJsonSync(json, "mySecurePassword123");
75
+ console.log(restored.address);
76
+ ```
77
+
61
78
  ## Contracts (read-only)
62
79
 
63
80
  ```js
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "quantumcoinjs-sdk-examples",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "quantumcoinjs-sdk-examples",
9
- "version": "1.0.0",
9
+ "version": "1.0.1",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "quantum-coin-js-sdk": "1.0.32",
12
+ "quantum-coin-js-sdk": "1.0.33",
13
13
  "quantumcoin": "file:.."
14
14
  },
15
15
  "devDependencies": {
@@ -18,10 +18,10 @@
18
18
  },
19
19
  "..": {
20
20
  "name": "quantumcoin",
21
- "version": "7.0.9",
21
+ "version": "7.0.10",
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
- "quantum-coin-js-sdk": "1.0.32",
24
+ "quantum-coin-js-sdk": "1.0.33",
25
25
  "seed-words": "^1.0.2"
26
26
  },
27
27
  "bin": {
@@ -201,7 +201,9 @@
201
201
  }
202
202
  },
203
203
  "node_modules/quantum-coin-js-sdk": {
204
- "version": "1.0.32",
204
+ "version": "1.0.33",
205
+ "resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.33.tgz",
206
+ "integrity": "sha512-n4Q/PBj6yQ2mj3MpvNdLlBSoSxM9+q+yTDz/l/zuWxeob/unj1ZQgzir1Qh4U/Vu7eAbZmAhRORFP9ttfw3ToA==",
205
207
  "license": "MIT",
206
208
  "dependencies": {
207
209
  "seed-words": "1.0.2"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quantumcoinjs-sdk-examples",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "QuantumCoin.js SDK Examples",
5
5
  "main": "example.js",
6
6
  "scripts": {
@@ -26,7 +26,7 @@
26
26
  "tsx": "^4.19.0"
27
27
  },
28
28
  "dependencies": {
29
- "quantum-coin-js-sdk": "1.0.32",
29
+ "quantum-coin-js-sdk": "1.0.33",
30
30
  "quantumcoin": "file:.."
31
31
  }
32
32
  }
@@ -26,6 +26,15 @@ async function walletOffline() {
26
26
  const json = wallet.encryptSync("mySecurePassword123");
27
27
  console.log("Encrypted wallet JSON length:", json.length);
28
28
  logExample("wallet-offline.js", "encryptSync", { jsonLength: json.length });
29
+
30
+ // Encrypt a raw seed (pre-expansion format) and restore it
31
+ const seed = [51,214,149,165,206,96,227,5,173,247,83,219,210,2,221,2,4,48,117,55,88,109,241,204,31,62,23,128,47,21,168,247,28,118,30,185,229,255,17,27,34,107,225,138,254,156,55,9,253,255,142,148,234,189,232,43,173,84,159,108,8,35,58,77];
32
+ const seedJson = Wallet.encryptSeedSync(seed, "mySecurePassword123");
33
+ console.log("Seed-encrypted wallet JSON length:", seedJson.length);
34
+ const restored = Wallet.fromEncryptedJsonSync(seedJson, "mySecurePassword123");
35
+ console.log("Restored from seed address:", restored.address);
36
+ logExample("wallet-offline.js", "encryptSeedSync", { jsonLength: seedJson.length });
37
+ logAddress("restored", restored.address);
29
38
  }
30
39
 
31
40
  walletOffline().catch((e) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quantumcoin",
3
- "version": "7.0.9",
3
+ "version": "7.0.10",
4
4
  "description": "QuantumCoin.js - a post quantum cryptography SDK for QuantumCoin",
5
5
  "main": "index.js",
6
6
  "types": "src/index.d.ts",
@@ -90,6 +90,6 @@
90
90
  },
91
91
  "dependencies": {
92
92
  "seed-words": "^1.0.2",
93
- "quantum-coin-js-sdk": "1.0.32"
93
+ "quantum-coin-js-sdk": "1.0.33"
94
94
  }
95
95
  }
@@ -148,6 +148,15 @@ export class Wallet extends BaseWallet {
148
148
  * @returns {string}
149
149
  */
150
150
  encryptSync(password: string | Uint8Array): string;
151
+ /**
152
+ * Encrypts raw seed bytes into a wallet JSON string (version 5 pre-expansion format).
153
+ * The resulting JSON can be opened with `Wallet.fromEncryptedJsonSync()` or
154
+ * Desktop/Mobile/Web/CLI wallet applications.
155
+ * @param {number[]|Uint8Array} seed Raw seed bytes: 64 (keyType 3), 72 (keyType 5), or 96 (legacy)
156
+ * @param {string|Uint8Array} password Passphrase (at least 12 characters)
157
+ * @returns {string}
158
+ */
159
+ static encryptSeedSync(seed: number[] | Uint8Array, password: string | Uint8Array): string;
151
160
  /**
152
161
  * Returns a new wallet connected to a provider.
153
162
  * @param {import("../providers/provider").AbstractProvider} provider
@@ -311,6 +311,26 @@ class Wallet extends BaseWallet {
311
311
  return json;
312
312
  }
313
313
 
314
+ /**
315
+ * Encrypts raw seed bytes into a wallet JSON string (version 5 pre-expansion format).
316
+ * The resulting JSON can be opened with `Wallet.fromEncryptedJsonSync()` or
317
+ * Desktop/Mobile/Web/CLI wallet applications.
318
+ * @param {number[]|Uint8Array} seed Raw seed bytes: 64 (keyType 3), 72 (keyType 5), or 96 (legacy)
319
+ * @param {string|Uint8Array} password Passphrase (at least 12 characters)
320
+ * @returns {string}
321
+ */
322
+ static encryptSeedSync(seed, password) {
323
+ _requireInitialized();
324
+ const seedArr = seed instanceof Uint8Array ? Array.from(seed) : seed;
325
+ assertArgument(Array.isArray(seedArr), "seed must be an array of numbers or Uint8Array", "seed", seed);
326
+ const allowedLengths = [64, 72, 96];
327
+ assertArgument(allowedLengths.includes(seedArr.length), "seed must be 64, 72, or 96 bytes", "seed", seedArr.length);
328
+ const pw = typeof password === "string" ? password : Buffer.from(arrayify(password)).toString("utf8");
329
+ const json = qcsdk.serializeSeedAsEncryptedWallet(seedArr, pw);
330
+ if (typeof json !== "string") throw makeError("serializeSeedAsEncryptedWallet failed", "UNKNOWN_ERROR", {});
331
+ return json;
332
+ }
333
+
314
334
  /**
315
335
  * Returns the recommended signing context for this wallet.
316
336
  * Setting fullSign to true may incur additional gas cost.
@@ -561,6 +561,96 @@ describe("Address + Wallet (offline)", () => {
561
561
  assert.equal(qc.isAddress(w.address), true);
562
562
  });
563
563
 
564
+ // ---------------------------------------------------------------------------
565
+ // encryptSeedSync
566
+ // ---------------------------------------------------------------------------
567
+
568
+ it("encryptSeedSync: 32-word seed (64 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
569
+ await Initialize(null);
570
+ const seedwords = require("seed-words");
571
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
572
+ assert.equal(seedArr.length, 64);
573
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
574
+
575
+ const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
576
+ assert.equal(typeof json, "string");
577
+ assert.ok(json.includes("address"));
578
+
579
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
580
+ assert.equal(restored.address, ref.address);
581
+ assert.equal(restored.address, TEST_SEED_ADDRESS_32);
582
+ assert.equal(restored.privateKey, ref.privateKey);
583
+ assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
584
+ });
585
+
586
+ it("encryptSeedSync: 36-word seed (72 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
587
+ await Initialize(null);
588
+ const seedwords = require("seed-words");
589
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_36);
590
+ assert.equal(seedArr.length, 72);
591
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
592
+
593
+ const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
594
+ assert.equal(typeof json, "string");
595
+ assert.ok(json.includes("address"));
596
+
597
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
598
+ assert.equal(restored.address, ref.address);
599
+ assert.equal(restored.address, TEST_SEED_ADDRESS_36);
600
+ assert.equal(restored.privateKey, ref.privateKey);
601
+ assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
602
+ });
603
+
604
+ it("encryptSeedSync: 48-word seed (96 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
605
+ await Initialize(null);
606
+ const seedwords = require("seed-words");
607
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS);
608
+ assert.equal(seedArr.length, 96);
609
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
610
+
611
+ const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
612
+ assert.equal(typeof json, "string");
613
+ assert.ok(json.includes("address"));
614
+
615
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
616
+ assert.equal(restored.address, ref.address);
617
+ assert.equal(restored.address, TEST_SEED_ADDRESS);
618
+ assert.equal(restored.privateKey, ref.privateKey);
619
+ assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
620
+ });
621
+
622
+ it("encryptSeedSync accepts Uint8Array seed", async () => {
623
+ await Initialize(null);
624
+ const seedwords = require("seed-words");
625
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
626
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
627
+
628
+ const json = qc.Wallet.encryptSeedSync(new Uint8Array(seedArr), PASSPHRASE_PHRASE);
629
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
630
+ assert.equal(restored.address, ref.address);
631
+ });
632
+
633
+ it("encryptSeedSync rejects non-array seed input", async () => {
634
+ await Initialize(null);
635
+ assert.throws(() => qc.Wallet.encryptSeedSync("not an array", PASSPHRASE_PHRASE), /seed must be an array/);
636
+ assert.throws(() => qc.Wallet.encryptSeedSync(12345, PASSPHRASE_PHRASE), /seed must be an array/);
637
+ assert.throws(() => qc.Wallet.encryptSeedSync(null, PASSPHRASE_PHRASE), /seed must be an array/);
638
+ });
639
+
640
+ it("encryptSeedSync rejects wrong-length seed arrays", async () => {
641
+ await Initialize(null);
642
+ assert.throws(() => qc.Wallet.encryptSeedSync(new Array(32).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
643
+ assert.throws(() => qc.Wallet.encryptSeedSync(new Array(48).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
644
+ assert.throws(() => qc.Wallet.encryptSeedSync(new Array(100).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
645
+ assert.throws(() => qc.Wallet.encryptSeedSync([], PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
646
+ });
647
+
648
+ it("encryptSeedSync rejects password shorter than 12 characters", async () => {
649
+ await Initialize(null);
650
+ const seed = new Array(64).fill(1);
651
+ assert.throws(() => qc.Wallet.encryptSeedSync(seed, "short"), /serializeSeedAsEncryptedWallet failed/);
652
+ });
653
+
564
654
  // ---------------------------------------------------------------------------
565
655
  // getSigningContext
566
656
  // ---------------------------------------------------------------------------
@@ -547,6 +547,96 @@ describe("Address + Wallet (offline)", () => {
547
547
  assert.equal(qc.isAddress(w.address), true);
548
548
  });
549
549
 
550
+ // ---------------------------------------------------------------------------
551
+ // encryptSeedSync
552
+ // ---------------------------------------------------------------------------
553
+
554
+ it("encryptSeedSync: 32-word seed (64 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
555
+ await Initialize(null);
556
+ const seedwords = require("seed-words");
557
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
558
+ assert.equal(seedArr.length, 64);
559
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
560
+
561
+ const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
562
+ assert.equal(typeof json, "string");
563
+ assert.ok(json.includes("address"));
564
+
565
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
566
+ assert.equal(restored.address, ref.address);
567
+ assert.equal(restored.address, TEST_SEED_ADDRESS_32);
568
+ assert.equal(restored.privateKey, ref.privateKey);
569
+ assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
570
+ });
571
+
572
+ it("encryptSeedSync: 36-word seed (72 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
573
+ await Initialize(null);
574
+ const seedwords = require("seed-words");
575
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_36);
576
+ assert.equal(seedArr.length, 72);
577
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
578
+
579
+ const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
580
+ assert.equal(typeof json, "string");
581
+ assert.ok(json.includes("address"));
582
+
583
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
584
+ assert.equal(restored.address, ref.address);
585
+ assert.equal(restored.address, TEST_SEED_ADDRESS_36);
586
+ assert.equal(restored.privateKey, ref.privateKey);
587
+ assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
588
+ });
589
+
590
+ it("encryptSeedSync: 48-word seed (96 bytes) roundtrip preserves address, privateKey, publicKey", async () => {
591
+ await Initialize(null);
592
+ const seedwords = require("seed-words");
593
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS);
594
+ assert.equal(seedArr.length, 96);
595
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
596
+
597
+ const json = qc.Wallet.encryptSeedSync(Array.from(seedArr), PASSPHRASE_PHRASE);
598
+ assert.equal(typeof json, "string");
599
+ assert.ok(json.includes("address"));
600
+
601
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
602
+ assert.equal(restored.address, ref.address);
603
+ assert.equal(restored.address, TEST_SEED_ADDRESS);
604
+ assert.equal(restored.privateKey, ref.privateKey);
605
+ assert.deepEqual(restored.signingKey.publicKeyBytes, ref.signingKey.publicKeyBytes);
606
+ });
607
+
608
+ it("encryptSeedSync accepts Uint8Array seed", async () => {
609
+ await Initialize(null);
610
+ const seedwords = require("seed-words");
611
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
612
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
613
+
614
+ const json = qc.Wallet.encryptSeedSync(new Uint8Array(seedArr), PASSPHRASE_PHRASE);
615
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
616
+ assert.equal(restored.address, ref.address);
617
+ });
618
+
619
+ it("encryptSeedSync rejects non-array seed input", async () => {
620
+ await Initialize(null);
621
+ assert.throws(() => qc.Wallet.encryptSeedSync("not an array" as any, PASSPHRASE_PHRASE), /seed must be an array/);
622
+ assert.throws(() => qc.Wallet.encryptSeedSync(12345 as any, PASSPHRASE_PHRASE), /seed must be an array/);
623
+ assert.throws(() => qc.Wallet.encryptSeedSync(null as any, PASSPHRASE_PHRASE), /seed must be an array/);
624
+ });
625
+
626
+ it("encryptSeedSync rejects wrong-length seed arrays", async () => {
627
+ await Initialize(null);
628
+ assert.throws(() => qc.Wallet.encryptSeedSync(new Array(32).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
629
+ assert.throws(() => qc.Wallet.encryptSeedSync(new Array(48).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
630
+ assert.throws(() => qc.Wallet.encryptSeedSync(new Array(100).fill(0), PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
631
+ assert.throws(() => qc.Wallet.encryptSeedSync([], PASSPHRASE_PHRASE), /seed must be 64, 72, or 96 bytes/);
632
+ });
633
+
634
+ it("encryptSeedSync rejects password shorter than 12 characters", async () => {
635
+ await Initialize(null);
636
+ const seed = new Array(64).fill(1);
637
+ assert.throws(() => qc.Wallet.encryptSeedSync(seed, "short"), /serializeSeedAsEncryptedWallet failed/);
638
+ });
639
+
550
640
  // ---------------------------------------------------------------------------
551
641
  // getSigningContext
552
642
  // ---------------------------------------------------------------------------