mnemonic.js (1402B)
1 import { WORDS } from "./words.js"; 2 import { normalizeSeed } from "./wallet-core.js"; 3 4 export async function generateMnemonic() { 5 const entropy = crypto.getRandomValues(new Uint8Array(32)); 6 const checksum = new Uint8Array(await crypto.subtle.digest("SHA-256", entropy)); 7 const bits = [...entropy].map((byte) => byte.toString(2).padStart(8, "0")).join("") 8 + checksum[0].toString(2).padStart(8, "0"); 9 return Array.from({ length: 24 }, (_, index) => WORDS[Number.parseInt(bits.slice(index * 11, index * 11 + 11), 2)]).join(" "); 10 } 11 12 export async function validateMnemonic(value) { 13 const words = normalizeSeed(value).split(" "); 14 if (words.length !== 24) throw new Error("A seed phrase must contain exactly 24 words"); 15 const indexes = words.map((word) => WORDS.indexOf(word)); 16 if (indexes.some((index) => index < 0)) throw new Error("The seed phrase contains an unknown BIP-39 word"); 17 const bits = indexes.map((index) => index.toString(2).padStart(11, "0")).join(""); 18 const entropyBits = bits.slice(0, 256); 19 const checksumBits = bits.slice(256); 20 const entropy = Uint8Array.from(entropyBits.match(/.{8}/g), (byte) => Number.parseInt(byte, 2)); 21 const checksum = new Uint8Array(await crypto.subtle.digest("SHA-256", entropy)); 22 if (checksum[0].toString(2).padStart(8, "0") !== checksumBits) throw new Error("The seed phrase checksum is invalid"); 23 return normalizeSeed(value); 24 }