wallet: create LoginId type to distinguish
This commit is contained in:
@@ -5,7 +5,7 @@ use crate::network::Network as WalletNetwork;
|
||||
use crate::network_config;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use crate::wallet_storage::{self, StoredLogin, DEFAULT_WALLET_ACCOUNT_ID};
|
||||
use crate::wallet_storage::{self, StoredLogin, DEFAULT_LOGIN_ID};
|
||||
|
||||
use bip39::{Language, Mnemonic};
|
||||
use config::defaults::all::Network;
|
||||
@@ -370,7 +370,7 @@ pub fn create_password(mnemonic: &str, password: String) -> Result<(), BackendEr
|
||||
let mnemonic = Mnemonic::from_str(mnemonic)?;
|
||||
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
// Currently we only support a single, default, id in the wallet
|
||||
let id = wallet_storage::AccountId::new(DEFAULT_WALLET_ACCOUNT_ID.to_string());
|
||||
let id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
|
||||
let password = wallet_storage::UserPassword::new(password);
|
||||
wallet_storage::store_wallet_login_multiple_information(mnemonic, hd_path, id, &password)
|
||||
}
|
||||
@@ -383,12 +383,13 @@ pub async fn sign_in_with_password(
|
||||
log::info!("Signing in with password");
|
||||
|
||||
// Currently we only support a single, default, id in the wallet
|
||||
let id = wallet_storage::AccountId::new(DEFAULT_WALLET_ACCOUNT_ID.to_string());
|
||||
let id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
|
||||
let password = wallet_storage::UserPassword::new(password);
|
||||
let stored_login = wallet_storage::load_existing_wallet_login_information(&id, &password)?;
|
||||
|
||||
let mnemonic = extract_first_mnemonic(&stored_login)?;
|
||||
set_state_with_all_accounts(stored_login, id, state.clone()).await?;
|
||||
let first_id_when_converting = id.into();
|
||||
set_state_with_all_accounts(stored_login, first_id_when_converting, state.clone()).await?;
|
||||
|
||||
_connect_with_mnemonic(mnemonic, state).await
|
||||
}
|
||||
@@ -414,7 +415,7 @@ fn extract_first_mnemonic(stored_account: &StoredLogin) -> Result<Mnemonic, Back
|
||||
#[tauri::command]
|
||||
pub fn remove_password() -> Result<(), BackendError> {
|
||||
log::info!("Removing password");
|
||||
let id = wallet_storage::AccountId::new(DEFAULT_WALLET_ACCOUNT_ID.to_string());
|
||||
let id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
|
||||
wallet_storage::remove_wallet_login_information(&id)
|
||||
}
|
||||
|
||||
@@ -429,11 +430,10 @@ pub async fn add_account_for_password(
|
||||
let mnemonic = Mnemonic::from_str(mnemonic)?;
|
||||
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
// Currently we only support a single, default, id in the wallet
|
||||
let id = wallet_storage::AccountId::new(DEFAULT_WALLET_ACCOUNT_ID.to_string());
|
||||
let id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
|
||||
let inner_id = wallet_storage::AccountId::new(inner_id.to_string());
|
||||
let password = wallet_storage::UserPassword::new(password.to_string());
|
||||
|
||||
// Creating the returned account entry could fail, so do it before attempting to store to wallet
|
||||
wallet_storage::append_account_to_wallet_login_information(
|
||||
mnemonic.clone(),
|
||||
hd_path,
|
||||
@@ -451,7 +451,10 @@ pub async fn add_account_for_password(
|
||||
// Re-read all the acccounts from the wallet to reset the state, rather than updating it
|
||||
// incrementally
|
||||
let stored_login = wallet_storage::load_existing_wallet_login_information(&id, &password)?;
|
||||
set_state_with_all_accounts(stored_login, id, state).await?;
|
||||
// NOTE: since we are appending, this id shouldn't be needed, but setting the state is supposed
|
||||
// to be a general function
|
||||
let first_id_when_converting = id.into();
|
||||
set_state_with_all_accounts(stored_login, first_id_when_converting, state).await?;
|
||||
|
||||
Ok(AccountEntry {
|
||||
id: inner_id.to_string(),
|
||||
@@ -459,14 +462,15 @@ pub async fn add_account_for_password(
|
||||
})
|
||||
}
|
||||
|
||||
// The first `AccoundId` when converting is the `LoginId` for the entry that was loaded.
|
||||
async fn set_state_with_all_accounts(
|
||||
stored_login: StoredLogin,
|
||||
id: wallet_storage::AccountId,
|
||||
first_id_when_converting: wallet_storage::AccountId,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
log::trace!("Set state with accounts:");
|
||||
let all_accounts: Vec<_> = stored_login
|
||||
.unwrap_into_multiple_accounts(id.clone())
|
||||
.unwrap_into_multiple_accounts(first_id_when_converting)
|
||||
.into_accounts()
|
||||
.collect();
|
||||
|
||||
@@ -487,14 +491,17 @@ pub async fn remove_account_for_password(
|
||||
) -> Result<(), BackendError> {
|
||||
log::info!("Removing account: {inner_id}");
|
||||
// Currently we only support a single, default, id in the wallet
|
||||
let id = wallet_storage::AccountId::new(DEFAULT_WALLET_ACCOUNT_ID.to_string());
|
||||
let id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
|
||||
let inner_id = wallet_storage::AccountId::new(inner_id.to_string());
|
||||
let password = wallet_storage::UserPassword::new(password.to_string());
|
||||
wallet_storage::remove_account_from_wallet_login(&id, &inner_id, &password)?;
|
||||
|
||||
// Load to reset the internal state
|
||||
let stored_login = wallet_storage::load_existing_wallet_login_information(&id, &password)?;
|
||||
set_state_with_all_accounts(stored_login, id, state).await
|
||||
// NOTE: Since we removed from a multi-account login, this id shouldn't be needed, but setting
|
||||
// the state is supposed to be a general function
|
||||
let first_id_when_converting = id.into();
|
||||
set_state_with_all_accounts(stored_login, first_id_when_converting, state).await
|
||||
}
|
||||
|
||||
fn derive_address(
|
||||
@@ -541,7 +548,7 @@ pub fn show_mnemonic_for_account_in_password(
|
||||
password: String,
|
||||
) -> Result<String, BackendError> {
|
||||
log::info!("Getting mnemonic for: {account_id}");
|
||||
let id = wallet_storage::AccountId::new(DEFAULT_WALLET_ACCOUNT_ID.to_string());
|
||||
let id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
|
||||
let account_id = wallet_storage::AccountId::new(account_id);
|
||||
let password = wallet_storage::UserPassword::new(password);
|
||||
let stored_account = wallet_storage::load_existing_wallet_login_information(&id, &password)?;
|
||||
@@ -601,20 +608,24 @@ mod tests {
|
||||
fn decrypt_stored_wallet_for_sign_in() {
|
||||
const SAVED_WALLET: &str = "src/wallet_storage/test-data/saved-wallet.json";
|
||||
let wallet_file = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(SAVED_WALLET);
|
||||
let id = wallet_storage::AccountId::new("first".to_string());
|
||||
let login_id = wallet_storage::LoginId::new("first".to_string());
|
||||
let account_id = wallet_storage::AccountId::new("first".to_string());
|
||||
let password = wallet_storage::UserPassword::new("password".to_string());
|
||||
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
|
||||
let stored_login =
|
||||
wallet_storage::load_existing_wallet_login_information_at_file(wallet_file, &id, &password)
|
||||
.unwrap();
|
||||
let stored_login = wallet_storage::load_existing_wallet_login_information_at_file(
|
||||
wallet_file,
|
||||
&login_id,
|
||||
&password,
|
||||
)
|
||||
.unwrap();
|
||||
let mnemonic = extract_first_mnemonic(&stored_login).unwrap();
|
||||
|
||||
let expected_mnemonic = bip39::Mnemonic::from_str("country mean universe text phone begin deputy reject result good cram illness common cluster proud swamp digital patrol spread bar face december base kick").unwrap();
|
||||
assert_eq!(mnemonic, expected_mnemonic);
|
||||
|
||||
let all_accounts: Vec<_> = stored_login
|
||||
.unwrap_into_multiple_accounts(id.clone())
|
||||
.unwrap_into_multiple_accounts(account_id.clone())
|
||||
.into_accounts()
|
||||
.collect();
|
||||
|
||||
@@ -622,7 +633,7 @@ mod tests {
|
||||
all_accounts,
|
||||
vec![
|
||||
wallet_storage::account_data::WalletAccount::new_mnemonic_backed_account(
|
||||
id,
|
||||
account_id,
|
||||
expected_mnemonic,
|
||||
hd_path
|
||||
)
|
||||
|
||||
@@ -21,7 +21,7 @@ use zeroize::Zeroize;
|
||||
use crate::error::BackendError;
|
||||
|
||||
use super::encryption::EncryptedData;
|
||||
use super::password::AccountId;
|
||||
use super::password::{AccountId, LoginId};
|
||||
use super::UserPassword;
|
||||
|
||||
const CURRENT_WALLET_FILE_VERSION: u32 = 1;
|
||||
@@ -56,10 +56,7 @@ impl StoredWallet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_encrypted_login(
|
||||
&self,
|
||||
id: &AccountId,
|
||||
) -> Result<&EncryptedData<StoredLogin>, BackendError> {
|
||||
fn get_encrypted_login(&self, id: &LoginId) -> Result<&EncryptedData<StoredLogin>, BackendError> {
|
||||
self
|
||||
.accounts
|
||||
.iter()
|
||||
@@ -68,10 +65,7 @@ impl StoredWallet {
|
||||
.ok_or(BackendError::NoSuchIdInWallet)
|
||||
}
|
||||
|
||||
fn get_encrypted_login_mut(
|
||||
&mut self,
|
||||
id: &AccountId,
|
||||
) -> Result<&mut EncryptedLogin, BackendError> {
|
||||
fn get_encrypted_login_mut(&mut self, id: &LoginId) -> Result<&mut EncryptedLogin, BackendError> {
|
||||
self
|
||||
.accounts
|
||||
.iter_mut()
|
||||
@@ -91,7 +85,7 @@ impl StoredWallet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_encrypted_login(&mut self, id: &AccountId) -> Option<EncryptedLogin> {
|
||||
pub fn remove_encrypted_login(&mut self, id: &LoginId) -> Option<EncryptedLogin> {
|
||||
if let Some(index) = self.accounts.iter().position(|account| &account.id == id) {
|
||||
log::info!("Removing from wallet file: {id}");
|
||||
Some(self.accounts.remove(index))
|
||||
@@ -103,7 +97,7 @@ impl StoredWallet {
|
||||
|
||||
pub fn decrypt_login(
|
||||
&self,
|
||||
id: &AccountId,
|
||||
id: &LoginId,
|
||||
password: &UserPassword,
|
||||
) -> Result<StoredLogin, BackendError> {
|
||||
self.get_encrypted_login(id)?.decrypt_struct(password)
|
||||
@@ -134,7 +128,7 @@ impl Default for StoredWallet {
|
||||
/// Each entry in the stored wallet file. An id field in plaintext and an encrypted stored login.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub(crate) struct EncryptedLogin {
|
||||
pub id: AccountId,
|
||||
pub id: LoginId,
|
||||
pub account: EncryptedData<StoredLogin>,
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub(crate) use crate::wallet_storage::account_data::StoredLogin;
|
||||
pub(crate) use crate::wallet_storage::password::{AccountId, UserPassword};
|
||||
pub(crate) use crate::wallet_storage::password::{AccountId, LoginId, UserPassword};
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::platform_constants::{STORAGE_DIR_NAME, WALLET_INFO_FILENAME};
|
||||
@@ -19,11 +19,11 @@ pub(crate) mod encryption;
|
||||
mod password;
|
||||
|
||||
/// The default wallet (top-level) login id.
|
||||
pub(crate) const DEFAULT_WALLET_ACCOUNT_ID: &str = "default";
|
||||
pub(crate) const DEFAULT_LOGIN_ID: &str = "default";
|
||||
|
||||
/// When converting a single account entry to one that contains many, the first account will use
|
||||
/// this name.
|
||||
pub(crate) const DEFAULT_NAME_FIRST_ACCOUNT: &str = "Account 1";
|
||||
pub(crate) const DEFAULT_FIRST_ACCOUNT_NAME: &str = "Account 1";
|
||||
|
||||
fn get_storage_directory() -> Result<PathBuf, BackendError> {
|
||||
tauri::api::path::local_data_dir()
|
||||
@@ -55,7 +55,7 @@ fn load_existing_wallet_at_file(filepath: PathBuf) -> Result<StoredWallet, Backe
|
||||
/// Load the stored wallet file and return the stored login for the given id.
|
||||
/// The returned login is either an account or list of (inner id, account) pairs.
|
||||
pub(crate) fn load_existing_wallet_login_information(
|
||||
id: &AccountId,
|
||||
id: &LoginId,
|
||||
password: &UserPassword,
|
||||
) -> Result<StoredLogin, BackendError> {
|
||||
let store_dir = get_storage_directory()?;
|
||||
@@ -65,7 +65,7 @@ pub(crate) fn load_existing_wallet_login_information(
|
||||
|
||||
pub(crate) fn load_existing_wallet_login_information_at_file(
|
||||
filepath: PathBuf,
|
||||
id: &AccountId,
|
||||
id: &LoginId,
|
||||
password: &UserPassword,
|
||||
) -> Result<StoredLogin, BackendError> {
|
||||
load_existing_wallet_at_file(filepath)?.decrypt_login(id, password)
|
||||
@@ -79,7 +79,7 @@ pub(crate) fn load_existing_wallet_login_information_at_file(
|
||||
pub(crate) fn store_wallet_login_information(
|
||||
mnemonic: bip39::Mnemonic,
|
||||
hd_path: DerivationPath,
|
||||
id: AccountId,
|
||||
id: LoginId,
|
||||
password: &UserPassword,
|
||||
) -> Result<(), BackendError> {
|
||||
// make sure the entire directory structure exists
|
||||
@@ -94,7 +94,7 @@ fn store_wallet_login_information_at_file(
|
||||
filepath: PathBuf,
|
||||
mnemonic: bip39::Mnemonic,
|
||||
hd_path: DerivationPath,
|
||||
id: AccountId,
|
||||
id: LoginId,
|
||||
password: &UserPassword,
|
||||
) -> Result<(), BackendError> {
|
||||
let mut stored_wallet = match load_existing_wallet_at_file(filepath.clone()) {
|
||||
@@ -128,7 +128,7 @@ fn store_wallet_login_information_at_file(
|
||||
pub(crate) fn store_wallet_login_multiple_information(
|
||||
mnemonic: bip39::Mnemonic,
|
||||
hd_path: DerivationPath,
|
||||
id: AccountId,
|
||||
id: LoginId,
|
||||
password: &UserPassword,
|
||||
) -> Result<(), BackendError> {
|
||||
// make sure the entire directory structure exists
|
||||
@@ -143,7 +143,7 @@ fn store_wallet_login_multiple_information_at_file(
|
||||
filepath: PathBuf,
|
||||
mnemonic: bip39::Mnemonic,
|
||||
hd_path: DerivationPath,
|
||||
id: AccountId,
|
||||
id: LoginId,
|
||||
password: &UserPassword,
|
||||
) -> Result<(), BackendError> {
|
||||
let mut stored_wallet = match load_existing_wallet_at_file(filepath.clone()) {
|
||||
@@ -159,7 +159,7 @@ fn store_wallet_login_multiple_information_at_file(
|
||||
|
||||
let mut new_accounts = account_data::MultipleAccounts::empty();
|
||||
new_accounts.add(
|
||||
DEFAULT_NAME_FIRST_ACCOUNT.to_string().into(),
|
||||
DEFAULT_FIRST_ACCOUNT_NAME.to_string().into(),
|
||||
mnemonic,
|
||||
hd_path,
|
||||
)?;
|
||||
@@ -188,7 +188,7 @@ fn store_wallet_login_multiple_information_at_file(
|
||||
pub(crate) fn append_account_to_wallet_login_information(
|
||||
mnemonic: bip39::Mnemonic,
|
||||
hd_path: DerivationPath,
|
||||
id: AccountId,
|
||||
id: LoginId,
|
||||
inner_id: AccountId,
|
||||
password: &UserPassword,
|
||||
) -> Result<(), BackendError> {
|
||||
@@ -206,7 +206,7 @@ fn append_account_to_wallet_login_information_at_file(
|
||||
filepath: PathBuf,
|
||||
mnemonic: bip39::Mnemonic,
|
||||
hd_path: DerivationPath,
|
||||
id: AccountId,
|
||||
id: LoginId,
|
||||
inner_id: AccountId,
|
||||
password: &UserPassword,
|
||||
) -> Result<(), BackendError> {
|
||||
@@ -220,7 +220,8 @@ fn append_account_to_wallet_login_information_at_file(
|
||||
// Add accounts to the inner structure.
|
||||
// Note that in case we only have single account entry, without an inner_id, we convert to
|
||||
// multiple accounts and we set the first inner_id to id.
|
||||
let mut accounts = decrypted_login.unwrap_into_multiple_accounts(id.clone());
|
||||
let first_id_when_converting = id.clone().into();
|
||||
let mut accounts = decrypted_login.unwrap_into_multiple_accounts(first_id_when_converting);
|
||||
accounts.add(inner_id, mnemonic, hd_path)?;
|
||||
|
||||
let encrypted_accounts = EncryptedLogin {
|
||||
@@ -242,7 +243,7 @@ fn append_account_to_wallet_login_information_at_file(
|
||||
/// Remove the entire encrypted login entry for the given `id`. This means potentially removing all
|
||||
/// associated accounts!
|
||||
/// If this was the last entry in the file, the file is removed.
|
||||
pub(crate) fn remove_wallet_login_information(id: &AccountId) -> Result<(), BackendError> {
|
||||
pub(crate) fn remove_wallet_login_information(id: &LoginId) -> Result<(), BackendError> {
|
||||
let store_dir = get_storage_directory()?;
|
||||
let filepath = store_dir.join(WALLET_INFO_FILENAME);
|
||||
remove_wallet_login_information_at_file(filepath, id)
|
||||
@@ -250,7 +251,7 @@ pub(crate) fn remove_wallet_login_information(id: &AccountId) -> Result<(), Back
|
||||
|
||||
fn remove_wallet_login_information_at_file(
|
||||
filepath: PathBuf,
|
||||
id: &AccountId,
|
||||
id: &LoginId,
|
||||
) -> Result<(), BackendError> {
|
||||
log::warn!("Removing wallet account with id: {id}. This includes all associated accounts!");
|
||||
let mut stored_wallet = match load_existing_wallet_at_file(filepath.clone()) {
|
||||
@@ -286,7 +287,7 @@ fn remove_wallet_login_information_at_file(
|
||||
/// - If it is the last associated account with that login, the encrypted login will be removed.
|
||||
/// - If this was the last encrypted login in the file, it will be removed.
|
||||
pub(crate) fn remove_account_from_wallet_login(
|
||||
id: &AccountId,
|
||||
id: &LoginId,
|
||||
inner_id: &AccountId,
|
||||
password: &UserPassword,
|
||||
) -> Result<(), BackendError> {
|
||||
@@ -297,7 +298,7 @@ pub(crate) fn remove_account_from_wallet_login(
|
||||
|
||||
fn remove_account_from_wallet_login_at_file(
|
||||
filepath: PathBuf,
|
||||
id: &AccountId,
|
||||
id: &LoginId,
|
||||
inner_id: &AccountId,
|
||||
password: &UserPassword,
|
||||
) -> Result<(), BackendError> {
|
||||
@@ -360,7 +361,7 @@ mod tests {
|
||||
fn trying_to_load_nonexistant_wallet_fails() {
|
||||
let store_dir = tempdir().unwrap();
|
||||
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
assert!(matches!(
|
||||
@@ -382,13 +383,13 @@ mod tests {
|
||||
let dummy_account1 = bip39::Mnemonic::generate(24).unwrap();
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
|
||||
store_wallet_login_information_at_file(
|
||||
wallet_file.clone(),
|
||||
dummy_account1,
|
||||
cosmos_hd_path,
|
||||
id1,
|
||||
id1.clone(),
|
||||
&password,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -397,7 +398,7 @@ mod tests {
|
||||
assert_eq!(stored_wallet.len(), 1);
|
||||
|
||||
let login = stored_wallet.get_encrypted_login_by_index(0).unwrap();
|
||||
assert_eq!(login.id, AccountId::new("first".to_string()));
|
||||
assert_eq!(login.id, id1);
|
||||
|
||||
// some actual ciphertext was saved
|
||||
assert!(!login.account.ciphertext().is_empty());
|
||||
@@ -411,13 +412,13 @@ mod tests {
|
||||
let dummy_account1 = bip39::Mnemonic::generate(24).unwrap();
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
wallet_file.clone(),
|
||||
dummy_account1,
|
||||
cosmos_hd_path,
|
||||
id1,
|
||||
id1.clone(),
|
||||
&password,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -426,7 +427,7 @@ mod tests {
|
||||
assert_eq!(stored_wallet.len(), 1);
|
||||
|
||||
let login = stored_wallet.get_encrypted_login_by_index(0).unwrap();
|
||||
assert_eq!(login.id, AccountId::new("first".to_string()));
|
||||
assert_eq!(login.id, id1);
|
||||
|
||||
// some actual ciphertext was saved
|
||||
assert!(!login.account.ciphertext().is_empty());
|
||||
@@ -440,7 +441,7 @@ mod tests {
|
||||
let dummy_account1 = bip39::Mnemonic::generate(24).unwrap();
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
|
||||
// Store the first login
|
||||
store_wallet_login_information_at_file(
|
||||
@@ -473,7 +474,7 @@ mod tests {
|
||||
let dummy_account1 = bip39::Mnemonic::generate(24).unwrap();
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
|
||||
// Store the first login
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
@@ -507,7 +508,7 @@ mod tests {
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let bad_password = UserPassword::new("bad-password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
|
||||
store_wallet_login_information_at_file(
|
||||
wallet_file.clone(),
|
||||
@@ -534,7 +535,7 @@ mod tests {
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let bad_password = UserPassword::new("bad-password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
wallet_file.clone(),
|
||||
@@ -560,8 +561,8 @@ mod tests {
|
||||
let dummy_account1 = bip39::Mnemonic::generate(24).unwrap();
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
store_wallet_login_information_at_file(
|
||||
wallet_file.clone(),
|
||||
@@ -587,8 +588,8 @@ mod tests {
|
||||
let dummy_account1 = bip39::Mnemonic::generate(24).unwrap();
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
wallet_file.clone(),
|
||||
@@ -614,7 +615,7 @@ mod tests {
|
||||
let dummy_account1 = bip39::Mnemonic::generate(24).unwrap();
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
|
||||
store_wallet_login_information_at_file(
|
||||
wallet_file.clone(),
|
||||
@@ -640,7 +641,7 @@ mod tests {
|
||||
let dummy_account1 = bip39::Mnemonic::generate(24).unwrap();
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
wallet_file.clone(),
|
||||
@@ -656,9 +657,9 @@ mod tests {
|
||||
let accounts = loaded_login.as_multiple_accounts().unwrap();
|
||||
assert_eq!(accounts.len(), 1);
|
||||
let account = accounts
|
||||
.get_account(&DEFAULT_NAME_FIRST_ACCOUNT.into())
|
||||
.get_account(&DEFAULT_FIRST_ACCOUNT_NAME.into())
|
||||
.unwrap();
|
||||
assert_eq!(account.id, DEFAULT_NAME_FIRST_ACCOUNT.into());
|
||||
assert_eq!(account.id, DEFAULT_FIRST_ACCOUNT_NAME.into());
|
||||
assert_eq!(account.account.mnemonic(), &dummy_account1);
|
||||
assert_eq!(account.account.hd_path(), &cosmos_hd_path);
|
||||
}
|
||||
@@ -675,8 +676,8 @@ mod tests {
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let bad_password = UserPassword::new("bad-password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
store_wallet_login_information_at_file(
|
||||
wallet_file.clone(),
|
||||
@@ -712,8 +713,8 @@ mod tests {
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let bad_password = UserPassword::new("bad-password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
wallet_file.clone(),
|
||||
@@ -749,8 +750,8 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
// Store the first account
|
||||
store_wallet_login_information_at_file(
|
||||
@@ -806,8 +807,8 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
// Store the first account
|
||||
store_wallet_login_information_at_file(
|
||||
@@ -861,8 +862,8 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
// Store the first account
|
||||
store_wallet_login_information_at_file(
|
||||
@@ -902,9 +903,9 @@ mod tests {
|
||||
let acc2 = loaded_account.as_multiple_accounts().unwrap();
|
||||
assert_eq!(acc2.len(), 1);
|
||||
let account = acc2
|
||||
.get_account(&DEFAULT_NAME_FIRST_ACCOUNT.into())
|
||||
.get_account(&DEFAULT_FIRST_ACCOUNT_NAME.into())
|
||||
.unwrap();
|
||||
assert_eq!(account.id, DEFAULT_NAME_FIRST_ACCOUNT.into());
|
||||
assert_eq!(account.id, DEFAULT_FIRST_ACCOUNT_NAME.into());
|
||||
assert_eq!(account.account.mnemonic(), &dummy_account2);
|
||||
assert_eq!(account.account.hd_path(), &different_hd_path);
|
||||
}
|
||||
@@ -919,8 +920,8 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
wallet_file.clone(),
|
||||
@@ -950,8 +951,8 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
// Store two accounts with two different passwords
|
||||
store_wallet_login_information_at_file(
|
||||
@@ -1025,7 +1026,7 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
|
||||
store_wallet_login_information_at_file(
|
||||
@@ -1059,7 +1060,7 @@ mod tests {
|
||||
load_existing_wallet_login_information_at_file(wallet_file, &id1, &password).unwrap();
|
||||
let accounts = loaded_accounts.as_multiple_accounts().unwrap();
|
||||
let expected = vec![
|
||||
WalletAccount::new_mnemonic_backed_account(id1, dummy_account1, hd_path.clone()),
|
||||
WalletAccount::new_mnemonic_backed_account(id1.into(), dummy_account1, hd_path.clone()),
|
||||
WalletAccount::new_mnemonic_backed_account(id2, dummy_account2, hd_path),
|
||||
]
|
||||
.into();
|
||||
@@ -1079,8 +1080,8 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
let id3 = AccountId::new("third".to_string());
|
||||
let id4 = AccountId::new("fourth".to_string());
|
||||
|
||||
@@ -1140,7 +1141,7 @@ mod tests {
|
||||
load_existing_wallet_login_information_at_file(wallet_file, &id2, &password).unwrap();
|
||||
let accounts = loaded_accounts.as_multiple_accounts().unwrap();
|
||||
let expected = vec![
|
||||
WalletAccount::new_mnemonic_backed_account(id2, dummy_account2, hd_path.clone()),
|
||||
WalletAccount::new_mnemonic_backed_account(id2.into(), dummy_account2, hd_path.clone()),
|
||||
WalletAccount::new_mnemonic_backed_account(id3, dummy_account3, hd_path.clone()),
|
||||
WalletAccount::new_mnemonic_backed_account(id4, dummy_account4, hd_path),
|
||||
]
|
||||
@@ -1161,8 +1162,8 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
let id3 = AccountId::new("third".to_string());
|
||||
let id4 = AccountId::new("fourth".to_string());
|
||||
|
||||
@@ -1209,7 +1210,7 @@ mod tests {
|
||||
load_existing_wallet_login_information_at_file(wallet_file.clone(), &id1, &password).unwrap();
|
||||
let accounts = loaded_login.as_multiple_accounts().unwrap();
|
||||
let expected = vec![WalletAccount::new_mnemonic_backed_account(
|
||||
DEFAULT_NAME_FIRST_ACCOUNT.into(),
|
||||
DEFAULT_FIRST_ACCOUNT_NAME.into(),
|
||||
dummy_account1,
|
||||
hd_path.clone(),
|
||||
)]
|
||||
@@ -1221,7 +1222,7 @@ mod tests {
|
||||
let accounts = loaded_login.as_multiple_accounts().unwrap();
|
||||
let expected = vec![
|
||||
WalletAccount::new_mnemonic_backed_account(
|
||||
DEFAULT_NAME_FIRST_ACCOUNT.into(),
|
||||
DEFAULT_FIRST_ACCOUNT_NAME.into(),
|
||||
dummy_account2,
|
||||
hd_path.clone(),
|
||||
),
|
||||
@@ -1243,7 +1244,7 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
|
||||
store_wallet_login_information_at_file(
|
||||
@@ -1284,7 +1285,7 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
@@ -1326,8 +1327,8 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
let id3 = AccountId::new("third".to_string());
|
||||
|
||||
store_wallet_login_information_at_file(
|
||||
@@ -1365,7 +1366,7 @@ mod tests {
|
||||
load_existing_wallet_login_information_at_file(wallet_file, &id2, &password).unwrap();
|
||||
let accounts = loaded_accounts.as_multiple_accounts().unwrap();
|
||||
let expected = vec![
|
||||
WalletAccount::new_mnemonic_backed_account(id2, dummy_account2, hd_path.clone()),
|
||||
WalletAccount::new_mnemonic_backed_account(id2.into(), dummy_account2, hd_path.clone()),
|
||||
WalletAccount::new_mnemonic_backed_account(id3, dummy_account3, hd_path),
|
||||
]
|
||||
.into();
|
||||
@@ -1383,7 +1384,7 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
@@ -1408,7 +1409,7 @@ mod tests {
|
||||
remove_account_from_wallet_login_at_file(
|
||||
wallet.clone(),
|
||||
&id1,
|
||||
&DEFAULT_NAME_FIRST_ACCOUNT.into(),
|
||||
&DEFAULT_FIRST_ACCOUNT_NAME.into(),
|
||||
&password,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1436,9 +1437,9 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id3 = AccountId::new("third".to_string());
|
||||
let id3 = LoginId::new("third".to_string());
|
||||
|
||||
store_wallet_login_multiple_information_at_file(
|
||||
wallet.clone(),
|
||||
@@ -1471,7 +1472,7 @@ mod tests {
|
||||
remove_account_from_wallet_login_at_file(
|
||||
wallet.clone(),
|
||||
&id1,
|
||||
&DEFAULT_NAME_FIRST_ACCOUNT.into(),
|
||||
&DEFAULT_FIRST_ACCOUNT_NAME.into(),
|
||||
&password,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1488,7 +1489,7 @@ mod tests {
|
||||
load_existing_wallet_login_information_at_file(wallet, &id3, &password).unwrap();
|
||||
let acc3 = loaded_account.as_multiple_accounts().unwrap();
|
||||
let expected = vec![WalletAccount::new_mnemonic_backed_account(
|
||||
DEFAULT_NAME_FIRST_ACCOUNT.into(),
|
||||
DEFAULT_FIRST_ACCOUNT_NAME.into(),
|
||||
dummy_account3,
|
||||
cosmos_hd_path,
|
||||
)]
|
||||
@@ -1509,8 +1510,8 @@ mod tests {
|
||||
|
||||
let password = UserPassword::new("password".to_string());
|
||||
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
let id3 = AccountId::new("third".to_string());
|
||||
let id4 = AccountId::new("fourth".to_string());
|
||||
|
||||
@@ -1560,14 +1561,19 @@ mod tests {
|
||||
load_existing_wallet_login_information_at_file(wallet.clone(), &id2, &password).unwrap();
|
||||
let accounts = loaded_accounts.as_multiple_accounts().unwrap();
|
||||
let expected = vec![
|
||||
WalletAccount::new_mnemonic_backed_account(id2.clone(), dummy_account2, hd_path.clone()),
|
||||
WalletAccount::new_mnemonic_backed_account(
|
||||
id2.clone().into(),
|
||||
dummy_account2,
|
||||
hd_path.clone(),
|
||||
),
|
||||
WalletAccount::new_mnemonic_backed_account(id4.clone(), dummy_account4, hd_path.clone()),
|
||||
]
|
||||
.into();
|
||||
assert_eq!(accounts, &expected);
|
||||
|
||||
// Delete the second and fourth mnemonic from the second login entry removes the login entry
|
||||
remove_account_from_wallet_login_at_file(wallet.clone(), &id2, &id2, &password).unwrap();
|
||||
remove_account_from_wallet_login_at_file(wallet.clone(), &id2, &id2.clone().into(), &password)
|
||||
.unwrap();
|
||||
remove_account_from_wallet_login_at_file(wallet.clone(), &id2, &id4, &password).unwrap();
|
||||
assert!(matches!(
|
||||
load_existing_wallet_login_information_at_file(wallet.clone(), &id2, &password),
|
||||
@@ -1594,8 +1600,8 @@ mod tests {
|
||||
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
let password = UserPassword::new("password".to_string());
|
||||
let bad_password = UserPassword::new("bad-password".to_string());
|
||||
let id1 = AccountId::new("first".to_string());
|
||||
let id2 = AccountId::new("second".to_string());
|
||||
let id1 = LoginId::new("first".to_string());
|
||||
let id2 = LoginId::new("second".to_string());
|
||||
|
||||
assert!(!wallet.password_can_decrypt_all(&bad_password));
|
||||
assert!(wallet.password_can_decrypt_all(&password));
|
||||
|
||||
@@ -6,6 +6,41 @@ use std::fmt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
// The `LoginId` is the top level id in the wallet file, and is not stored encrypted
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
|
||||
pub(crate) struct LoginId(String);
|
||||
|
||||
impl LoginId {
|
||||
pub(crate) fn new(id: String) -> LoginId {
|
||||
LoginId(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for LoginId {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for LoginId {
|
||||
fn from(id: String) -> Self {
|
||||
Self::new(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for LoginId {
|
||||
fn from(id: &str) -> Self {
|
||||
Self::new(id.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LoginId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
// For each encrypted login, we can have multiple encrypted accounts.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
|
||||
pub(crate) struct AccountId(String);
|
||||
|
||||
@@ -22,14 +57,20 @@ impl AsRef<str> for AccountId {
|
||||
}
|
||||
|
||||
impl From<String> for AccountId {
|
||||
fn from(id: String) -> Self {
|
||||
Self::new(id)
|
||||
}
|
||||
fn from(id: String) -> Self {
|
||||
Self::new(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for AccountId {
|
||||
fn from(id: &str) -> Self {
|
||||
Self::new(id.to_string())
|
||||
fn from(id: &str) -> Self {
|
||||
Self::new(id.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LoginId> for AccountId {
|
||||
fn from(login_id: LoginId) -> Self {
|
||||
Self::new(login_id.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user