]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/BIP39.git/blame - tests/spec/tests.js
Merge pull request #317 from skironDotNet/Crown_new_address_format
[perso/Immae/Projets/Cryptomonnaies/BIP39.git] / tests / spec / tests.js
CommitLineData
0460b53f
IC
1// Usage:
2// cd /path/to/repo/tests
3// jasmine spec/tests.js
4//
5// Dependencies:
6// nodejs
7// selenium
8// jasmine
9// see https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode#Automated_testing_with_headless_mode
10
11// USER SPECIFIED OPTIONS
12var browser = process.env.BROWSER; //"firefox"; // or "chrome"
13if (!browser) {
14 console.log("Browser can be set via environment variable, eg");
15 console.log("BROWSER=firefox jasmine spec/tests.js");
16 console.log("Options for BROWSER are firefox chrome");
17 console.log("Using default browser: chrome");
18 browser = "chrome";
19}
20else {
21 console.log("Using browser: " + browser);
22}
23
24// Globals
25
26var webdriver = require('selenium-webdriver');
27var By = webdriver.By;
28var Key = webdriver.Key;
29var until = webdriver.until;
30var newDriver = null;
31var driver = null;
32// Delays in ms
9fae1ffb 33var generateDelay = 1500;
0460b53f
IC
34var feedbackDelay = 500;
35var entropyFeedbackDelay = 500;
e21e32da 36var bip38delay = 15000;
0460b53f
IC
37
38// url uses file:// scheme
39var path = require('path')
40var parentDir = path.resolve(process.cwd(), '..', 'src', 'index.html');
41var url = "file://" + parentDir;
42if (browser == "firefox") {
43 // TODO loading local html in firefox is broken
44 console.log("Loading local html in firefox is broken, see https://stackoverflow.com/q/46367054");
45 console.log("You must run a server in this case, ie do this:");
46 console.log("$ cd /path/to/bip39/src");
47 console.log("$ python -m http.server");
48 url = "http://localhost:8000";
49}
50
51// Variables dependent on specific browser selection
52
53if (browser == "firefox") {
54 var firefox = require('selenium-webdriver/firefox');
55 var binary = new firefox.Binary(firefox.Channel.NIGHTLY);
56 binary.addArguments("-headless");
57 newDriver = function() {
58 return new webdriver.Builder()
59 .forBrowser('firefox')
60 .setFirefoxOptions(new firefox.Options().setBinary(binary))
61 .build();
62 }
63}
64else if (browser == "chrome") {
65 var chrome = require('selenium-webdriver/chrome');
66 newDriver = function() {
67 return new webdriver.Builder()
68 .forBrowser('chrome')
69 .setChromeOptions(new chrome.Options().addArguments("headless"))
70 .build();
71 }
72}
73
74// Helper functions
75
76function testNetwork(done, params) {
77 var phrase = params.phrase || 'abandon abandon ability';
78 driver.findElement(By.css('.phrase'))
79 .sendKeys(phrase);
80 selectNetwork(params.selectText);
81 driver.sleep(generateDelay).then(function() {
82 getFirstAddress(function(address) {
83 expect(address).toBe(params.firstAddress);
84 done();
85 });
86 });
87}
88
89function getFirstRowValue(handler, selector) {
90 driver.findElements(By.css(selector))
91 .then(function(els) {
92 els[0].getText()
93 .then(handler);
94 })
95}
96
97function getFirstAddress(handler) {
98 getFirstRowValue(handler, ".address");
99}
100
101function getFirstPath(handler) {
102 getFirstRowValue(handler, ".index");
103}
104
105function testColumnValuesAreInvisible(done, columnClassName) {
106 var selector = "." + columnClassName + " span";
107 driver.findElements(By.css(selector))
108 .then(function(els) {
109 els[0].getAttribute("class")
110 .then(function(classes) {
111 expect(classes).toContain("invisible");
112 done();
113 });
114 })
115}
116
117function testRowsAreInCorrectOrder(done) {
118 driver.findElements(By.css('.index'))
119 .then(function(els) {
120 var testRowAtIndex = function(i) {
121 if (i >= els.length) {
122 done();
123 }
124 else {
125 els[i].getText()
126 .then(function(actualPath) {
127 var noHardened = actualPath.replace(/'/g, "");
128 var pathBits = noHardened.split("/")
129 var lastBit = pathBits[pathBits.length-1];
130 var actualIndex = parseInt(lastBit);
131 expect(actualIndex).toBe(i);
132 testRowAtIndex(i+1);
133 });
134 }
135 }
136 testRowAtIndex(0);
137 });
138}
139
140function selectNetwork(name) {
141 driver.executeScript(function() {
142 var selectText = arguments[0];
143 $(".network option[selected]").removeAttr("selected");
144 $(".network option").filter(function(i,e) {
145 return $(e).html() == selectText;
146 }).prop("selected", true);
147 $(".network").trigger("change");
148 }, name);
149}
150
151function testEntropyType(done, entropyText, entropyTypeUnsafe) {
152 // entropy type is compiled into regexp so needs escaping
153 // see https://stackoverflow.com/a/2593661
154 var entropyType = (entropyTypeUnsafe+'').replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&");
155 driver.findElement(By.css('.use-entropy'))
156 .click();
157 driver.findElement(By.css('.entropy'))
158 .sendKeys(entropyText);
159 driver.sleep(generateDelay).then(function() {
160 driver.findElement(By.css('.entropy-container'))
161 .getText()
162 .then(function(text) {
163 var re = new RegExp("Entropy Type\\s+" + entropyType);
164 expect(text).toMatch(re);
165 done();
166 });
167 });
168}
169
170function testEntropyBits(done, entropyText, entropyBits) {
171 driver.findElement(By.css('.use-entropy'))
172 .click();
173 driver.findElement(By.css('.entropy'))
174 .sendKeys(entropyText);
175 driver.sleep(generateDelay).then(function() {
176 driver.findElement(By.css('.entropy-container'))
177 .getText()
178 .then(function(text) {
179 var re = new RegExp("Total Bits\\s+" + entropyBits);
180 expect(text).toMatch(re);
181 done();
182 });
183 });
184}
185
186function testEntropyFeedback(done, entropyDetail) {
187 // entropy type is compiled into regexp so needs escaping
188 // see https://stackoverflow.com/a/2593661
189 if ("type" in entropyDetail) {
190 entropyDetail.type = (entropyDetail.type+'').replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&");
191 }
192 driver.findElement(By.css('.use-entropy'))
193 .click();
194 driver.findElement(By.css('.entropy'))
195 .sendKeys(entropyDetail.entropy);
196 driver.sleep(entropyFeedbackDelay).then(function() {
197 driver.findElement(By.css('.entropy-container'))
198 .getText()
199 .then(function(text) {
200 driver.findElement(By.css('.phrase'))
201 .getAttribute("value")
202 .then(function(phrase) {
203 if ("filtered" in entropyDetail) {
204 var key = "Filtered Entropy";
205 var value = entropyDetail.filtered;
206 var reText = key + "\\s+" + value;
207 var re = new RegExp(reText);
208 expect(text).toMatch(re);
209 }
210 if ("type" in entropyDetail) {
211 var key = "Entropy Type";
212 var value = entropyDetail.type;
213 var reText = key + "\\s+" + value;
214 var re = new RegExp(reText);
215 expect(text).toMatch(re);
216 }
217 if ("events" in entropyDetail) {
218 var key = "Event Count";
219 var value = entropyDetail.events;
220 var reText = key + "\\s+" + value;
221 var re = new RegExp(reText);
222 expect(text).toMatch(re);
223 }
224 if ("bits" in entropyDetail) {
225 var key = "Total Bits";
226 var value = entropyDetail.bits;
227 var reText = key + "\\s+" + value;
228 var re = new RegExp(reText);
229 expect(text).toMatch(re);
230 }
231 if ("bitsPerEvent" in entropyDetail) {
232 var key = "Bits Per Event";
233 var value = entropyDetail.bitsPerEvent;
234 var reText = key + "\\s+" + value;
235 var re = new RegExp(reText);
236 expect(text).toMatch(re);
237 }
238 if ("words" in entropyDetail) {
239 var actualWords = phrase.split(/\s+/)
240 .filter(function(w) { return w.length > 0 })
241 .length;
242 expect(actualWords).toBe(entropyDetail.words);
243 }
244 if ("strength" in entropyDetail) {
245 var key = "Time To Crack";
246 var value = entropyDetail.strength;
247 var reText = key + "\\s+" + value;
248 var re = new RegExp(reText);
249 expect(text).toMatch(re);
250 }
251 done();
252 });
253 });
254 });
255}
256
257function testClientSelect(done, params) {
258 // set mnemonic and select bip32 tab
259 driver.findElement(By.css('#bip32-tab a'))
260 .click()
261 driver.findElement(By.css('.phrase'))
262 .sendKeys("abandon abandon ability");
263 driver.sleep(generateDelay).then(function() {
264 // BITCOIN CORE
265 // set bip32 client to bitcoin core
266 driver.executeScript(function() {
267 $("#bip32-client").val(arguments[0]).trigger("change");
268 }, params.selectValue);
269 driver.sleep(generateDelay).then(function() {
270 // check the derivation path is correct
271 driver.findElement(By.css("#bip32-path"))
272 .getAttribute("value")
273 .then(function(path) {
274 expect(path).toBe(params.bip32path);
275 // check hardened addresses is selected
276 driver.findElement(By.css(".hardened-addresses"))
277 .getAttribute("checked")
278 .then(function(isChecked) {
279 expect(isChecked).toBe(params.useHardenedAddresses);
280 // check input is readonly
281 driver.findElement(By.css("#bip32-path"))
282 .getAttribute("readonly")
283 .then(function(isReadonly) {
284 expect(isReadonly).toBe("true");
285 done();
286 });
287 });
288 });
289 });
290 });
291}
292
293// Tests
294
295describe('BIP39 Tool Tests', function() {
296
297 beforeEach(function(done) {
298 driver = newDriver();
d2f5d28e 299 driver.get(url).then(done);
0460b53f
IC
300 });
301
302 // Close the website after each test is run (so that it is opened fresh each time)
303 afterEach(function(done) {
304 driver.quit().then(done);
305 });
306
307// BEGIN TESTS
308
309// Page initially loads with blank phrase
310it('Should load the page', function(done) {
311 driver.findElement(By.css('.phrase'))
312 .getAttribute('value').then(function(value) {
313 expect(value).toBe('');
314 done();
315 });
316});
317
318// Page has text
319it('Should have text on the page', function(done) {
320 driver.findElement(By.css('body'))
321 .getText()
322 .then(function(text) {
323 var textToFind = "You can enter an existing BIP39 mnemonic";
324 expect(text).toContain(textToFind);
325 done();
326 });
327});
328
329// Entering mnemonic generates addresses
330it('Should have a list of addresses', function(done) {
331 driver.findElement(By.css('.phrase'))
332 .sendKeys('abandon abandon ability');
333 driver.sleep(generateDelay).then(function() {
334 driver.findElements(By.css('.address'))
335 .then(function(els) {
336 expect(els.length).toBe(20);
337 done();
338 })
339 });
340});
341
342// Generate button generates random mnemonic
343it('Should be able to generate a random mnemonic', function(done) {
344 // initial phrase is blank
345 driver.findElement(By.css('.phrase'))
346 .getAttribute("value")
347 .then(function(phrase) {
348 expect(phrase.length).toBe(0);
349 // press generate
350 driver.findElement(By.css('.generate')).click();
351 driver.sleep(generateDelay).then(function() {
352 // new phrase is not blank
353 driver.findElement(By.css('.phrase'))
354 .getAttribute("value")
355 .then(function(phrase) {
356 expect(phrase.length).toBeGreaterThan(0);
357 done();
358 });
359 });
360 });
361});
362
363// Mnemonic length can be customized
364it('Should allow custom length mnemonics', function(done) {
365 // set strength to 6
366 driver.executeScript(function() {
367 $(".strength option[selected]").removeAttr("selected");
368 $(".strength option[value=6]").prop("selected", true);
369 });
370 driver.findElement(By.css('.generate')).click();
371 driver.sleep(generateDelay).then(function() {
372 driver.findElement(By.css('.phrase'))
373 .getAttribute("value")
374 .then(function(phrase) {
375 var words = phrase.split(" ");
376 expect(words.length).toBe(6);
377 done();
378 });
379 });
380});
381
382// Passphrase can be set
383it('Allows a passphrase to be set', function(done) {
384 driver.findElement(By.css('.phrase'))
385 .sendKeys('abandon abandon ability');
386 driver.findElement(By.css('.passphrase'))
387 .sendKeys('secure_passphrase');
388 driver.sleep(generateDelay).then(function() {
389 getFirstAddress(function(address) {
390 expect(address).toBe("15pJzUWPGzR7avffV9nY5by4PSgSKG9rba");
391 done();
392 })
393 });
394});
395
396// Network can be set to networks other than bitcoin
397it('Allows selection of bitcoin testnet', function(done) {
398 var params = {
399 selectText: "BTC - Bitcoin Testnet",
400 firstAddress: "mucaU5iiDaJDb69BHLeDv8JFfGiyg2nJKi",
401 };
402 testNetwork(done, params);
403});
404it('Allows selection of litecoin', function(done) {
405 var params = {
406 selectText: "LTC - Litecoin",
407 firstAddress: "LQ4XU8RX2ULPmPq9FcUHdVmPVchP9nwXdn",
408 };
409 testNetwork(done, params);
410});
411it('Allows selection of ripple', function(done) {
412 var params = {
413 selectText: "XRP - Ripple",
414 firstAddress: "rLTFnqbmCVPGx6VfaygdtuKWJgcN4v1zRS",
415 phrase: "ill clump only blind unit burden thing track silver cloth review awake useful craft whale all satisfy else trophy sunset walk vanish hope valve",
416 };
417 testNetwork(done, params);
418});
419it('Allows selection of dogecoin', function(done) {
420 var params = {
421 selectText: "DOGE - Dogecoin",
422 firstAddress: "DPQH2AtuzkVSG6ovjKk4jbUmZ6iXLpgbJA",
423 };
424 testNetwork(done, params);
425});
40209fd8 426it('Allows selection of denarius', function(done) {
427 var params = {
428 selectText: "DNR - Denarius",
50289881 429 firstAddress: "DFdFMVUMzU9xX88EywXvAGwjiwpxyh9vKb",
40209fd8 430 };
431 testNetwork(done, params);
432});
0460b53f
IC
433it('Allows selection of shadowcash', function(done) {
434 var params = {
435 selectText: "SDC - ShadowCash",
436 firstAddress: "SiSZtfYAXEFvMm3XM8hmtkGDyViRwErtCG",
437 };
438 testNetwork(done, params);
439});
440it('Allows selection of shadowcash testnet', function(done) {
441 var params = {
442 selectText: "SDC - ShadowCash Testnet",
443 firstAddress: "tM2EDpVKaTiEg2NZg3yKg8eqjLr55BErHe",
444 };
445 testNetwork(done, params);
446});
447it('Allows selection of viacoin', function(done) {
448 var params = {
449 selectText: "VIA - Viacoin",
450 firstAddress: "Vq9Eq4N5SQnjqZvxtxzo7hZPW5XnyJsmXT",
451 };
452 testNetwork(done, params);
453});
454it('Allows selection of viacoin testnet', function(done) {
455 var params = {
456 selectText: "VIA - Viacoin Testnet",
457 firstAddress: "tM2EDpVKaTiEg2NZg3yKg8eqjLr55BErHe",
458 };
459 testNetwork(done, params);
460});
461it('Allows selection of jumbucks', function(done) {
462 var params = {
463 selectText: "JBS - Jumbucks",
464 firstAddress: "JLEXccwDXADK4RxBPkRez7mqsHVoJBEUew",
465 };
466 testNetwork(done, params);
467});
468it('Allows selection of clam', function(done) {
469 var params = {
470 selectText: "CLAM - Clams",
471 firstAddress: "xCp4sakjVx4pUAZ6cBCtuin8Ddb6U1sk9y",
472 };
473 testNetwork(done, params);
474});
bf13c95f
PC
475it('Allows selection of crown', function(done) {
476 var params = {
477 selectText: "CRW - Crown (Legacy)",
478 firstAddress: "18pWSwSUAQdiwMHUfFZB1fM2xue9X1FqE5",
479 };
480 testNetwork(done, params);
481});
0460b53f
IC
482it('Allows selection of crown', function(done) {
483 var params = {
484 selectText: "CRW - Crown",
bf13c95f 485 firstAddress: "CRWKnVmVhvH1KWTYe6sq8xV4dFGcFpBEEkPQ",
0460b53f
IC
486 };
487 testNetwork(done, params);
488});
489it('Allows selection of dash', function(done) {
490 var params = {
491 selectText: "DASH - Dash",
492 firstAddress: "XdbhtMuGsPSkE6bPdNTHoFSszQKmK4S5LT",
493 };
494 testNetwork(done, params);
495});
496it('Allows selection of dash testnet', function(done) {
497 var params = {
498 selectText: "DASH - Dash Testnet",
499 firstAddress: "yaR52EN4oojdJfBgzWJTymC4uuCLPT29Gw",
500 };
501 testNetwork(done, params);
502});
503it('Allows selection of game', function(done) {
504 var params = {
505 selectText: "GAME - GameCredits",
506 firstAddress: "GSMY9bAp36cMR4zyT4uGVS7GFjpdXbao5Q",
507 };
508 testNetwork(done, params);
509});
91eb2cbc 510it('Allows selection of komodo', function(done) {
aab3645f 511 var params = {
512 selectText: "KMD - Komodo",
5c1003dd 513 firstAddress: "RMPPzJwAjPVZZAwJvXivHJGGjdCx6WBD2t",
aab3645f 514 };
515 testNetwork(done, params);
516});
0460b53f
IC
517it('Allows selection of namecoin', function(done) {
518 var params = {
519 selectText: "NMC - Namecoin",
520 firstAddress: "Mw2vK2Bvex1yYtYF6sfbEg2YGoUc98YUD2",
521 };
522 testNetwork(done, params);
523});
c51bb4f9
IC
524it('Allows selection of onixcoin', function(done) {
525 var params = {
526 selectText: "ONX - Onixcoin",
527 firstAddress: "XGwMqddeKjT3ddgX73QokjVbCL3aK6Yxfk",
528 };
529 testNetwork(done, params);
530});
ae27549b
JLEP
531it('Allows selection of lkrcoin', function(done) {
532 var params = {
533 selectText: "LKR - Lkrcoin",
534 firstAddress: "LfbT296e7AEEnn4bYDbL535Nd8P9g98CdJ",
535 };
536 testNetwork(done, params);
537});
0460b53f
IC
538it('Allows selection of peercoin', function(done) {
539 var params = {
540 selectText: "PPC - Peercoin",
541 firstAddress: "PVAiioTaK2eDHSEo3tppT9AVdBYqxRTBAm",
542 };
543 testNetwork(done, params);
544});
545it('Allows selection of ethereum', function(done) {
546 var params = {
547 selectText: "ETH - Ethereum",
548 firstAddress: "0xe5815d5902Ad612d49283DEdEc02100Bd44C2772",
549 };
550 testNetwork(done, params);
551 // TODO test private key and public key
552});
553it('Allows selection of slimcoin', function(done) {
554 var params = {
555 selectText: "SLM - Slimcoin",
556 firstAddress: "SNzPi1CafHFm3WWjRo43aMgiaEEj3ogjww",
557 };
558 testNetwork(done, params);
559});
560it('Allows selection of slimcoin testnet', function(done) {
561 var params = {
562 selectText: "SLM - Slimcoin Testnet",
563 firstAddress: "n3nMgWufTek5QQAr6uwMhg5xbzj8xqc4Dq",
564 };
565 testNetwork(done, params);
566});
567it('Allows selection of bitcoin cash', function(done) {
568 var params = {
569 selectText: "BCH - Bitcoin Cash",
e0f91e20 570 firstAddress: "bitcoincash:qzlquk7w4hkudxypl4fgv8x279r754dkvur7jpcsps",
0460b53f
IC
571 };
572 testNetwork(done, params);
573});
d0889ab9 574
575it('Allows selection of simpleledger(SLP)', function(done) {
576 var params = {
577 selectText: "SLP - Simple Ledger Protocol",
578 firstAddress: "simpleledger:qrtffz6ajfsn74gpur7y3epjquz42pvww5acewqmre",
579 };
580 testNetwork(done, params);
581});
582
0460b53f
IC
583it('Allows selection of myriadcoin', function(done) {
584 var params = {
585 selectText: "XMY - Myriadcoin",
586 firstAddress: "MJEswvRR46wh9BoiVj9DzKYMBkCramhoBV",
587 };
588 testNetwork(done, params);
589});
590it('Allows selection of pivx', function(done) {
591 var params = {
592 selectText: "PIVX - PIVX",
593 firstAddress: "DBxgT7faCuno7jmtKuu6KWCiwqsVPqh1tS",
594 };
595 testNetwork(done, params);
596});
597it('Allows selection of pivx testnet', function(done) {
598 var params = {
599 selectText: "PIVX - PIVX Testnet",
600 firstAddress: "yB5U384n6dGkVE3by5y9VdvHHPwPg68fQj",
601 };
602 testNetwork(done, params);
603});
604it('Allows selection of maza', function(done) {
605 var params = {
606 selectText: "MAZA - Maza",
607 firstAddress: "MGW4Bmi2NEm4PxSjgeFwhP9vg18JHoRnfw",
608 };
609 testNetwork(done, params);
610});
611it('Allows selection of fujicoin', function(done) {
612 var params = {
613 selectText: "FJC - Fujicoin",
614 firstAddress: "FgiaLpG7C99DyR4WnPxXedRVHXSfKzUDhF",
615 };
616 testNetwork(done, params);
617});
618it('Allows selection of nubits', function(done) {
619 var params = {
620 selectText: "USNBT - NuBits",
621 firstAddress: "BLxkabXuZSJSdesLD7KxZdqovd4YwyBTU6",
622 };
623 testNetwork(done, params);
624});
1f354b03
IC
625it('Allows selection of bitcoin gold', function(done) {
626 var params = {
627 selectText: "BTG - Bitcoin Gold",
88ae1301 628 firstAddress: "GdDqug4WUsn5syNbSTHatNn4XnuwZtzedx",
1f354b03
IC
629 };
630 testNetwork(done, params);
631});
5a10834a
IC
632it('Allows selection of monacoin', function(done) {
633 var params = {
634 selectText: "MONA - Monacoin",
635 firstAddress: "MKMiMr7MyjDKjJbCBzgF6u4ByqTS4NkRB1",
636 };
637 testNetwork(done, params);
638});
423fb969
IC
639it('Allows selection of AXE', function(done) {
640 var params = {
641 selectText: "AXE - Axe",
2ab3faf4 642 firstAddress: "PScwtLUyPiGrqtKXrHF37DGETLXLZdw4up",
423fb969
IC
643 };
644 testNetwork(done, params);
645});
048721a6
IC
646it('Allows selection of BlackCoin', function(done) {
647 var params = {
648 selectText: "BLK - BlackCoin",
649 firstAddress: "B5MznAKwj7uQ42vDz3w4onhBXPcqhTwJ9z",
650 };
651 testNetwork(done, params);
652});
e5167afe
IC
653it('Allows selection of Neblio', function(done) {
654 var params = {
655 selectText: "NEBL - Neblio",
656 firstAddress: "NefkeEEvhusbHMmTRrxx7H9wFnUXd8qQsE",
657 };
658 testNetwork(done, params);
659});
680b94c1
IC
660it('Allows selection of Beetlecoin', function(done) {
661 var params = {
662 selectText: "BEET - Beetlecoin",
663 firstAddress: "BVmtbEsGrjpknprmpHFq26z4kYHJUFHE71",
664 };
665 testNetwork(done, params);
666});
85f762c9 667it('Allows selection of Adcoin', function(done) {
668 var params = {
669 selectText: "ACC - Adcoin",
670 firstAddress: "AcEDM6V5sF4kFHC76MJjjfProtS5Sw2qcd",
671 };
672 testNetwork(done, params);
673});
674it('Allows selection of Asiacoin', function(done) {
675 var params = {
676 selectText: "AC - Asiacoin",
677 firstAddress: "ALupuEEz7kJjQTAvmtcBMBVuEjPa7GqZzE",
678 };
679 testNetwork(done, params);
680});
681it('Allows selection of Auroracoin', function(done) {
682 var params = {
683 selectText: "AUR - Auroracoin",
684 firstAddress: "ANuraS6F4Jpi413FEnavjYkKYJJRHkgYCm",
685 };
686 testNetwork(done, params);
687});
688it('Allows selection of Bata', function(done) {
689 var params = {
690 selectText: "BTA - Bata",
691 firstAddress: "BGxBdNeYPtF3GCuTtZBPQdFxCkdBYSF3fj",
692 };
693 testNetwork(done, params);
694});
695it('Allows selection of Belacoin', function(done) {
696 var params = {
697 selectText: "BELA - Belacoin",
698 firstAddress: "BEeetqpNffdzeknSpNmQp5KAFh2KK1Qx7S",
699 };
700 testNetwork(done, params);
701});
702it('Allows selection of Bitcoin Atom', function(done) {
703 var params = {
704 selectText: "BCA - Bitcoin Atom",
705 firstAddress: "AMy6qMbJeC4zsGRL6iWszmeCdQH65fgfih",
706 };
707 testNetwork(done, params);
708});
709it('Allows selection of Bitcoinplus', function(done) {
710 var params = {
711 selectText: "XBC - Bitcoinplus",
712 firstAddress: "B7FSynZoDbEwTCSgsXq9nJ5ue8owYLVL8r",
713 };
714 testNetwork(done, params);
715});
1e2cc748 716it('Allows selection of Bitcoin Private', function(done) {
717 var params = {
718 selectText: "BTCP - Bitcoin Private",
719 firstAddress: "b1M3PbiXXyN6Hdivdw5rJv5VKpLjPzhm4jM",
720 };
721 testNetwork(done, params);
722});
723it('Allows selection of Bitcoinz', function(done) {
724 var params = {
725 selectText: "BTCZ - Bitcoinz",
726 firstAddress: "t1X2YQoxs8cYRo2oaBYgVEwW5QNjCC59NYc",
727 };
728 testNetwork(done, params);
729});
5ed5f661
D
730it('Allows selection of BitCloud', function(done) {
731 var params = {
732 selectText: "BTDX - BitCloud",
33816040 733 firstAddress: "BHbWitXCNgTf1BhsRDNMP186EeibuzmrBi",
5ed5f661
D
734 };
735 testNetwork(done, params);
736});
85f762c9 737it('Allows selection of Bitcore', function(done) {
738 var params = {
739 selectText: "BTX - Bitcore",
b7de1f3d 740 firstAddress: "2Rgp5Znhpy34TK4QmPkfCiYs9r4KovfTH9",
85f762c9 741 };
742 testNetwork(done, params);
743});
744it('Allows selection of Bitsend', function(done) {
745 var params = {
746 selectText: "BSD - Bitsend",
747 firstAddress: "iBPk7LYjDun3EPk7CRR8UUmnPoceVc1bp2",
748 };
749 testNetwork(done, params);
750});
751it('Allows selection of Britcoin', function(done) {
752 var params = {
753 selectText: "BRIT - Britcoin",
754 firstAddress: "B6Aue4J2XLs1f1dtD4H1SHYFfh4XrmEbrw",
755 };
756 testNetwork(done, params);
757});
758it('Allows selection of Canadaecoin', function(done) {
759 var params = {
760 selectText: "CDN - Canadaecoin",
761 firstAddress: "CanAyCfd5Rj2CQVfaoAmvDUZunPM5W1AEQ",
762 };
763 testNetwork(done, params);
764});
765it('Allows selection of Cannacoin', function(done) {
766 var params = {
767 selectText: "CCN - Cannacoin",
768 firstAddress: "CYjW8xWB43g6krLJTmmrPk1PonoQX7h9Qd",
769 };
770 testNetwork(done, params);
771});
772it('Allows selection of Clubcoin', function(done) {
773 var params = {
774 selectText: "CLUB - Clubcoin",
775 firstAddress: "CHMDEXN4sihpSVX4GyAa2hZ62shnby7uyN",
776 };
777 testNetwork(done, params);
778});
779it('Allows selection of Compcoin', function(done) {
780 var params = {
781 selectText: "CMP - Compcoin",
782 firstAddress: "CLshtw3zhxkseBJS46UF12v3AFy9Dx7JVv",
783 };
784 testNetwork(done, params);
785});
786it('Allows selection of Crave', function(done) {
787 var params = {
788 selectText: "CRAVE - Crave",
789 firstAddress: "VCYJeti6uKMNBFKCL7eP96UwuFWYHM7c85",
790 };
791 testNetwork(done, params);
792});
793it('Allows selection of Defcoin', function(done) {
794 var params = {
795 selectText: "DFC - Defcoin",
796 firstAddress: "D8swcgyaaFUrXZU3ATwbgy16buCpWqbG1M",
797 };
798 testNetwork(done, params);
799});
800it('Allows selection of Diamond', function(done) {
801 var params = {
802 selectText: "DMD - Diamond",
803 firstAddress: "dJnrVbLL9UPjdaVRz2C8VpqHZknqAqjLek",
804 };
805 testNetwork(done, params);
806});
807it('Allows selection of Digibyte', function(done) {
808 var params = {
809 selectText: "DGB - Digibyte",
810 firstAddress: "D85Rp9jwLtMdmP6wGjTiqHBdVQLST3YCEq",
811 };
812 testNetwork(done, params);
813});
814it('Allows selection of Digitalcoin', function(done) {
815 var params = {
816 selectText: "DGC - Digitalcoin",
817 firstAddress: "DKw4UGKEAZWweDNEbBFNQx4EM8x1mpUdia",
818 };
819 testNetwork(done, params);
820});
821it('Allows selection of Ecoin', function(done) {
822 var params = {
823 selectText: "ECN - Ecoin",
824 firstAddress: "e6WFPLG5gcXyF7cESFteH1hE2XSmowW5yB",
825 };
826 testNetwork(done, params);
827});
828it('Allows selection of Edrcoin', function(done) {
829 var params = {
830 selectText: "EDRC - Edrcoin",
831 firstAddress: "eh1nUJsvgKPFv6ebMBfcwJ299GMCpjeZUG",
832 };
833 testNetwork(done, params);
834});
835it('Allows selection of Egulden', function(done) {
836 var params = {
837 selectText: "EFL - Egulden",
838 firstAddress: "Lg66yt55R7edRM58cDhKzXik2kFme3viX7",
839 };
840 testNetwork(done, params);
841});
842it('Allows selection of Einsteinium', function(done) {
843 var params = {
844 selectText: "EMC2 - Einsteinium",
845 firstAddress: "EVAABm9hXKHk2MpVMbwNakRubFnNha5m8m",
846 };
847 testNetwork(done, params);
848});
849it('Allows selection of Europecoin', function(done) {
850 var params = {
851 selectText: "ERC - Europecoin",
852 firstAddress: "ESA2YwPYntAoaPrE8Fm5qkKRtkcwLcwD6R",
853 };
854 testNetwork(done, params);
855});
856it('Allows selection of Exclusivecoin', function(done) {
857 var params = {
858 selectText: "EXCL - Exclusivecoin",
859 firstAddress: "EbUa6m8UZW6nTxsYZD2FsDjkadKbp5M6JT",
860 };
861 testNetwork(done, params);
862});
863it('Allows selection of Feathercoin', function(done) {
864 var params = {
865 selectText: "FTC - Feathercoin",
866 firstAddress: "6gDdjAMoSgQaW8UhqK3oboHs6ftGAroKkM",
867 };
868 testNetwork(done, params);
869});
870it('Allows selection of Firstcoin', function(done) {
871 var params = {
872 selectText: "FRST - Firstcoin",
873 firstAddress: "FJN9GzfMm7Q8R4DJwK1H9F6A1GTghvFiMJ",
874 };
875 testNetwork(done, params);
876});
877it('Allows selection of Flashcoin', function(done) {
878 var params = {
879 selectText: "FLASH - Flashcoin",
880 firstAddress: "UWfpf5LfMmLxZYooEb2EyvWhZ8NG7EZDRt",
881 };
882 testNetwork(done, params);
883});
884it('Allows selection of GCRCoin', function(done) {
885 var params = {
886 selectText: "GCR - GCRCoin",
887 firstAddress: "GJjF5cLwyXLacpuvXAVksxGxKvHDjx58d6",
888 };
889 testNetwork(done, params);
890});
891it('Allows selection of Gobyte', function(done) {
892 var params = {
893 selectText: "GBX - Gobyte",
894 firstAddress: "GS813Ys2brkmvSUw1rUqGPm2HqQVDHJRyA",
895 };
896 testNetwork(done, params);
897});
898it('Allows selection of Gridcoin', function(done) {
899 var params = {
900 selectText: "GRC - Gridcoin",
901 firstAddress: "SGrWbBPvobgqKRF8td1Kdc9vbRY7MJ78Y9",
902 };
903 testNetwork(done, params);
904});
905it('Allows selection of Gulden', function(done) {
906 var params = {
907 selectText: "NLG - Gulden",
908 firstAddress: "GcDP7cNEc33MPPdTFNJ8pZc6VMZJ2CbKxY",
909 };
910 testNetwork(done, params);
911});
912it('Allows selection of Helleniccoin', function(done) {
913 var params = {
914 selectText: "HNC - Helleniccoin",
915 firstAddress: "LbHEKe5H72zp9G1fuWNiiNePTUfJb88915",
916 };
917 testNetwork(done, params);
918});
919it('Allows selection of Hempcoin', function(done) {
920 var params = {
921 selectText: "THC - Hempcoin",
922 firstAddress: "H8sdWbZyJV4gyXyHtLXDaNnAuUDhK5mfTV",
923 };
924 testNetwork(done, params);
925});
926it('Allows selection of Insane', function(done) {
927 var params = {
928 selectText: "INSN - Insane",
929 firstAddress: "iMPqEJMiXWuxC9U2NVinCCMr4t72h58EWx",
930 };
931 testNetwork(done, params);
932});
933it('Allows selection of Iop', function(done) {
934 var params = {
935 selectText: "IOP - Iop",
936 firstAddress: "pGKQmcaPf95Ur5o6oHK4qdiZ52p1yaTvq1",
937 };
938 testNetwork(done, params);
939});
940it('Allows selection of Ixcoin', function(done) {
941 var params = {
942 selectText: "IXC - Ixcoin",
943 firstAddress: "xgE9bTZ6YypT3E6ByzkTt31Hq68E9BqywH",
944 };
945 testNetwork(done, params);
946});
0a5d28a7 947it('Allows selection of Kobocoin', function(done) {
948 var params = {
949 selectText: "KOBO - Kobocoin",
950 firstAddress: "FTVoNJETXDAM8x7MnmdE8RwWndSr9PQWhy",
951 };
952 testNetwork(done, params);
953});
85f762c9 954it('Allows selection of Landcoin', function(done) {
955 var params = {
956 selectText: "LDCN - Landcoin",
957 firstAddress: "LLvLwNjG1aJcn1RS4W4GJUbv8fNaRATG7c",
958 };
959 testNetwork(done, params);
960});
961it('Allows selection of Library Credits', function(done) {
962 var params = {
963 selectText: "LBC - Library Credits",
964 firstAddress: "bQJEQrHDJyHdqycB32uysh1SWn8Ln8LMdg",
965 };
966 testNetwork(done, params);
967});
968it('Allows selection of Linx', function(done) {
969 var params = {
970 selectText: "LINX - Linx",
971 firstAddress: "XGWQ3cb3LGUB3VnHmj6xYSMgnokNbf6dyk",
972 };
973 testNetwork(done, params);
974});
975it('Allows selection of Litecoincash', function(done) {
976 var params = {
977 selectText: "LCC - Litecoincash",
978 firstAddress: "Ce5n7fjUuQPLutJ4W5nCCfQLKdKLE1mv9A",
979 };
980 testNetwork(done, params);
981});
982it('Allows selection of Lynx', function(done) {
983 var params = {
984 selectText: "LYNX - Lynx",
985 firstAddress: "KUeY3ZdZkg96p4W98pj1JjygCFU1XqWdw3",
986 };
987 testNetwork(done, params);
988});
5ed5f661
D
989it('Allows selection of Megacoin', function(done) {
990 var params = {
991 selectText: "MEC - Megacoin",
33816040 992 firstAddress: "MDfAj9CzkC1HpcUiVGnHp8yKTa7WXgu8AY",
5ed5f661
D
993 };
994 testNetwork(done, params);
995});
85f762c9 996it('Allows selection of Minexcoin', function(done) {
997 var params = {
998 selectText: "MNX - Minexcoin",
999 firstAddress: "XC1VnyJVfiMDwWgFtAHDp41cgY3AHk3dJT",
1000 };
1001 testNetwork(done, params);
1002});
1003it('Allows selection of Navcoin', function(done) {
1004 var params = {
1005 selectText: "NAV - Navcoin",
1006 firstAddress: "NTQVTPK3NWSQLKoffkiQw99T8PifkF1Y2U",
1007 };
1008 testNetwork(done, params);
1009});
491948db 1010it('Allows selection of Nebulas', function(done) {
1011 var params = {
1012 selectText: "NAS - Nebulas",
1013 firstAddress: "n1PbK61DGBfDoDusLw621G6sVSMfLLHdfnm",
1014 };
1015 testNetwork(done, params);
1016});
85f762c9 1017it('Allows selection of Neoscoin', function(done) {
1018 var params = {
1019 selectText: "NEOS - Neoscoin",
1020 firstAddress: "NgATz6QbQNXvayHQ4CpZayugb9HeaPDdby",
1021 };
1022 testNetwork(done, params);
1023});
10980ed6 1024it('Allows selection of Nix', function(done) {
1025 var params = {
1026 selectText: "NIX - NIX Platform",
1027 firstAddress: "GgcNW2SQQXB4LWHRQTHKkQF3GzXNSLqS8u",
1028 };
1029 testNetwork(done, params);
1030});
85f762c9 1031it('Allows selection of Neurocoin', function(done) {
1032 var params = {
1033 selectText: "NRO - Neurocoin",
1034 firstAddress: "NVdYErQ3mFpDuF5DquW9WMiT7sLc8ufFTn",
1035 };
1036 testNetwork(done, params);
1037});
1038it('Allows selection of Newyorkc', function(done) {
1039 var params = {
1040 selectText: "NYC - Newyorkc",
1041 firstAddress: "RSVMfyH1fKfy3puADJEhut2vfkRyon6imm",
1042 };
1043 testNetwork(done, params);
1044});
1045it('Allows selection of Novacoin', function(done) {
1046 var params = {
1047 selectText: "NVC - Novacoin",
1048 firstAddress: "4JRvUmxcKCJmaMXZyvRoSS1cmG2XvnZfHN",
1049 };
1050 testNetwork(done, params);
1051});
1052it('Allows selection of Nushares', function(done) {
1053 var params = {
1054 selectText: "NSR - Nushares",
1055 firstAddress: "SecjXzU3c7EecdT7EbC4vvmbdtBBokWh6J",
1056 };
1057 testNetwork(done, params);
1058});
1059it('Allows selection of Okcash', function(done) {
1060 var params = {
1061 selectText: "OK - Okcash",
1062 firstAddress: "PV4Qp1TUYuGv4TqVtLZtqvrsWWRycfx1Yi",
1063 };
1064 testNetwork(done, params);
1065});
1066it('Allows selection of Omnicore', function(done) {
1067 var params = {
1068 selectText: "OMNI - Omnicore",
1069 firstAddress: "1Q1t3gonjCT3rW38TsTsCvgSc3hh7zBGbi",
1070 };
1071 testNetwork(done, params);
1072});
1073it('Allows selection of Pesobit', function(done) {
1074 var params = {
1075 selectText: "PSB - Pesobit",
1076 firstAddress: "PDePsF7ALyXP7JaywokdYiRTDtKa14MAr1",
1077 };
1078 testNetwork(done, params);
1079});
1080it('Allows selection of Pinkcoin', function(done) {
1081 var params = {
1082 selectText: "PINK - Pinkcoin",
1083 firstAddress: "2TgjYQffjbzUHJghNaVbdsjHbRwruC3yzC",
1084 };
1085 testNetwork(done, params);
1086});
1087it('Allows selection of POSWcoin', function(done) {
1088 var params = {
1089 selectText: "POSW - POSWcoin",
1090 firstAddress: "PNxewmZoPnGBvoEbH6hgQZCK1igDiBCdgC",
1091 };
1092 testNetwork(done, params);
1093});
1094it('Allows selection of Potcoin', function(done) {
1095 var params = {
1096 selectText: "POT - Potcoin",
1097 firstAddress: "PEo7Vg2ctXgpP4vuLPeY9aGJtZotyrmiHc",
1098 };
1099 testNetwork(done, params);
1100});
1101it('Allows selection of Putincoin', function(done) {
1102 var params = {
1103 selectText: "PUT - Putincoin",
1104 firstAddress: "PViWnfr2uFtovd6e7joM49C94CsGSnqJis",
1105 };
1106 testNetwork(done, params);
1107});
1fe8f519 1108it('Allows selection of Ravencoin', function(done) {
1109 var params = {
1110 selectText: "RVN - Ravencoin",
1111 firstAddress: "RBuDoVNnzvFsEcX8XKPm8ic4mgiCzjUCNk",
1112 };
1113 testNetwork(done, params);
1114});
85f762c9 1115it('Allows selection of Reddcoin', function(done) {
1116 var params = {
1117 selectText: "RDD - Reddcoin",
2ab3faf4 1118 firstAddress: "RtgRvXMBng1y51ftteveFqwNfyRG18HpxQ",
85f762c9 1119 };
1120 testNetwork(done, params);
1121});
1122it('Allows selection of RevolutionVR', function(done) {
1123 var params = {
1124 selectText: "RVR - RevolutionVR",
1125 firstAddress: "VXeeoP2jkzZnMFxtc66ZBZK1NHN5QJnnjL",
1126 };
1127 testNetwork(done, params);
1128});
1129it('Allows selection of Rubycoin', function(done) {
1130 var params = {
1131 selectText: "RBY - Rubycoin",
1132 firstAddress: "RV76JDtjTs11JdMDRToYn6CHecMRPLnKS6",
1133 };
1134 testNetwork(done, params);
1135});
7878bb32
S
1136it('Allows selection of Salus', function(done) {
1137 var params = {
1138 selectText: "SLS - Salus",
65afae0b 1139 firstAddress: "SNzPi1CafHFm3WWjRo43aMgiaEEj3ogjww",
7878bb32 1140 };
65afae0b 1141 testNetwork(done, params);
c4086c24 1142});
85f762c9 1143it('Allows selection of Smileycoin', function(done) {
1144 var params = {
1145 selectText: "SMLY - Smileycoin",
1146 firstAddress: "BEZVnEBCAyFByrgKpwAgYgtvP4rKAd9Sj2",
1147 };
1148 testNetwork(done, params);
1149});
1150it('Allows selection of Solarcoin', function(done) {
1151 var params = {
1152 selectText: "SLR - Solarcoin",
1153 firstAddress: "8LZ13HbnjtaMJWSvvVFNTLf71zFfDrhwLu",
1154 };
1155 testNetwork(done, params);
1156});
ae51db39
B
1157it('Allows selection of stash', function(done) {
1158 var params = {
1159 selectText: "STASH - Stash",
1160 firstAddress: "XxwAsWB7REDKmAvHA85SbEZQQtpxeUDxS3",
1161 };
1162 testNetwork(done, params);
1163});
1164it('Allows selection of stash testnet', function(done) {
1165 var params = {
1166 selectText: "STASH - Stash Testnet",
f40c5c24 1167 firstAddress: "yWQCTSkUst7ddYuebKsqa1kSoXEjpCkGKR",
ae51db39
B
1168 };
1169 testNetwork(done, params);
1170});
85f762c9 1171it('Allows selection of Stratis', function(done) {
1172 var params = {
1173 selectText: "STRAT - Stratis",
1174 firstAddress: "ScfJnq3QDhKgDMEds6sqUE1ot6ShfhmXXq",
1175 };
1176 testNetwork(done, params);
1177});
e96d3876
AD
1178it('Allows selection of Stratis Test', function(done) {
1179 var params = {
c990aff8 1180 selectText: "TSTRAT - Stratis Testnet",
e96d3876
AD
1181 firstAddress: "TRLWm3dye4FRrDWouwYUSUZP96xb76mBE3",
1182 };
1183 testNetwork(done, params);
1184});
85f762c9 1185it('Allows selection of Syscoin', function(done) {
1186 var params = {
1187 selectText: "SYS - Syscoin",
1188 firstAddress: "SZwJi42Pst3VAMomyK5DG4157WM5ofRmSj",
1189 };
1190 testNetwork(done, params);
1191});
1192it('Allows selection of Toa', function(done) {
1193 var params = {
1194 selectText: "TOA - Toa",
1195 firstAddress: "TSe1QAnUwQzUfbBusDzRJ9URttrRGKoNKF",
1196 };
1197 testNetwork(done, params);
1198});
1199it('Allows selection of Ultimatesecurecash', function(done) {
1200 var params = {
1201 selectText: "USC - Ultimatesecurecash",
1202 firstAddress: "UPyLAZU2Che5fiy7Ed8xVJFmXAUhitA4ug",
1203 };
1204 testNetwork(done, params);
1205});
1206it('Allows selection of Unobtanium', function(done) {
1207 var params = {
1208 selectText: "UNO - Unobtanium",
1209 firstAddress: "uUBMPVMXrR6qhqornJqKTWgr8L69vihSL9",
1210 };
1211 testNetwork(done, params);
1212});
1213it('Allows selection of Vcash', function(done) {
1214 var params = {
1215 selectText: "XVC - Vcash",
1216 firstAddress: "VuL53MSY6KjvAjKSeRkh3NDnKykacDVeps",
1217 };
1218 testNetwork(done, params);
1219});
1220it('Allows selection of Verge', function(done) {
1221 var params = {
1222 selectText: "XVG - Verge",
1223 firstAddress: "DCrVuGkMjLJpTGgwAgv9AcMdeb1nkWbjZA",
1224 };
1225 testNetwork(done, params);
1226});
1227it('Allows selection of Vertcoin', function(done) {
1228 var params = {
1229 selectText: "VTC - Vertcoin",
1230 firstAddress: "Vf6koGuiWdXQfx8tNqxoNeEDxh4xh5cxsG",
1231 };
1232 testNetwork(done, params);
1233});
1234it('Allows selection of Vivo', function(done) {
1235 var params = {
1236 selectText: "VIVO - Vivo",
1237 firstAddress: "VFmBwuXXGhJe7MarQG2GfzHMFebRHgfSpB",
1238 };
1239 testNetwork(done, params);
1240});
1241it('Allows selection of Vpncoin', function(done) {
1242 var params = {
1243 selectText: "VASH - Vpncoin",
1244 firstAddress: "VoEmH1qXC4TsSgBAStR21QYetwnFqbqCx9",
1245 };
1246 testNetwork(done, params);
1247});
1248it('Allows selection of Whitecoin', function(done) {
1249 var params = {
1250 selectText: "XWC - Whitecoin",
1251 firstAddress: "WcSwCAUqrSgeSYbsaS3SSWWhsx8KRYTFDR",
1252 };
1253 testNetwork(done, params);
1254});
1255it('Allows selection of Wincoin', function(done) {
1256 var params = {
1257 selectText: "WC - Wincoin",
1258 firstAddress: "WaDVCESMGgyKgNESdn3u43NnwmGSkZED3Z",
1259 };
1260 testNetwork(done, params);
1261});
1262it('Allows selection of Zcoin', function(done) {
1263 var params = {
1264 selectText: "XZC - Zcoin",
1265 firstAddress: "a6VcMdP4XgAA9Tr7xNszmPG5FZpfRf17Cq",
1266 };
1267 testNetwork(done, params);
1268});
0702ecd3 1269it('Allows selection of Zcash', function(done) {
1270 var params = {
1271 selectText: "ZEC - Zcash",
1272 firstAddress: "t1Sz8AneMcVuzUg3tPJ8et5AS5LFJ7K2EF9",
1273 };
1274 testNetwork(done, params);
1275});
1e2cc748 1276it('Allows selection of Zclassic', function(done) {
1277 var params = {
1278 selectText: "ZCL - Zclassic",
1279 firstAddress: "t1TBMxTvVJRybUbMLGWq8H4A8F4VUL7czEc",
1280 };
1281 testNetwork(done, params);
1282});
1283it('Allows selection of Zencash', function(done) {
1284 var params = {
1285 selectText: "ZEN - Zencash",
1286 firstAddress: "znWh9XASyW2dZq5tck84wFjiwuqVysi7q3p",
1287 };
1288 testNetwork(done, params);
1289});
1290it('Allows selection of Energi', function(done) {
1291 var params = {
1292 selectText: "NRG - Energi",
1293 firstAddress: "EejRy4t4nidzhGGzkJUgFP3z4HYBjhTsRt",
1294 };
1295 testNetwork(done, params);
1296});
bb381a72 1297it('Allows selection of Ethereum Classic', function(done) {
1298 var params = {
1299 selectText: "ETC - Ethereum Classic",
1300 firstAddress: "0x3c05e5556693808367afB62eF3b63e35d6eD249A",
1301 };
1302 testNetwork(done, params);
1303});
1304it('Allows selection of Pirl', function(done) {
1305 var params = {
1306 selectText: "PIRL - Pirl",
1307 firstAddress: "0xe77FC0723dA122B5025CA79193c28563eB47e776",
1308 };
1309 testNetwork(done, params);
1310});
1311it('Allows selection of MIX', function(done) {
1312 var params = {
1313 selectText: "MIX - MIX",
1314 firstAddress: "0x98BC5e63aeb6A4e82d72850d20710F07E29A29F1",
1315 };
1316 testNetwork(done, params);
1317});
1318it('Allows selection of Musicoin', function(done) {
1319 var params = {
1320 selectText: "MUSIC - Musicoin",
1321 firstAddress: "0xDc060e4A0b0313ea83Cf6B3A39B9db2D29004897",
1322 };
1323 testNetwork(done, params);
1324});
1325it('Allows selection of Poa', function(done) {
1326 var params = {
1327 selectText: "POA - Poa",
1328 firstAddress: "0x53aF28d754e106210C3d0467Dd581eaf7e3C5e60",
1329 };
1330 testNetwork(done, params);
1331});
1332it('Allows selection of Expanse', function(done) {
1333 var params = {
1334 selectText: "EXP - Expanse",
1335 firstAddress: "0xf57FeAbf26582b6E3E666559d3B1Cc6fB2b2c5F6",
1336 };
1337 testNetwork(done, params);
1338});
1339it('Allows selection of Callisto', function(done) {
1340 var params = {
1341 selectText: "CLO - Callisto",
1342 firstAddress: "0x4f9364F7420B317266C51Dc8eB979717D4dE3f4E",
1343 };
1344 testNetwork(done, params);
1345});
0afecfc7
IC
1346it('Allows selection of HUSH', function(done) {
1347 var params = {
1348 selectText: "HUSH - Hush",
1349 firstAddress: "t1g6rLXUnJaiJuu4q4zmJjoa9Gk4fwKpiuA",
1350 };
1351 testNetwork(done, params);
1352});
a44c45e3 1353it('Allows selection of ExchangeCoin', function(done) {
1354 var params = {
1355 selectText: "EXCC - ExchangeCoin",
1356 firstAddress: "22txYKpFN5fwGwdSs2UBf7ywewbLM92YqK7E",
1357 };
1358 testNetwork(done, params);
1359});
2575538b
PC
1360it('Allows selection of Artax', function(done) {
1361 var params = {
1362 selectText: "XAX - Artax",
1363 firstAddress: "AYxaQPY7XLidG31V7F3yNzwxPYpYzRqG4q",
1364 };
1365 testNetwork(done, params);
1366});
8b2a093c
PC
1367it('Allows selection of BitcoinGreen', function(done) {
1368 var params = {
1369 selectText: "BITG - Bitcoin Green",
1370 firstAddress: "GeNGm9SkEfwbsws3UrrUSE2sJeyWYjzraY",
1371 };
1372 testNetwork(done, params);
1373});
45588661
KP
1374it('Allows selection of ANON', function(done) {
1375 var params = {
1376 selectText: "ANON - ANON",
1377 firstAddress: "AnU6pijpEeUZFWSTyM2qTqZQn996Zq1Xard",
1378 };
1379 testNetwork(done, params);
1380});
d2ba3871
PC
1381it('Allows selection of ProjectCoin', function(done) {
1382 var params = {
1383 selectText: "PRJ - ProjectCoin",
1384 firstAddress: "PXZG97saRseSCftfe1mcFmfAA7pf6qBbaz",
1385 };
1386 testNetwork(done, params);
1387});
38d1b296
PC
1388it('Allows selection of Phore', function(done) {
1389 var params = {
1390 selectText: "PHR - Phore",
1391 firstAddress: "PJThxpoXAG6hqrmdeQQbVDX4TJtFTMMymC",
1392 };
1393 testNetwork(done, params);
1394});
f1f1e39f
E
1395it('Allows selection of Safecoin', function(done) {
1396 var params = {
1397 selectText: "SAFE - Safecoin",
869f5375 1398 firstAddress: "RtxHpnhJz6RY8k9owP3ua5QWraunmewB1G",
f1f1e39f
E
1399 };
1400 testNetwork(done, params);
1401 });
6f435817
U
1402it('Allows selection of Blocknode', function(done) {
1403 var params = {
1404 selectText: "BND - Blocknode",
1405 firstAddress: "BG8xZSAur2jYLG9VXt8dYfkKxxeR7w9bSe",
1406 };
1407 testNetwork(done, params);
1408});
1409it('Allows selection of Blocknode Testnet', function(done) {
1410 var params = {
1411 selectText: "tBND - Blocknode Testnet",
1412 firstAddress: "bSptsFyDktFSKpWveRywJsDoJA2TC6qfHv",
1413 };
1414 testNetwork(done, params);
1415});
d4fcdda9
PC
1416it('Allows selection of LitecoinZ', function(done) {
1417 var params = {
1418 selectText: "LTZ - LitecoinZ",
1419 firstAddress: "L1VTXju7hLgKV4T7fGXS9sKsnm2gmtRCmyw",
1420 };
1421 testNetwork(done, params);
1422});
f22f7677
PC
1423it('Allows selection of BlockStamp', function(done) {
1424 var params = {
1425 selectText: "BST - BlockStamp",
1426 firstAddress: "15gypKtim4cVTj137ApfryG17RkvSbPazZ",
1427 };
1428 testNetwork(done, params);
1429});
6cbd3bc8
HL
1430it('Allows selection of DEXON', function(done) {
1431 var params = {
1432 selectText: "DXN - DEXON",
1433 firstAddress: "0x136a58788033E028CCd740FbDec6734358DB56Ec",
1434 };
1435 testNetwork(done, params);
1436});
0460b53f
IC
1437
1438// BIP39 seed is set from phrase
1439it('Sets the bip39 seed from the prhase', function(done) {
1440 driver.findElement(By.css('.phrase'))
1441 .sendKeys('abandon abandon ability');
1442 driver.sleep(generateDelay).then(function() {
1443 driver.findElement(By.css('.seed'))
1444 .getAttribute("value")
1445 .then(function(seed) {
1446 expect(seed).toBe("20da140d3dd1df8713cefcc4d54ce0e445b4151027a1ab567b832f6da5fcc5afc1c3a3f199ab78b8e0ab4652efd7f414ac2c9a3b81bceb879a70f377aa0a58f3");
1447 done();
1448 })
1449 });
1450});
1451
1452// BIP32 root key is set from phrase
1453it('Sets the bip39 root key from the prhase', function(done) {
1454 driver.findElement(By.css('.phrase'))
1455 .sendKeys('abandon abandon ability');
1456 driver.sleep(generateDelay).then(function() {
1457 driver.findElement(By.css('.root-key'))
1458 .getAttribute("value")
1459 .then(function(seed) {
1460 expect(seed).toBe("xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi");
1461 done();
1462 })
1463 });
1464});
1465
1466// Tabs show correct addresses when changed
1467it('Shows the correct address when tab is changed', function(done) {
1468 driver.findElement(By.css('.phrase'))
1469 .sendKeys('abandon abandon ability');
1470 driver.sleep(generateDelay).then(function() {
1471 driver.findElement(By.css('#bip32-tab a'))
1472 .click();
1473 driver.sleep(generateDelay).then(function() {
1474 getFirstAddress(function(address) {
1475 expect(address).toBe("17uQ7s2izWPwBmEVFikTmZUjbBKWYdJchz");
1476 done();
1477 });
1478 });
1479 });
1480});
1481
1482// BIP44 derivation path is shown
1483it('Shows the derivation path for bip44 tab', function(done) {
1484 driver.findElement(By.css('.phrase'))
1485 .sendKeys('abandon abandon ability');
1486 driver.sleep(generateDelay).then(function() {
1487 driver.findElement(By.css('#bip44 .path'))
1488 .getAttribute("value")
1489 .then(function(path) {
1490 expect(path).toBe("m/44'/0'/0'/0");
1491 done();
1492 })
1493 });
1494});
1495
1496// BIP44 extended private key is shown
1497it('Shows the extended private key for bip44 tab', function(done) {
1498 driver.findElement(By.css('.phrase'))
1499 .sendKeys('abandon abandon ability');
1500 driver.sleep(generateDelay).then(function() {
1501 driver.findElement(By.css('.extended-priv-key'))
1502 .getAttribute("value")
1503 .then(function(path) {
1504 expect(path).toBe("xprvA2DxxvPZcyRvYgZMGS53nadR32mVDeCyqQYyFhrCVbJNjPoxMeVf7QT5g7mQASbTf9Kp4cryvcXnu2qurjWKcrdsr91jXymdCDNxKgLFKJG");
1505 done();
1506 })
1507 });
1508});
1509
1510// BIP44 extended public key is shown
1511it('Shows the extended public key for bip44 tab', function(done) {
1512 driver.findElement(By.css('.phrase'))
1513 .sendKeys('abandon abandon ability');
1514 driver.sleep(generateDelay).then(function() {
1515 driver.findElement(By.css('.extended-pub-key'))
1516 .getAttribute("value")
1517 .then(function(path) {
1518 expect(path).toBe("xpub6FDKNRvTTLzDmAdpNTc49ia9b4byd6vqCdUa46Fp3vqMcC96uBoufCmZXQLiN5AK3iSCJMhf9gT2sxkpyaPepRuA7W3MujV5tGmF5VfbueM");
1519 done();
1520 })
1521 });
1522});
1523
1524// BIP44 account field changes address list
1525it('Changes the address list if bip44 account is changed', function(done) {
1526 driver.findElement(By.css('#bip44 .account'))
1527 .sendKeys('1');
1528 driver.findElement(By.css('.phrase'))
1529 .sendKeys('abandon abandon ability');
1530 driver.sleep(generateDelay).then(function() {
1531 getFirstAddress(function(address) {
1532 expect(address).toBe("1Nq2Wmu726XHCuGhctEtGmhxo3wzk5wZ1H");
1533 done();
1534 });
1535 });
1536});
1537
1538// BIP44 change field changes address list
1539it('Changes the address list if bip44 change is changed', function(done) {
1540 driver.findElement(By.css('#bip44 .change'))
1541 .sendKeys('1');
1542 driver.findElement(By.css('.phrase'))
1543 .sendKeys('abandon abandon ability');
1544 driver.sleep(generateDelay).then(function() {
1545 getFirstAddress(function(address) {
1546 expect(address).toBe("1KAGfWgqfVbSSXY56fNQ7YnhyKuoskHtYo");
1547 done();
1548 });
1549 });
1550});
1551
1552// BIP32 derivation path can be set
1553it('Can use a custom bip32 derivation path', function(done) {
1554 driver.findElement(By.css('#bip32-tab a'))
1555 .click();
1556 driver.findElement(By.css('#bip32 .path'))
1557 .clear();
1558 driver.findElement(By.css('#bip32 .path'))
1559 .sendKeys('m/1');
1560 driver.findElement(By.css('.phrase'))
1561 .sendKeys('abandon abandon ability');
1562 driver.sleep(generateDelay).then(function() {
1563 getFirstAddress(function(address) {
1564 expect(address).toBe("16pYQQdLD1hH4hwTGLXBaZ9Teboi1AGL8L");
1565 done();
1566 });
1567 });
1568});
1569
1570// BIP32 can use hardened derivation paths
1571it('Can use a hardened derivation paths', function(done) {
1572 driver.findElement(By.css('#bip32-tab a'))
1573 .click();
1574 driver.findElement(By.css('#bip32 .path'))
1575 .clear();
1576 driver.findElement(By.css('#bip32 .path'))
1577 .sendKeys("m/0'");
1578 driver.findElement(By.css('.phrase'))
1579 .sendKeys('abandon abandon ability');
1580 driver.sleep(generateDelay).then(function() {
1581 getFirstAddress(function(address) {
1582 expect(address).toBe("14aXZeprXAE3UUKQc4ihvwBvww2LuEoHo4");
1583 done();
1584 });
1585 });
1586});
1587
1588// BIP32 extended private key is shown
1589it('Shows the BIP32 extended private key', function(done) {
1590 driver.findElement(By.css('#bip32-tab a'))
1591 .click();
1592 driver.findElement(By.css('.phrase'))
1593 .sendKeys('abandon abandon ability');
1594 driver.sleep(generateDelay).then(function() {
1595 driver.findElement(By.css('.extended-priv-key'))
1596 .getAttribute("value")
1597 .then(function(privKey) {
1598 expect(privKey).toBe("xprv9va99uTVE5aLiutUVLTyfxfe8v8aaXjSQ1XxZbK6SezYVuikA9MnjQVTA8rQHpNA5LKvyQBpLiHbBQiiccKiBDs7eRmBogsvq3THFeLHYbe");
1599 done();
1600 });
1601 });
1602});
1603
1604// BIP32 extended public key is shown
1605it('Shows the BIP32 extended public key', function(done) {
1606 driver.findElement(By.css('#bip32-tab a'))
1607 .click();
1608 driver.findElement(By.css('.phrase'))
1609 .sendKeys('abandon abandon ability');
1610 driver.sleep(generateDelay).then(function() {
1611 driver.findElement(By.css('.extended-pub-key'))
1612 .getAttribute("value")
1613 .then(function(pubKey) {
1614 expect(pubKey).toBe("xpub69ZVZQzP4T8dwPxwbMzz36cNgwy4yzTHmETZMyihzzXXNi3thgg3HCow1RtY252wdw5rS8369xKnraN5Q93y3FkFfJp2XEHWUrkyXsjS93P");
1615 done();
1616 });
1617 });
1618});
1619
1620// Derivation path is shown in table
1621it('Shows the derivation path in the table', function(done) {
1622 driver.findElement(By.css('.phrase'))
1623 .sendKeys('abandon abandon ability');
1624 driver.sleep(generateDelay).then(function() {
1625 getFirstPath(function(path) {
1626 expect(path).toBe("m/44'/0'/0'/0/0");
1627 done();
1628 });
1629 });
1630});
1631
1632// Derivation path for address can be hardened
1633it('Can derive hardened addresses', function(done) {
1634 driver.findElement(By.css('#bip32-tab a'))
1635 .click();
1636 driver.executeScript(function() {
1637 $(".hardened-addresses").prop("checked", true);
1638 });
1639 driver.findElement(By.css('.phrase'))
1640 .sendKeys('abandon abandon ability');
1641 driver.sleep(generateDelay).then(function() {
1642 getFirstAddress(function(address) {
1643 expect(address).toBe("18exLzUv7kfpiXRzmCjFDoC9qwNLFyvwyd");
1644 done();
1645 });
1646 });
1647});
1648
1649// Derivation path visibility can be toggled
1650it('Can toggle visibility of the derivation path column', function(done) {
1651 driver.findElement(By.css('.phrase'))
1652 .sendKeys('abandon abandon ability');
1653 driver.sleep(generateDelay).then(function() {
1654 driver.findElement(By.css('.index-toggle'))
1655 .click();
1656 testColumnValuesAreInvisible(done, "index");
1657 });
1658});
1659
1660// Address is shown
1661it('Shows the address in the table', function(done) {
1662 driver.findElement(By.css('.phrase'))
1663 .sendKeys('abandon abandon ability');
1664 driver.sleep(generateDelay).then(function() {
1665 getFirstAddress(function(address) {
1666 expect(address).toBe("1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug");
1667 done();
1668 });
1669 });
1670});
1671
1672// Addresses are shown in order of derivation path
1673it('Shows the address in order of derivation path', function(done) {
1674 driver.findElement(By.css('.phrase'))
1675 .sendKeys('abandon abandon ability');
1676 driver.sleep(generateDelay).then(function() {
1677 testRowsAreInCorrectOrder(done);
1678 });
1679});
1680
1681// Address visibility can be toggled
1682it('Can toggle visibility of the address column', function(done) {
1683 driver.findElement(By.css('.phrase'))
1684 .sendKeys('abandon abandon ability');
1685 driver.sleep(generateDelay).then(function() {
1686 driver.findElement(By.css('.address-toggle'))
1687 .click();
1688 testColumnValuesAreInvisible(done, "address");
1689 });
1690});
1691
1692// Public key is shown in table
1693it('Shows the public key in the table', function(done) {
1694 driver.findElement(By.css('.phrase'))
1695 .sendKeys('abandon abandon ability');
1696 driver.sleep(generateDelay).then(function() {
1697 driver.findElements(By.css('.pubkey'))
1698 .then(function(els) {
1699 els[0].getText()
1700 .then(function(pubkey) {
1701 expect(pubkey).toBe("033f5aed5f6cfbafaf223188095b5980814897295f723815fea5d3f4b648d0d0b3");
1702 done();
1703 });
1704 });
1705 });
1706});
1707
1708// Public key visibility can be toggled
1709it('Can toggle visibility of the public key column', function(done) {
1710 driver.findElement(By.css('.phrase'))
1711 .sendKeys('abandon abandon ability');
1712 driver.sleep(generateDelay).then(function() {
1713 driver.findElement(By.css('.public-key-toggle'))
1714 .click();
1715 testColumnValuesAreInvisible(done, "pubkey");
1716 });
1717});
1718
1719// Private key is shown in table
1720it('Shows the private key in the table', function(done) {
1721 driver.findElement(By.css('.phrase'))
1722 .sendKeys('abandon abandon ability');
1723 driver.sleep(generateDelay).then(function() {
1724 driver.findElements(By.css('.privkey'))
1725 .then(function(els) {
1726 els[0].getText()
1727 .then(function(pubkey) {
1728 expect(pubkey).toBe("L26cVSpWFkJ6aQkPkKmTzLqTdLJ923e6CzrVh9cmx21QHsoUmrEE");
1729 done();
1730 });
1731 });
1732 });
1733});
1734
1735// Private key visibility can be toggled
1736it('Can toggle visibility of the private key column', function(done) {
1737 driver.findElement(By.css('.phrase'))
1738 .sendKeys('abandon abandon ability');
1739 driver.sleep(generateDelay).then(function() {
1740 driver.findElement(By.css('.private-key-toggle'))
1741 .click();
1742 testColumnValuesAreInvisible(done, "privkey");
1743 });
1744});
1745
1746// More addresses can be generated
1747it('Can generate more rows in the table', function(done) {
1748 driver.findElement(By.css('.phrase'))
1749 .sendKeys('abandon abandon ability');
1750 driver.sleep(generateDelay).then(function() {
1751 driver.findElement(By.css('.more'))
1752 .click();
1753 driver.sleep(generateDelay).then(function() {
1754 driver.findElements(By.css('.address'))
1755 .then(function(els) {
1756 expect(els.length).toBe(40);
1757 done();
1758 });
1759 });
1760 });
1761});
1762
1763// A custom number of additional addresses can be generated
1764it('Can generate more rows in the table', function(done) {
0460b53f
IC
1765 driver.findElement(By.css('.phrase'))
1766 .sendKeys('abandon abandon ability');
1767 driver.sleep(generateDelay).then(function() {
5dfe77e4
IC
1768 driver.findElement(By.css('.rows-to-add'))
1769 .clear();
1770 driver.findElement(By.css('.rows-to-add'))
1771 .sendKeys('1');
0460b53f
IC
1772 driver.findElement(By.css('.more'))
1773 .click();
1774 driver.sleep(generateDelay).then(function() {
1775 driver.findElements(By.css('.address'))
1776 .then(function(els) {
1777 expect(els.length).toBe(21);
1778 done();
1779 });
1780 });
1781 });
1782});
1783
1784// Additional addresses are shown in order of derivation path
1785it('Shows additional addresses in order of derivation path', function(done) {
1786 driver.findElement(By.css('.phrase'))
1787 .sendKeys('abandon abandon ability');
1788 driver.sleep(generateDelay).then(function() {
1789 driver.findElement(By.css('.more'))
1790 .click();
1791 driver.sleep(generateDelay).then(function() {
1792 testRowsAreInCorrectOrder(done);
1793 });
1794 });
1795});
1796
1797// BIP32 root key can be set by the user
1798it('Allows the user to set the BIP32 root key', function(done) {
1799 driver.findElement(By.css('.root-key'))
1800 .sendKeys('xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi');
1801 driver.sleep(generateDelay).then(function() {
1802 getFirstAddress(function(address) {
1803 expect(address).toBe("1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug");
1804 done();
1805 });
1806 });
1807});
1808
1809// Setting BIP32 root key clears the existing phrase, passphrase and seed
1810// TODO this doesn't work in selenium with chrome
1811it('Confirms the existing phrase should be cleared', function(done) {
1812 if (browser == "chrome") {
1813 pending("Selenium + Chrome headless bug for alert, see https://stackoverflow.com/q/45242264");
1814 }
1815 driver.findElement(By.css('.phrase'))
1816 .sendKeys('A non-blank but invalid value');
1817 driver.findElement(By.css('.root-key'))
1818 .sendKeys('xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi');
1819 driver.switchTo().alert().accept();
1820 driver.findElement(By.css('.phrase'))
1821 .getAttribute("value").then(function(value) {
1822 expect(value).toBe("");
1823 done();
1824 });
1825});
1826
1827// Clearing of phrase, passphrase and seed can be cancelled by user
1828// TODO this doesn't work in selenium with chrome
1829it('Allows the clearing of the phrase to be cancelled', function(done) {
1830 if (browser == "chrome") {
1831 pending("Selenium + Chrome headless bug for alert, see https://stackoverflow.com/q/45242264");
1832 }
1833 driver.findElement(By.css('.phrase'))
1834 .sendKeys('abandon abandon ability');
1835 driver.sleep(generateDelay).then(function() {
1836 driver.findElement(By.css('.root-key'))
1837 .clear();
1838 driver.findElement(By.css('.root-key'))
1839 .sendKeys('x');
1840 driver.switchTo().alert().dismiss();
1841 driver.findElement(By.css('.phrase'))
1842 .getAttribute("value").then(function(value) {
1843 expect(value).toBe("abandon abandon ability");
1844 done();
1845 });
1846 });
1847});
1848
1849// Custom BIP32 root key is used when changing the derivation path
1850it('Can set derivation path for root key instead of phrase', function(done) {
1851 driver.findElement(By.css('#bip44 .account'))
1852 .sendKeys('1');
1853 driver.findElement(By.css('.root-key'))
1854 .sendKeys('xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi');
1855 driver.sleep(generateDelay).then(function() {
1856 getFirstAddress(function(address) {
1857 expect(address).toBe("1Nq2Wmu726XHCuGhctEtGmhxo3wzk5wZ1H");
1858 done();
1859 });
1860 });
1861});
1862
1863// Incorrect mnemonic shows error
1864it('Shows an error for incorrect mnemonic', function(done) {
1865 driver.findElement(By.css('.phrase'))
1866 .sendKeys('abandon abandon abandon');
1867 driver.sleep(feedbackDelay).then(function() {
1868 driver.findElement(By.css('.feedback'))
1869 .getText()
1870 .then(function(feedback) {
1871 expect(feedback).toBe("Invalid mnemonic");
1872 done();
1873 });
1874 });
1875});
1876
1877// Incorrect word shows suggested replacement
1878it('Shows word suggestion for incorrect word', function(done) {
1879 driver.findElement(By.css('.phrase'))
1880 .sendKeys('abandon abandon abiliti');
1881 driver.sleep(feedbackDelay).then(function() {
1882 driver.findElement(By.css('.feedback'))
1883 .getText()
1884 .then(function(feedback) {
1885 var msg = "abiliti not in wordlist, did you mean ability?";
1886 expect(feedback).toBe(msg);
1887 done();
1888 });
1889 });
1890});
1891
1892// Github pull request 48
1893// First four letters of word shows that word, not closest
1894// since first four letters gives unique word in BIP39 wordlist
1895// eg ille should show illegal, not idle
1896it('Shows word suggestion based on first four chars', function(done) {
1897 driver.findElement(By.css('.phrase'))
1898 .sendKeys('ille');
1899 driver.sleep(feedbackDelay).then(function() {
1900 driver.findElement(By.css('.feedback'))
1901 .getText()
1902 .then(function(feedback) {
1903 var msg = "ille not in wordlist, did you mean illegal?";
1904 expect(feedback).toBe(msg);
1905 done();
1906 });
1907 });
1908});
1909
1910// Incorrect BIP32 root key shows error
1911it('Shows error for incorrect root key', function(done) {
1912 driver.findElement(By.css('.root-key'))
1913 .sendKeys('xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpj');
1914 driver.sleep(feedbackDelay).then(function() {
1915 driver.findElement(By.css('.feedback'))
1916 .getText()
1917 .then(function(feedback) {
1918 var msg = "Invalid root key";
1919 expect(feedback).toBe(msg);
1920 done();
1921 });
1922 });
1923});
1924
1925// Derivation path not starting with m shows error
1926it('Shows error for derivation path not starting with m', function(done) {
1927 driver.findElement(By.css('#bip32-tab a'))
1928 .click();
1929 driver.findElement(By.css('#bip32 .path'))
1930 .clear();
1931 driver.findElement(By.css('#bip32 .path'))
1932 .sendKeys('n/0');
1933 driver.findElement(By.css('.phrase'))
1934 .sendKeys('abandon abandon ability');
1935 driver.sleep(feedbackDelay).then(function() {
1936 driver.findElement(By.css('.feedback'))
1937 .getText()
1938 .then(function(feedback) {
1939 var msg = "First character must be 'm'";
1940 expect(feedback).toBe(msg);
1941 done();
1942 });
1943 });
1944});
1945
1946// Derivation path containing invalid characters shows useful error
1947it('Shows error for derivation path not starting with m', function(done) {
1948 driver.findElement(By.css('#bip32-tab a'))
1949 .click();
1950 driver.findElement(By.css('#bip32 .path'))
1951 .clear();
1952 driver.findElement(By.css('#bip32 .path'))
1953 .sendKeys('m/1/0wrong1/1');
1954 driver.findElement(By.css('.phrase'))
1955 .sendKeys('abandon abandon ability');
1956 driver.sleep(feedbackDelay).then(function() {
1957 driver.findElement(By.css('.feedback'))
1958 .getText()
1959 .then(function(feedback) {
1960 var msg = "Invalid characters 0wrong1 found at depth 2";
1961 expect(feedback).toBe(msg);
1962 done();
1963 });
1964 });
1965});
1966
1967// Github Issue 11: Default word length is 15
1968// https://github.com/iancoleman/bip39/issues/11
1969it('Sets the default word length to 15', function(done) {
1970 driver.findElement(By.css('.strength'))
1971 .getAttribute("value")
1972 .then(function(strength) {
1973 expect(strength).toBe("15");
1974 done();
1975 });
1976});
1977
1978// Github Issue 12: Generate more rows with private keys hidden
1979// https://github.com/iancoleman/bip39/issues/12
1980it('Sets the correct hidden column state on new rows', function(done) {
1981 driver.findElement(By.css('.phrase'))
1982 .sendKeys("abandon abandon ability");
1983 driver.sleep(generateDelay).then(function() {
1984 driver.findElement(By.css('.private-key-toggle'))
1985 .click();
1986 driver.findElement(By.css('.more'))
1987 .click();
1988 driver.sleep(generateDelay).then(function() {
1989 driver.findElements(By.css('.privkey'))
1990 .then(function(els) {
1991 expect(els.length).toBe(40);
1992 });
1993 testColumnValuesAreInvisible(done, "privkey");
1994 });
1995 });
1996});
1997
1998// Github Issue 19: Mnemonic is not sensitive to whitespace
1999// https://github.com/iancoleman/bip39/issues/19
2000it('Ignores excess whitespace in the mnemonic', function(done) {
2001 var doublespace = " ";
2002 var mnemonic = "urge cat" + doublespace + "bid";
2003 driver.findElement(By.css('.phrase'))
2004 .sendKeys(mnemonic);
2005 driver.sleep(generateDelay).then(function() {
2006 driver.findElement(By.css('.root-key'))
2007 .getAttribute("value")
2008 .then(function(seed) {
2009 expect(seed).toBe("xprv9s21ZrQH143K3isaZsWbKVoTtbvd34Y1ZGRugGdMeBGbM3AgBVzTH159mj1cbbtYSJtQr65w6L5xy5L9SFC7c9VJZWHxgAzpj4mun5LhrbC");
2010 done();
2011 });
2012 });
2013});
2014
2015// Github Issue 23: Part 1: Use correct derivation path when changing tabs
2016// https://github.com/iancoleman/bip39/issues/23
2017it('Uses the correct derivation path when changing tabs', function(done) {
2018 // 1) and 2) set the phrase
2019 driver.findElement(By.css('.phrase'))
2020 .sendKeys("abandon abandon ability");
2021 driver.sleep(generateDelay).then(function() {
2022 // 3) select bip32 tab
2023 driver.findElement(By.css('#bip32-tab a'))
2024 .click();
2025 driver.sleep(generateDelay).then(function() {
2026 // 4) switch from bitcoin to litecoin
2027 selectNetwork("LTC - Litecoin");
2028 driver.sleep(generateDelay).then(function() {
2029 // 5) Check address is displayed correctly
2030 getFirstAddress(function(address) {
2031 expect(address).toBe("LS8MP5LZ5AdzSZveRrjm3aYVoPgnfFh5T5");
2032 // 5) Check derivation path is displayed correctly
2033 getFirstPath(function(path) {
2034 expect(path).toBe("m/0/0");
2035 done();
2036 });
2037 });
2038 });
2039 });
2040 });
2041});
2042
2043// Github Issue 23 Part 2: Coin selection in derivation path
2044// https://github.com/iancoleman/bip39/issues/23#issuecomment-238011920
2045it('Uses the correct derivation path when changing coins', function(done) {
2046 // set the phrase
2047 driver.findElement(By.css('.phrase'))
2048 .sendKeys("abandon abandon ability");
2049 driver.sleep(generateDelay).then(function() {
2050 // switch from bitcoin to clam
2051 selectNetwork("CLAM - Clams");
2052 driver.sleep(generateDelay).then(function() {
2053 // check derivation path is displayed correctly
2054 getFirstPath(function(path) {
2055 expect(path).toBe("m/44'/23'/0'/0/0");
2056 done();
2057 });
2058 });
2059 });
2060});
2061
2062// Github Issue 26: When using a Root key derrived altcoins are incorrect
2063// https://github.com/iancoleman/bip39/issues/26
2064it('Uses the correct derivation for altcoins with root keys', function(done) {
2065 // 1) 2) and 3) set the root key
2066 driver.findElement(By.css('.root-key'))
2067 .sendKeys("xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi");
2068 driver.sleep(generateDelay).then(function() {
2069 // 4) switch from bitcoin to viacoin
2070 selectNetwork("VIA - Viacoin");
2071 driver.sleep(generateDelay).then(function() {
2072 // 5) ensure the derived address is correct
2073 getFirstAddress(function(address) {
2074 expect(address).toBe("Vq9Eq4N5SQnjqZvxtxzo7hZPW5XnyJsmXT");
2075 done();
2076 });
2077 });
2078 });
2079});
2080
2081// Selecting a language with no existing phrase should generate a phrase in
2082// that language.
2083it('Generate a random phrase when language is selected and no current phrase', function(done) {
2084 driver.findElement(By.css("a[href='#japanese']"))
2085 .click();
2086 driver.sleep(generateDelay).then(function() {
2087 driver.findElement(By.css(".phrase"))
2088 .getAttribute("value").then(function(phrase) {
2089 expect(phrase.search(/[a-z]/)).toBe(-1);
2090 expect(phrase.length).toBeGreaterThan(0);
2091 done();
2092 });
2093 });
2094});
2095
2096// Selecting a language with existing phrase should update the phrase to use
2097// that language.
2098it('Updates existing phrases when the language is changed', function(done) {
2099 driver.findElement(By.css(".phrase"))
2100 .sendKeys("abandon abandon ability");
2101 driver.sleep(generateDelay).then(function() {
2102 driver.findElement(By.css("a[href='#italian']"))
2103 .click();
2104 driver.sleep(generateDelay).then(function() {
2105 driver.findElement(By.css(".phrase"))
2106 .getAttribute("value").then(function(phrase) {
2107 // Check only the language changes, not the phrase
2108 expect(phrase).toBe("abaco abaco abbaglio");
2109 getFirstAddress(function(address) {
2110 // Check the address is correct
2111 expect(address).toBe("1Dz5TgDhdki9spa6xbPFbBqv5sjMrx3xgV");
2112 done();
2113 });
2114 });
2115 });
2116 });
2117});
2118
2119// Suggested replacement for erroneous word in non-English language
2120it('Shows word suggestion for incorrect word in non-English language', function(done) {
2121 driver.findElement(By.css('.phrase'))
2122 .sendKeys('abaco abaco zbbaglio');
2123 driver.sleep(feedbackDelay).then(function() {
2124 driver.findElement(By.css('.feedback'))
2125 .getText()
2126 .then(function(feedback) {
2127 var msg = "zbbaglio not in wordlist, did you mean abbaglio?";
2128 expect(feedback).toBe(msg);
2129 done();
2130 });
2131 });
2132});
2133
2134// Japanese word does not break across lines.
2135// Point 2 from
2136// https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md#japanese
2137it('Does not break Japanese words across lines', function(done) {
2138 driver.findElement(By.css('.phrase'))
2139 .getCssValue("word-break")
2140 .then(function(value) {
2141 expect(value).toBe("keep-all");
2142 done();
2143 });
2144});
2145
2146// Language can be specified at page load using hash value in url
2147it('Can set the language from the url hash', function(done) {
2148 driver.get(url + "#japanese").then(function() {
2149 driver.findElement(By.css('.generate')).click();
2150 driver.sleep(generateDelay).then(function() {
2151 driver.findElement(By.css(".phrase"))
2152 .getAttribute("value").then(function(phrase) {
2153 expect(phrase.search(/[a-z]/)).toBe(-1);
2154 expect(phrase.length).toBeGreaterThan(0);
2155 done();
2156 });
2157 });
2158 });
2159});
2160
2161// Entropy can be entered by the user
2162it('Allows entropy to be entered', function(done) {
2163 driver.findElement(By.css('.use-entropy'))
2164 .click();
2165 driver.findElement(By.css('.entropy'))
2166 .sendKeys('00000000 00000000 00000000 00000000');
2167 driver.sleep(generateDelay).then(function() {
2168 driver.findElement(By.css(".phrase"))
2169 .getAttribute("value").then(function(phrase) {
2170 expect(phrase).toBe("abandon abandon ability");
2171 getFirstAddress(function(address) {
2172 expect(address).toBe("1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug");
2173 done();
2174 })
2175 });
2176 });
2177});
2178
2179// A warning about entropy is shown to the user, with additional information
2180it('Shows a warning about using entropy', function(done) {
2181 driver.findElement(By.css('.use-entropy'))
2182 .click();
2183 driver.findElement(By.css('.entropy-container'))
2184 .getText()
2185 .then(function(containerText) {
2186 var warning = "mnemonic may be insecure";
2187 expect(containerText).toContain(warning);
2188 driver.findElement(By.css('#entropy-notes'))
2189 .findElement(By.xpath("parent::*"))
2190 .getText()
2191 .then(function(notesText) {
2192 var detail = "flipping a fair coin, rolling a fair dice, noise measurements etc";
2193 expect(notesText).toContain(detail);
2194 done();
2195 });
2196 });
2197});
2198
2199// The types of entropy available are described to the user
2200it('Shows the types of entropy available', function(done) {
2201 driver.findElement(By.css('.entropy'))
2202 .getAttribute("placeholder")
2203 .then(function(placeholderText) {
2204 var options = [
2205 "binary",
2206 "base 6",
2207 "dice",
2208 "base 10",
2209 "hexadecimal",
2210 "cards",
2211 ];
2212 for (var i=0; i<options.length; i++) {
2213 var option = options[i];
2214 expect(placeholderText).toContain(option);
2215 }
2216 done();
2217 });
2218});
2219
2220// The actual entropy used is shown to the user
2221it('Shows the actual entropy used', function(done) {
2222 driver.findElement(By.css('.use-entropy'))
2223 .click();
2224 driver.findElement(By.css('.entropy'))
2225 .sendKeys('Not A Very Good Entropy Source At All');
2226 driver.sleep(generateDelay).then(function() {
2227 driver.findElement(By.css('.entropy-container'))
2228 .getText()
2229 .then(function(text) {
2230 expect(text).toMatch(/Filtered Entropy\s+AedEceAA/);
2231 done();
2232 });
2233 });
2234});
2235
2236// Binary entropy can be entered
2237it('Allows binary entropy to be entered', function(done) {
2238 testEntropyType(done, "01", "binary");
2239});
2240
2241// Base 6 entropy can be entered
2242it('Allows base 6 entropy to be entered', function(done) {
2243 testEntropyType(done, "012345", "base 6");
2244});
2245
2246// Base 6 dice entropy can be entered
2247it('Allows base 6 dice entropy to be entered', function(done) {
2248 testEntropyType(done, "123456", "base 6 (dice)");
2249});
2250
2251// Base 10 entropy can be entered
2252it('Allows base 10 entropy to be entered', function(done) {
2253 testEntropyType(done, "789", "base 10");
2254});
2255
2256// Hexadecimal entropy can be entered
2257it('Allows hexadecimal entropy to be entered', function(done) {
2258 testEntropyType(done, "abcdef", "hexadecimal");
2259});
2260
2261// Dice entropy value is shown as the converted base 6 value
2262// ie 123456 is converted to 123450
2263it('Shows dice entropy as base 6', function(done) {
2264 driver.findElement(By.css('.use-entropy'))
2265 .click();
2266 driver.findElement(By.css('.entropy'))
2267 .sendKeys("123456");
2268 driver.sleep(generateDelay).then(function() {
2269 driver.findElement(By.css('.entropy-container'))
2270 .getText()
2271 .then(function(text) {
2272 expect(text).toMatch(/Filtered Entropy\s+123450/);
2273 done();
2274 });
2275 });
2276});
2277
2278// The number of bits of entropy accumulated is shown
2279it("Shows the number of bits of entropy for 20 bits of binary", function(done) {
2280 testEntropyBits(done, "0000 0000 0000 0000 0000", "20");
2281});
2282it("Shows the number of bits of entropy for 1 bit of binary", function(done) {
2283 testEntropyBits(done, "0", "1");
2284});
2285it("Shows the number of bits of entropy for 4 bits of binary", function(done) {
2286 testEntropyBits(done, "0000", "4");
2287});
2288it("Shows the number of bits of entropy for 1 character of base 6 (dice)", function(done) {
2289 // 6 in card is 0 in base 6, 0 in base 6 is 2.6 bits (rounded down to 2 bits)
2290 testEntropyBits(done, "6", "2");
2291});
2292it("Shows the number of bits of entropy for 1 character of base 10 with 3 bits", function(done) {
2293 // 7 in base 10 is 111 in base 2, no leading zeros
2294 testEntropyBits(done, "7", "3");
2295});
2296it("Shows the number of bits of entropy for 1 character of base 10 with 4 bis", function(done) {
2297 testEntropyBits(done, "8", "4");
2298});
2299it("Shows the number of bits of entropy for 1 character of hex", function(done) {
2300 testEntropyBits(done, "F", "4");
2301});
2302it("Shows the number of bits of entropy for 2 characters of base 10", function(done) {
2303 testEntropyBits(done, "29", "6");
2304});
2305it("Shows the number of bits of entropy for 2 characters of hex", function(done) {
2306 testEntropyBits(done, "0A", "8");
2307});
2308it("Shows the number of bits of entropy for 2 characters of hex with 3 leading zeros", function(done) {
2309 // hex is always multiple of 4 bits of entropy
2310 testEntropyBits(done, "1A", "8");
2311});
2312it("Shows the number of bits of entropy for 2 characters of hex with 2 leading zeros", function(done) {
2313 testEntropyBits(done, "2A", "8");
2314});
2315it("Shows the number of bits of entropy for 2 characters of hex with 1 leading zero", function(done) {
2316 testEntropyBits(done, "4A", "8");
2317});
2318it("Shows the number of bits of entropy for 2 characters of hex with no leading zeros", function(done) {
2319 testEntropyBits(done, "8A", "8");
2320});
2321it("Shows the number of bits of entropy for 2 characters of hex starting with F", function(done) {
2322 testEntropyBits(done, "FA", "8");
2323});
2324it("Shows the number of bits of entropy for 4 characters of hex with leading zeros", function(done) {
2325 testEntropyBits(done, "000A", "16");
2326});
2327it("Shows the number of bits of entropy for 4 characters of base 6", function(done) {
2328 testEntropyBits(done, "5555", "11");
2329});
2330it("Shows the number of bits of entropy for 4 characters of base 6 dice", function(done) {
2331 // uses dice, so entropy is actually 0000 in base 6, which is 4 lots of
2332 // 2.58 bits, which is 10.32 bits (rounded down to 10 bits)
2333 testEntropyBits(done, "6666", "10");
2334});
2335it("Shows the number of bits of entropy for 4 charactes of base 10", function(done) {
2336 // Uses base 10, which is 4 lots of 3.32 bits, which is 13.3 bits (rounded
2337 // down to 13)
2338 testEntropyBits(done, "2227", "13");
2339});
2340it("Shows the number of bits of entropy for 4 characters of hex with 2 leading zeros", function(done) {
2341 testEntropyBits(done, "222F", "16");
2342});
2343it("Shows the number of bits of entropy for 4 characters of hex starting with F", function(done) {
2344 testEntropyBits(done, "FFFF", "16");
2345});
2346it("Shows the number of bits of entropy for 10 characters of base 10", function(done) {
2347 // 10 events at 3.32 bits per event
2348 testEntropyBits(done, "0000101017", "33");
2349});
2350it("Shows the number of bits of entropy for a full deck of cards", function(done) {
2351 // cards are not replaced, so a full deck is not 52^52 entropy which is 296
2352 // bits, it's 52!, which is 225 bits
2353 testEntropyBits(done, "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks", "225");
2354});
2355
2356it("Shows details about the entered entropy", function(done) {
2357 testEntropyFeedback(done,
2358 {
2359 entropy: "A",
2360 filtered: "A",
2361 type: "hexadecimal",
2362 events: "1",
2363 bits: "4",
2364 words: 0,
2365 strength: "less than a second",
2366 }
2367 );
2368});
2369it("Shows details about the entered entropy", function(done) {
2370 testEntropyFeedback(done,
2371 {
2372 entropy: "AAAAAAAA",
2373 filtered: "AAAAAAAA",
2374 type: "hexadecimal",
2375 events: "8",
2376 bits: "32",
2377 words: 3,
2378 strength: "less than a second - Repeats like \"aaa\" are easy to guess",
2379 }
2380 );
2381});
2382it("Shows details about the entered entropy", function(done) {
2383 testEntropyFeedback(done,
2384 {
2385 entropy: "AAAAAAAA B",
2386 filtered: "AAAAAAAAB",
2387 type: "hexadecimal",
2388 events: "9",
2389 bits: "36",
2390 words: 3,
2391 strength: "less than a second - Repeats like \"aaa\" are easy to guess",
2392 }
2393 );
2394});
2395it("Shows details about the entered entropy", function(done) {
2396 testEntropyFeedback(done,
2397 {
2398 entropy: "AAAAAAAA BBBBBBBB",
2399 filtered: "AAAAAAAABBBBBBBB",
2400 type: "hexadecimal",
2401 events: "16",
2402 bits: "64",
2403 words: 6,
2404 strength: "less than a second - Repeats like \"aaa\" are easy to guess",
2405 }
2406 );
2407});
2408it("Shows details about the entered entropy", function(done) {
2409 testEntropyFeedback(done,
2410 {
2411 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC",
2412 filtered: "AAAAAAAABBBBBBBBCCCCCCCC",
2413 type: "hexadecimal",
2414 events: "24",
2415 bits: "96",
2416 words: 9,
2417 strength: "less than a second",
2418 }
2419 );
2420});
2421it("Shows details about the entered entropy", function(done) {
2422 testEntropyFeedback(done,
2423 {
2424 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD",
2425 filtered: "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD",
2426 type: "hexadecimal",
2427 events: "32",
2428 bits: "128",
2429 words: 12,
2430 strength: "2 minutes",
2431 }
2432 );
2433});
2434it("Shows details about the entered entropy", function(done) {
2435 testEntropyFeedback(done,
2436 {
2437 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDA",
2438 filtered: "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDA",
2439 type: "hexadecimal",
2440 events: "32",
2441 bits: "128",
2442 words: 12,
2443 strength: "2 days",
2444 }
2445 );
2446});
2447it("Shows details about the entered entropy", function(done) {
2448 testEntropyFeedback(done,
2449 {
2450 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDA EEEEEEEE",
2451 filtered: "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDAEEEEEEEE",
2452 type: "hexadecimal",
2453 events: "40",
2454 bits: "160",
2455 words: 15,
2456 strength: "3 years",
2457 }
2458 );
2459});
2460it("Shows details about the entered entropy", function(done) {
2461 testEntropyFeedback(done,
2462 {
2463 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDA EEEEEEEE FFFFFFFF",
2464 filtered: "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDAEEEEEEEEFFFFFFFF",
2465 type: "hexadecimal",
2466 events: "48",
2467 bits: "192",
2468 words: 18,
2469 strength: "centuries",
2470 }
2471 );
2472});
2473it("Shows details about the entered entropy", function(done) {
2474 testEntropyFeedback(done,
2475 {
2476 entropy: "7d",
2477 type: "card",
2478 events: "1",
2479 bits: "4",
2480 words: 0,
2481 strength: "less than a second",
2482 }
2483 );
2484});
2485it("Shows details about the entered entropy", function(done) {
2486 testEntropyFeedback(done,
2487 {
2488 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
2489 type: "card (full deck)",
2490 events: "52",
2491 bits: "225",
2492 words: 21,
2493 strength: "centuries",
2494 }
2495 );
2496});
2497it("Shows details about the entered entropy", function(done) {
2498 testEntropyFeedback(done,
2499 {
2500 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks3d",
2501 type: "card (full deck, 1 duplicate: 3d)",
2502 events: "53",
2503 bits: "254",
2504 words: 21,
2505 strength: "centuries",
2506 }
2507 );
2508});
2509it("Shows details about the entered entropy", function(done) {
2510 testEntropyFeedback(done,
2511 {
2512 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqs3d4d",
2513 type: "card (2 duplicates: 3d 4d, 1 missing: KS)",
2514 events: "53",
2515 bits: "254",
2516 words: 21,
2517 strength: "centuries",
2518 }
2519 );
2520});
2521it("Shows details about the entered entropy", function(done) {
2522 testEntropyFeedback(done,
2523 {
2524 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqs3d4d5d6d",
2525 type: "card (4 duplicates: 3d 4d 5d..., 1 missing: KS)",
2526 events: "55",
2527 bits: "264",
2528 words: 24,
2529 strength: "centuries",
2530 }
2531 );
2532});
2533it("Shows details about the entered entropy", function(done) {
2534 testEntropyFeedback(done,
2535 // Next test was throwing uncaught error in zxcvbn
2536 // Also tests 451 bits, ie Math.log2(52!)*2 = 225.58 * 2
2537 {
2538 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsksac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
2539 type: "card (full deck, 52 duplicates: ac 2c 3c...)",
2540 events: "104",
2541 bits: "499",
2542 words: 45,
2543 strength: "centuries",
2544 }
2545 );
2546});
2547it("Shows details about the entered entropy", function(done) {
2548 testEntropyFeedback(done,
2549 // Case insensitivity to duplicate cards
2550 {
2551 entropy: "asAS",
2552 type: "card (1 duplicate: AS)",
2553 events: "2",
2554 bits: "9",
2555 words: 0,
2556 strength: "less than a second",
2557 }
2558 );
2559});
2560it("Shows details about the entered entropy", function(done) {
2561 testEntropyFeedback(done,
2562 {
2563 entropy: "ASas",
2564 type: "card (1 duplicate: as)",
2565 events: "2",
2566 bits: "9",
2567 words: 0,
2568 strength: "less than a second",
2569 }
2570 );
2571});
2572it("Shows details about the entered entropy", function(done) {
2573 testEntropyFeedback(done,
2574 // Missing cards are detected
2575 {
2576 entropy: "ac2c3c4c5c6c7c8c tcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
2577 type: "card (1 missing: 9C)",
2578 events: "51",
2579 bits: "221",
2580 words: 18,
2581 strength: "centuries",
2582 }
2583 );
2584});
2585it("Shows details about the entered entropy", function(done) {
2586 testEntropyFeedback(done,
2587 {
2588 entropy: "ac2c3c4c5c6c7c8c tcjcqckcad2d3d4d 6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
2589 type: "card (2 missing: 9C 5D)",
2590 events: "50",
2591 bits: "216",
2592 words: 18,
2593 strength: "centuries",
2594 }
2595 );
2596});
2597it("Shows details about the entered entropy", function(done) {
2598 testEntropyFeedback(done,
2599 {
2600 entropy: "ac2c3c4c5c6c7c8c tcjcqckcad2d3d4d 6d7d8d9dtdjd kdah2h3h 5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
2601 type: "card (4 missing: 9C 5D QD...)",
2602 events: "48",
2603 bits: "208",
2604 words: 18,
2605 strength: "centuries",
2606 }
2607 );
2608});
2609it("Shows details about the entered entropy", function(done) {
2610 testEntropyFeedback(done,
2611 // More than six missing cards does not show message
2612 {
2613 entropy: "ac2c3c4c5c6c7c8c tcjcqckcad2d3d4d 6d 8d9d jd kdah2h3h 5h6h7h8h9hthjhqhkh 2s3s4s5s6s7s8s9stsjsqsks",
2614 type: "card",
2615 events: "45",
2616 bits: "195",
2617 words: 18,
2618 strength: "centuries",
2619 }
2620 );
2621});
2622it("Shows details about the entered entropy", function(done) {
2623 testEntropyFeedback(done,
2624 // Multiple decks of cards increases bits per event
2625 {
2626 entropy: "3d",
2627 events: "1",
2628 bits: "4",
2629 bitsPerEvent: "4.34",
2630 }
2631 );
2632});
2633it("Shows details about the entered entropy", function(done) {
2634 testEntropyFeedback(done,
2635 {
2636 entropy: "3d3d",
2637 events: "2",
2638 bits: "9",
2639 bitsPerEvent: "4.80",
2640 }
2641 );
2642});
2643it("Shows details about the entered entropy", function(done) {
2644 testEntropyFeedback(done,
2645 {
2646 entropy: "3d3d3d",
2647 events: "3",
2648 bits: "15",
2649 bitsPerEvent: "5.01",
2650 }
2651 );
2652});
2653it("Shows details about the entered entropy", function(done) {
2654 testEntropyFeedback(done,
2655 {
2656 entropy: "3d3d3d3d",
2657 events: "4",
2658 bits: "20",
2659 bitsPerEvent: "5.14",
2660 }
2661 );
2662});
2663it("Shows details about the entered entropy", function(done) {
2664 testEntropyFeedback(done,
2665 {
2666 entropy: "3d3d3d3d3d",
2667 events: "5",
2668 bits: "26",
2669 bitsPerEvent: "5.22",
2670 }
2671 );
2672});
2673it("Shows details about the entered entropy", function(done) {
2674 testEntropyFeedback(done,
2675 {
2676 entropy: "3d3d3d3d3d3d",
2677 events: "6",
2678 bits: "31",
2679 bitsPerEvent: "5.28",
2680 }
2681 );
2682});
2683it("Shows details about the entered entropy", function(done) {
2684 testEntropyFeedback(done,
2685 {
2686 entropy: "3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d",
2687 events: "33",
2688 bits: "184",
2689 bitsPerEvent: "5.59",
2690 strength: 'less than a second - Repeats like "abcabcabc" are only slightly harder to guess than "abc"',
2691 }
2692 );
2693});
2694
2695// Entropy is truncated from the left
2696it('Truncates entropy from the left', function(done) {
2697 // Truncate from left means 0000 is removed from the start
2698 // which gives mnemonic 'avocado zoo zone'
2699 // not 1111 removed from the end
2700 // which gives the mnemonic 'abstract zoo zoo'
2701 var entropy = "00000000 00000000 00000000 00000000";
2702 entropy += "11111111 11111111 11111111 1111"; // Missing last byte
2703 driver.findElement(By.css('.use-entropy'))
2704 .click();
2705 driver.findElement(By.css('.entropy'))
2706 .sendKeys(entropy);
2707 driver.sleep(generateDelay).then(function() {
2708 driver.findElement(By.css(".phrase"))
2709 .getAttribute("value").then(function(phrase) {
2710 expect(phrase).toBe("avocado zoo zone");
2711 done();
2712 });
2713 });
2714});
2715
2716// Very large entropy results in very long mnemonics
2717it('Converts very long entropy to very long mnemonics', function(done) {
2718 var entropy = "";
2719 for (var i=0; i<33; i++) {
2720 entropy += "AAAAAAAA"; // 3 words * 33 iterations = 99 words
2721 }
2722 driver.findElement(By.css('.use-entropy'))
2723 .click();
2724 driver.findElement(By.css('.entropy'))
2725 .sendKeys(entropy);
2726 driver.sleep(generateDelay).then(function() {
2727 driver.findElement(By.css(".phrase"))
2728 .getAttribute("value").then(function(phrase) {
2729 var wordCount = phrase.split(/\s+/g).length;
2730 expect(wordCount).toBe(99);
2731 done();
2732 });
2733 });
2734});
2735
2736// Is compatible with bip32jp entropy
2737// https://bip32jp.github.io/english/index.html
2738// NOTES:
2739// Is incompatible with:
2740// base 20
2741it('Is compatible with bip32jp.github.io', function(done) {
2742 var entropy = "543210543210543210543210543210543210543210543210543210543210543210543210543210543210543210543210543";
2743 var expectedPhrase = "train then jungle barely whip fiber purpose puppy eagle cloud clump hospital robot brave balcony utility detect estate old green desk skill multiply virus";
2744 driver.findElement(By.css('.use-entropy'))
2745 .click();
2746 driver.findElement(By.css('.entropy'))
2747 .sendKeys(entropy);
2748 driver.sleep(generateDelay).then(function() {
2749 driver.findElement(By.css(".phrase"))
2750 .getAttribute("value").then(function(phrase) {
2751 expect(phrase).toBe(expectedPhrase);
2752 done();
2753 });
2754 });
2755});
2756
2757// Blank entropy does not generate mnemonic or addresses
2758it('Does not generate mnemonic for blank entropy', function(done) {
2759 driver.findElement(By.css('.use-entropy'))
2760 .click();
2761 driver.findElement(By.css('.entropy'))
2762 .clear();
2763 // check there is no mnemonic
2764 driver.sleep(generateDelay).then(function() {
2765 driver.findElement(By.css(".phrase"))
2766 .getAttribute("value").then(function(phrase) {
2767 expect(phrase).toBe("");
2768 // check there is no mnemonic
2769 driver.findElements(By.css(".address"))
2770 .then(function(addresses) {
2771 expect(addresses.length).toBe(0);
2772 // Check the feedback says 'blank entropy'
2773 driver.findElement(By.css(".feedback"))
2774 .getText()
2775 .then(function(feedbackText) {
2776 expect(feedbackText).toBe("Blank entropy");
2777 done();
2778 });
2779 })
2780 });
2781 });
2782});
2783
2784// Mnemonic length can be selected even for weak entropy
2785it('Allows selection of mnemonic length even for weak entropy', function(done) {
2786 driver.findElement(By.css('.use-entropy'))
2787 .click();
2788 driver.executeScript(function() {
2789 $(".mnemonic-length").val("18").trigger("change");
2790 });
2791 driver.findElement(By.css('.entropy'))
2792 .sendKeys("012345");
2793 driver.sleep(generateDelay).then(function() {
2794 driver.findElement(By.css(".phrase"))
2795 .getAttribute("value").then(function(phrase) {
2796 var wordCount = phrase.split(/\s+/g).length;
2797 expect(wordCount).toBe(18);
2798 done();
2799 });
2800 });
2801});
2802
2803// Github issue 33
2804// https://github.com/iancoleman/bip39/issues/33
2805// Final cards should contribute entropy
2806it('Uses as much entropy as possible for the mnemonic', function(done) {
2807 driver.findElement(By.css('.use-entropy'))
2808 .click();
2809 driver.findElement(By.css('.entropy'))
2810 .sendKeys("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");
2811 driver.sleep(generateDelay).then(function() {
2812 // Get mnemonic
2813 driver.findElement(By.css(".phrase"))
2814 .getAttribute("value").then(function(originalPhrase) {
2815 // Set the last 12 cards to be AS
2816 driver.findElement(By.css('.entropy'))
2817 .clear();
2818 driver.findElement(By.css('.entropy'))
2819 .sendKeys("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-AS AS AS AS AS AS AS AS AS AS AS AS");
2820 driver.sleep(generateDelay).then(function() {
2821 // Get new mnemonic
2822 driver.findElement(By.css(".phrase"))
2823 .getAttribute("value").then(function(newPhrase) {
2824 expect(originalPhrase).not.toEqual(newPhrase);
2825 done();
2826 });
2827 });
2828 });
2829 });
2830});
2831
2832// Github issue 35
2833// https://github.com/iancoleman/bip39/issues/35
2834// QR Code support
2835// TODO this doesn't work in selenium with firefox
2836// see https://stackoverflow.com/q/40360223
2837it('Shows a qr code on hover for the phrase', function(done) {
2838 if (browser == "firefox") {
2839 pending("Selenium + Firefox bug for mouseMove, see https://stackoverflow.com/q/40360223");
2840 }
2841 // generate a random mnemonic
2842 var generateEl = driver.findElement(By.css('.generate'));
2843 generateEl.click();
2844 // toggle qr to show (hidden by default)
2845 var phraseEl = driver.findElement(By.css(".phrase"));
2846 phraseEl.click();
2847 var rootKeyEl = driver.findElement(By.css(".root-key"));
2848 driver.sleep(generateDelay).then(function() {
2849 // hover over the root key
2850 driver.actions().mouseMove(rootKeyEl).perform().then(function() {
2851 // check the qr code shows
2852 driver.executeScript(function() {
2853 return $(".qr-container").find("canvas").length > 0;
2854 })
2855 .then(function(qrShowing) {
2856 expect(qrShowing).toBe(true);
2857 // hover away from the phrase
2858 driver.actions().mouseMove(generateEl).perform().then(function() {;
2859 // check the qr code hides
2860 driver.executeScript(function() {
2861 return $(".qr-container").find("canvas").length == 0;
2862 })
2863 .then(function(qrHidden) {
2864 expect(qrHidden).toBe(true);
2865 done();
2866 });
2867 });
2868 });
2869 });
2870 });
2871});
2872
2873// BIP44 account extendend private key is shown
2874// github issue 37 - compatibility with electrum
2875it('Shows the bip44 account extended private key', function(done) {
2876 driver.findElement(By.css(".phrase"))
2877 .sendKeys("abandon abandon ability");
2878 driver.sleep(generateDelay).then(function() {
2879 driver.findElement(By.css("#bip44 .account-xprv"))
2880 .getAttribute("value")
2881 .then(function(xprv) {
2882 expect(xprv).toBe("xprv9yzrnt4zWVJUr1k2VxSPy9ettKz5PpeDMgaVG7UKedhqnw1tDkxP2UyYNhuNSumk2sLE5ctwKZs9vwjsq3e1vo9egCK6CzP87H2cVYXpfwQ");
2883 done();
2884 });
2885 });
2886});
2887
2888// BIP44 account extendend public key is shown
2889// github issue 37 - compatibility with electrum
2890it('Shows the bip44 account extended public key', function(done) {
2891 driver.findElement(By.css(".phrase"))
2892 .sendKeys("abandon abandon ability");
2893 driver.sleep(generateDelay).then(function() {
2894 driver.findElement(By.css("#bip44 .account-xpub"))
2895 .getAttribute("value")
2896 .then(function(xprv) {
2897 expect(xprv).toBe("xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf");
2898 done();
2899 });
2900 });
2901});
2902
2903// github issue 40
2904// BIP32 root key can be set as an xpub
2905it('Generates addresses from xpub as bip32 root key', function(done) {
2906 driver.findElement(By.css('#bip32-tab a'))
2907 .click();
2908 // set xpub for account 0 of bip44 for 'abandon abandon ability'
2909 driver.findElement(By.css("#root-key"))
2910 .sendKeys("xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf");
2911 driver.sleep(generateDelay).then(function() {
2912 // check the addresses are generated
2913 getFirstAddress(function(address) {
2914 expect(address).toBe("1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug");
2915 // check the xprv key is not set
2916 driver.findElement(By.css(".extended-priv-key"))
2917 .getAttribute("value")
2918 .then(function(xprv) {
2919 expect(xprv).toBe("NA");
2920 // check the private key is not set
2921 driver.findElements(By.css(".privkey"))
2922 .then(function(els) {
2923 els[0]
2924 .getText()
2925 .then(function(privkey) {
2926 expect(xprv).toBe("NA");
2927 done();
2928 });
2929 });
2930 });
2931 });
2932 });
2933});
2934
2935// github issue 40
2936// xpub for bip32 root key will not work with hardened derivation paths
2937it('Shows error for hardened derivation paths with xpub root key', function(done) {
2938 // set xpub for account 0 of bip44 for 'abandon abandon ability'
2939 driver.findElement(By.css("#root-key"))
2940 .sendKeys("xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf");
2941 driver.sleep(feedbackDelay).then(function() {
2942 // Check feedback is correct
2943 driver.findElement(By.css('.feedback'))
2944 .getText()
2945 .then(function(feedback) {
2946 var msg = "Hardened derivation path is invalid with xpub key";
2947 expect(feedback).toBe(msg);
2948 // Check no addresses are shown
2949 driver.findElements(By.css('.addresses tr'))
2950 .then(function(rows) {
2951 expect(rows.length).toBe(0);
2952 done();
2953 });
2954 });
2955 });
2956});
2957
2958// github issue 39
2959// no root key shows feedback
2960it('Shows feedback for no root key', function(done) {
2961 // set xpub for account 0 of bip44 for 'abandon abandon ability'
2962 driver.findElement(By.css('#bip32-tab a'))
2963 .click();
2964 driver.sleep(feedbackDelay).then(function() {
2965 // Check feedback is correct
2966 driver.findElement(By.css('.feedback'))
2967 .getText()
2968 .then(function(feedback) {
2969 expect(feedback).toBe("Invalid root key");
2970 done();
2971 });
2972 });
2973});
2974
2975// Github issue 44
2976// display error switching tabs while addresses are generating
2977it('Can change details while old addresses are still being generated', function(done) {
2978 // Set to generate 199 more addresses.
2979 // This will take a long time allowing a new set of addresses to be
2980 // generated midway through this lot.
2981 // The newly generated addresses should not include any from the old set.
2982 // Any more than 199 will show an alert which needs to be accepted.
2983 driver.findElement(By.css('.rows-to-add'))
2984 .clear();
2985 driver.findElement(By.css('.rows-to-add'))
2986 .sendKeys('199');
2987 // set the prhase
2988 driver.findElement(By.css('.phrase'))
2989 .sendKeys("abandon abandon ability");
2990 driver.sleep(generateDelay).then(function() {
0460b53f 2991 // change tabs which should cancel the previous generating
5dfe77e4
IC
2992 driver.findElement(By.css('.rows-to-add'))
2993 .clear();
2994 driver.findElement(By.css('.rows-to-add'))
2995 .sendKeys('20');
0460b53f
IC
2996 driver.findElement(By.css('#bip32-tab a'))
2997 .click()
2998 driver.sleep(generateDelay).then(function() {
2999 driver.findElements(By.css('.index'))
3000 .then(function(els) {
3001 // check the derivation paths have the right quantity
3002 expect(els.length).toBe(20);
3003 // check the derivation paths are in order
3004 testRowsAreInCorrectOrder(done);
3005 });
3006 });
3007 });
628a2f53 3008}, generateDelay + 10000);
0460b53f
IC
3009
3010// Github issue 49
3011// padding for binary should give length with multiple of 256
3012// hashed entropy 1111 is length 252, so requires 4 leading zeros
3013// prior to issue 49 it would only generate 2 leading zeros, ie missing 2
3014it('Pads hashed entropy with leading zeros', function(done) {
3015 driver.findElement(By.css('.use-entropy'))
3016 .click();
3017 driver.executeScript(function() {
3018 $(".mnemonic-length").val("15").trigger("change");
3019 });
3020 driver.findElement(By.css('.entropy'))
3021 .sendKeys("1111");
3022 driver.sleep(generateDelay).then(function() {
3023 driver.findElement(By.css('.phrase'))
3024 .getAttribute("value")
3025 .then(function(phrase) {
3026 expect(phrase).toBe("avocado valid quantum cross link predict excuse edit street able flame large galaxy ginger nuclear");
3027 done();
3028 });
3029 });
3030});
3031
3032// Github pull request 55
3033// https://github.com/iancoleman/bip39/pull/55
3034// Client select
3035it('Can set the derivation path on bip32 tab for bitcoincore', function(done) {
3036 testClientSelect(done, {
3037 selectValue: "0",
3038 bip32path: "m/0'/0'",
3039 useHardenedAddresses: "true",
3040 });
3041});
3042it('Can set the derivation path on bip32 tab for multibit', function(done) {
3043 testClientSelect(done, {
3044 selectValue: "2",
3045 bip32path: "m/0'/0",
3046 useHardenedAddresses: null,
3047 });
3048});
44a5d363
IC
3049it('Can set the derivation path on bip32 tab for coinomi/ledger', function(done) {
3050 testClientSelect(done, {
3051 selectValue: "3",
3052 bip32path: "m/44'/0'/0'",
3053 useHardenedAddresses: null,
3054 });
3055});
0460b53f
IC
3056
3057// github issue 58
3058// https://github.com/iancoleman/bip39/issues/58
3059// bip32 derivation is correct, does not drop leading zeros
3060// see also
3061// https://medium.com/@alexberegszaszi/why-do-my-bip32-wallets-disagree-6f3254cc5846
3062it('Retains leading zeros for bip32 derivation', function(done) {
3063 driver.findElement(By.css(".phrase"))
3064 .sendKeys("fruit wave dwarf banana earth journey tattoo true farm silk olive fence");
3065 driver.findElement(By.css(".passphrase"))
3066 .sendKeys("banana");
3067 driver.sleep(generateDelay).then(function() {
3068 getFirstAddress(function(address) {
3069 // Note that bitcore generates an incorrect address
3070 // 13EuKhffWkBE2KUwcbkbELZb1MpzbimJ3Y
3071 // see the medium.com link above for more details
3072 expect(address).toBe("17rxURoF96VhmkcEGCj5LNQkmN9HVhWb7F");
3073 done();
3074 });
3075 });
3076});
3077
3078// github issue 60
3079// Japanese mnemonics generate incorrect bip32 seed
3080// BIP39 seed is set from phrase
3081it('Generates correct seed for Japanese mnemonics', function(done) {
3082 driver.findElement(By.css(".phrase"))
3083 .sendKeys("あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あおぞら");
3084 driver.findElement(By.css(".passphrase"))
3085 .sendKeys("メートルガバヴァぱばぐゞちぢ十人十色");
3086 driver.sleep(generateDelay).then(function() {
3087 driver.findElement(By.css(".seed"))
3088 .getAttribute("value")
3089 .then(function(seed) {
3090 expect(seed).toBe("a262d6fb6122ecf45be09c50492b31f92e9beb7d9a845987a02cefda57a15f9c467a17872029a9e92299b5cbdf306e3a0ee620245cbd508959b6cb7ca637bd55");
3091 done();
3092 });
3093 });
3094});
3095
3096// BIP49 official test vectors
3097// https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki#test-vectors
3098it('Generates BIP49 addresses matching the official test vectors', function(done) {
3099 driver.findElement(By.css('#bip49-tab a'))
3100 .click();
3101 selectNetwork("BTC - Bitcoin Testnet");
3102 driver.findElement(By.css(".phrase"))
3103 .sendKeys("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about");
3104 driver.sleep(generateDelay).then(function() {
3105 getFirstAddress(function(address) {
3106 expect(address).toBe("2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2");
3107 done();
3108 });
3109 });
3110});
3111
3112// BIP49 derivation path is shown
3113it('Shows the bip49 derivation path', function(done) {
3114 driver.findElement(By.css('#bip49-tab a'))
3115 .click();
3116 driver.findElement(By.css(".phrase"))
3117 .sendKeys("abandon abandon ability");
3118 driver.sleep(generateDelay).then(function() {
3119 driver.findElement(By.css('#bip49 .path'))
3120 .getAttribute("value")
3121 .then(function(path) {
3122 expect(path).toBe("m/49'/0'/0'/0");
3123 done();
3124 });
3125 });
3126});
3127
3128// BIP49 extended private key is shown
3129it('Shows the bip49 extended private key', function(done) {
3130 driver.findElement(By.css('#bip49-tab a'))
3131 .click();
3132 driver.findElement(By.css(".phrase"))
3133 .sendKeys("abandon abandon ability");
3134 driver.sleep(generateDelay).then(function() {
3135 driver.findElement(By.css('.extended-priv-key'))
3136 .getAttribute("value")
3137 .then(function(xprv) {
3138 expect(xprv).toBe("yprvALYB4DYRG6CzzVgzQZwwqjAA2wjBGC3iEd7KYYScpoDdmf75qMRWZWxoFcRXBJjgEXdFqJ9vDRGRLJQsrL22Su5jMbNFeM9vetaGVqy9Qy2");
3139 done();
3140 });
3141 });
3142});
3143
3144// BIP49 extended public key is shown
3145it('Shows the bip49 extended public key', function(done) {
3146 driver.findElement(By.css('#bip49-tab a'))
3147 .click();
3148 driver.findElement(By.css(".phrase"))
3149 .sendKeys("abandon abandon ability");
3150 driver.sleep(generateDelay).then(function() {
3151 driver.findElement(By.css('.extended-pub-key'))
3152 .getAttribute("value")
3153 .then(function(xprv) {
3154 expect(xprv).toBe("ypub6ZXXTj5K6TmJCymTWbUxCs6tayZffemZbr2vLvrEP8kceTSENtjm7KHH6thvAKxVar9fGe8rgsPEX369zURLZ68b4f7Vexz7RuXsjQ69YDt");
3155 done();
3156 });
3157 });
3158});
3159
3160// BIP49 account field changes address list
3161it('Can set the bip49 account field', function(done) {
3162 driver.findElement(By.css('#bip49-tab a'))
3163 .click();
3164 driver.findElement(By.css('#bip49 .account'))
3165 .clear();
3166 driver.findElement(By.css('#bip49 .account'))
3167 .sendKeys("1");
3168 driver.findElement(By.css(".phrase"))
3169 .sendKeys("abandon abandon ability");
3170 driver.sleep(generateDelay).then(function() {
3171 getFirstAddress(function(address) {
3172 expect(address).toBe("381wg1GGN4rP88rNC9v7QWsiww63yLVPsn");
3173 done();
3174 });
3175 });
3176});
3177
3178// BIP49 change field changes address list
3179it('Can set the bip49 change field', function(done) {
3180 driver.findElement(By.css('#bip49-tab a'))
3181 .click();
3182 driver.findElement(By.css('#bip49 .change'))
3183 .clear();
3184 driver.findElement(By.css('#bip49 .change'))
3185 .sendKeys("1");
3186 driver.findElement(By.css(".phrase"))
3187 .sendKeys("abandon abandon ability");
3188 driver.sleep(generateDelay).then(function() {
3189 getFirstAddress(function(address) {
3190 expect(address).toBe("3PEM7MiKed5konBoN66PQhK8r3hjGhy9dT");
3191 done();
3192 });
3193 });
3194});
3195
3196// BIP49 account extendend private key is shown
3197it('Shows the bip49 account extended private key', function(done) {
3198 driver.findElement(By.css('#bip49-tab a'))
3199 .click();
3200 driver.findElement(By.css(".phrase"))
3201 .sendKeys("abandon abandon ability");
3202 driver.sleep(generateDelay).then(function() {
3203 driver.findElement(By.css('#bip49 .account-xprv'))
3204 .getAttribute("value")
3205 .then(function(xprv) {
3206 expect(xprv).toBe("yprvAHtB1M5Wp675aLzFy9TJYK2mSsLkg6mcBRh5DZTR7L4EnYSmYPaL63KFA4ycg1PngW5LfkmejxzosCs17TKZMpRFKc3z5SJar6QAKaFcaZL");
3207 done();
3208 });
3209 });
3210});
3211
3212// BIP49 account extendend public key is shown
3213it('Shows the bip49 account extended public key', function(done) {
3214 driver.findElement(By.css('#bip49-tab a'))
3215 .click();
3216 driver.findElement(By.css(".phrase"))
3217 .sendKeys("abandon abandon ability");
3218 driver.sleep(generateDelay).then(function() {
3219 driver.findElement(By.css('#bip49 .account-xpub'))
3220 .getAttribute("value")
3221 .then(function(xprv) {
3222 expect(xprv).toBe("ypub6WsXQrcQeTfNnq4j5AzJuSyVzuBF5ZVTYecg1ws2ffbDfLmv5vtadqdj1NgR6C6gufMpMfJpHxvb6JEQKvETVNWCRanNedfJtnTchZiJtsL");
3223 done();
3224 });
3225 });
3226});
3227
3228// Test selecting coin where bip49 is unavailable (eg CLAM)
3229it('Shows an error on bip49 tab for coins without bip49', function(done) {
3230 driver.findElement(By.css('#bip49-tab a'))
3231 .click();
3232 driver.findElement(By.css(".phrase"))
3233 .sendKeys("abandon abandon ability");
3234 driver.sleep(generateDelay).then(function() {
3235 selectNetwork("CLAM - Clams");
3236 // bip49 available is hidden
3237 driver.findElement(By.css('#bip49 .available'))
3238 .getAttribute("class")
3239 .then(function(classes) {
3240 expect(classes).toContain("hidden");
3241 // bip49 unavailable is shown
3242 driver.findElement(By.css('#bip49 .unavailable'))
3243 .getAttribute("class")
3244 .then(function(classes) {
3245 expect(classes).not.toContain("hidden");
3246 // check there are no addresses shown
3247 driver.findElements(By.css('.addresses tr'))
3248 .then(function(rows) {
3249 expect(rows.length).toBe(0);
3250 // check the derived private key is blank
3251 driver.findElement(By.css('.extended-priv-key'))
3252 .getAttribute("value")
3253 .then(function(xprv) {
3254 expect(xprv).toBe('');
3255 // check the derived public key is blank
3256 driver.findElement(By.css('.extended-pub-key'))
3257 .getAttribute("value")
3258 .then(function(xpub) {
3259 expect(xpub).toBe('');
3260 done();
3261 });
3262 });
3263 })
3264 });
3265 });
3266 });
3267});
3268
3269// github issue 43
3270// Cleared mnemonic and root key still allows addresses to be generated
3271// https://github.com/iancoleman/bip39/issues/43
3272it('Clears old root keys from memory when mnemonic is cleared', function(done) {
3273 // set the phrase
3274 driver.findElement(By.css(".phrase"))
3275 .sendKeys("abandon abandon ability");
3276 driver.sleep(generateDelay).then(function() {
3277 // clear the mnemonic and root key
3278 // using selenium .clear() doesn't seem to trigger the 'input' event
3279 // so clear it using keys instead
3280 driver.findElement(By.css('.phrase'))
3281 .sendKeys(Key.CONTROL,"a");
3282 driver.findElement(By.css('.phrase'))
3283 .sendKeys(Key.DELETE);
3284 driver.findElement(By.css('.root-key'))
3285 .sendKeys(Key.CONTROL,"a");
3286 driver.findElement(By.css('.root-key'))
3287 .sendKeys(Key.DELETE);
3288 driver.sleep(generateDelay).then(function() {
3289 // try to generate more addresses
3290 driver.findElement(By.css('.more'))
3291 .click();
3292 driver.sleep(generateDelay).then(function() {
3293 driver.findElements(By.css(".addresses tr"))
3294 .then(function(els) {
3295 // check there are no addresses shown
3296 expect(els.length).toBe(0);
3297 done();
3298 });
3299 });
3300 });
3301 });
3302});
3303
3304// Github issue 95
3305// error trying to generate addresses from xpub with hardened derivation
3306it('Shows error for hardened addresses with xpub root key', function(done) {
3307 driver.findElement(By.css('#bip32-tab a'))
3308 .click()
3309 driver.executeScript(function() {
3310 $(".hardened-addresses").prop("checked", true);
3311 });
3312 // set xpub for account 0 of bip44 for 'abandon abandon ability'
3313 driver.findElement(By.css("#root-key"))
3314 .sendKeys("xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf");
3315 driver.sleep(feedbackDelay).then(function() {
3316 // Check feedback is correct
3317 driver.findElement(By.css('.feedback'))
3318 .getText()
3319 .then(function(feedback) {
3320 var msg = "Hardened derivation path is invalid with xpub key";
3321 expect(feedback).toBe(msg);
3322 done();
3323 });
3324 });
3325});
3326
1c2b8c6b 3327// Litecoin uses ltub by default, and can optionally be set to xprv
0460b53f
IC
3328// github issue 96
3329// https://github.com/iancoleman/bip39/issues/96
3330// Issue with extended keys on Litecoin
1c2b8c6b 3331it('Uses ltub by default for litecoin, but can be set to xprv', function(done) {
0460b53f
IC
3332 driver.findElement(By.css('.phrase'))
3333 .sendKeys("abandon abandon ability");
3334 selectNetwork("LTC - Litecoin");
3335 driver.sleep(generateDelay).then(function() {
3336 // check the extended key is generated correctly
3337 driver.findElement(By.css('.root-key'))
3338 .getAttribute("value")
3339 .then(function(rootKey) {
1c2b8c6b 3340 expect(rootKey).toBe("Ltpv71G8qDifUiNesiPqf6h5V6eQ8ic77oxQiYtawiACjBEx3sTXNR2HGDGnHETYxESjqkMLFBkKhWVq67ey1B2MKQXannUqNy1RZVHbmrEjnEU");
0460b53f
IC
3341 // set litecoin to use ltub
3342 driver.executeScript(function() {
1c2b8c6b 3343 $(".litecoin-use-ltub").prop("checked", false);
0460b53f
IC
3344 $(".litecoin-use-ltub").trigger("change");
3345 });
3346 driver.sleep(generateDelay).then(function() {
3347 driver.findElement(By.css('.root-key'))
3348 .getAttribute("value")
3349 .then(function(rootKey) {
1c2b8c6b 3350 expect(rootKey).toBe("xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi");
0460b53f
IC
3351 done();
3352 });
3353 })
3354 });
3355 });
0460b53f
IC
3356});
3357
3358// github issue 99
3359// https://github.com/iancoleman/bip39/issues/99#issuecomment-327094159
3360// "warn me emphatically when they have detected invalid input" to the entropy field
3361// A warning is shown when entropy is filtered and discarded
3362it('Warns when entropy is filtered and discarded', function(done) {
3363 driver.findElement(By.css('.use-entropy'))
3364 .click();
3365 // set entropy to have no filtered content
3366 driver.findElement(By.css('.entropy'))
3367 .sendKeys("00000000 00000000 00000000 00000000");
3368 driver.sleep(generateDelay).then(function() {
3369 // check the filter warning does not show
3370 driver.findElement(By.css('.entropy-container .filter-warning'))
3371 .getAttribute("class")
3372 .then(function(classes) {
3373 expect(classes).toContain("hidden");
3374 // set entropy to have some filtered content
3375 driver.findElement(By.css('.entropy'))
3376 .sendKeys("10000000 zxcvbn 00000000 00000000 00000000");
3377 driver.sleep(entropyFeedbackDelay).then(function() {
3378 // check the filter warning shows
3379 driver.findElement(By.css('.entropy-container .filter-warning'))
3380 .getAttribute("class")
3381 .then(function(classes) {
3382 expect(classes).not.toContain("hidden");
3383 done();
3384 });
3385 });
3386 });
3387 });
3388});
3389
e0f91e20
IC
3390// Bitcoin Cash address can be set to use cashaddr format
3391it('Can use cashaddr format for bitcoin cash addresses', function(done) {
3392 driver.executeScript(function() {
3393 $(".use-bch-cashaddr-addresses").prop("checked", true);
3394 });
3395 driver.findElement(By.css('.phrase'))
3396 .sendKeys("abandon abandon ability");
3397 selectNetwork("BCH - Bitcoin Cash");
3398 driver.sleep(generateDelay).then(function() {
3399 getFirstAddress(function(address) {
3400 expect(address).toBe("bitcoincash:qzlquk7w4hkudxypl4fgv8x279r754dkvur7jpcsps");
3401 done();
3402 });
3403 });
3404});
3405
0460b53f
IC
3406// Bitcoin Cash address can be set to use bitpay format
3407it('Can use bitpay format for bitcoin cash addresses', function(done) {
3408 driver.executeScript(function() {
e0f91e20 3409 $(".use-bch-bitpay-addresses").prop("checked", true);
0460b53f
IC
3410 });
3411 driver.findElement(By.css('.phrase'))
3412 .sendKeys("abandon abandon ability");
3413 selectNetwork("BCH - Bitcoin Cash");
3414 driver.sleep(generateDelay).then(function() {
3415 getFirstAddress(function(address) {
3416 expect(address).toBe("CZnpA9HPmvhuhLLPWJP8rNDpLUYXy1LXFk");
3417 done();
3418 });
3419 });
3420});
3421
e0f91e20
IC
3422// Bitcoin Cash address can be set to use legacy format
3423it('Can use legacy format for bitcoin cash addresses', function(done) {
3424 driver.executeScript(function() {
3425 $(".use-bch-legacy-addresses").prop("checked", true);
3426 });
3427 driver.findElement(By.css('.phrase'))
3428 .sendKeys("abandon abandon ability");
3429 selectNetwork("BCH - Bitcoin Cash");
3430 driver.sleep(generateDelay).then(function() {
3431 getFirstAddress(function(address) {
3432 expect(address).toBe("1JKvb6wKtsjNoCRxpZ4DGrbniML7z5U16A");
3433 done();
3434 });
3435 });
3436});
3437
9183f9f6
IC
3438// End of tests ported from old suit, so no more comments above each test now
3439
3440it('Can generate more addresses from a custom index', function(done) {
3441 var expectedIndexes = [
3442 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
3443 40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59
3444 ];
3445 driver.findElement(By.css('.phrase'))
3446 .sendKeys("abandon abandon ability");
3447 driver.sleep(generateDelay).then(function() {
3448 // Set start of next lot of rows to be from index 40
3449 // which means indexes 20-39 will not be in the table.
3450 driver.findElement(By.css('.more-rows-start-index'))
3451 .sendKeys("40");
3452 driver.findElement(By.css('.more'))
3453 .click();
3454 driver.sleep(generateDelay).then(function() {
3455 // Check actual indexes in the table match the expected pattern
3456 driver.findElements(By.css(".index"))
3457 .then(function(els) {
3458 expect(els.length).toBe(expectedIndexes.length);
3459 var testRowAtIndex = function(i) {
3460 if (i >= expectedIndexes.length) {
3461 done();
3462 }
3463 else {
3464 els[i].getText()
3465 .then(function(actualPath) {
3466 var noHardened = actualPath.replace(/'/g, "");
3467 var pathBits = noHardened.split("/")
3468 var lastBit = pathBits[pathBits.length-1];
3469 var actualIndex = parseInt(lastBit);
3470 var expectedIndex = expectedIndexes[i];
3471 expect(actualIndex).toBe(expectedIndex);
3472 testRowAtIndex(i+1);
3473 });
3474 }
3475 }
3476 testRowAtIndex(0);
3477 });
3478 });
3479 });
3480});
3481
c49e8812
IC
3482it('Can generate BIP141 addresses with P2WPKH-in-P2SH semanitcs', function(done) {
3483 // Sourced from BIP49 official test specs
3484 driver.findElement(By.css('#bip141-tab a'))
3485 .click();
3486 driver.findElement(By.css('.bip141-path'))
3487 .clear();
3488 driver.findElement(By.css('.bip141-path'))
3489 .sendKeys("m/49'/1'/0'/0");
3490 selectNetwork("BTC - Bitcoin Testnet");
3491 driver.findElement(By.css(".phrase"))
3492 .sendKeys("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about");
3493 driver.sleep(generateDelay).then(function() {
3494 getFirstAddress(function(address) {
3495 expect(address).toBe("2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2");
3496 done();
3497 });
3498 });
3499});
3500
3501it('Can generate BIP141 addresses with P2WPKH semanitcs', function(done) {
3502 // This result tested against bitcoinjs-lib test spec for segwit address
3503 // using the first private key of this mnemonic and default path m/0
3504 // https://github.com/bitcoinjs/bitcoinjs-lib/blob/9c8503cab0c6c30a95127042703bc18e8d28c76d/test/integration/addresses.js#L50
3505 // so whilst not directly comparable, substituting the private key produces
3506 // identical results between this tool and the bitcoinjs-lib test.
3507 // Private key generated is:
3508 // L3L8Nu9whawPBNLGtFqDhKut9DKKfG3CQoysupT7BimqVCZsLFNP
3509 driver.findElement(By.css('#bip141-tab a'))
3510 .click();
3511 // Choose P2WPKH
3512 driver.executeScript(function() {
3513 $(".bip141-semantics option[selected]").removeAttr("selected");
3514 $(".bip141-semantics option").filter(function(i,e) {
3515 return $(e).html() == "P2WPKH";
3516 }).prop("selected", true);
3517 $(".bip141-semantics").trigger("change");
3518 });
3519 driver.findElement(By.css(".phrase"))
3520 .sendKeys("abandon abandon ability");
3521 driver.sleep(generateDelay).then(function() {
3522 getFirstAddress(function(address) {
3523 expect(address).toBe("bc1qfwu6a5a3evygrk8zvdxxvz4547lmpyx5vsfxe9");
3524 done();
3525 });
3526 });
3527});
3528
74ab4cbe
IC
3529it('Shows the entropy used by the PRNG when clicking generate', function(done) {
3530 driver.findElement(By.css('.generate')).click();
3531 driver.sleep(generateDelay).then(function() {
3532 driver.findElement(By.css('.entropy'))
3533 .getAttribute("value")
3534 .then(function(entropy) {
3535 expect(entropy).not.toBe("");
3536 done();
3537 });
3538 });
3539});
3540
3541it('Shows the index of each word in the mnemonic', function(done) {
3542 driver.findElement(By.css('.phrase'))
3543 .sendKeys("abandon abandon ability");
3544 driver.sleep(generateDelay).then(function() {
3545 driver.findElement(By.css('.use-entropy'))
3546 .click();
3547 driver.findElement(By.css('.word-indexes'))
3548 .getText()
3549 .then(function(indexes) {
3550 expect(indexes).toBe("0, 0, 1");
3551 done();
3552 });
3553 });
3554});
3555
4e9b492c
IC
3556it('Shows the derivation path for bip84 tab', function(done) {
3557 driver.findElement(By.css('#bip84-tab a'))
3558 .click()
3559 driver.findElement(By.css('.phrase'))
3560 .sendKeys('abandon abandon ability');
3561 driver.sleep(generateDelay).then(function() {
3562 driver.findElement(By.css('#bip84 .path'))
3563 .getAttribute("value")
3564 .then(function(path) {
3565 expect(path).toBe("m/84'/0'/0'/0");
3566 done();
3567 })
3568 });
3569});
3570
3571it('Shows the extended private key for bip84 tab', function(done) {
3572 driver.findElement(By.css('#bip84-tab a'))
3573 .click()
3574 driver.findElement(By.css('.phrase'))
3575 .sendKeys('abandon abandon ability');
3576 driver.sleep(generateDelay).then(function() {
3577 driver.findElement(By.css('.extended-priv-key'))
3578 .getAttribute("value")
3579 .then(function(path) {
3580 expect(path).toBe("zprvAev3RKrZ3QVKiUFCfdeMRen1BPDJgdNt1XpxiDy8acSs4kkAGTCvq7HeRYRNNpo8EtEjCFQBWavJwtCUR29y4TUCH4X5RXMcyq48uN8y9BP");
3581 done();
3582 })
3583 });
3584});
3585
3586it('Shows the extended public key for bip84 tab', function(done) {
3587 driver.findElement(By.css('#bip84-tab a'))
3588 .click()
3589 driver.findElement(By.css('.phrase'))
3590 .sendKeys('abandon abandon ability');
3591 driver.sleep(generateDelay).then(function() {
3592 driver.findElement(By.css('.extended-pub-key'))
3593 .getAttribute("value")
3594 .then(function(path) {
3595 expect(path).toBe("zpub6suPpqPSsn3cvxKfmfBMnnijjR3o666jNkkZWcNk8wyqwZ5JozXBNuc8Gs7DB3uLwTDvGVTspVEAUQcEjKF3pZHgywVbubdTqbXTUg7usyx");
3596 done();
3597 })
3598 });
3599});
3600
3601it('Changes the address list if bip84 account is changed', function(done) {
3602 driver.findElement(By.css('#bip84-tab a'))
3603 .click()
3604 driver.findElement(By.css('#bip84 .account'))
3605 .sendKeys('1');
3606 driver.findElement(By.css('.phrase'))
3607 .sendKeys('abandon abandon ability');
3608 driver.sleep(generateDelay).then(function() {
3609 getFirstAddress(function(address) {
3610 expect(address).toBe("bc1qp7vv669t2fy965jdzvqwrraana89ctd5ewc662");
3611 done();
3612 });
3613 });
3614});
3615
3616it('Changes the address list if bip84 change is changed', function(done) {
3617 driver.findElement(By.css('#bip84-tab a'))
3618 .click()
3619 driver.findElement(By.css('#bip84 .change'))
3620 .sendKeys('1');
3621 driver.findElement(By.css('.phrase'))
3622 .sendKeys('abandon abandon ability');
3623 driver.sleep(generateDelay).then(function() {
3624 getFirstAddress(function(address) {
3625 expect(address).toBe("bc1qr39vj6rh06ff05m53uxq8uazehwhccswylhrs2");
3626 done();
3627 });
3628 });
3629});
3630
3631it('Passes the official BIP84 test spec for rootpriv', function(done) {
3632 driver.findElement(By.css('#bip84-tab a'))
3633 .click()
3634 driver.findElement(By.css('.phrase'))
3635 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
3636 driver.sleep(generateDelay).then(function() {
3637 driver.findElement(By.css(".root-key"))
3638 .getAttribute("value")
3639 .then(function(rootKey) {
3640 expect(rootKey).toBe("zprvAWgYBBk7JR8Gjrh4UJQ2uJdG1r3WNRRfURiABBE3RvMXYSrRJL62XuezvGdPvG6GFBZduosCc1YP5wixPox7zhZLfiUm8aunE96BBa4Kei5");
3641 done();
3642 })
3643 });
3644});
3645
3646it('Passes the official BIP84 test spec for account 0 xprv', function(done) {
3647 driver.findElement(By.css('#bip84-tab a'))
3648 .click()
3649 driver.findElement(By.css('.phrase'))
3650 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
3651 driver.sleep(generateDelay).then(function() {
3652 driver.findElement(By.css("#bip84 .account-xprv"))
3653 .getAttribute("value")
3654 .then(function(rootKey) {
3655 expect(rootKey).toBe("zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE");
3656 done();
3657 })
3658 });
3659});
3660
3661it('Passes the official BIP84 test spec for account 0 xpub', function(done) {
3662 driver.findElement(By.css('#bip84-tab a'))
3663 .click()
3664 driver.findElement(By.css('.phrase'))
3665 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
3666 driver.sleep(generateDelay).then(function() {
3667 driver.findElement(By.css("#bip84 .account-xpub"))
3668 .getAttribute("value")
3669 .then(function(rootKey) {
3670 expect(rootKey).toBe("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs");
3671 done();
3672 })
3673 });
3674});
3675
3676it('Passes the official BIP84 test spec for account 0 first address', function(done) {
3677 driver.findElement(By.css('#bip84-tab a'))
3678 .click()
3679 driver.findElement(By.css('.phrase'))
3680 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
3681 driver.sleep(generateDelay).then(function() {
3682 getFirstAddress(function(address) {
3683 expect(address).toBe("bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu");
3684 done();
3685 });
3686 });
3687});
3688
3689it('Passes the official BIP84 test spec for account 0 first change address', function(done) {
3690 driver.findElement(By.css('#bip84-tab a'))
3691 .click()
3692 driver.findElement(By.css('.phrase'))
3693 .sendKeys('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about');
3694 driver.findElement(By.css('#bip84 .change'))
3695 .sendKeys('1');
3696 driver.sleep(generateDelay).then(function() {
3697 getFirstAddress(function(address) {
3698 expect(address).toBe("bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el");
3699 done();
3700 });
3701 });
3702});
3703
a78f4e28
IC
3704it('Can display the table as csv', function(done) {
3705 var headings = "path,address,public key,private key";
3706 var row1 = "m/44'/0'/0'/0/0,1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug,033f5aed5f6cfbafaf223188095b5980814897295f723815fea5d3f4b648d0d0b3,L26cVSpWFkJ6aQkPkKmTzLqTdLJ923e6CzrVh9cmx21QHsoUmrEE";
3707 var row20 = "m/44'/0'/0'/0/19,1KhBy28XLAciXnnRvm71PvQJaETyrxGV55,02b4b3e396434d8cdd20c03ac4aaa07387784d5d867b75987f516f5705ee68cb3a,L4GrDrjReMsCAu5DkLXn79jSb95qR7Zfx7eshybCQZ1qL32MXJab";
3708 driver.findElement(By.css('.phrase'))
3709 .sendKeys('abandon abandon ability');
3710 driver.sleep(generateDelay).then(function() {
3711 driver.findElement(By.css('.csv'))
3712 .getAttribute("value")
3713 .then(function(csv) {
3714 expect(csv).toContain(headings);
3715 expect(csv).toContain(row1);
3716 expect(csv).toContain(row20);
3717 done();
3718 });
3719 });
3720});
3721
78db37f6
IC
3722it('LeftPads ethereum keys that are less than 32 bytes', function(done) {
3723 // see https://github.com/iancoleman/bip39/issues/155
3724 selectNetwork("ETH - Ethereum");
3725 driver.findElement(By.css('#bip32-tab a'))
3726 .click()
3727 driver.findElement(By.css('#bip32-path'))
3728 .clear();
3729 driver.findElement(By.css('#bip32-path'))
3730 .sendKeys("m/44'/60'/0'");
3731 driver.findElement(By.css('.phrase'))
3732 .sendKeys('scout sort custom elite radar rare vivid thing trophy gesture cover snake change narrow kite list nation sustain buffalo erode open balance system young');
3733 driver.sleep(generateDelay).then(function() {
2ef27fb8
IC
3734 getFirstAddress(function(address) {
3735 expect(address).toBe("0x8943E785B4a5714FC87a3aFAad1eB1FeB602B118");
3736 done();
3737 });
78db37f6
IC
3738 });
3739});
3740
e21e32da
IC
3741it('Can encrypt private keys using BIP38', function(done) {
3742 // see https://github.com/iancoleman/bip39/issues/140
3743 driver.executeScript(function() {
3744 $(".use-bip38").prop("checked", true);
3745 });
3746 driver.findElement(By.css('.bip38-password'))
3747 .sendKeys('bip38password');
3748 driver.findElement(By.css('.rows-to-add'))
3749 .clear();
3750 driver.findElement(By.css('.rows-to-add'))
3751 .sendKeys('1');
3752 driver.findElement(By.css('.phrase'))
3753 .sendKeys('abandon abandon ability');
3754 driver.sleep(bip38delay).then(function() {
3755 // address
3756 getFirstRowValue(function(address) {
3757 expect(address).toBe("1NCvSdumA3ngMM9c4aqU56AM6rqXddfuXB");
3758 // pubkey
3759 getFirstRowValue(function(pubkey) {
3760 expect(pubkey).toBe("043f5aed5f6cfbafaf223188095b5980814897295f723815fea5d3f4b648d0d0b3884a74447ea901729b1e73a999b7520e7cb55b4120e6432c64153ccab8a848e1");
3761 // privkey
3762 getFirstRowValue(function(privkey) {
3763 expect(privkey).toBe("6PRNRiFnj1RoR3sXhymdCvoZCgnUHQpfupNdKkFbWJkwWQEKesWt1EDMDM");
3764 done();
3765 }, ".privkey");
3766 }, ".pubkey");
3767 }, ".address");
3768 });
3769}, bip38delay + 5000);
3770
09d63290
IC
3771it('Shows the checksum for the entropy', function(done) {
3772 driver.findElement(By.css('.use-entropy'))
3773 .click();
3774 driver.findElement(By.css('.entropy'))
3775 .sendKeys("00000000000000000000000000000000");
3776 driver.sleep(generateDelay).then(function() {
3777 driver.findElement(By.css('.checksum'))
3778 .getText()
3779 .then(function(text) {
3780 expect(text).toBe("1");
3781 done();
3782 });
3783 });
3784});
3785
f8ca25c3
IC
3786it('Shows the checksum for the entropy with the correct groupings', function(done) {
3787 driver.findElement(By.css('.use-entropy'))
3788 .click();
3789 // create a checksum of 20 bits, which spans multiple words
3790 driver.findElement(By.css('.entropy'))
3791 .sendKeys("F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
3792 driver.sleep(generateDelay).then(function() {
3793 driver.findElement(By.css('.checksum'))
3794 .getText()
3795 .then(function(text) {
3796 // first group is 9 bits, second group is 11
3797 expect(text).toBe("011010111 01110000110");
3798 done();
3799 });
3800 });
3801});
3802
38122a3d
IC
3803it('Uses vprv for bitcoin testnet p2wpkh', function(done) {
3804 selectNetwork("BTC - Bitcoin Testnet");
3805 driver.findElement(By.css('#bip84-tab a'))
3806 .click()
3807 driver.findElement(By.css('.phrase'))
3808 .sendKeys('abandon abandon ability');
3809 driver.sleep(generateDelay).then(function() {
3810 driver.findElement(By.css('.root-key'))
3811 .getAttribute("value")
3812 .then(function(path) {
3813 expect(path).toBe("vprv9DMUxX4ShgxML9N2YV5CvWEebWrM9aJ5ULpbRRyzyWu6vs4BzTvbfFFrH41N5hVi7MYSfiugd765L3JmAfDM5po36Y8ouCKRDeYQwByCmS7");
3814 done();
3815 })
3816 });
3817});
3818
85c90672
IC
3819it('Shows a warning if generating weak mnemonics', function(done) {
3820 driver.executeScript(function() {
3821 $(".strength option[selected]").removeAttr("selected");
3822 $(".strength option[value=6]").prop("selected", true);
3823 $(".strength").trigger("change");
3824 });
3825 driver.findElement(By.css(".generate-container .warning"))
3826 .getAttribute("class")
3827 .then(function(classes) {
3828 expect(classes).not.toContain("hidden");
3829 done();
3830 });
3831});
3832
3833it('Does not show a warning if generating strong mnemonics', function(done) {
3834 driver.executeScript(function() {
3835 $(".strength option[selected]").removeAttr("selected");
3836 $(".strength option[value=12]").prop("selected", true);
3837 });
3838 driver.findElement(By.css(".generate-container .warning"))
3839 .getAttribute("class")
3840 .then(function(classes) {
3841 expect(classes).toContain("hidden");
3842 done();
3843 });
3844});
3845
645945a0
IC
3846it('Shows a warning if overriding weak entropy with longer mnemonics', function(done) {
3847 driver.findElement(By.css('.use-entropy'))
3848 .click();
3849 driver.findElement(By.css('.entropy'))
3850 .sendKeys("0123456789abcdef"); // 6 words
3851 driver.executeScript(function() {
3852 $(".mnemonic-length").val("12").trigger("change");
3853 });
3854 driver.findElement(By.css(".weak-entropy-override-warning"))
3855 .getAttribute("class")
3856 .then(function(classes) {
3857 expect(classes).not.toContain("hidden");
3858 done();
3859 });
3860});
3861
3862it('Does not show a warning if entropy is stronger than mnemonic length', function(done) {
3863 driver.findElement(By.css('.use-entropy'))
3864 .click();
3865 driver.findElement(By.css('.entropy'))
3866 .sendKeys("0123456789abcdef0123456789abcdef0123456789abcdef"); // 18 words
3867 driver.executeScript(function() {
3868 $(".mnemonic-length").val("12").trigger("change");
3869 });
3870 driver.findElement(By.css(".weak-entropy-override-warning"))
3871 .getAttribute("class")
3872 .then(function(classes) {
3873 expect(classes).toContain("hidden");
3874 done();
3875 });
3876});
3877
530648c1
IC
3878it('Shows litecoin BIP49 addresses', function(done) {
3879 driver.findElement(By.css('.phrase'))
3880 .sendKeys('abandon abandon ability');
3881 selectNetwork("LTC - Litecoin");
3882 driver.findElement(By.css('#bip49-tab a'))
3883 .click()
3884 // bip49 addresses are shown
3885 driver.sleep(generateDelay).then(function() {
3886 driver.findElement(By.css('#bip49 .available'))
3887 .getAttribute("class")
3888 .then(function(classes) {
3889 expect(classes).not.toContain("hidden");
3890 // check first address
3891 getFirstAddress(function(address) {
3892 expect(address).toBe("MFwLPhsXoBuSLL8cLmW9uK6tChkzduV8qN");
3893 done();
3894 });
3895 });
3896 });
3897});
3898
6f7fa353
IC
3899it('Can use root keys to generate segwit table rows', function(done) {
3900 // segwit uses ypub / zpub instead of xpub but the root key should still
3901 // be valid regardless of the encoding used to import that key.
3902 // Maybe this breaks the reason for the different extended key prefixes, but
3903 // since the parsed root key is used behind the scenes anyhow this should be
3904 // allowed.
3905 driver.findElement(By.css('#root-key'))
3906 .sendKeys('xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi');
3907 driver.findElement(By.css('#bip49-tab a'))
3908 .click()
3909 // bip49 addresses are shown
3910 driver.sleep(generateDelay).then(function() {
3911 getFirstAddress(function(address) {
3912 expect(address).toBe("3QG2Y9AA4xZ846gKHZqNf7mvVKbLqMKxr2");
3913 done();
3914 });
3915 });
3916});
3917
0460b53f 3918});