UNPKG

chaingate

Version:

Multi-chain cryptocurrency SDK for TypeScript — unified API for Bitcoin, Ethereum, Litecoin, Dogecoin, Bitcoin Cash, Polygon, Arbitrum, and any EVM-compatible chain. Create wallets, query balances, send transactions, and manage tokens and NFTs across UTXO

141 lines (140 loc) 4.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Phrase = void 0; const bip39_1 = require("@scure/bip39"); const czech_js_1 = require("@scure/bip39/wordlists/czech.js"); const english_js_1 = require("@scure/bip39/wordlists/english.js"); const french_js_1 = require("@scure/bip39/wordlists/french.js"); const italian_js_1 = require("@scure/bip39/wordlists/italian.js"); const japanese_js_1 = require("@scure/bip39/wordlists/japanese.js"); const korean_js_1 = require("@scure/bip39/wordlists/korean.js"); const portuguese_js_1 = require("@scure/bip39/wordlists/portuguese.js"); const simplified_chinese_js_1 = require("@scure/bip39/wordlists/simplified-chinese.js"); const spanish_js_1 = require("@scure/bip39/wordlists/spanish.js"); // Local copy — @scure/bip39@2.0.1 has a broken exports map for this wordlist const traditional_chinese_1 = require("../../../../wordlists/traditional-chinese"); const Secret_1 = require("../../../Secret"); const utils_1 = require("../../../../utils"); const Seed_1 = require("../SeedWallet/Seed"); const errors_1 = require("../../../errors"); const wordlists = { czech: czech_js_1.wordlist, english: english_js_1.wordlist, french: french_js_1.wordlist, italian: italian_js_1.wordlist, japanese: japanese_js_1.wordlist, korean: korean_js_1.wordlist, portuguese: portuguese_js_1.wordlist, simplifiedChinese: simplified_chinese_js_1.wordlist, spanish: spanish_js_1.wordlist, traditionalChinese: traditional_chinese_1.wordlist, }; // Build a reverse lookup: word -> Set of language names const wordToLanguages = new Map(); for (const [lang, wl] of Object.entries(wordlists)) { for (const word of wl) { let langs = wordToLanguages.get(word); if (!langs) { langs = new Set(); wordToLanguages.set(word, langs); } langs.add(lang); } } const VALID_WORD_COUNTS = [12, 15, 18, 21, 24]; const WORDS_TO_STRENGTH = { 12: 128, 15: 160, 18: 192, 21: 224, 24: 256, }; /** * A mnemonic phrase (e.g. 12 or 24 words). Supports encryption and multi-language mnemonics. * * @example * ```ts * const phrase = Phrase.new('english', 12); * const phrase = new Phrase('abandon abandon ... about'); * ``` */ class Phrase extends Secret_1.Secret { /** * @param phrase - A mnemonic string or {@link EncryptedState}. * @throws {@link InvalidPhraseError} if the mnemonic is invalid. */ constructor(phrase) { if (typeof phrase === 'object') { super(phrase); } else { Phrase.validate(phrase); super(new TextEncoder().encode(phrase.trim())); } } get phrase() { return new TextDecoder().decode(this.data); } /** The mnemonic as raw bytes. */ get raw() { return this.data; } /** The mnemonic as hex. */ get hex() { return (0, utils_1.bytesToHex)(this.data); } /** The individual words of the mnemonic phrase. */ get words() { return this.phrase.split(/\s+/); } /** Converts this mnemonic to a {@link Seed}. */ getSeed() { return new Seed_1.Seed((0, bip39_1.mnemonicToSeedSync)(this.phrase)); } /** * Generates a new random mnemonic phrase. * * @param language - Wordlist language. Defaults to `'english'`. * @param numberOfWords - Number of words. Defaults to `12`. */ static new(language = 'english', numberOfWords = 12) { const wordlist = wordlists[language]; const strength = WORDS_TO_STRENGTH[numberOfWords]; const mnemonic = (0, bip39_1.generateMnemonic)(wordlist, strength); return new Phrase(mnemonic); } /** * Checks whether a string is a valid mnemonic phrase (any supported language). * * @param phrase - The string to validate. */ static isValid(phrase) { try { Phrase.validate(phrase); return true; } catch { return false; } } static validate(phrase) { const trimmed = phrase.trim(); if (!trimmed) throw new errors_1.InvalidPhraseError('Mnemonic phrase is empty'); const words = trimmed.split(/\s+/); if (!VALID_WORD_COUNTS.includes(words.length)) { throw new errors_1.InvalidPhraseError(`Mnemonic must be ${VALID_WORD_COUNTS.join(', ')} words, got ${words.length}`); } // Detect candidate languages from the first word to narrow the search const firstWord = words[0]; const candidateLangs = wordToLanguages.get(firstWord); if (candidateLangs) { for (const lang of candidateLangs) { if ((0, bip39_1.validateMnemonic)(trimmed, wordlists[lang])) return; } } throw new errors_1.InvalidPhraseError('Invalid mnemonic phrase'); } } exports.Phrase = Phrase;