quantumcoin 7.0.11 → 7.0.12

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.
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "..": {
20
20
  "name": "quantumcoin",
21
- "version": "7.0.11",
21
+ "version": "7.0.12",
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
24
  "quantum-coin-js-sdk": "1.0.35",
package/generate-sdk.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  /**
3
3
  * sdkgen
4
4
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quantumcoin",
3
- "version": "7.0.11",
3
+ "version": "7.0.12",
4
4
  "description": "QuantumCoin.js - a post quantum cryptography SDK for QuantumCoin",
5
5
  "main": "index.js",
6
6
  "types": "src/index.d.ts",
@@ -58,6 +58,11 @@ export class BaseWallet extends AbstractSigner {
58
58
  * Wallet - convenience methods around BaseWallet.
59
59
  */
60
60
  export class Wallet extends BaseWallet {
61
+ /**
62
+ * Returns the seed phrase (list of words) if this wallet has a seed, else null.
63
+ * Derived from the stored pre-expansion seed via seed-words.getWordListFromSeedArray.
64
+ */
65
+ getPhrase(): string[] | null;
61
66
  /**
62
67
  * Returns the recommended signing context for this wallet.
63
68
  * Setting fullSign to true may incur additional gas cost.
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  const qcsdk = require("quantum-coin-js-sdk");
12
+ const seedWords = require("seed-words");
12
13
  const { JsonRpcProvider } = require("../providers/json-rpc-provider");
13
14
  const { assertArgument, assertSecretArgument, makeError } = require("../errors");
14
15
  const { arrayify, bytesToHex, hexToBytes, isHexString, normalizeHex } = require("../internal/hex");
@@ -354,6 +355,25 @@ class Wallet extends BaseWallet {
354
355
  return json;
355
356
  }
356
357
 
358
+ /**
359
+ * Returns the seed phrase (list of words) if this wallet has a seed, else null.
360
+ * Derived from the stored pre-expansion seed via seed-words.getWordListFromSeedArray.
361
+ *
362
+ * Non-null for wallets created via createRandom, fromPhrase, fromSeed, and
363
+ * fromEncryptedJsonSync when the JSON is a version-5 keystore produced by
364
+ * encryptSync on a seed-bearing wallet or by encryptSeedSync.
365
+ * Null for fromKeys and for v3/v4 keystores without preExpansionSeed.
366
+ *
367
+ * @returns {string[]|null}
368
+ */
369
+ getPhrase() {
370
+ _requireInitialized();
371
+ if (this._seed == null) return null;
372
+ const bytes = Array.from(hexToBytes(this._seed));
373
+ const words = seedWords.getWordListFromSeedArray(bytes);
374
+ return Array.isArray(words) ? words : null;
375
+ }
376
+
357
377
  /**
358
378
  * Returns the recommended signing context for this wallet.
359
379
  * Setting fullSign to true may incur additional gas cost.
@@ -649,6 +649,147 @@ describe("Address + Wallet (offline)", () => {
649
649
  assert.equal(w48.seed, null);
650
650
  });
651
651
 
652
+ // ---------------------------------------------------------------------------
653
+ // getPhrase()
654
+ // ---------------------------------------------------------------------------
655
+
656
+ it("getPhrase returns 32 words and roundtrips through fromPhrase (same address)", async () => {
657
+ await Initialize(null);
658
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
659
+ const phrase = w.getPhrase();
660
+ assert.ok(Array.isArray(phrase));
661
+ assert.equal(phrase.length, 32);
662
+ assert.deepEqual(phrase, TEST_SEED_WORDS_32);
663
+ const w2 = qc.Wallet.fromPhrase(phrase);
664
+ assert.equal(w2.address, TEST_SEED_ADDRESS_32);
665
+ assert.equal(w2.address, w.address);
666
+ });
667
+
668
+ it("getPhrase returns 36 words and roundtrips through fromPhrase (same address)", async () => {
669
+ await Initialize(null);
670
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
671
+ const phrase = w.getPhrase();
672
+ assert.ok(Array.isArray(phrase));
673
+ assert.equal(phrase.length, 36);
674
+ assert.deepEqual(phrase, TEST_SEED_WORDS_36);
675
+ const w2 = qc.Wallet.fromPhrase(phrase);
676
+ assert.equal(w2.address, TEST_SEED_ADDRESS_36);
677
+ assert.equal(w2.address, w.address);
678
+ });
679
+
680
+ it("getPhrase returns 48 words and roundtrips through fromPhrase (same address)", async () => {
681
+ await Initialize(null);
682
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
683
+ const phrase = w.getPhrase();
684
+ assert.ok(Array.isArray(phrase));
685
+ assert.equal(phrase.length, 48);
686
+ assert.deepEqual(phrase, TEST_SEED_WORDS);
687
+ const w2 = qc.Wallet.fromPhrase(phrase);
688
+ assert.equal(w2.address, TEST_SEED_ADDRESS);
689
+ assert.equal(w2.address, w.address);
690
+ });
691
+
692
+ it("getPhrase on fromSeed(32-word seed) returns the matching 32 words", async () => {
693
+ await Initialize(null);
694
+ const seedwords = require("seed-words");
695
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
696
+ const w = qc.Wallet.fromSeed(Array.from(seedArr));
697
+ assert.deepEqual(w.getPhrase(), TEST_SEED_WORDS_32);
698
+ const w2 = qc.Wallet.fromPhrase(w.getPhrase());
699
+ assert.equal(w2.address, TEST_SEED_ADDRESS_32);
700
+ assert.equal(w2.address, w.address);
701
+ });
702
+
703
+ it("getPhrase on fromSeed(36-word seed) returns the matching 36 words", async () => {
704
+ await Initialize(null);
705
+ const seedwords = require("seed-words");
706
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_36);
707
+ const w = qc.Wallet.fromSeed(Array.from(seedArr));
708
+ assert.deepEqual(w.getPhrase(), TEST_SEED_WORDS_36);
709
+ const w2 = qc.Wallet.fromPhrase(w.getPhrase());
710
+ assert.equal(w2.address, TEST_SEED_ADDRESS_36);
711
+ assert.equal(w2.address, w.address);
712
+ });
713
+
714
+ it("getPhrase on fromSeed(48-word seed) returns the matching 48 words", async () => {
715
+ await Initialize(null);
716
+ const seedwords = require("seed-words");
717
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS);
718
+ const w = qc.Wallet.fromSeed(Array.from(seedArr));
719
+ assert.deepEqual(w.getPhrase(), TEST_SEED_WORDS);
720
+ const w2 = qc.Wallet.fromPhrase(w.getPhrase());
721
+ assert.equal(w2.address, TEST_SEED_ADDRESS);
722
+ assert.equal(w2.address, w.address);
723
+ });
724
+
725
+ it("seed and getPhrase survive encryptSync + fromEncryptedJsonSync (32-word)", async () => {
726
+ await Initialize(null);
727
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
728
+ const json = w.encryptSync(PASSPHRASE_PHRASE);
729
+ assert.equal(JSON.parse(json).version, 5);
730
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
731
+ assert.equal(restored.seed, w.seed);
732
+ assert.deepEqual(restored.getPhrase(), TEST_SEED_WORDS_32);
733
+ assert.equal(restored.address, TEST_SEED_ADDRESS_32);
734
+ });
735
+
736
+ it("seed and getPhrase survive encryptSync + fromEncryptedJsonSync (36-word)", async () => {
737
+ await Initialize(null);
738
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
739
+ const json = w.encryptSync(PASSPHRASE_PHRASE);
740
+ assert.equal(JSON.parse(json).version, 5);
741
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
742
+ assert.equal(restored.seed, w.seed);
743
+ assert.deepEqual(restored.getPhrase(), TEST_SEED_WORDS_36);
744
+ assert.equal(restored.address, TEST_SEED_ADDRESS_36);
745
+ });
746
+
747
+ it("seed and getPhrase survive encryptSync + fromEncryptedJsonSync (48-word)", async () => {
748
+ await Initialize(null);
749
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
750
+ const json = w.encryptSync(PASSPHRASE_PHRASE);
751
+ assert.equal(JSON.parse(json).version, 5);
752
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
753
+ assert.equal(restored.seed, w.seed);
754
+ assert.deepEqual(restored.getPhrase(), TEST_SEED_WORDS);
755
+ assert.equal(restored.address, TEST_SEED_ADDRESS);
756
+ });
757
+
758
+ it("getPhrase on createRandom returns 32 words that recreate the same wallet", async () => {
759
+ await Initialize(null);
760
+ const w = qc.Wallet.createRandom();
761
+ const phrase = w.getPhrase();
762
+ assert.ok(Array.isArray(phrase));
763
+ assert.equal(phrase.length, 32);
764
+ const w2 = qc.Wallet.fromPhrase(phrase);
765
+ assert.equal(w2.address, w.address);
766
+ });
767
+
768
+ it("getPhrase on createRandom(null, 5) returns 36 words that recreate the same wallet", async () => {
769
+ await Initialize(null);
770
+ const w = qc.Wallet.createRandom(null, 5);
771
+ const phrase = w.getPhrase();
772
+ assert.ok(Array.isArray(phrase));
773
+ assert.equal(phrase.length, 36);
774
+ const w2 = qc.Wallet.fromPhrase(phrase);
775
+ assert.equal(w2.address, w.address);
776
+ });
777
+
778
+ it("getPhrase returns null when seed is null (fromKeys wallet)", async () => {
779
+ await Initialize(null);
780
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
781
+ const w = qc.Wallet.fromKeys(ref.signingKey.privateKeyBytes, ref.signingKey.publicKeyBytes);
782
+ assert.equal(w.seed, null);
783
+ assert.equal(w.getPhrase(), null);
784
+ });
785
+
786
+ it("getPhrase returns null for v3 encrypted-JSON wallet (no preExpansionSeed)", async () => {
787
+ await Initialize(null);
788
+ const w = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
789
+ assert.equal(w.seed, null);
790
+ assert.equal(w.getPhrase(), null);
791
+ });
792
+
652
793
  // ---------------------------------------------------------------------------
653
794
  // seed roundtrip through encryptSync / fromEncryptedJsonSync
654
795
  // ---------------------------------------------------------------------------
@@ -635,6 +635,147 @@ describe("Address + Wallet (offline)", () => {
635
635
  assert.equal(w48.seed, null);
636
636
  });
637
637
 
638
+ // ---------------------------------------------------------------------------
639
+ // getPhrase()
640
+ // ---------------------------------------------------------------------------
641
+
642
+ it("getPhrase returns 32 words and roundtrips through fromPhrase (same address)", async () => {
643
+ await Initialize(null);
644
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
645
+ const phrase = w.getPhrase();
646
+ assert.ok(Array.isArray(phrase));
647
+ assert.equal(phrase!.length, 32);
648
+ assert.deepEqual(phrase, TEST_SEED_WORDS_32);
649
+ const w2 = qc.Wallet.fromPhrase(phrase!);
650
+ assert.equal(w2.address, TEST_SEED_ADDRESS_32);
651
+ assert.equal(w2.address, w.address);
652
+ });
653
+
654
+ it("getPhrase returns 36 words and roundtrips through fromPhrase (same address)", async () => {
655
+ await Initialize(null);
656
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
657
+ const phrase = w.getPhrase();
658
+ assert.ok(Array.isArray(phrase));
659
+ assert.equal(phrase!.length, 36);
660
+ assert.deepEqual(phrase, TEST_SEED_WORDS_36);
661
+ const w2 = qc.Wallet.fromPhrase(phrase!);
662
+ assert.equal(w2.address, TEST_SEED_ADDRESS_36);
663
+ assert.equal(w2.address, w.address);
664
+ });
665
+
666
+ it("getPhrase returns 48 words and roundtrips through fromPhrase (same address)", async () => {
667
+ await Initialize(null);
668
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
669
+ const phrase = w.getPhrase();
670
+ assert.ok(Array.isArray(phrase));
671
+ assert.equal(phrase!.length, 48);
672
+ assert.deepEqual(phrase, TEST_SEED_WORDS);
673
+ const w2 = qc.Wallet.fromPhrase(phrase!);
674
+ assert.equal(w2.address, TEST_SEED_ADDRESS);
675
+ assert.equal(w2.address, w.address);
676
+ });
677
+
678
+ it("getPhrase on fromSeed(32-word seed) returns the matching 32 words", async () => {
679
+ await Initialize(null);
680
+ const seedwords = require("seed-words");
681
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_32);
682
+ const w = qc.Wallet.fromSeed(Array.from(seedArr));
683
+ assert.deepEqual(w.getPhrase(), TEST_SEED_WORDS_32);
684
+ const w2 = qc.Wallet.fromPhrase(w.getPhrase()!);
685
+ assert.equal(w2.address, TEST_SEED_ADDRESS_32);
686
+ assert.equal(w2.address, w.address);
687
+ });
688
+
689
+ it("getPhrase on fromSeed(36-word seed) returns the matching 36 words", async () => {
690
+ await Initialize(null);
691
+ const seedwords = require("seed-words");
692
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS_36);
693
+ const w = qc.Wallet.fromSeed(Array.from(seedArr));
694
+ assert.deepEqual(w.getPhrase(), TEST_SEED_WORDS_36);
695
+ const w2 = qc.Wallet.fromPhrase(w.getPhrase()!);
696
+ assert.equal(w2.address, TEST_SEED_ADDRESS_36);
697
+ assert.equal(w2.address, w.address);
698
+ });
699
+
700
+ it("getPhrase on fromSeed(48-word seed) returns the matching 48 words", async () => {
701
+ await Initialize(null);
702
+ const seedwords = require("seed-words");
703
+ const seedArr = seedwords.getSeedArrayFromWordList(TEST_SEED_WORDS);
704
+ const w = qc.Wallet.fromSeed(Array.from(seedArr));
705
+ assert.deepEqual(w.getPhrase(), TEST_SEED_WORDS);
706
+ const w2 = qc.Wallet.fromPhrase(w.getPhrase()!);
707
+ assert.equal(w2.address, TEST_SEED_ADDRESS);
708
+ assert.equal(w2.address, w.address);
709
+ });
710
+
711
+ it("seed and getPhrase survive encryptSync + fromEncryptedJsonSync (32-word)", async () => {
712
+ await Initialize(null);
713
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
714
+ const json = w.encryptSync(PASSPHRASE_PHRASE);
715
+ assert.equal(JSON.parse(json).version, 5);
716
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
717
+ assert.equal(restored.seed, w.seed);
718
+ assert.deepEqual(restored.getPhrase(), TEST_SEED_WORDS_32);
719
+ assert.equal(restored.address, TEST_SEED_ADDRESS_32);
720
+ });
721
+
722
+ it("seed and getPhrase survive encryptSync + fromEncryptedJsonSync (36-word)", async () => {
723
+ await Initialize(null);
724
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS_36);
725
+ const json = w.encryptSync(PASSPHRASE_PHRASE);
726
+ assert.equal(JSON.parse(json).version, 5);
727
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
728
+ assert.equal(restored.seed, w.seed);
729
+ assert.deepEqual(restored.getPhrase(), TEST_SEED_WORDS_36);
730
+ assert.equal(restored.address, TEST_SEED_ADDRESS_36);
731
+ });
732
+
733
+ it("seed and getPhrase survive encryptSync + fromEncryptedJsonSync (48-word)", async () => {
734
+ await Initialize(null);
735
+ const w = qc.Wallet.fromPhrase(TEST_SEED_WORDS);
736
+ const json = w.encryptSync(PASSPHRASE_PHRASE);
737
+ assert.equal(JSON.parse(json).version, 5);
738
+ const restored = qc.Wallet.fromEncryptedJsonSync(json, PASSPHRASE_PHRASE);
739
+ assert.equal(restored.seed, w.seed);
740
+ assert.deepEqual(restored.getPhrase(), TEST_SEED_WORDS);
741
+ assert.equal(restored.address, TEST_SEED_ADDRESS);
742
+ });
743
+
744
+ it("getPhrase on createRandom returns 32 words that recreate the same wallet", async () => {
745
+ await Initialize(null);
746
+ const w = qc.Wallet.createRandom();
747
+ const phrase = w.getPhrase();
748
+ assert.ok(Array.isArray(phrase));
749
+ assert.equal(phrase!.length, 32);
750
+ const w2 = qc.Wallet.fromPhrase(phrase!);
751
+ assert.equal(w2.address, w.address);
752
+ });
753
+
754
+ it("getPhrase on createRandom(null, 5) returns 36 words that recreate the same wallet", async () => {
755
+ await Initialize(null);
756
+ const w = qc.Wallet.createRandom(undefined, 5);
757
+ const phrase = w.getPhrase();
758
+ assert.ok(Array.isArray(phrase));
759
+ assert.equal(phrase!.length, 36);
760
+ const w2 = qc.Wallet.fromPhrase(phrase!);
761
+ assert.equal(w2.address, w.address);
762
+ });
763
+
764
+ it("getPhrase returns null when seed is null (fromKeys wallet)", async () => {
765
+ await Initialize(null);
766
+ const ref = qc.Wallet.fromPhrase(TEST_SEED_WORDS_32);
767
+ const w = qc.Wallet.fromKeys(ref.signingKey.privateKeyBytes, ref.signingKey.publicKeyBytes);
768
+ assert.equal(w.seed, null);
769
+ assert.equal(w.getPhrase(), null);
770
+ });
771
+
772
+ it("getPhrase returns null for v3 encrypted-JSON wallet (no preExpansionSeed)", async () => {
773
+ await Initialize(null);
774
+ const w = qc.Wallet.fromEncryptedJsonSync(TEST_WALLET_ENCRYPTED_JSON, TEST_WALLET_PASSPHRASE);
775
+ assert.equal(w.seed, null);
776
+ assert.equal(w.getPhrase(), null);
777
+ });
778
+
638
779
  // ---------------------------------------------------------------------------
639
780
  // seed roundtrip through encryptSync / fromEncryptedJsonSync
640
781
  // ---------------------------------------------------------------------------