diff options
author | Ian Coleman <coleman.ian@gmail.com> | 2016-08-23 10:31:39 +1000 |
---|---|---|
committer | Ian Coleman <coleman.ian@gmail.com> | 2016-08-23 10:31:39 +1000 |
commit | efe41586705d3eba480da31bb1002c4e54e73ef0 (patch) | |
tree | f071e764935ce06c165fdc014ed29172271c3cef /src/js | |
parent | 563e401a4f3880da88bfc69cf51be5a1becd4c66 (diff) | |
download | BIP39-efe41586705d3eba480da31bb1002c4e54e73ef0.tar.gz BIP39-efe41586705d3eba480da31bb1002c4e54e73ef0.tar.zst BIP39-efe41586705d3eba480da31bb1002c4e54e73ef0.zip |
BIP32 Root Key can be specified by user
Diffstat (limited to 'src/js')
-rw-r--r-- | src/js/index.js | 85 |
1 files changed, 74 insertions, 11 deletions
diff --git a/src/js/index.js b/src/js/index.js index f3582b0..88e891c 100644 --- a/src/js/index.js +++ b/src/js/index.js | |||
@@ -12,6 +12,7 @@ | |||
12 | var showPrivKey = true; | 12 | var showPrivKey = true; |
13 | 13 | ||
14 | var phraseChangeTimeoutEvent = null; | 14 | var phraseChangeTimeoutEvent = null; |
15 | var rootKeyChangedTimeoutEvent = null; | ||
15 | 16 | ||
16 | var DOM = {}; | 17 | var DOM = {}; |
17 | DOM.network = $(".network"); | 18 | DOM.network = $(".network"); |
@@ -50,12 +51,13 @@ | |||
50 | DOM.passphrase.on("input", delayedPhraseChanged); | 51 | DOM.passphrase.on("input", delayedPhraseChanged); |
51 | DOM.generate.on("click", generateClicked); | 52 | DOM.generate.on("click", generateClicked); |
52 | DOM.more.on("click", showMore); | 53 | DOM.more.on("click", showMore); |
53 | DOM.bip32path.on("input", delayedPhraseChanged); | 54 | DOM.rootKey.on("input", delayedRootKeyChanged); |
54 | DOM.bip44purpose.on("input", delayedPhraseChanged); | 55 | DOM.bip32path.on("input", calcForDerivationPath); |
55 | DOM.bip44coin.on("input", delayedPhraseChanged); | 56 | DOM.bip44purpose.on("input", calcForDerivationPath); |
56 | DOM.bip44account.on("input", delayedPhraseChanged); | 57 | DOM.bip44coin.on("input", calcForDerivationPath); |
57 | DOM.bip44change.on("input", delayedPhraseChanged); | 58 | DOM.bip44account.on("input", calcForDerivationPath); |
58 | DOM.tab.on("click", delayedPhraseChanged); | 59 | DOM.bip44change.on("input", calcForDerivationPath); |
60 | DOM.tab.on("shown.bs.tab", calcForDerivationPath); | ||
59 | DOM.indexToggle.on("click", toggleIndexes); | 61 | DOM.indexToggle.on("click", toggleIndexes); |
60 | DOM.addressToggle.on("click", toggleAddresses); | 62 | DOM.addressToggle.on("click", toggleAddresses); |
61 | DOM.privateKeyToggle.on("click", togglePrivateKeys); | 63 | DOM.privateKeyToggle.on("click", togglePrivateKeys); |
@@ -70,7 +72,7 @@ | |||
70 | function networkChanged(e) { | 72 | function networkChanged(e) { |
71 | var network = e.target.value; | 73 | var network = e.target.value; |
72 | networks[network].onSelect(); | 74 | networks[network].onSelect(); |
73 | delayedPhraseChanged(); | 75 | displayBip32Info(); |
74 | } | 76 | } |
75 | 77 | ||
76 | function delayedPhraseChanged() { | 78 | function delayedPhraseChanged() { |
@@ -87,12 +89,57 @@ | |||
87 | hideValidationError(); | 89 | hideValidationError(); |
88 | // Get the mnemonic phrase | 90 | // Get the mnemonic phrase |
89 | var phrase = DOM.phrase.val(); | 91 | var phrase = DOM.phrase.val(); |
90 | var passphrase = DOM.passphrase.val(); | ||
91 | var errorText = findPhraseErrors(phrase); | 92 | var errorText = findPhraseErrors(phrase); |
92 | if (errorText) { | 93 | if (errorText) { |
93 | showValidationError(errorText); | 94 | showValidationError(errorText); |
94 | return; | 95 | return; |
95 | } | 96 | } |
97 | // Calculate and display | ||
98 | var passphrase = DOM.passphrase.val(); | ||
99 | calcBip32RootKeyFromSeed(phrase, passphrase); | ||
100 | calcForDerivationPath(); | ||
101 | hidePending(); | ||
102 | } | ||
103 | |||
104 | function delayedRootKeyChanged() { | ||
105 | // Warn if there is an existing mnemonic or passphrase. | ||
106 | if (DOM.phrase.val().length > 0 || DOM.passphrase.val().length > 0) { | ||
107 | if (!confirm("This will clear existing mnemonic and passphrase")) { | ||
108 | DOM.rootKey.val(bip32RootKey); | ||
109 | return | ||
110 | } | ||
111 | } | ||
112 | hideValidationError(); | ||
113 | showPending(); | ||
114 | // Clear existing mnemonic and passphrase | ||
115 | DOM.phrase.val(""); | ||
116 | DOM.passphrase.val(""); | ||
117 | seed = null; | ||
118 | if (rootKeyChangedTimeoutEvent != null) { | ||
119 | clearTimeout(rootKeyChangedTimeoutEvent); | ||
120 | } | ||
121 | rootKeyChangedTimeoutEvent = setTimeout(rootKeyChanged, 400); | ||
122 | } | ||
123 | |||
124 | function rootKeyChanged() { | ||
125 | showPending(); | ||
126 | hideValidationError(); | ||
127 | // Validate the root key TODO | ||
128 | var rootKeyBase58 = DOM.rootKey.val(); | ||
129 | var errorText = validateRootKey(rootKeyBase58); | ||
130 | if (errorText) { | ||
131 | showValidationError(errorText); | ||
132 | return; | ||
133 | } | ||
134 | // Calculate and display | ||
135 | calcBip32RootKeyFromBase58(rootKeyBase58); | ||
136 | calcForDerivationPath(); | ||
137 | hidePending(); | ||
138 | } | ||
139 | |||
140 | function calcForDerivationPath() { | ||
141 | showPending(); | ||
142 | hideValidationError(); | ||
96 | // Get the derivation path | 143 | // Get the derivation path |
97 | var derivationPath = getDerivationPath(); | 144 | var derivationPath = getDerivationPath(); |
98 | var errorText = findDerivationPathErrors(derivationPath); | 145 | var errorText = findDerivationPathErrors(derivationPath); |
@@ -100,8 +147,7 @@ | |||
100 | showValidationError(errorText); | 147 | showValidationError(errorText); |
101 | return; | 148 | return; |
102 | } | 149 | } |
103 | // Calculate and display | 150 | calcBip32ExtendedKey(derivationPath); |
104 | calcBip32Seed(phrase, passphrase, derivationPath); | ||
105 | displayBip32Info(); | 151 | displayBip32Info(); |
106 | hidePending(); | 152 | hidePending(); |
107 | } | 153 | } |
@@ -148,9 +194,16 @@ | |||
148 | return words; | 194 | return words; |
149 | } | 195 | } |
150 | 196 | ||
151 | function calcBip32Seed(phrase, passphrase, path) { | 197 | function calcBip32RootKeyFromSeed(phrase, passphrase) { |
152 | seed = mnemonic.toSeed(phrase, passphrase); | 198 | seed = mnemonic.toSeed(phrase, passphrase); |
153 | bip32RootKey = bitcoin.HDNode.fromSeedHex(seed, network); | 199 | bip32RootKey = bitcoin.HDNode.fromSeedHex(seed, network); |
200 | } | ||
201 | |||
202 | function calcBip32RootKeyFromBase58(rootKeyBase58) { | ||
203 | bip32RootKey = bitcoin.HDNode.fromBase58(rootKeyBase58); | ||
204 | } | ||
205 | |||
206 | function calcBip32ExtendedKey(path) { | ||
154 | bip32ExtendedKey = bip32RootKey; | 207 | bip32ExtendedKey = bip32RootKey; |
155 | // Derive the key from the path | 208 | // Derive the key from the path |
156 | var pathBits = path.split("/"); | 209 | var pathBits = path.split("/"); |
@@ -213,6 +266,16 @@ | |||
213 | return false; | 266 | return false; |
214 | } | 267 | } |
215 | 268 | ||
269 | function validateRootKey(rootKeyBase58) { | ||
270 | try { | ||
271 | bitcoin.HDNode.fromBase58(rootKeyBase58); | ||
272 | } | ||
273 | catch (e) { | ||
274 | return "Invalid root key"; | ||
275 | } | ||
276 | return ""; | ||
277 | } | ||
278 | |||
216 | function getDerivationPath() { | 279 | function getDerivationPath() { |
217 | if (DOM.bip44tab.hasClass("active")) { | 280 | if (DOM.bip44tab.hasClass("active")) { |
218 | var purpose = parseIntNoNaN(DOM.bip44purpose.val(), 44); | 281 | var purpose = parseIntNoNaN(DOM.bip44purpose.val(), 44); |