X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=src%2Fjs%2Findex.js;h=261a6d19c43005d77809bae797f7f1726fdbee0e;hb=c49e881294343b762109bb8104e7c1b45898c894;hp=b1876cbdd11e08e9b1212754f02d355a75c88d25;hpb=daab55dc613a1eef22463356eba1a742cb814cb2;p=perso%2FImmae%2FProjets%2FCryptomonnaies%2FBIP39.git diff --git a/src/js/index.js b/src/js/index.js index b1876cb..261a6d1 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -14,6 +14,7 @@ var showPubKey = true; var showPrivKey = true; var showQr = false; + var litecoinUseLtub = true; var entropyChangeTimeoutEvent = null; var phraseChangeTimeoutEvent = null; @@ -37,17 +38,21 @@ DOM.entropyWordCount = DOM.entropyContainer.find(".word-count"); DOM.entropyBinary = DOM.entropyContainer.find(".binary"); DOM.entropyMnemonicLength = DOM.entropyContainer.find(".mnemonic-length"); + DOM.entropyFilterWarning = DOM.entropyContainer.find(".filter-warning"); DOM.phrase = $(".phrase"); DOM.passphrase = $(".passphrase"); DOM.generateContainer = $(".generate-container"); DOM.generate = $(".generate"); DOM.seed = $(".seed"); DOM.rootKey = $(".root-key"); + DOM.litecoinLtubContainer = $(".litecoin-ltub-container"); + DOM.litecoinUseLtub = $(".litecoin-use-ltub"); DOM.extendedPrivKey = $(".extended-priv-key"); DOM.extendedPubKey = $(".extended-pub-key"); DOM.bip32tab = $("#bip32-tab"); DOM.bip44tab = $("#bip44-tab"); DOM.bip49tab = $("#bip49-tab"); + DOM.bip141tab = $("#bip141-tab"); DOM.bip32panel = $("#bip32"); DOM.bip44panel = $("#bip44"); DOM.bip49panel = $("#bip49"); @@ -68,11 +73,18 @@ DOM.bip49accountXprv = $("#bip49 .account-xprv"); DOM.bip49accountXpub = $("#bip49 .account-xpub"); DOM.bip49change = $("#bip49 .change"); + DOM.bip141unavailable = $("#bip141 .unavailable"); + DOM.bip141available = $("#bip141 .available"); + DOM.bip141path = $("#bip141-path"); + DOM.bip141semantics = $(".bip141-semantics"); DOM.generatedStrength = $(".generate-container .strength"); DOM.hardenedAddresses = $(".hardened-addresses"); + DOM.useBitpayAddressesContainer = $(".use-bitpay-addresses-container"); + DOM.useBitpayAddresses = $(".use-bitpay-addresses"); DOM.addresses = $(".addresses"); DOM.rowsToAdd = $(".rows-to-add"); DOM.more = $(".more"); + DOM.moreRowsStartIndex = $(".more-rows-start-index"); DOM.feedback = $(".feedback"); DOM.tab = $(".derivation-type a"); DOM.indexToggle = $(".index-toggle"); @@ -98,18 +110,22 @@ DOM.generate.on("click", generateClicked); DOM.more.on("click", showMore); DOM.rootKey.on("input", delayedRootKeyChanged); + DOM.litecoinUseLtub.on("change", litecoinUseLtubChanged); DOM.bip32path.on("input", calcForDerivationPath); DOM.bip44account.on("input", calcForDerivationPath); DOM.bip44change.on("input", calcForDerivationPath); DOM.bip49account.on("input", calcForDerivationPath); DOM.bip49change.on("input", calcForDerivationPath); - DOM.tab.on("shown.bs.tab", calcForDerivationPath); + DOM.bip141path.on("input", calcForDerivationPath); + DOM.bip141semantics.on("change", tabChanged); + DOM.tab.on("shown.bs.tab", tabChanged); DOM.hardenedAddresses.on("change", calcForDerivationPath); DOM.indexToggle.on("click", toggleIndexes); DOM.addressToggle.on("click", toggleAddresses); DOM.publicKeyToggle.on("click", togglePublicKeys); DOM.privateKeyToggle.on("click", togglePrivateKeys); DOM.languages.on("click", languageChanged); + DOM.useBitpayAddresses.on("change", useBitpayAddressesChange); setQrEvents(DOM.showQrEls); disableForms(); hidePending(); @@ -123,14 +139,17 @@ function networkChanged(e) { clearDerivedKeys(); clearAddressesList(); + DOM.litecoinLtubContainer.addClass("hidden"); + DOM.useBitpayAddressesContainer.addClass("hidden"); var networkIndex = e.target.value; var network = networks[networkIndex]; network.onSelect(); - if (network.bip49available) { - showBip49(); + if (network.segwitAvailable) { + adjustNetworkForSegwit(); + showSegwitAvailable(); } else { - hideBip49(); + showSegwitUnavailable(); } if (seed != null) { phraseChanged(); @@ -175,6 +194,10 @@ function delayedPhraseChanged() { hideValidationError(); + seed = null; + bip32RootKey = null; + bip32ExtendedKey = null; + clearAddressesList(); showPending(); if (phraseChangeTimeoutEvent != null) { clearTimeout(phraseChangeTimeoutEvent); @@ -184,7 +207,6 @@ function phraseChanged() { showPending(); - hideValidationError(); setMnemonicLanguage(); // Get the mnemonic phrase var phrase = DOM.phrase.val(); @@ -197,7 +219,35 @@ var passphrase = DOM.passphrase.val(); calcBip32RootKeyFromSeed(phrase, passphrase); calcForDerivationPath(); - hidePending(); + } + + function tabChanged() { + showPending(); + adjustNetworkForSegwit(); + var phrase = DOM.phrase.val(); + if (phrase != "") { + // Calculate and display for mnemonic + var errorText = findPhraseErrors(phrase); + if (errorText) { + showValidationError(errorText); + return; + } + // Calculate and display + var passphrase = DOM.passphrase.val(); + calcBip32RootKeyFromSeed(phrase, passphrase); + } + else { + // Calculate and display for root key + var rootKeyBase58 = DOM.rootKey.val(); + var errorText = validateRootKey(rootKeyBase58); + if (errorText) { + showValidationError(errorText); + return; + } + // Calculate and display + calcBip32RootKeyFromBase58(rootKeyBase58); + } + calcForDerivationPath(); } function delayedEntropyChanged() { @@ -260,7 +310,6 @@ function rootKeyChanged() { showPending(); hideValidationError(); - // Validate the root key TODO var rootKeyBase58 = DOM.rootKey.val(); var errorText = validateRootKey(rootKeyBase58); if (errorText) { @@ -272,13 +321,23 @@ calcForDerivationPath(); } + function litecoinUseLtubChanged() { + litecoinUseLtub = DOM.litecoinUseLtub.prop("checked"); + if (litecoinUseLtub) { + network = bitcoinjs.bitcoin.networks.litecoin; + } + else { + network = bitcoinjs.bitcoin.networks.litecoinXprv; + } + phraseChanged(); + } + function calcForDerivationPath() { - showPending(); clearDerivedKeys(); clearAddressesList(); - hideValidationError(); - // Don't show bip49 if it's selected but network doesn't support it - if (bip49TabSelected() && !networkHasBip49()) { + showPending(); + // Don't show segwit if it's selected but network doesn't support it + if (segwitSelected() && !networkHasSegwit()) { return; } // Get the derivation path @@ -292,11 +351,10 @@ if (bip44TabSelected()) { displayBip44Info(); } - if (bip49TabSelected()) { + else if (bip49TabSelected()) { displayBip49Info(); } displayBip32Info(); - hidePending(); } function generateClicked() { @@ -329,6 +387,11 @@ }, 50); } + function useBitpayAddressesChange() { + setBitcoinCashNetworkValues(); + phraseChanged(); + } + function toggleIndexes() { showIndex = !showIndex; $("td.index span").toggleClass("invisible"); @@ -444,7 +507,7 @@ function validateRootKey(rootKeyBase58) { try { - bitcoinjs.bitcoin.HDNode.fromBase58(rootKeyBase58); + bitcoinjs.bitcoin.HDNode.fromBase58(rootKeyBase58, network); } catch (e) { return "Invalid root key"; @@ -468,7 +531,7 @@ console.log("Using derivation path from BIP44 tab: " + derivationPath); return derivationPath; } - if (bip49TabSelected()) { + else if (bip49TabSelected()) { var purpose = parseIntNoNaN(DOM.bip49purpose.val(), 49); var coin = parseIntNoNaN(DOM.bip49coin.val(), 0); var account = parseIntNoNaN(DOM.bip49account.val(), 0); @@ -488,6 +551,11 @@ console.log("Using derivation path from BIP32 tab: " + derivationPath); return derivationPath; } + else if (bip141TabSelected()) { + var derivationPath = DOM.bip141path.val(); + console.log("Using derivation path from BIP141 tab: " + derivationPath); + return derivationPath; + } else { console.log("Unknown derivation path"); } @@ -532,7 +600,9 @@ return "No root key"; } // Check no hardened derivation path when using xpub keys - var hardened = path.indexOf("'") > -1; + var hardenedPath = path.indexOf("'") > -1; + var hardenedAddresses = bip32TabSelected() && DOM.hardenedAddresses.prop("checked"); + var hardened = hardenedPath || hardenedAddresses; var isXpubkey = bip32RootKey.isNeutered(); if (hardened && isXpubkey) { return "Hardened derivation path is invalid with xpub key"; @@ -603,23 +673,40 @@ for (var i=0; i 200) { var msg = "Generating " + rowsToAdd + " rows could take a while. "; msg += "Do you want to continue?"; @@ -1037,6 +1141,16 @@ DOM.entropyWordCount.text(wordCount); DOM.entropyBinary.text(entropy.binaryStr); DOM.entropyBitsPerEvent.text(bitsPerEvent); + // detect and warn of filtering + var rawNoSpaces = DOM.entropy.val().replace(/\s/g, ""); + var cleanNoSpaces = entropy.cleanStr.replace(/\s/g, ""); + var isFiltered = rawNoSpaces.length != cleanNoSpaces.length; + if (isFiltered) { + DOM.entropyFilterWarning.removeClass('hidden'); + } + else { + DOM.entropyFilterWarning.addClass('hidden'); + } } function getEntropyTypeStr(entropy) { @@ -1142,41 +1256,91 @@ return DOM.bip32tab.hasClass("active"); } - function networkHasBip49() { - return networks[DOM.network.val()].bip49available; + function networkHasSegwit() { + return networks[DOM.network.val()].segwitAvailable; } function bip49TabSelected() { return DOM.bip49tab.hasClass("active"); } + function bip141TabSelected() { + return DOM.bip141tab.hasClass("active"); + } + function setHdCoin(coinValue) { DOM.bip44coin.val(coinValue); DOM.bip49coin.val(coinValue); } - function showBip49() { + function showSegwitAvailable() { DOM.bip49unavailable.addClass("hidden"); DOM.bip49available.removeClass("hidden"); + DOM.bip141unavailable.addClass("hidden"); + DOM.bip141available.removeClass("hidden"); } - function hideBip49() { + function showSegwitUnavailable() { DOM.bip49available.addClass("hidden"); DOM.bip49unavailable.removeClass("hidden"); + DOM.bip141available.addClass("hidden"); + DOM.bip141unavailable.removeClass("hidden"); + } + + function useBitpayAddresses() { + return !(DOM.useBitpayAddresses.prop("checked")); + } + + function setBitcoinCashNetworkValues() { + if (useBitpayAddresses()) { + network = bitcoinjs.bitcoin.networks.bitcoin; + } + else { + network = bitcoinjs.bitcoin.networks.bitcoinCashBitbpay; + } + } + + function adjustNetworkForSegwit() { + // If segwit is selected the xpub/xprv prefixes need to be adjusted + // to avoid accidentally importing BIP49 xpub to BIP44 watch only + // wallet. + // See https://github.com/iancoleman/bip39/issues/125 + var segwitNetworks = null; + // if a segwit network is alread selected, need to use base network to + // look up new parameters + if ("baseNetwork" in network) { + network = bitcoinjs.bitcoin.networks[network.baseNetwork]; + } + // choose the right segwit params + if (p2wpkhSelected() && "p2wpkh" in network) { + network = network.p2wpkh; + } + else if (p2wpkhInP2shSelected() && "p2wpkhInP2sh" in network) { + network = network.p2wpkhInP2sh; + } + } + + function lastIndexInTable() { + var pathText = DOM.addresses.find(".index").last().text(); + var pathBits = pathText.split("/"); + var lastBit = pathBits[pathBits.length-1]; + var lastBitClean = lastBit.replace("'", ""); + return parseInt(lastBitClean); } var networks = [ { name: "BCH - Bitcoin Cash", - bip49available: false, + segwitAvailable: false, onSelect: function() { - network = bitcoinjs.bitcoin.networks.bitcoin; + DOM.useBitpayAddressesContainer.removeClass("hidden"); + setBitcoinCashNetworkValues(); setHdCoin(145); }, }, { name: "BTC - Bitcoin", - bip49available: true, + segwitAvailable: true, onSelect: function() { network = bitcoinjs.bitcoin.networks.bitcoin; setHdCoin(0); @@ -1184,15 +1348,23 @@ }, { name: "BTC - Bitcoin Testnet", - bip49available: true, + segwitAvailable: true, onSelect: function() { network = bitcoinjs.bitcoin.networks.testnet; setHdCoin(1); }, }, + { + name: "BTG - Bitcoin Gold", + segwitAvailable: true, + onSelect: function() { + network = bitcoinjs.bitcoin.networks.bgold; + setHdCoin(0); + }, + }, { name: "CLAM - Clams", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.clam; setHdCoin(23); @@ -1200,7 +1372,7 @@ }, { name: "CRW - Crown", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.crown; setHdCoin(72); @@ -1208,7 +1380,7 @@ }, { name: "DASH - Dash", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.dash; setHdCoin(5); @@ -1216,7 +1388,7 @@ }, { name: "DASH - Dash Testnet", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.dashtn; setHdCoin(1); @@ -1224,7 +1396,7 @@ }, { name: "DOGE - Dogecoin", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.dogecoin; setHdCoin(3); @@ -1232,15 +1404,23 @@ }, { name: "ETH - Ethereum", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.bitcoin; setHdCoin(60); }, }, + { + name: "FJC - Fujicoin", + segwitAvailable: false, + onSelect: function() { + network = bitcoinjs.bitcoin.networks.fujicoin; + setHdCoin(75); + }, + }, { name: "GAME - GameCredits", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.game; setHdCoin(101); @@ -1248,7 +1428,7 @@ }, { name: "JBS - Jumbucks", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.jumbucks; setHdCoin(26); @@ -1256,23 +1436,56 @@ }, { name: "LTC - Litecoin", - bip49available: false, + segwitAvailable: true, onSelect: function() { network = bitcoinjs.bitcoin.networks.litecoin; setHdCoin(2); + DOM.litecoinLtubContainer.removeClass("hidden"); + }, + }, + { + name: "MAZA - Maza", + segwitAvailable: false, + onSelect: function() { + network = bitcoinjs.bitcoin.networks.maza; + setHdCoin(13); + }, + }, + { + name: "MONA - Monacoin", + segwitAvailable: true, + onSelect: function() { + network = bitcoinjs.bitcoin.networks.monacoin, + setHdCoin(22); }, }, { name: "NMC - Namecoin", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.namecoin; setHdCoin(7); }, }, + { + name: "PIVX - PIVX", + segwitAvailable: false, + onSelect: function() { + network = bitcoinjs.bitcoin.networks.pivx; + setHdCoin(119); + }, + }, + { + name: "PIVX - PIVX Testnet", + segwitAvailable: false, + onSelect: function() { + network = bitcoinjs.bitcoin.networks.pivxtestnet; + setHdCoin(1); + }, + }, { name: "PPC - Peercoin", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.peercoin; setHdCoin(6); @@ -1280,7 +1493,7 @@ }, { name: "SDC - ShadowCash", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.shadow; setHdCoin(35); @@ -1288,7 +1501,7 @@ }, { name: "SDC - ShadowCash Testnet", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.shadowtn; setHdCoin(1); @@ -1296,7 +1509,7 @@ }, { name: "SLM - Slimcoin", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.slimcoin; setHdCoin(63); @@ -1304,15 +1517,23 @@ }, { name: "SLM - Slimcoin Testnet", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.slimcointn; setHdCoin(111); }, }, + { + name: "USNBT - NuBits", + segwitAvailable: false, + onSelect: function() { + network = bitcoinjs.bitcoin.networks.nubits; + setHdCoin(12); + }, + }, { name: "VIA - Viacoin", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.viacoin; setHdCoin(14); @@ -1320,26 +1541,26 @@ }, { name: "VIA - Viacoin Testnet", - bip49available: false, + segwitAvailable: false, onSelect: function() { network = bitcoinjs.bitcoin.networks.viacointestnet; setHdCoin(1); }, }, { - name: "XRP - Ripple", - bip49available: false, + name: "XMY - Myriadcoin", + segwitAvailable: false, onSelect: function() { - network = bitcoinjs.bitcoin.networks.bitcoin; - setHdCoin(144); + network = bitcoinjs.bitcoin.networks.myriadcoin; + setHdCoin(90); }, }, { - name: "XMY - Myriadcoin", - bip49available: false, + name: "XRP - Ripple", + segwitAvailable: false, onSelect: function() { - network = bitcoinjs.bitcoin.networks.myriadcoin; - setHdCoin(90); + network = bitcoinjs.bitcoin.networks.bitcoin; + setHdCoin(144); }, } ]