use crate::filesystem::Filesystem;
use crate::wallet;
const WALLET_FILE: &str = ".lh_wallet";
pub(crate) struct MasterWallet {
pub(crate) mnemonic: bip39::Mnemonic,
#[allow(dead_code)]
pub(crate) signer: k256::ecdsa::SigningKey,
pub(crate) address: [u8; 20],
}
impl MasterWallet {
pub(crate) fn address_hex(&self) -> String {
let mut s = String::with_capacity(42);
s.push_str("0x");
for b in &self.address {
s.push_str(&format!("{b:02x}"));
}
s
}
}
pub(crate) async fn load() -> Option<MasterWallet> {
let fs = super::shared_opfs();
let bytes = fs.read(WALLET_FILE).await.ok()?;
if bytes.is_empty() {
return None;
}
let phrase = String::from_utf8(bytes).ok()?;
restore_from_phrase(&phrase).ok()
}
pub(crate) async fn create_and_persist() -> Result<MasterWallet, String> {
let fs = super::shared_opfs();
let (mnemonic, signer) = wallet::generate_with_mnemonic();
fs.write_atomic(WALLET_FILE, mnemonic.to_string().as_bytes())
.await
.map_err(|e| format!("wallet save: {e}"))?;
let address = wallet::address(&signer);
Ok(MasterWallet {
mnemonic,
signer,
address,
})
}
pub(crate) async fn import(phrase: &str) -> Result<MasterWallet, String> {
let mnemonic = wallet::mnemonic_from_phrase(phrase)?;
let fs = super::shared_opfs();
fs.write_atomic(WALLET_FILE, mnemonic.to_string().as_bytes())
.await
.map_err(|e| format!("wallet save: {e}"))?;
let signer = wallet::signer_from_mnemonic(&mnemonic);
let address = wallet::address(&signer);
Ok(MasterWallet {
mnemonic,
signer,
address,
})
}
#[allow(dead_code)]
pub(crate) async fn forget() {
let fs = super::shared_opfs();
let _ = fs.delete(WALLET_FILE).await;
}
fn restore_from_phrase(phrase: &str) -> Result<MasterWallet, String> {
let mnemonic = wallet::mnemonic_from_phrase(phrase)?;
let signer = wallet::signer_from_mnemonic(&mnemonic);
let address = wallet::address(&signer);
Ok(MasterWallet {
mnemonic,
signer,
address,
})
}