DOM.bip32tab = $("#bip32-tab");
DOM.bip44tab = $("#bip44-tab");
DOM.bip49tab = $("#bip49-tab");
+ DOM.bip84tab = $("#bip84-tab");
DOM.bip141tab = $("#bip141-tab");
DOM.bip32panel = $("#bip32");
DOM.bip44panel = $("#bip44");
DOM.bip49accountXprv = $("#bip49 .account-xprv");
DOM.bip49accountXpub = $("#bip49 .account-xpub");
DOM.bip49change = $("#bip49 .change");
+ DOM.bip84path = $("#bip84-path");
+ DOM.bip84purpose = $("#bip84 .purpose");
+ DOM.bip84coin = $("#bip84 .coin");
+ DOM.bip84account = $("#bip84 .account");
+ DOM.bip84accountXprv = $("#bip84 .account-xprv");
+ DOM.bip84accountXpub = $("#bip84 .account-xpub");
+ DOM.bip84change = $("#bip84 .change");
DOM.bip141unavailable = $("#bip141 .unavailable");
DOM.bip141available = $("#bip141 .available");
DOM.bip141path = $("#bip141-path");
DOM.hardenedAddresses = $(".hardened-addresses");
DOM.useBitpayAddressesContainer = $(".use-bitpay-addresses-container");
DOM.useBitpayAddresses = $(".use-bitpay-addresses");
+ DOM.useBip38 = $(".use-bip38");
+ DOM.bip38Password = $(".bip38-password");
DOM.addresses = $(".addresses");
+ DOM.csvTab = $("#csv-tab a");
+ DOM.csv = $(".csv");
DOM.rowsToAdd = $(".rows-to-add");
DOM.more = $(".more");
DOM.moreRowsStartIndex = $(".more-rows-start-index");
DOM.bip44change.on("input", calcForDerivationPath);
DOM.bip49account.on("input", calcForDerivationPath);
DOM.bip49change.on("input", calcForDerivationPath);
+ DOM.bip84account.on("input", calcForDerivationPath);
+ DOM.bip84change.on("input", calcForDerivationPath);
DOM.bip141path.on("input", calcForDerivationPath);
DOM.bip141semantics.on("change", tabChanged);
DOM.tab.on("shown.bs.tab", tabChanged);
DOM.hardenedAddresses.on("change", calcForDerivationPath);
+ DOM.useBip38.on("change", calcForDerivationPath);
+ DOM.bip38Password.on("change", calcForDerivationPath);
DOM.indexToggle.on("click", toggleIndexes);
DOM.addressToggle.on("click", toggleAddresses);
DOM.publicKeyToggle.on("click", togglePublicKeys);
DOM.privateKeyToggle.on("click", togglePrivateKeys);
+ DOM.csvTab.on("click", updateCsv);
DOM.languages.on("click", languageChanged);
DOM.useBitpayAddresses.on("change", useBitpayAddressesChange);
setQrEvents(DOM.showQrEls);
else if (bip49TabSelected()) {
displayBip49Info();
}
+ else if (bip84TabSelected()) {
+ displayBip84Info();
+ }
displayBip32Info();
}
console.log("Using derivation path from BIP49 tab: " + derivationPath);
return derivationPath;
}
+ else if (bip84TabSelected()) {
+ var purpose = parseIntNoNaN(DOM.bip84purpose.val(), 84);
+ var coin = parseIntNoNaN(DOM.bip84coin.val(), 0);
+ var account = parseIntNoNaN(DOM.bip84account.val(), 0);
+ var change = parseIntNoNaN(DOM.bip84change.val(), 0);
+ var path = "m/";
+ path += purpose + "'/";
+ path += coin + "'/";
+ path += account + "'/";
+ path += change;
+ DOM.bip84path.val(path);
+ var derivationPath = DOM.bip84path.val();
+ console.log("Using derivation path from BIP84 tab: " + derivationPath);
+ return derivationPath;
+ }
else if (bip32TabSelected()) {
var derivationPath = DOM.bip32path.val();
console.log("Using derivation path from BIP32 tab: " + derivationPath);
DOM.bip49accountXpub.val(accountXpub);
}
+ function displayBip84Info() {
+ // Get the derivation path for the account
+ var purpose = parseIntNoNaN(DOM.bip84purpose.val(), 84);
+ var coin = parseIntNoNaN(DOM.bip84coin.val(), 0);
+ var account = parseIntNoNaN(DOM.bip84account.val(), 0);
+ var path = "m/";
+ path += purpose + "'/";
+ path += coin + "'/";
+ path += account + "'/";
+ // Calculate the account extended keys
+ var accountExtendedKey = calcBip32ExtendedKey(path);
+ var accountXprv = accountExtendedKey.toBase58();
+ var accountXpub = accountExtendedKey.neutered().toBase58();
+ // Display the extended keys
+ DOM.bip84accountXprv.val(accountXprv);
+ DOM.bip84accountXpub.val(accountXpub);
+ }
+
function displayBip32Info() {
// Display the key
DOM.seed.val(seed);
DOM.extendedPubKey.val(extendedPubKey);
// Display the addresses and privkeys
clearAddressesList();
- displayAddresses(0, 20);
+ var initialAddressCount = parseInt(DOM.rowsToAdd.val());
+ displayAddresses(0, initialAddressCount);
}
function displayAddresses(start, total) {
}
function segwitSelected() {
- return bip49TabSelected() || bip141TabSelected();
+ return bip49TabSelected() || bip84TabSelected() || bip141TabSelected();
}
function p2wpkhSelected() {
- return bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh";
+ return bip84TabSelected() ||
+ bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh";
}
function p2wpkhInP2shSelected() {
var self = this;
this.shouldGenerate = true;
var useHardenedAddresses = DOM.hardenedAddresses.prop("checked");
+ var useBip38 = DOM.useBip38.prop("checked");
+ var bip38password = DOM.bip38Password.val();
var isSegwit = segwitSelected();
var segwitAvailable = networkHasSegwit();
var isP2wpkh = p2wpkhSelected();
if (!self.shouldGenerate) {
return;
}
+ // derive HDkey for this row of the table
var key = "NA";
if (useHardenedAddresses) {
key = bip32ExtendedKey.deriveHardened(index);
else {
key = bip32ExtendedKey.derive(index);
}
- var address = key.getAddress().toString();
+ // bip38 requires uncompressed keys
+ // see https://github.com/iancoleman/bip39/issues/140#issuecomment-352164035
+ var keyPair = key.keyPair;
+ var useUncompressed = useBip38;
+ if (useUncompressed) {
+ keyPair = new bitcoinjs.bitcoin.ECPair(keyPair.d, null, { compressed: false });
+ }
+ // get address
+ var address = keyPair.getAddress().toString();
+ // get privkey
+ var hasPrivkey = !key.isNeutered();
var privkey = "NA";
- if (!key.isNeutered()) {
- privkey = key.keyPair.toWIF(network);
+ if (hasPrivkey) {
+ privkey = keyPair.toWIF(network);
+ // BIP38 encode private key if required
+ if (useBip38) {
+ privkey = bitcoinjsBip38.encrypt(keyPair.d.toBuffer(), false, bip38password, function(p) {
+ console.log("Progressed " + p.percent.toFixed(1) + "% for index " + index);
+ });
+ }
}
- var pubkey = key.getPublicKeyBuffer().toString('hex');
+ // get pubkey
+ var pubkey = keyPair.getPublicKeyBuffer().toString('hex');
var indexText = getDerivationPath() + "/" + index;
if (useHardenedAddresses) {
indexText = indexText + "'";
}
// Ethereum values are different
if (networks[DOM.network.val()].name == "ETH - Ethereum") {
- var privKeyBuffer = key.keyPair.d.toBuffer();
+ var privKeyBuffer = keyPair.d.toBuffer(32);
privkey = privKeyBuffer.toString('hex');
var addressBuffer = ethUtil.privateToAddress(privKeyBuffer);
var hexAddress = addressBuffer.toString('hex');
addAddressToList(indexText, address, pubkey, privkey);
if (isLast) {
hidePending();
+ updateCsv();
}
}, 50)
}
function clearAddressesList() {
DOM.addresses.empty();
+ DOM.csv.val("");
stopGenerating();
}
var entropyTypeStr = getEntropyTypeStr(entropy);
var wordCount = Math.floor(numberOfBits / 32) * 3;
var bitsPerEvent = entropy.bitsPerEvent.toFixed(2);
+ var spacedBinaryStr = entropy.binaryStr.match(/.{1,11}/g).join(" " );
DOM.entropyFiltered.html(entropy.cleanHtml);
DOM.entropyType.text(entropyTypeStr);
DOM.entropyCrackTime.text(timeToCrack);
DOM.entropyEventCount.text(entropy.base.ints.length);
DOM.entropyBits.text(numberOfBits);
DOM.entropyWordCount.text(wordCount);
- DOM.entropyBinary.text(entropy.binaryStr);
+ DOM.entropyBinary.text(spacedBinaryStr);
DOM.entropyBitsPerEvent.text(bitsPerEvent);
// detect and warn of filtering
var rawNoSpaces = DOM.entropy.val().replace(/\s/g, "");
return DOM.bip49tab.hasClass("active");
}
+ function bip84TabSelected() {
+ return DOM.bip84tab.hasClass("active");
+ }
+
function bip141TabSelected() {
return DOM.bip141tab.hasClass("active");
}
function setHdCoin(coinValue) {
DOM.bip44coin.val(coinValue);
DOM.bip49coin.val(coinValue);
+ DOM.bip84coin.val(coinValue);
}
function showSegwitAvailable() {
DOM.entropyWordIndexes.text(wordIndexesStr);
}
+ function updateCsv() {
+ var tableCsv = "path,address,public key,private key\n";
+ var rows = DOM.addresses.find("tr");
+ for (var i=0; i<rows.length; i++) {
+ var row = $(rows[i]);
+ var cells = row.find("td");
+ for (var j=0; j<cells.length; j++) {
+ var cell = $(cells[j]);
+ if (!cell.children().hasClass("invisible")) {
+ tableCsv = tableCsv + cell.text();
+ }
+ if (j != cells.length - 1) {
+ tableCsv = tableCsv + ",";
+ }
+ }
+ tableCsv = tableCsv + "\n";
+ }
+ DOM.csv.val(tableCsv);
+ }
+
var networks = [
+ {
+ name: "AXE - Axe",
+ segwitAvailable: false,
+ onSelect: function() {
+ network = bitcoinjs.bitcoin.networks.axe;
+ setHdCoin(0);
+ },
+ },
{
name: "BCH - Bitcoin Cash",
segwitAvailable: false,
setHdCoin(145);
},
},
+ {
+ name: "BLK - BlackCoin",
+ segwitAvailable: false,
+ onSelect: function() {
+ network = bitcoinjs.bitcoin.networks.blackcoin;
+ setHdCoin(10);
+ },
+ },
{
name: "BTC - Bitcoin",
segwitAvailable: true,
setHdCoin(1);
},
},
+ {
+ name: "DNR - Denarius",
+ segwitAvailable: false,
+ onSelect: function() {
+ network = bitcoinjs.bitcoin.networks.denarius;
+ setHdCoin(0);
+ },
+ },
{
name: "DOGE - Dogecoin",
segwitAvailable: false,
setHdCoin(26);
},
},
+ {
+ name: "KMD - Komodo",
+ bip49available: false,
+ onSelect: function() {
+ network = bitcoinjs.bitcoin.networks.komodo;
+ setHdCoin(141);
+ },
+ },
{
name: "LTC - Litecoin",
segwitAvailable: true,
network = bitcoinjs.bitcoin.networks.bitcoin;
setHdCoin(144);
},
- }
+ },
]
var clients = [