]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/BIP39.git/blobdiff - src/js/index.js
Words not in list show error with suggestion
[perso/Immae/Projets/Cryptomonnaies/BIP39.git] / src / js / index.js
index f131e01c84d1832d0238ca6d9d28ac8a41e57381..f3582b0f17461de4de8ce9d8c37038be0ea2bcc0 100644 (file)
                 proper.push(part.toLowerCase());
             }
         }
-        // TODO some levenstein on the words
         var properPhrase = proper.join(' ');
+        // Check each word
+        for (var i=0; i<proper.length; i++) {
+            var word = proper[i];
+            if (WORDLISTS["english"].indexOf(word) == -1) {
+                console.log("Finding closest match to " + word);
+                var nearestWord = findNearestWord(word);
+                return word + " not in wordlist, did you mean " + nearestWord + "?";
+            }
+        }
         // Check the words are valid
         var isValid = mnemonic.check(properPhrase);
         if (!isValid) {
     }
 
     function findDerivationPathErrors(path) {
-        // TODO
+        // TODO is not perfect but is better than nothing
+        // Inspired by
+        // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vectors
+        // and
+        // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#extended-keys
+        var maxDepth = 255; // TODO verify this!!
+        var maxIndexValue = Math.pow(2, 31); // TODO verify this!!
+        if (path[0] != "m") {
+            return "First character must be 'm'";
+        }
+        if (path.length > 1) {
+            if (path[1] != "/") {
+                return "Separator must be '/'";
+            }
+            var indexes = path.split("/");
+            if (indexes.length > maxDepth) {
+                return "Derivation depth is " + indexes.length + ", must be less than " + maxDepth;
+            }
+            for (var depth = 1; depth<indexes.length; depth++) {
+                var index = indexes[depth];
+                var invalidChars = index.replace(/^[0-9]+'?$/g, "")
+                if (invalidChars.length > 0) {
+                    return "Invalid characters " + invalidChars + " found at depth " + depth;
+                }
+                var indexValue = parseInt(index.replace("'", ""));
+                if (isNaN(depth)) {
+                    return "Invalid number at depth " + depth;
+                }
+                if (indexValue > maxIndexValue) {
+                    return "Value of " + indexValue + " at depth " + depth + " must be less than " + maxIndexValue;
+                }
+            }
+        }
         return false;
     }
 
             .show();
     }
 
+    function findNearestWord(word) {
+        var words = WORDLISTS["english"];
+        var minDistance = 99;
+        var closestWord = words[0];
+        for (var i=0; i<words.length; i++) {
+            var comparedTo = words[i];
+            var distance = Levenshtein.get(word, comparedTo);
+            if (distance < minDistance) {
+                closestWord = comparedTo;
+                minDistance = distance;
+            }
+        }
+        return closestWord;
+    }
+
     function hidePending() {
         DOM.feedback
             .text("")