use crate::{Controller, Observable, Signer, Account, Vault};
#[derive(Clone, Debug)]
pub struct KeychainState {
pub accounts: Vec<Account>,
}
pub struct Keychain {
vault: Vault,
store: Observable<KeychainState>,
}
impl Keychain {
pub fn new() -> Self {
Keychain {
vault: Vault::new(),
store: Observable::new(KeychainState { accounts: vec![] }),
}
}
pub fn from_mnemonic(mnemonic: String) -> Result<Self, String> {
Ok(Keychain {
vault: Vault::from_phrase(mnemonic)?,
store: Observable::new(KeychainState { accounts: vec![] }),
})
}
pub fn add_account(&mut self) -> Result<Account, String> {
let account = self.vault.add_key()?;
self.store.update(|state| {
state.accounts.push(account.clone());
});
Ok(account)
}
pub fn use_signer<T, R>(&self, address: String, hook: T) -> Result<R, String>
where
T: FnMut(&Signer) -> R,
{
match self
.store
.get_state()
.accounts
.iter()
.enumerate()
.find(|(_, key)| key.address == address)
{
Some((key_index, _)) => self.vault.use_signer(key_index, hook),
None => Err("Key not found".to_string()),
}
}
pub fn lock(&mut self, password: &str) -> Result<(), String> {
self.vault.lock(password.as_bytes())
}
pub fn unlock(&mut self, password: &str) -> Result<(), String> {
self.vault.unlock(password.as_bytes())
}
}
impl Controller<KeychainState> for Keychain {
fn get_state(&self) -> &KeychainState {
&self.store.get_state()
}
fn update<F>(&mut self, updater: F) -> ()
where
F: Fn(&mut KeychainState),
{
self.store.update(updater);
}
fn subscribe<F>(&mut self, subscriber: F) -> usize
where
F: 'static + FnMut(&KeychainState),
{
self.store.subscribe(subscriber)
}
fn unsubscribe(&mut self, id: usize) -> () {
self.store.unsubscribe(id)
}
}