aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/index.html83
-rw-r--r--src/js/index.js56
-rw-r--r--tests/spec/tests.js148
3 files changed, 285 insertions, 2 deletions
diff --git a/src/index.html b/src/index.html
index 8d8f756..0d1a2c6 100644
--- a/src/index.html
+++ b/src/index.html
@@ -204,6 +204,9 @@
204 <li id="bip49-tab"> 204 <li id="bip49-tab">
205 <a href="#bip49" role="tab" data-toggle="tab">BIP49</a> 205 <a href="#bip49" role="tab" data-toggle="tab">BIP49</a>
206 </li> 206 </li>
207 <li id="bip84-tab">
208 <a href="#bip84" role="tab" data-toggle="tab">BIP84</a>
209 </li>
207 <li id="bip141-tab"> 210 <li id="bip141-tab">
208 <a href="#bip141" role="tab" data-toggle="tab">BIP141</a> 211 <a href="#bip141" role="tab" data-toggle="tab">BIP141</a>
209 </li> 212 </li>
@@ -487,6 +490,86 @@
487 </div> 490 </div>
488 </form> 491 </form>
489 </div> 492 </div>
493 <div id="bip84" class="tab-pane">
494 <form class="form-horizontal" role="form">
495 <br>
496 <div class="col-sm-2"></div>
497 <div class="col-sm-10">
498 <p>
499 For more info see the
500 <a href="https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki" target="_blank">BIP84 spec</a>.
501 </p>
502 </div>
503 <div class="form-group">
504 <label for="purpose" class="col-sm-2 control-label">
505 Purpose
506 </label>
507 <div class="col-sm-10">
508 <input id="purpose" type="text" class="purpose form-control" value="84" readonly>
509 </div>
510 </div>
511 <div class="form-group">
512 <label for="coin" class="col-sm-2 control-label">
513 Coin
514 </label>
515 <div class="col-sm-10">
516 <input id="coin" type="text" class="coin form-control" value="0" readonly>
517 </div>
518 </div>
519 <div class="form-group">
520 <label for="account" class="col-sm-2 control-label">
521 Account
522 </label>
523 <div class="col-sm-10">
524 <input id="account" type="text" class="account form-control" value="0">
525 </div>
526 </div>
527 <div class="form-group">
528 <label for="change" class="col-sm-2 control-label">
529 External / Internal
530 </label>
531 <div class="col-sm-10">
532 <input id="change" type="text" class="change form-control" value="0">
533 </div>
534 </div>
535 <div class="form-group">
536 <label class="col-sm-2 control-label">
537 </label>
538 <div class="col-sm-10">
539 <p>The account extended keys can be used for importing to most BIP84 compatible wallets.</p>
540 </div>
541 </div>
542 <div class="form-group">
543 <label for="account-xprv" class="col-sm-2 control-label">
544 <span>Account Extended Private Key</span>
545 </label>
546 <div class="col-sm-10">
547 <textarea id="account-xprv" type="text" class="account-xprv form-control" readonly data-show-qr></textarea>
548 </div>
549 </div>
550 <div class="form-group">
551 <label for="account-xpub" class="col-sm-2 control-label">
552 <span>Account Extended Public Key</span>
553 </label>
554 <div class="col-sm-10">
555 <textarea id="account-xpub" type="text" class="account-xpub form-control" readonly data-show-qr></textarea>
556 </div>
557 </div>
558 <div class="form-group">
559 <label class="col-sm-2 control-label">
560 </label>
561 <div class="col-sm-10">
562 <p>The BIP32 derivation path and extended keys are the basis for the derived addresses.</p>
563 </div>
564 </div>
565 <div class="form-group">
566 <label for="bip84-path" class="col-sm-2 control-label">BIP32 Derivation Path</label>
567 <div class="col-sm-10">
568 <input id="bip84-path" type="text" class="path form-control" value="m/84'/0'/0'/0" readonly="readonly">
569 </div>
570 </div>
571 </form>
572 </div>
490 </div> 573 </div>
491 <form class="form-horizontal" role="form"> 574 <form class="form-horizontal" role="form">
492 <div class="form-group"> 575 <div class="form-group">
diff --git a/src/js/index.js b/src/js/index.js
index 9c9ad58..e63c65f 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -53,6 +53,7 @@
53 DOM.bip32tab = $("#bip32-tab"); 53 DOM.bip32tab = $("#bip32-tab");
54 DOM.bip44tab = $("#bip44-tab"); 54 DOM.bip44tab = $("#bip44-tab");
55 DOM.bip49tab = $("#bip49-tab"); 55 DOM.bip49tab = $("#bip49-tab");
56 DOM.bip84tab = $("#bip84-tab");
56 DOM.bip141tab = $("#bip141-tab"); 57 DOM.bip141tab = $("#bip141-tab");
57 DOM.bip32panel = $("#bip32"); 58 DOM.bip32panel = $("#bip32");
58 DOM.bip44panel = $("#bip44"); 59 DOM.bip44panel = $("#bip44");
@@ -74,6 +75,13 @@
74 DOM.bip49accountXprv = $("#bip49 .account-xprv"); 75 DOM.bip49accountXprv = $("#bip49 .account-xprv");
75 DOM.bip49accountXpub = $("#bip49 .account-xpub"); 76 DOM.bip49accountXpub = $("#bip49 .account-xpub");
76 DOM.bip49change = $("#bip49 .change"); 77 DOM.bip49change = $("#bip49 .change");
78 DOM.bip84path = $("#bip84-path");
79 DOM.bip84purpose = $("#bip84 .purpose");
80 DOM.bip84coin = $("#bip84 .coin");
81 DOM.bip84account = $("#bip84 .account");
82 DOM.bip84accountXprv = $("#bip84 .account-xprv");
83 DOM.bip84accountXpub = $("#bip84 .account-xpub");
84 DOM.bip84change = $("#bip84 .change");
77 DOM.bip141unavailable = $("#bip141 .unavailable"); 85 DOM.bip141unavailable = $("#bip141 .unavailable");
78 DOM.bip141available = $("#bip141 .available"); 86 DOM.bip141available = $("#bip141 .available");
79 DOM.bip141path = $("#bip141-path"); 87 DOM.bip141path = $("#bip141-path");
@@ -117,6 +125,8 @@
117 DOM.bip44change.on("input", calcForDerivationPath); 125 DOM.bip44change.on("input", calcForDerivationPath);
118 DOM.bip49account.on("input", calcForDerivationPath); 126 DOM.bip49account.on("input", calcForDerivationPath);
119 DOM.bip49change.on("input", calcForDerivationPath); 127 DOM.bip49change.on("input", calcForDerivationPath);
128 DOM.bip84account.on("input", calcForDerivationPath);
129 DOM.bip84change.on("input", calcForDerivationPath);
120 DOM.bip141path.on("input", calcForDerivationPath); 130 DOM.bip141path.on("input", calcForDerivationPath);
121 DOM.bip141semantics.on("change", tabChanged); 131 DOM.bip141semantics.on("change", tabChanged);
122 DOM.tab.on("shown.bs.tab", tabChanged); 132 DOM.tab.on("shown.bs.tab", tabChanged);
@@ -357,6 +367,9 @@
357 else if (bip49TabSelected()) { 367 else if (bip49TabSelected()) {
358 displayBip49Info(); 368 displayBip49Info();
359 } 369 }
370 else if (bip84TabSelected()) {
371 displayBip84Info();
372 }
360 displayBip32Info(); 373 displayBip32Info();
361 } 374 }
362 375
@@ -559,6 +572,21 @@
559 console.log("Using derivation path from BIP49 tab: " + derivationPath); 572 console.log("Using derivation path from BIP49 tab: " + derivationPath);
560 return derivationPath; 573 return derivationPath;
561 } 574 }
575 else if (bip84TabSelected()) {
576 var purpose = parseIntNoNaN(DOM.bip84purpose.val(), 84);
577 var coin = parseIntNoNaN(DOM.bip84coin.val(), 0);
578 var account = parseIntNoNaN(DOM.bip84account.val(), 0);
579 var change = parseIntNoNaN(DOM.bip84change.val(), 0);
580 var path = "m/";
581 path += purpose + "'/";
582 path += coin + "'/";
583 path += account + "'/";
584 path += change;
585 DOM.bip84path.val(path);
586 var derivationPath = DOM.bip84path.val();
587 console.log("Using derivation path from BIP84 tab: " + derivationPath);
588 return derivationPath;
589 }
562 else if (bip32TabSelected()) { 590 else if (bip32TabSelected()) {
563 var derivationPath = DOM.bip32path.val(); 591 var derivationPath = DOM.bip32path.val();
564 console.log("Using derivation path from BIP32 tab: " + derivationPath); 592 console.log("Using derivation path from BIP32 tab: " + derivationPath);
@@ -659,6 +687,24 @@
659 DOM.bip49accountXpub.val(accountXpub); 687 DOM.bip49accountXpub.val(accountXpub);
660 } 688 }
661 689
690 function displayBip84Info() {
691 // Get the derivation path for the account
692 var purpose = parseIntNoNaN(DOM.bip84purpose.val(), 84);
693 var coin = parseIntNoNaN(DOM.bip84coin.val(), 0);
694 var account = parseIntNoNaN(DOM.bip84account.val(), 0);
695 var path = "m/";
696 path += purpose + "'/";
697 path += coin + "'/";
698 path += account + "'/";
699 // Calculate the account extended keys
700 var accountExtendedKey = calcBip32ExtendedKey(path);
701 var accountXprv = accountExtendedKey.toBase58();
702 var accountXpub = accountExtendedKey.neutered().toBase58();
703 // Display the extended keys
704 DOM.bip84accountXprv.val(accountXprv);
705 DOM.bip84accountXpub.val(accountXpub);
706 }
707
662 function displayBip32Info() { 708 function displayBip32Info() {
663 // Display the key 709 // Display the key
664 DOM.seed.val(seed); 710 DOM.seed.val(seed);
@@ -699,11 +745,12 @@
699 } 745 }
700 746
701 function segwitSelected() { 747 function segwitSelected() {
702 return bip49TabSelected() || bip141TabSelected(); 748 return bip49TabSelected() || bip84TabSelected() || bip141TabSelected();
703 } 749 }
704 750
705 function p2wpkhSelected() { 751 function p2wpkhSelected() {
706 return bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh"; 752 return bip84TabSelected() ||
753 bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh";
707 } 754 }
708 755
709 function p2wpkhInP2shSelected() { 756 function p2wpkhInP2shSelected() {
@@ -1284,6 +1331,10 @@
1284 return DOM.bip49tab.hasClass("active"); 1331 return DOM.bip49tab.hasClass("active");
1285 } 1332 }
1286 1333
1334 function bip84TabSelected() {
1335 return DOM.bip84tab.hasClass("active");
1336 }
1337
1287 function bip141TabSelected() { 1338 function bip141TabSelected() {
1288 return DOM.bip141tab.hasClass("active"); 1339 return DOM.bip141tab.hasClass("active");
1289 } 1340 }
@@ -1291,6 +1342,7 @@
1291 function setHdCoin(coinValue) { 1342 function setHdCoin(coinValue) {
1292 DOM.bip44coin.val(coinValue); 1343 DOM.bip44coin.val(coinValue);
1293 DOM.bip49coin.val(coinValue); 1344 DOM.bip49coin.val(coinValue);
1345 DOM.bip84coin.val(coinValue);
1294 } 1346 }
1295 1347
1296 function showSegwitAvailable() { 1348 function showSegwitAvailable() {
diff --git a/tests/spec/tests.js b/tests/spec/tests.js
index 7691fcc..07b7b1a 100644
--- a/tests/spec/tests.js
+++ b/tests/spec/tests.js
@@ -2684,4 +2684,152 @@ it('Shows the index of each word in the mnemonic', function(done) {
2684 }); 2684 });
2685}); 2685});
2686 2686
2687it('Shows the derivation path for bip84 tab', function(done) {
2688 driver.findElement(By.css('#bip84-tab a'))
2689 .click()
2690 driver.findElement(By.css('.phrase'))
2691 .sendKeys('abandon abandon ability');
2692 driver.sleep(generateDelay).then(function() {
2693 driver.findElement(By.css('#bip84 .path'))
2694 .getAttribute("value")
2695 .then(function(path) {
2696 expect(path).toBe("m/84'/0'/0'/0");
2697 done();
2698 })
2699 });
2700});
2701
2702it('Shows the extended private key for bip84 tab', function(done) {
2703 driver.findElement(By.css('#bip84-tab a'))
2704 .click()
2705 driver.findElement(By.css('.phrase'))
2706 .sendKeys('abandon abandon ability');
2707 driver.sleep(generateDelay).then(function() {
2708 driver.findElement(By.css('.extended-priv-key'))
2709 .getAttribute("value")
2710 .then(function(path) {
2711 expect(path).toBe("zprvAev3RKrZ3QVKiUFCfdeMRen1BPDJgdNt1XpxiDy8acSs4kkAGTCvq7HeRYRNNpo8EtEjCFQBWavJwtCUR29y4TUCH4X5RXMcyq48uN8y9BP");
2712 done();
2713 })
2714 });
2715});
2716
2717it('Shows the extended public key for bip84 tab', function(done) {
2718 driver.findElement(By.css('#bip84-tab a'))
2719 .click()
2720 driver.findElement(By.css('.phrase'))
2721 .sendKeys('abandon abandon ability');
2722 driver.sleep(generateDelay).then(function() {
2723 driver.findElement(By.css('.extended-pub-key'))
2724 .getAttribute("value")
2725 .then(function(path) {
2726 expect(path).toBe("zpub6suPpqPSsn3cvxKfmfBMnnijjR3o666jNkkZWcNk8wyqwZ5JozXBNuc8Gs7DB3uLwTDvGVTspVEAUQcEjKF3pZHgywVbubdTqbXTUg7usyx");
2727 done();
2728 })
2729 });
2730});
2731
2732it('Changes the address list if bip84 account is changed', function(done) {
2733 driver.findElement(By.css('#bip84-tab a'))
2734 .click()
2735 driver.findElement(By.css('#bip84 .account'))
2736 .sendKeys('1');
2737 driver.findElement(By.css('.phrase'))
2738 .sendKeys('abandon abandon ability');
2739 driver.sleep(generateDelay).then(function() {
2740 getFirstAddress(function(address) {
2741 expect(address).toBe("bc1qp7vv669t2fy965jdzvqwrraana89ctd5ewc662");
2742 done();
2743 });
2744 });
2745});
2746
2747it('Changes the address list if bip84 change is changed', function(done) {
2748 driver.findElement(By.css('#bip84-tab a'))
2749 .click()
2750 driver.findElement(By.css('#bip84 .change'))
2751 .sendKeys('1');
2752 driver.findElement(By.css('.phrase'))
2753 .sendKeys('abandon abandon ability');
2754 driver.sleep(generateDelay).then(function() {
2755 getFirstAddress(function(address) {
2756 expect(address).toBe("bc1qr39vj6rh06ff05m53uxq8uazehwhccswylhrs2");
2757 done();
2758 });
2759 });
2760});
2761
2762it('Passes the official BIP84 test spec for rootpriv', function(done) {
2763 driver.findElement(By.css('#bip84-tab a'))
2764 .click()
2765 driver.findElement(By.css('.phrase'))
2766 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
2767 driver.sleep(generateDelay).then(function() {
2768 driver.findElement(By.css(".root-key"))
2769 .getAttribute("value")
2770 .then(function(rootKey) {
2771 expect(rootKey).toBe("zprvAWgYBBk7JR8Gjrh4UJQ2uJdG1r3WNRRfURiABBE3RvMXYSrRJL62XuezvGdPvG6GFBZduosCc1YP5wixPox7zhZLfiUm8aunE96BBa4Kei5");
2772 done();
2773 })
2774 });
2775});
2776
2777it('Passes the official BIP84 test spec for account 0 xprv', function(done) {
2778 driver.findElement(By.css('#bip84-tab a'))
2779 .click()
2780 driver.findElement(By.css('.phrase'))
2781 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
2782 driver.sleep(generateDelay).then(function() {
2783 driver.findElement(By.css("#bip84 .account-xprv"))
2784 .getAttribute("value")
2785 .then(function(rootKey) {
2786 expect(rootKey).toBe("zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE");
2787 done();
2788 })
2789 });
2790});
2791
2792it('Passes the official BIP84 test spec for account 0 xpub', function(done) {
2793 driver.findElement(By.css('#bip84-tab a'))
2794 .click()
2795 driver.findElement(By.css('.phrase'))
2796 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
2797 driver.sleep(generateDelay).then(function() {
2798 driver.findElement(By.css("#bip84 .account-xpub"))
2799 .getAttribute("value")
2800 .then(function(rootKey) {
2801 expect(rootKey).toBe("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs");
2802 done();
2803 })
2804 });
2805});
2806
2807it('Passes the official BIP84 test spec for account 0 first address', function(done) {
2808 driver.findElement(By.css('#bip84-tab a'))
2809 .click()
2810 driver.findElement(By.css('.phrase'))
2811 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
2812 driver.sleep(generateDelay).then(function() {
2813 getFirstAddress(function(address) {
2814 expect(address).toBe("bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu");
2815 done();
2816 });
2817 });
2818});
2819
2820it('Passes the official BIP84 test spec for account 0 first change address', function(done) {
2821 driver.findElement(By.css('#bip84-tab a'))
2822 .click()
2823 driver.findElement(By.css('.phrase'))
2824 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
2825 driver.findElement(By.css('#bip84 .change'))
2826 .sendKeys('1');
2827 driver.sleep(generateDelay).then(function() {
2828 getFirstAddress(function(address) {
2829 expect(address).toBe("bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el");
2830 done();
2831 });
2832 });
2833});
2834
2687}); 2835});