use std::io::{self, Write};
use bip0039::{Language, Mnemonic};
use zeroize::Zeroizing;
enum ReadWord {
Word(Zeroizing<String>),
Break,
}
fn read_word<L: Language>(id: usize) -> ReadWord {
loop {
print!("({}) ", id + 1);
io::stdout().flush().unwrap();
let word = readpass::from_tty().unwrap();
if word.is_empty() {
break ReadWord::Break;
}
if !L::WORD_LIST.contains(&word.as_str()) {
print!("invalid\n");
} else {
#[cfg(feature = "console")]
let _ = console::Term::stdout().move_cursor_up(1);
break ReadWord::Word(word);
}
}
}
fn read_words<L: Language>() -> Zeroizing<String> {
let mut out = String::new();
for i in 0_usize.. {
match read_word::<L>(i) {
ReadWord::Word(s) => {
if !out.is_empty() {
out.push(' ');
}
out.push_str(s.as_str())
}
ReadWord::Break => break
}
}
Zeroizing::new(out)
}
pub fn read_mnemonic<L: Language>() -> Result<Zeroizing<Mnemonic<L>>, bip0039::Error> {
let words = read_words::<L>();
let mnem = Mnemonic::<L>::from_phrase(words.as_str())?;
let mnem = Zeroizing::new(mnem);
Ok(mnem)
}
pub fn read_mnemonic_until_ok<L: Language>() -> Zeroizing<Mnemonic<L>> {
loop {
match read_mnemonic::<L>() {
Ok(val) => break val,
Err(err) => {
println!("Error: {}\n", err.to_string());
}
}
}
}