Merge pull request #1 from amougel/master

Ripple support
This commit is contained in:
Pierre Pollastri
2017-06-01 16:00:20 +02:00
committed by GitHub
13 changed files with 50674 additions and 89 deletions

File diff suppressed because one or more lines are too long

View File

@@ -6,7 +6,7 @@ import datetime
# It removes script and style tags and replaces with the file content.
f = open('src/index.html')
f = open('src/index.html', "r", encoding="utf-8")
page = f.read()
f.close()
@@ -18,7 +18,7 @@ scripts = scriptsFinder.findall(page)
for script in scripts:
filename = os.path.join("src", script)
s = open(filename)
s = open(filename, "r", encoding="utf-8")
scriptContent = "<script>%s</script>" % s.read()
s.close()
scriptTag = """<script src="%s"></script>""" % script
@@ -32,7 +32,7 @@ styles = stylesFinder.findall(page)
for style in styles:
filename = os.path.join("src", style)
s = open(filename)
s = open(filename, "r", encoding="utf-8")
styleContent = "<style>%s</style>" % s.read()
s.close()
styleTag = """<link rel="stylesheet" href="%s">""" % style
@@ -41,8 +41,8 @@ for style in styles:
# Write the standalone file
f = open('bip39-standalone.html', 'w')
f = open('bip39-standalone.html', 'w', encoding="utf-8")
f.write(page)
f.close()
print "%s - DONE" % datetime.datetime.now()
print("%s - DONE" % datetime.datetime.now())

View File

