wallet: backend account switching
This commit is contained in:
@@ -44,6 +44,7 @@ fn main() {
|
||||
mixnet::account::get_validator_api_urls,
|
||||
mixnet::account::get_validator_nymd_urls,
|
||||
mixnet::account::list_accounts_for_password,
|
||||
mixnet::account::sign_in_decrypted_account,
|
||||
mixnet::account::logout,
|
||||
mixnet::account::remove_account_for_password,
|
||||
mixnet::account::remove_password,
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::config::Config;
|
||||
use crate::error::BackendError;
|
||||
use crate::network::Network as WalletNetwork;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use crate::state::{DecryptedAccount, State};
|
||||
use crate::wallet_storage::account_data::StoredLogin;
|
||||
use crate::wallet_storage::{self, DEFAULT_WALLET_ACCOUNT_ID};
|
||||
|
||||
@@ -14,7 +14,7 @@ use cosmrs::bip32::DerivationPath;
|
||||
use itertools::Itertools;
|
||||
use rand::seq::SliceRandom;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::convert::TryInto;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
@@ -51,6 +51,14 @@ pub struct CreatedAccount {
|
||||
mnemonic: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/createdaccount.ts"))]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct AccountEntry {
|
||||
id: String,
|
||||
address: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/balance.ts"))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -432,6 +440,37 @@ pub async fn sign_in_with_password(
|
||||
.clone()
|
||||
}
|
||||
};
|
||||
|
||||
// Keep track of all accounts
|
||||
// WIP(JON): simplify
|
||||
let all_accounts: HashMap<_, _> = match stored_account {
|
||||
StoredLogin::Mnemonic(ref account) => [(
|
||||
id.to_string(),
|
||||
DecryptedAccount {
|
||||
id: id.to_string(),
|
||||
mnemonic: account.mnemonic().clone(),
|
||||
},
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
StoredLogin::Multiple(ref accounts) => accounts
|
||||
.get_accounts()
|
||||
.map(|account| {
|
||||
(
|
||||
account.id.to_string(),
|
||||
DecryptedAccount {
|
||||
id: account.id.to_string(),
|
||||
mnemonic: account.account.mnemonic().clone(),
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
{
|
||||
let mut w_state = state.write().await;
|
||||
w_state.set_all_accounts(all_accounts);
|
||||
}
|
||||
|
||||
_connect_with_mnemonic(mnemonic, state).await
|
||||
}
|
||||
|
||||
@@ -468,6 +507,23 @@ pub fn remove_account_for_password(password: &str, inner_id: &str) -> Result<(),
|
||||
wallet_storage::remove_account_from_wallet_login(&id, &inner_id, &password)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn list_accounts(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Vec<AccountEntry>, BackendError> {
|
||||
let state = state.read().await;
|
||||
let all_accounts = state.get_all_accounts();
|
||||
let a = all_accounts
|
||||
.values()
|
||||
.map(|account| AccountEntry {
|
||||
id: account.id.clone(),
|
||||
address: "placeholder".to_string(),
|
||||
})
|
||||
.collect();
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
// WIP(JON): consider changing return type
|
||||
#[tauri::command]
|
||||
pub fn list_accounts_for_password(password: &str) -> Result<Vec<String>, BackendError> {
|
||||
// Currently we only support a single, default, id in the wallet
|
||||
@@ -483,3 +539,20 @@ pub fn list_accounts_for_password(password: &str) -> Result<Vec<String>, Backend
|
||||
};
|
||||
Ok(ids)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn sign_in_decrypted_account(
|
||||
account_id: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Account, BackendError> {
|
||||
let account = {
|
||||
let state = state.read().await;
|
||||
state
|
||||
.get_all_accounts()
|
||||
.get(account_id)
|
||||
.ok_or(BackendError::NoSuchIdInWalletLoginEntry)?
|
||||
.clone()
|
||||
};
|
||||
let mnemonic = account.mnemonic;
|
||||
_connect_with_mnemonic(mnemonic, state).await
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::config::{Config, OptionalValidators, ValidatorUrl};
|
||||
use crate::error::BackendError;
|
||||
use crate::network::Network;
|
||||
|
||||
use bip39::Mnemonic;
|
||||
use strum::IntoEnumIterator;
|
||||
use validator_client::nymd::SigningNymdClient;
|
||||
use validator_client::Client;
|
||||
@@ -18,6 +19,10 @@ pub struct State {
|
||||
signing_clients: HashMap<Network, Client<SigningNymdClient>>,
|
||||
current_network: Network,
|
||||
|
||||
// All the accounts the we get from decrypting the wallet. We hold on to these for being able to
|
||||
// switch accounts on-the-fly
|
||||
all_accounts: HashMap<String, DecryptedAccount>,
|
||||
|
||||
/// Validators that have been fetched dynamically, probably during startup.
|
||||
fetched_validators: OptionalValidators,
|
||||
}
|
||||
@@ -63,6 +68,15 @@ impl State {
|
||||
self.current_network
|
||||
}
|
||||
|
||||
pub(crate) fn set_all_accounts(&mut self, all_accounts: HashMap<String, DecryptedAccount>) {
|
||||
self.all_accounts.clear();
|
||||
self.all_accounts.extend(all_accounts)
|
||||
}
|
||||
|
||||
pub(crate) fn get_all_accounts(&self) -> &HashMap<String, DecryptedAccount> {
|
||||
&self.all_accounts
|
||||
}
|
||||
|
||||
pub fn logout(&mut self) {
|
||||
self.signing_clients = HashMap::new();
|
||||
}
|
||||
@@ -162,6 +176,14 @@ macro_rules! client {
|
||||
};
|
||||
}
|
||||
|
||||
// Keep track of mnemonics on the backend, so we can switch accounts
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct DecryptedAccount {
|
||||
pub id: String,
|
||||
pub mnemonic: Mnemonic,
|
||||
// address: String
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! nymd_client {
|
||||
($state:ident) => {
|
||||
|
||||
@@ -153,6 +153,7 @@ fn append_account_to_wallet_login_information_at_file(
|
||||
|
||||
let mut decrypted_login = stored_wallet.decrypt_login(&id, password)?;
|
||||
|
||||
// WIP(JON): redo this since we now can clone the mnemonic
|
||||
// Since we can't clone the mnemonic, we have to perform a little dance were we add the mnemonic
|
||||
// to the inner enum payload, while also converting by swapping if necessary.
|
||||
if let StoredLogin::Multiple(ref mut accounts) = decrypted_login {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface AccountEntry {
|
||||
id: string;
|
||||
address: string;
|
||||
}
|
||||
Reference in New Issue
Block a user