// mnemonics is populated as required by getLanguage
var mnemonics = { "english": new Mnemonic("english") };
var mnemonic = mnemonics["english"];
- var seed = null
+ var seed = null;
var bip32RootKey = null;
var bip32ExtendedKey = null;
var network = bitcoin.networks.bitcoin;
var phraseChangeTimeoutEvent = null;
var rootKeyChangedTimeoutEvent = null;
+ var generationProcesses = [];
+
var DOM = {};
DOM.network = $(".network");
+ DOM.client = $(".client");
DOM.phraseNetwork = $("#network-phrase");
+ DOM.phraseClient = $("#client-phrase");
DOM.useEntropy = $(".use-entropy");
DOM.entropyContainer = $(".entropy-container");
DOM.entropy = $(".entropy");
function init() {
// Events
DOM.network.on("change", networkChanged);
+ DOM.client.on("change", clientChanged);
DOM.useEntropy.on("change", setEntropyVisibility);
DOM.entropy.on("input", delayedEntropyChanged);
DOM.entropyMnemonicLength.on("change", entropyChanged);
hidePending();
hideValidationError();
populateNetworkSelect();
+ populateClientSelect();
}
// Event handlers
rootKeyChanged();
}
}
+
+ function clientChanged(e) {
+ var clientIndex = e.target.value;
+ clients[clientIndex].onSelect();
+ if (seed != null) {
+ phraseChanged();
+ }
+ else {
+ rootKeyChanged();
+ }
+ }
function setEntropyVisibility() {
if (isUsingOwnEntropy()) {
}
function calcBip32ExtendedKey(path) {
+ // Check there's a root key to derive from
+ if (!bip32RootKey) {
+ return bip32RootKey;
+ }
var extendedKey = bip32RootKey;
// Derive the key from the path
var pathBits = path.split("/");
}
}
}
+ // Check root key exists or else derivation path is useless!
+ if (!bip32RootKey) {
+ return "No root key";
+ }
// Check no hardened derivation path when using xpub keys
var hardened = path.indexOf("'") > -1;
var isXpubkey = !("privKey" in bip32RootKey);
}
function displayAddresses(start, total) {
- for (var i=0; i<total; i++) {
- var index = i + start;
- new TableRow(index);
- }
+ generationProcesses.push(new (function() {
+
+ var rows = [];
+
+ this.stop = function() {
+ for (var i=0; i<rows.length; i++) {
+ rows[i].shouldGenerate = false;
+ }
+ }
+
+ for (var i=0; i<total; i++) {
+ var index = i + start;
+ rows.push(new TableRow(index));
+ }
+
+ })());
}
function TableRow(index) {
+ var self = this;
+ this.shouldGenerate = true;
var useHardenedAddresses = DOM.hardenedAddresses.prop("checked");
function init() {
function calculateValues() {
setTimeout(function() {
+ if (!self.shouldGenerate) {
+ return;
+ }
var key = "";
if (useHardenedAddresses) {
key = bip32ExtendedKey.deriveHardened(index);
function clearAddressesList() {
DOM.addresses.empty();
+ stopGenerating();
+ }
+
+ function stopGenerating() {
+ while (generationProcesses.length > 0) {
+ var generation = generationProcesses.shift();
+ generation.stop();
+ }
}
function clearKey() {
var closestWord = words[0];
for (var i=0; i<words.length; i++) {
var comparedTo = words[i];
+ if (comparedTo.indexOf(word) == 0) {
+ return comparedTo;
+ }
var distance = Levenshtein.get(word, comparedTo);
if (distance < minDistance) {
closestWord = comparedTo;
DOM.phraseNetwork.append(option);
}
}
+
+ function populateClientSelect() {
+ for (var i=0; i<clients.length; i++) {
+ var client = clients[i];
+ var option = $("<option>");
+ option.attr("value", i);
+ option.text(client.name);
+ DOM.phraseClient.append(option);
+ }
+ }
function getLanguage() {
var defaultLanguage = "english";
var hash = sjcl.hash.sha256.hash(entropy.cleanStr);
var hex = sjcl.codec.hex.fromBits(hash);
bits = BigInteger.parse(hex, 16).toString(2);
- for (var i=0; i<256-bits.length; i++) {
+ while (bits.length % 256 != 0) {
bits = "0" + bits;
}
// Truncate hash to suit number of words
},
},
]
+
+ var clients = [
+ {
+ name: "Bitcoin Core",
+ onSelect: function() {
+ DOM.bip32path.val("m/0'/0'");
+ DOM.hardenedAddresses.prop('checked', true);
+ },
+ },
+ {
+ name: "blockchain.info",
+ onSelect: function() {
+ DOM.bip32path.val("m/44'/0'/0'");
+ DOM.hardenedAddresses.prop('checked', false);
+ },
+ },
+ {
+ name: "MultiBit HD",
+ onSelect: function() {
+ DOM.bip32path.val("m/0'/0");
+ DOM.hardenedAddresses.prop('checked', false);
+ },
+ }
+ ]
init();