@@ -28,6 +28,28 @@ import private keys into a wallet or supply someone with a list of addresses.
The BIP32 keys can be used at [bip32.org](https://bip32.org) if desired.
## Donations
Since this project is the efforts of many people, most of which don't appear in
the obvious places like code or issues, donating to the project itself causes
significant operational difficulties.
As a result, if you would like to support this project financially you are
encouraged to donate to one of the many groups that makes the internet a place
amenable to projects such as this one.
[Donation-accepting organizations and projects](https://en.bitcoin.it/wiki/Donation-accepting_organizations_and_projects)
If the list is too difficult to choose from, the EFF is a good choice.
[Electronic Frontier Foundation](https://supporters.eff.org/donate)
or for a direct bitcoin address, consider donating to the
[Free Software Foundation](https://www.fsf.org/about/ways-to-donate/)
at 1PC9aZC4hNX2rmmrt7uHTfYAS3hRbph4UN
![alt text](https://static.fsf.org/nosvn/images/bitcoin_qrcodes/fsf.png "FSF Bitcoin Address")
## Making changes
Please do not make modifications to `bip39-standalone.html`, since they will

View File

@@ -8,6 +8,7 @@
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<meta content="bitcoin mnemonic converter" name="description" />
<meta content="Ian Coleman" name="author" />
<link type="image/x-icon" rel="icon" href="data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAF0lEQVRIx2NgGAWjYBSMglEwCkbBSAcACBAAAeaR9cIAAAAASUVORK5CYII=" />
<style>
body {
@@ -182,9 +183,9 @@
<label class="col-sm-3 control-label" data-translate>Mnemonic Length</label>
<div class="col-sm-9">
<select class="mnemonic-length form-control">
<option value="raw" data-translate>From entropy length (3 words per 32 bits)</option>
<option value="raw" selected data-translate>Use Raw Entropy (3 words per 32 bits)</option>
<option value="12">12 <span data-translate>Words</span></option>
<option value="15" selected>15 <span data-translate>Words</option>
<option value="15">15 <span data-translate>Words</option>
<option value="18">18 <span data-translate>Words</span></option>
<option value="21">21 <span data-translate>Words</span></option>
<option value="24">24 <span data-translate>Words</span></option>
@@ -367,6 +368,15 @@
<a href="https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki" target="_blank">BIP32 spec</a>
</p>
</div>
<div class="form-group">
<label for="bip32-client" class="col-sm-2 control-label" data-translate>Client</label>
<div class="col-sm-10">
<select id="bip32-client" class="client form-control">
<option value="custom">Custom derivation path</option>
<!-- populated by javascript -->
</select>
</div>
</div>
<div class="form-group">
<label for="bip32-path" class="col-sm-2 control-label" data-translate>BIP32 Derivation Path</label>
<div class="col-sm-10">
@@ -392,6 +402,18 @@
</p>
</div>
</div>
<div class="form-group">
<label for="core-path" class="col-sm-2 control-label" data-translate>Multibit</label>
<div class="col-sm-10">
<p class="form-control no-border">
<span data-translate-html>Use path <code>m/0'/0</code>.</span>
</p>
<p class="form-control no-border">
<span data-translate>For more info see</span>
<a href="https://multibit.org/" target="_blank">MultiBit HD</a>
</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" data-translate>Block Explorers</label>
<div class="col-sm-10">
@@ -651,12 +673,17 @@
<td class="privkey"><span data-show-qr></span></td>
</tr>
</script>
<script src="js/polyfill.es6.js"></script>
<script src="js/basex.js"></script>
<script src="js/unorm.js"></script>
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/levenshtein.js"></script>
<script src="js/jquery.qrcode.min.js"></script>
<script src="js/bitcoinjs-1-5-7.js"></script>
<script src="js/bitcoinjs-extensions.js"></script>
<script src="js/ethereumjs-util.js"></script>
<script src="js/ripple-util.js"></script>
<script src="js/sjcl-bip39.js"></script>
<script src="js/translate.js"></script>
<script src="js/phrases_en.js"></script>

2010
src/js/basex.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,16 @@ bitcoin.networks.dash = {
wif: 0xcc,
};
bitcoin.networks.game = {
bip32: {
public: 0x0488b21e,
private: 0x0488ade4
},
pubKeyHash: 0x26,
scriptHash: 0x05,
wif: 0xa6,
};
bitcoin.networks.namecoin = {
bip32: {
public: 0x0488b21e,

18762
src/js/ethereumjs-util.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@
var DOM = {};
DOM.network = $(".network");
DOM.bip32Client = $("#bip32-client");
DOM.phraseNetwork = $("#network-phrase");
DOM.useEntropy = $(".use-entropy");
DOM.entropyContainer = $(".entropy-container");
@@ -77,6 +78,7 @@
function init() {
// Events
DOM.network.on("change", networkChanged);
DOM.bip32Client.on("change", bip32ClientChanged);
DOM.useEntropy.on("change", setEntropyVisibility);
DOM.entropy.on("input", delayedEntropyChanged);
DOM.entropyMnemonicLength.on("change", entropyChanged);
@@ -102,6 +104,7 @@
hidePending();
hideValidationError();
populateNetworkSelect();
populateClientSelect();
}
// Event handlers
@@ -117,6 +120,23 @@
}
}
function bip32ClientChanged(e) {
var clientIndex = DOM.bip32Client.val();
if (clientIndex == "custom") {
DOM.bip32path.prop("readonly", false);
}
else {
DOM.bip32path.prop("readonly", true);
clients[clientIndex].onSelect();
if (seed != null) {
phraseChanged();
}
else {
rootKeyChanged();
}
}
}
function setEntropyVisibility() {
if (isUsingOwnEntropy()) {
DOM.entropyContainer.removeClass("hidden");
@@ -564,6 +584,20 @@
if (useHardenedAddresses) {
indexText = indexText + "'";
}
// Ethereum values are different
if (networks[DOM.network.val()].name == "Ethereum") {
var privKeyBuffer = key.privKey.d.toBuffer();
privkey = privKeyBuffer.toString('hex');
var addressBuffer = ethUtil.privateToAddress(privKeyBuffer);
var hexAddress = addressBuffer.toString('hex');
var checksumAddress = ethUtil.toChecksumAddress(hexAddress);
address = ethUtil.addHexPrefix(checksumAddress);
}
// Ripple values are different
if (networks[DOM.network.val()].name == "Ripple") {
privkey = convertRipplePriv(privkey);
address = convertRippleAdrr(address);
}
addAddressToList(indexText, address, pubkey, privkey);
}, 50)
}
@@ -702,6 +736,16 @@
}
}
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.bip32Client.append(option);
}
}
function getLanguage() {
var defaultLanguage = "english";
// Try to get from existing phrase
@@ -1047,10 +1091,10 @@
},
},
{
name: "Litecoin",
name: "CLAM",
onSelect: function() {
network = bitcoin.networks.litecoin;
DOM.bip44coin.val(2);
network = bitcoin.networks.clam;
DOM.bip44coin.val(23);
},
},
{
@@ -1060,6 +1104,62 @@
DOM.bip44coin.val(3);
},
},
{
name: "DASH",
onSelect: function() {
network = bitcoin.networks.dash;
DOM.bip44coin.val(5);
},
},
{
name: "Ethereum",
onSelect: function() {
network = bitcoin.networks.bitcoin;
DOM.bip44coin.val(60);
},
},
{
name: "GAME",
onSelect: function() {
network = bitcoin.networks.game;
DOM.bip44coin.val(101);
},
},
{
name: "Jumbucks",
onSelect: function() {
network = bitcoin.networks.jumbucks;
DOM.bip44coin.val(26);
},
},
{
name: "Litecoin",
onSelect: function() {
network = bitcoin.networks.litecoin;
DOM.bip44coin.val(2);
},
},
{
name: "Namecoin",
onSelect: function() {
network = bitcoin.networks.namecoin;
DOM.bip44coin.val(7);
},
},
{
name: "Peercoin",
onSelect: function() {
network = bitcoin.networks.peercoin;
DOM.bip44coin.val(6);
},
},
{
name: "Ripple",
onSelect: function() {
network = bitcoin.networks.bitcoin;
DOM.bip44coin.val(144);
},
},
{
name: "ShadowCash",
onSelect: function() {
@@ -1088,41 +1188,30 @@
DOM.bip44coin.val(1);
},
},
]
var clients = [
{
name: "Jumbucks",
name: "Bitcoin Core",
onSelect: function() {
network = bitcoin.networks.jumbucks;
DOM.bip44coin.val(26);
DOM.bip32path.val("m/0'/0'");
DOM.hardenedAddresses.prop('checked', true);
},
},
{
name: "CLAM",
name: "blockchain.info",
onSelect: function() {
network = bitcoin.networks.clam;
DOM.bip44coin.val(23);
DOM.bip32path.val("m/44'/0'/0'");
DOM.hardenedAddresses.prop('checked', false);
},
},
{
name: "DASH",
name: "MultiBit HD",
onSelect: function() {
network = bitcoin.networks.dash;
DOM.bip44coin.val(5);
DOM.bip32path.val("m/0'/0");
DOM.hardenedAddresses.prop('checked', false);
},
},
{
name: "Namecoin",
onSelect: function() {
network = bitcoin.networks.namecoin;
DOM.bip44coin.val(7);
},
},
{
name: "Peercoin",
onSelect: function() {
network = bitcoin.networks.peercoin;
DOM.bip44coin.val(6);
},
},
}
]
init();

View File

@@ -130,10 +130,11 @@ var Mnemonic = function(language) {
self.toSeed = function(mnemonic, passphrase) {
passphrase = passphrase || '';
mnemonic = self.joinWords(self.splitWords(self.normalizeString(mnemonic))); // removes blanks
mnemonic = self.joinWords(self.splitWords(mnemonic)); // removes duplicate blanks
var mnemonicNormalized = self.normalizeString(mnemonic);
passphrase = self.normalizeString(passphrase)
passphrase = "mnemonic" + passphrase;
var mnemonicBits = sjcl.codec.utf8String.toBits(mnemonic);
var mnemonicBits = sjcl.codec.utf8String.toBits(mnemonicNormalized);
var passphraseBits = sjcl.codec.utf8String.toBits(passphrase);
var result = sjcl.misc.pbkdf2(mnemonicBits, passphraseBits, PBKDF2_ROUNDS, 512, hmacSHA512);
var hashHex = sjcl.codec.hex.fromBits(result);

3793
src/js/polyfill.es6.js Normal file

File diff suppressed because it is too large Load Diff

10
src/js/ripple-util.js Normal file
View File

@@ -0,0 +1,10 @@
function convertRippleAdrr(address) {
return window.basex('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz').encode(
window.basex('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz').decode(address)
)
}
function convertRipplePriv(priv) {
return window.basex('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz').decode(priv).toString("hex").slice(2)
}

442
src/js/unorm.js Normal file

File diff suppressed because one or more lines are too long

321
tests.js
View File

@@ -4,7 +4,7 @@
var page = require('webpage').create();
var url = 'src/index.html';
var testMaxTime = 10000;
var testMaxTime = 20000;
page.viewportSize = {
width: 1024,
@@ -280,7 +280,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=1]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "Bitcoin Testnet";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -308,7 +310,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=2]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "Litecoin";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -336,7 +340,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=3]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "Dogecoin";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -364,7 +370,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=4]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "ShadowCash";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -392,7 +400,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=5]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "ShadowCash Testnet";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -420,7 +430,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=6]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "Viacoin";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -448,7 +460,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=7]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "Viacoin Testnet";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -476,7 +490,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=8]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "Jumbucks";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -504,7 +520,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=9]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "CLAM";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -532,7 +550,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=10]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "DASH";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -551,6 +571,36 @@ page.open(url, function(status) {
});
},
// Network can be set to game
function() {
page.open(url, function(status) {
// set the phrase and coin
var expected = "GSMY9bAp36cMR4zyT4uGVS7GFjpdXbao5Q";
page.evaluate(function() {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option").filter(function() {
return $(this).html() == "GAME";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
waitForGenerate(function() {
var actual = page.evaluate(function() {
return $(".address:first").text();
});
if (actual != expected) {
console.log("GAME address is incorrect");
console.log("Expected: " + expected);
console.log("Actual: " + actual);
fail();
}
next();
});
});
},
// Network can be set to namecoin
function() {
page.open(url, function(status) {
@@ -560,7 +610,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=11]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "Namecoin";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -588,7 +640,9 @@ page.open(url, function(status) {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option[value=12]").prop("selected", true);
$(".network option").filter(function() {
return $(this).html() == "Peercoin";
}).prop("selected", true);
$(".network").trigger("change");
});
// check the address is generated correctly
@@ -607,6 +661,68 @@ page.open(url, function(status) {
});
},
// Network can be set to ethereum
function() {
page.open(url, function(status) {
// set the phrase and coin
page.evaluate(function() {
$(".phrase").val("abandon abandon ability");
$(".phrase").trigger("input");
$(".network option[selected]").removeAttr("selected");
$(".network option").filter(function() {
return $(this).html() == "Ethereum";
}).prop("selected", true);
$(".network").trigger("change");
});
waitForGenerate(function() {
// check the address is generated correctly
// this value comes from
// https://www.myetherwallet.com/#view-wallet-info
// Unusual capitalization is due to checksum
var expected = "0xe5815d5902Ad612d49283DEdEc02100Bd44C2772";
var actual = page.evaluate(function() {
return $(".address:first").text();
});
if (actual != expected) {
console.log("Ethereum address is incorrect");
console.log("Expected: " + expected);
console.log("Actual: " + actual);
fail();
}
// check the private key is correct
// this private key can be imported into
// https://www.myetherwallet.com/#view-wallet-info
// and it should correlate to the address above
var expected = "8f253078b73d7498302bb78c171b23ce7a8fb511987d2b2702b731638a4a15e7";
var actual = page.evaluate(function() {
return $(".privkey:first").text();
});
if (actual != expected) {
console.log("Ethereum privkey is incorrect");
console.log("Expected: " + expected);
console.log("Actual: " + actual);
fail();
}
// check the public key is correct
// TODO
// don't have any third-party source to generate the expected value
//var expected = "?";
//var actual = page.evaluate(function() {
// return $(".pubkey:first").text();
//});
//if (actual != expected) {
// console.log("Ethereum privkey is incorrect");
// console.log("Expected: " + expected);
// console.log("Actual: " + actual);
// fail();
//}
next();
});
});
},
// BIP39 seed is set from phrase
function() {
page.open(url, function(status) {
@@ -1778,7 +1894,10 @@ page.open(url, function(status) {
waitForGenerate(function() {
// 4) switch from bitcoin to litecoin
page.evaluate(function() {
$(".network").val("2").trigger("change");
$(".network option").filter(function() {
return $(this).html() == "Litecoin";
}).prop("selected", true);
$(".network").trigger("change");
});
waitForGenerate(function() {
// 5) Check derivation path is displayed correctly
@@ -1821,7 +1940,10 @@ page.open(url, function(status) {
waitForGenerate(function() {
// switch from bitcoin to clam
page.evaluate(function() {
$(".network").val("9").trigger("change");
$(".network option").filter(function() {
return $(this).html() == "CLAM";
}).prop("selected", true);
$(".network").trigger("change");
});
waitForGenerate(function() {
// check derivation path is displayed correctly
@@ -1852,7 +1974,10 @@ page.open(url, function(status) {
waitForGenerate(function() {
// 4) switch from bitcoin to viacoin
page.evaluate(function() {
$(".network").val("6").trigger("change");
$(".network option").filter(function() {
return $(this).html() == "Viacoin";
}).prop("selected", true);
$(".network").trigger("change");
});
waitForGenerate(function() {
// 5) ensure the derived address is correct
@@ -2268,7 +2393,6 @@ page.open(url, function(status) {
// use entropy
page.evaluate(function() {
$(".use-entropy").prop("checked", true).trigger("change");
$(".mnemonic-length").val("raw");
$(".entropy").val("00000000 00000000 00000000 00000000").trigger("input");
});
// check the mnemonic is set and address is correct
@@ -2804,7 +2928,6 @@ page.open(url, function(status) {
// use entropy
page.evaluate(function() {
$(".use-entropy").prop("checked", true).trigger("change");
$(".mnemonic-length").val("raw");
});
var nextTest = function runNextTest(i) {
function getFeedbackError(expected, actual) {
@@ -2886,7 +3009,6 @@ page.open(url, function(status) {
// use entropy
page.evaluate(function() {
$(".use-entropy").prop("checked", true).trigger("change");
$(".mnemonic-length").val("raw");
var entropy = "00000000 00000000 00000000 00000000";
entropy += "11111111 11111111 11111111 1111"; // Missing last byte
$(".entropy").val(entropy).trigger("input");
@@ -2913,7 +3035,6 @@ page.open(url, function(status) {
// use entropy
page.evaluate(function() {
$(".use-entropy").prop("checked", true).trigger("change");
$(".mnemonic-length").val("raw");
var entropy = "";
// Generate a very long entropy string
for (var i=0; i<33; i++) {
@@ -2947,7 +3068,6 @@ page.open(url, function(status) {
// use entropy
page.evaluate(function() {
$(".use-entropy").prop("checked", true).trigger("change");
$(".mnemonic-length").val("raw");
var entropy = "543210543210543210543210543210543210543210543210543210543210543210543210543210543210543210543210543";
$(".entropy").val(entropy).trigger("input");
});
@@ -3039,7 +3159,6 @@ page.open(url, function(status) {
// use entropy
page.evaluate(function() {
$(".use-entropy").prop("checked", true).trigger("change");
$(".mnemonic-length").val("raw");
$(".entropy").val("7S 9H 9S QH 8C KS AS 7D 7C QD 4S 4D TC 2D 5S JS 3D 8S 8H 4C 3C AC 3S QC 9C JC 7H AD TD JD 6D KH 5C QS 2S 6S 6H JH KD 9D-6C TS TH 4H KC 5H 2H AH 2C 8D 3H 5D").trigger("input");
});
// get the mnemonic
@@ -3345,6 +3464,7 @@ page.open(url, function(status) {
// use entropy
page.evaluate(function() {
$(".use-entropy").prop("checked", true).trigger("change");
$(".mnemonic-length").val("15");
$(".entropy").val("1111").trigger("input");
});
waitForGenerate(function() {
@@ -3364,6 +3484,163 @@ page.open(url, function(status) {
});
},
// Github pull request 55
// https://github.com/iancoleman/bip39/pull/55
// Client select
function() {
page.open(url, function(status) {
// set mnemonic and select bip32 tab
page.evaluate(function() {
$("#bip32-tab a").click();
$(".phrase").val("abandon abandon ability").trigger("input");
});
waitForGenerate(function() {
// BITCOIN CORE
// set bip32 client to bitcoin core
page.evaluate(function() {
var bitcoinCoreIndex = "0";
$("#bip32-client").val(bitcoinCoreIndex).trigger("change");
});
waitForGenerate(function() {
// get the derivation path
var actual = page.evaluate(function() {
return $("#bip32-path").val();
});
// check the derivation path is correct
expected = "m/0'/0'"
if (actual != expected) {
console.log("Selecting Bitcoin Core client does not set correct derivation path");
console.log("Expected: " + expected);
console.log("Actual: " + actual);
fail();
}
// get hardened addresses
var usesHardenedAddresses = page.evaluate(function() {
return $(".hardened-addresses").prop("checked");
});
// check hardened addresses is selected
if(!usesHardenedAddresses) {
console.log("Selecting Bitcoin Core client does not use hardened addresses");
fail();
}
// check input is readonly
var pathIsReadonly = page.evaluate(function() {
return $("#bip32-path").prop("readonly");
});
if (!pathIsReadonly) {
console.log("Selecting Bitcoin Core client does not set derivation path to readonly");
fail();
}
// MULTIBIT
// set bip32 client to multibit
page.evaluate(function() {
var multibitIndex = "2";
$("#bip32-client").val(multibitIndex).trigger("change");
});
waitForGenerate(function() {
// get the derivation path
var actual = page.evaluate(function() {
return $("#bip32-path").val();
});
// check the derivation path is correct
expected = "m/0'/0"
if (actual != expected) {
console.log("Selecting Multibit client does not set correct derivation path");
console.log("Expected: " + expected);
console.log("Actual: " + actual);
fail();
}
// get hardened addresses
var usesHardenedAddresses = page.evaluate(function() {
return $(".hardened-addresses").prop("checked");
});
// check hardened addresses is selected
if(usesHardenedAddresses) {
console.log("Selecting Multibit client does not uncheck hardened addresses");
fail();
}
// CUSTOM DERIVATION PATH
// check input is not readonly
page.evaluate(function() {
$("#bip32-client").val("custom").trigger("change");
});
// do not wait for generate, since there is no change to the
// derivation path there is no new generation performed
var pathIsReadonly = page.evaluate(function() {
return $("#bip32-path").prop("readonly");
});
if (pathIsReadonly) {
console.log("Selecting Custom Derivation Path does not allow derivation path input");
fail();
}
next();
});
});
});
});
},
// github issue 58
// https://github.com/iancoleman/bip39/issues/58
// bip32 derivation is correct, does not drop leading zeros
// see also
// https://medium.com/@alexberegszaszi/why-do-my-bip32-wallets-disagree-6f3254cc5846
function() {
page.open(url, function(status) {
// set the phrase and passphrase
var expected = "17rxURoF96VhmkcEGCj5LNQkmN9HVhWb7F";
// Note that bitcore generates an incorrect address
// 13EuKhffWkBE2KUwcbkbELZb1MpzbimJ3Y
// see the medium.com link above for more details
page.evaluate(function() {
$(".phrase").val("fruit wave dwarf banana earth journey tattoo true farm silk olive fence");
$(".passphrase").val("banana").trigger("input");
});
// check the address is generated correctly
waitForGenerate(function() {
var actual = page.evaluate(function() {
return $(".address:first").text();
});
if (actual != expected) {
console.log("BIP32 derivation is incorrect");
console.log("Expected: " + expected);
console.log("Actual: " + actual);
fail();
}
next();
});
});
},
// github issue 60
// Japanese mnemonics generate incorrect bip32 seed
// BIP39 seed is set from phrase
function() {
page.open(url, function(status) {
// set the phrase
var expected = "a262d6fb6122ecf45be09c50492b31f92e9beb7d9a845987a02cefda57a15f9c467a17872029a9e92299b5cbdf306e3a0ee620245cbd508959b6cb7ca637bd55";
page.evaluate(function() {
$(".phrase").val("あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あおぞら");
$("#passphrase").val("メートルガバヴァぱばぐゞちぢ十人十色");
$("#passphrase").trigger("input");
});
// check the seed is generated correctly
waitForGenerate(function() {
var actual = page.evaluate(function() {
return $(".seed").val();
});
if (actual != expected) {
console.log("BIP39 seed is incorrectly generated from Japanese mnemonic");
console.log("Expected: " + expected);
console.log("Actual: " + actual);
fail();
}
next();
});
});
},
// If you wish to add more tests, do so here...
// Here is a blank test template