2023-04-21 03:45:59 +03:00
|
|
|
// Copyright 2023 The Grim Developers
|
2023-04-10 16:02:53 +03:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2023-07-25 03:42:52 +03:00
|
|
|
use std::path::PathBuf;
|
2023-08-09 02:22:16 +03:00
|
|
|
use std::sync::{Arc, mpsc, RwLock};
|
2023-08-09 20:11:44 +03:00
|
|
|
use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU8, Ordering};
|
2023-08-09 04:19:15 +03:00
|
|
|
use std::thread;
|
2023-08-03 23:49:11 +03:00
|
|
|
use std::time::Duration;
|
2023-07-28 00:00:57 +03:00
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
use grin_chain::SyncStatus;
|
2023-07-28 00:00:57 +03:00
|
|
|
use grin_core::global;
|
2023-07-29 00:17:54 +03:00
|
|
|
use grin_core::global::ChainTypes;
|
2023-08-09 02:22:16 +03:00
|
|
|
use grin_keychain::{ExtKeychain, Keychain};
|
2023-08-09 04:19:15 +03:00
|
|
|
use grin_util::secp::SecretKey;
|
2023-07-28 00:00:57 +03:00
|
|
|
use grin_util::types::ZeroingString;
|
|
|
|
use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient};
|
2023-08-09 02:22:16 +03:00
|
|
|
use grin_wallet_libwallet::{Error, NodeClient, StatusMessage, WalletBackend, WalletInfo, WalletInst, WalletLCProvider};
|
|
|
|
use grin_wallet_libwallet::api_impl::owner::retrieve_summary_info;
|
2023-07-28 00:00:57 +03:00
|
|
|
use parking_lot::Mutex;
|
2023-07-25 03:42:52 +03:00
|
|
|
|
2023-08-03 00:00:23 +03:00
|
|
|
use crate::AppConfig;
|
2023-08-09 20:11:44 +03:00
|
|
|
use crate::node::{Node, NodeConfig};
|
2023-08-09 02:22:16 +03:00
|
|
|
use crate::wallet::{ConnectionsConfig, ExternalConnection, WalletConfig};
|
|
|
|
use crate::wallet::types::{ConnectionMethod, WalletInstance};
|
2023-07-25 03:42:52 +03:00
|
|
|
|
2023-08-03 00:00:23 +03:00
|
|
|
/// [`Wallet`] list wrapper.
|
2023-07-29 00:17:54 +03:00
|
|
|
pub struct Wallets {
|
|
|
|
/// List of wallets.
|
2023-08-03 00:00:23 +03:00
|
|
|
pub(crate) list: Vec<Wallet>,
|
2023-07-30 18:57:12 +03:00
|
|
|
/// Selected [`Wallet`] identifier.
|
2023-07-29 00:17:54 +03:00
|
|
|
selected_id: Option<i64>,
|
|
|
|
}
|
|
|
|
|
2023-08-03 00:00:23 +03:00
|
|
|
impl Default for Wallets {
|
|
|
|
fn default() -> Self {
|
2023-07-29 00:17:54 +03:00
|
|
|
Self {
|
2023-08-03 04:11:25 +03:00
|
|
|
list: Self::init(AppConfig::chain_type()),
|
2023-08-03 00:00:23 +03:00
|
|
|
selected_id: None
|
2023-07-30 18:57:12 +03:00
|
|
|
}
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
2023-08-03 00:00:23 +03:00
|
|
|
}
|
2023-07-29 00:17:54 +03:00
|
|
|
|
2023-08-03 00:00:23 +03:00
|
|
|
impl Wallets {
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Initialize [`Wallet`] list from base directory for provided [`ChainType`].
|
2023-08-03 04:11:25 +03:00
|
|
|
fn init(chain_type: ChainTypes) -> Vec<Wallet> {
|
2023-07-29 00:17:54 +03:00
|
|
|
let mut wallets = Vec::new();
|
2023-08-03 00:00:23 +03:00
|
|
|
let wallets_dir = WalletConfig::get_base_path(chain_type);
|
2023-07-29 00:17:54 +03:00
|
|
|
// Load wallets from base directory.
|
|
|
|
for dir in wallets_dir.read_dir().unwrap() {
|
|
|
|
let wallet_dir = dir.unwrap().path();
|
|
|
|
if wallet_dir.is_dir() {
|
|
|
|
let wallet = Wallet::init(wallet_dir);
|
|
|
|
if let Some(w) = wallet {
|
|
|
|
wallets.push(w);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wallets
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Reinitialize [`Wallet`] list for provided [`ChainTypes`].
|
2023-08-03 04:11:25 +03:00
|
|
|
pub fn reinit(&mut self, chain_type: ChainTypes) {
|
2023-08-09 04:19:15 +03:00
|
|
|
for w in self.list.iter_mut() {
|
|
|
|
let _ = w.close();
|
|
|
|
}
|
2023-08-03 00:00:23 +03:00
|
|
|
self.list = Self::init(chain_type);
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
|
|
|
|
2023-08-03 00:00:23 +03:00
|
|
|
/// Add created [`Wallet`] to the list.
|
|
|
|
pub fn add(&mut self, wallet: Wallet) {
|
|
|
|
self.selected_id = Some(wallet.config.id);
|
|
|
|
self.list.insert(0, wallet);
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Select [`Wallet`] with provided identifier.
|
2023-08-03 00:00:23 +03:00
|
|
|
pub fn select(&mut self, id: Option<i64>) {
|
|
|
|
self.selected_id = id;
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Check if [`Wallet`] is selected for provided identifier.
|
2023-08-03 00:00:23 +03:00
|
|
|
pub fn is_selected(&self, id: i64) -> bool {
|
|
|
|
return Some(id) == self.selected_id;
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Check if selected [`Wallet`] is open.
|
2023-08-03 00:00:23 +03:00
|
|
|
pub fn is_selected_open(&self) -> bool {
|
|
|
|
for w in &self.list {
|
|
|
|
if Some(w.config.id) == self.selected_id {
|
|
|
|
return w.is_open()
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
|
|
|
}
|
2023-08-03 00:00:23 +03:00
|
|
|
false
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Open selected [`Wallet`].
|
|
|
|
pub fn open_selected(&mut self, password: String) -> Result<(), Error> {
|
2023-08-03 04:11:25 +03:00
|
|
|
for w in self.list.iter_mut() {
|
2023-08-03 00:00:23 +03:00
|
|
|
if Some(w.config.id) == self.selected_id {
|
2023-08-09 02:22:16 +03:00
|
|
|
return w.open(password.clone());
|
2023-08-03 00:00:23 +03:00
|
|
|
}
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
2023-08-03 00:00:23 +03:00
|
|
|
Err(Error::GenericError("Wallet is not selected".to_string()))
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Contains wallet instance and handles wallet commands.
|
2023-07-25 03:42:52 +03:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Wallet {
|
2023-07-29 00:17:54 +03:00
|
|
|
/// Wallet instance.
|
|
|
|
instance: WalletInstance,
|
2023-07-28 00:00:57 +03:00
|
|
|
/// Wallet configuration.
|
2023-08-09 02:22:16 +03:00
|
|
|
pub config: WalletConfig,
|
2023-08-03 00:00:23 +03:00
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Identifier for launched wallet thread.
|
|
|
|
thread_id: Arc<AtomicI64>,
|
|
|
|
|
2023-08-03 00:00:23 +03:00
|
|
|
/// Flag to check if wallet is open.
|
|
|
|
is_open: Arc<AtomicBool>,
|
|
|
|
|
|
|
|
/// Error on wallet loading.
|
2023-08-09 04:19:15 +03:00
|
|
|
loading_error: Arc<AtomicBool>,
|
2023-08-03 00:00:23 +03:00
|
|
|
/// Loading progress in percents
|
2023-08-09 20:11:44 +03:00
|
|
|
loading_progress: Arc<AtomicU8>,
|
2023-08-09 02:22:16 +03:00
|
|
|
|
|
|
|
/// Wallet balance information.
|
|
|
|
info: Arc<RwLock<Option<WalletInfo>>>
|
2023-07-25 03:42:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Wallet {
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Instantiate [`Wallet`] from provided [`WalletInstance`] and [`WalletConfig`].
|
2023-08-03 00:00:23 +03:00
|
|
|
fn new(instance: WalletInstance, config: WalletConfig) -> Self {
|
|
|
|
Self {
|
|
|
|
instance,
|
|
|
|
config,
|
2023-08-09 20:11:44 +03:00
|
|
|
thread_id: Arc::new(AtomicI64::new(0)),
|
2023-08-09 02:22:16 +03:00
|
|
|
is_open: Arc::from(AtomicBool::new(false)),
|
2023-08-09 04:19:15 +03:00
|
|
|
loading_error: Arc::from(AtomicBool::new(false)),
|
2023-08-09 02:22:16 +03:00
|
|
|
loading_progress: Arc::new(AtomicU8::new(0)),
|
|
|
|
info: Arc::new(RwLock::new(None)),
|
2023-08-03 00:00:23 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create new wallet.
|
|
|
|
pub fn create(
|
2023-07-28 00:00:57 +03:00
|
|
|
name: String,
|
|
|
|
password: String,
|
|
|
|
mnemonic: String,
|
2023-08-09 02:22:16 +03:00
|
|
|
conn_method: &ConnectionMethod
|
2023-07-28 00:00:57 +03:00
|
|
|
) -> Result<Wallet, Error> {
|
2023-08-09 02:22:16 +03:00
|
|
|
let config = WalletConfig::create(name, conn_method);
|
2023-08-03 00:00:23 +03:00
|
|
|
let instance = Self::create_wallet_instance(config.clone())?;
|
|
|
|
let w = Wallet::new(instance, config);
|
2023-07-29 00:17:54 +03:00
|
|
|
{
|
|
|
|
let mut w_lock = w.instance.lock();
|
|
|
|
let p = w_lock.lc_provider()?;
|
|
|
|
p.create_wallet(None,
|
|
|
|
Some(ZeroingString::from(mnemonic.clone())),
|
|
|
|
mnemonic.len(),
|
2023-08-03 00:00:23 +03:00
|
|
|
ZeroingString::from(password),
|
2023-07-29 00:17:54 +03:00
|
|
|
false,
|
|
|
|
)?;
|
|
|
|
}
|
2023-07-28 00:00:57 +03:00
|
|
|
Ok(w)
|
2023-07-25 03:42:52 +03:00
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Initialize [`Wallet`] from provided data path.
|
2023-07-29 00:17:54 +03:00
|
|
|
fn init(data_path: PathBuf) -> Option<Wallet> {
|
2023-07-25 03:42:52 +03:00
|
|
|
let wallet_config = WalletConfig::load(data_path.clone());
|
|
|
|
if let Some(config) = wallet_config {
|
2023-07-29 00:17:54 +03:00
|
|
|
if let Ok(instance) = Self::create_wallet_instance(config.clone()) {
|
2023-08-03 00:00:23 +03:00
|
|
|
return Some(Wallet::new(instance, config));
|
2023-07-29 00:17:54 +03:00
|
|
|
}
|
2023-07-25 03:42:52 +03:00
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Reinitialize [`WalletInstance`] to apply new [`WalletConfig`].
|
2023-08-03 00:00:23 +03:00
|
|
|
pub fn reinit(&mut self) -> Result<(), Error> {
|
|
|
|
self.close()?;
|
|
|
|
self.instance = Self::create_wallet_instance(self.config.clone())?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Create [`WalletInstance`] from provided [`WalletConfig`].
|
2023-07-28 00:00:57 +03:00
|
|
|
fn create_wallet_instance(config: WalletConfig) -> Result<WalletInstance, Error> {
|
|
|
|
// Assume global chain type has already been initialized.
|
2023-07-31 01:04:41 +03:00
|
|
|
let chain_type = config.chain_type;
|
2023-07-28 00:00:57 +03:00
|
|
|
if !global::GLOBAL_CHAIN_TYPE.is_init() {
|
|
|
|
global::init_global_chain_type(chain_type);
|
|
|
|
} else {
|
|
|
|
global::set_global_chain_type(chain_type);
|
|
|
|
global::set_local_chain_type(chain_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup node client.
|
2023-08-09 02:22:16 +03:00
|
|
|
let (node_api_url, node_secret) = if let Some(id) = config.ext_conn_id {
|
|
|
|
if let Some(conn) = ConnectionsConfig::ext_conn(id) {
|
|
|
|
(conn.url, conn.secret)
|
|
|
|
} else {
|
|
|
|
(ExternalConnection::DEFAULT_MAIN_URL.to_string(), None)
|
|
|
|
}
|
2023-07-28 00:00:57 +03:00
|
|
|
} else {
|
2023-08-03 00:00:23 +03:00
|
|
|
let api_url = format!("http://{}", NodeConfig::get_api_address());
|
|
|
|
let api_secret = NodeConfig::get_foreign_api_secret();
|
|
|
|
(api_url, api_secret)
|
2023-07-28 00:00:57 +03:00
|
|
|
};
|
|
|
|
let node_client = HTTPNodeClient::new(&node_api_url, node_secret)?;
|
|
|
|
|
|
|
|
// Create wallet instance.
|
|
|
|
let wallet = Self::inst_wallet::<
|
|
|
|
DefaultLCProvider<HTTPNodeClient, ExtKeychain>,
|
|
|
|
HTTPNodeClient,
|
|
|
|
ExtKeychain,
|
|
|
|
>(config, node_client)?;
|
|
|
|
Ok(wallet)
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Instantiate [`WalletInstance`] from provided node client and [`WalletConfig`].
|
2023-07-28 00:00:57 +03:00
|
|
|
fn inst_wallet<L, C, K>(
|
|
|
|
config: WalletConfig,
|
|
|
|
node_client: C,
|
|
|
|
) -> Result<Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>, Error>
|
|
|
|
where
|
|
|
|
DefaultWalletImpl<'static, C>: WalletInst<'static, L, C, K>,
|
|
|
|
L: WalletLCProvider<'static, C, K>,
|
|
|
|
C: NodeClient + 'static,
|
|
|
|
K: Keychain + 'static,
|
|
|
|
{
|
|
|
|
let mut wallet = Box::new(DefaultWalletImpl::<'static, C>::new(node_client).unwrap())
|
|
|
|
as Box<dyn WalletInst<'static, L, C, K>>;
|
|
|
|
let lc = wallet.lc_provider()?;
|
|
|
|
lc.set_top_level_directory(config.get_data_path().as_str())?;
|
|
|
|
Ok(Arc::new(Mutex::new(wallet)))
|
|
|
|
}
|
|
|
|
|
2023-08-09 04:19:15 +03:00
|
|
|
/// Open the wallet and start commands handling and updating info at separate thread.
|
2023-08-03 00:00:23 +03:00
|
|
|
pub fn open(&self, password: String) -> Result<(), Error> {
|
2023-07-29 00:17:54 +03:00
|
|
|
let mut wallet_lock = self.instance.lock();
|
|
|
|
let lc = wallet_lock.lc_provider()?;
|
2023-08-03 00:00:23 +03:00
|
|
|
lc.close_wallet(None)?;
|
2023-08-09 02:22:16 +03:00
|
|
|
|
2023-08-09 04:19:15 +03:00
|
|
|
// Open the wallet.
|
|
|
|
match lc.open_wallet(None, ZeroingString::from(password), false, false) {
|
|
|
|
Ok(keychain) => {
|
|
|
|
self.is_open.store(true, Ordering::Relaxed);
|
2023-08-09 20:11:44 +03:00
|
|
|
// Start info updating and commands handling.
|
2023-08-09 04:19:15 +03:00
|
|
|
start_wallet(self.clone(), keychain);
|
2023-08-09 02:22:16 +03:00
|
|
|
}
|
2023-08-09 04:19:15 +03:00
|
|
|
Err(e) => return Err(e)
|
|
|
|
}
|
2023-07-28 00:00:57 +03:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Get wallet thread identifier.
|
|
|
|
fn get_thread_id(&self) -> i64 {
|
|
|
|
self.thread_id.load(Ordering::Relaxed)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Refresh wallet thread identifier.
|
|
|
|
fn new_thread_id(&self) -> i64 {
|
|
|
|
let id = chrono::Utc::now().timestamp();
|
|
|
|
self.thread_id.store(id, Ordering::Relaxed);
|
|
|
|
id
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get wallet loading progress after opening.
|
2023-08-09 02:22:16 +03:00
|
|
|
pub fn loading_progress(&self) -> u8 {
|
|
|
|
self.loading_progress.load(Ordering::Relaxed)
|
|
|
|
}
|
|
|
|
|
2023-08-09 04:19:15 +03:00
|
|
|
/// Check if wallet had an error on loading.
|
|
|
|
pub fn loading_error(&self) -> bool {
|
|
|
|
self.loading_error.load(Ordering::Relaxed)
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Set an error for wallet on loading.
|
|
|
|
pub fn set_loading_error(&self, error: bool) {
|
|
|
|
self.loading_error.store(error, Ordering::Relaxed);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Check if wallet was open.
|
2023-08-03 00:00:23 +03:00
|
|
|
pub fn is_open(&self) -> bool {
|
|
|
|
self.is_open.load(Ordering::Relaxed)
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Close the wallet.
|
2023-08-03 00:00:23 +03:00
|
|
|
pub fn close(&mut self) -> Result<(), Error> {
|
|
|
|
if self.is_open() {
|
|
|
|
let mut wallet_lock = self.instance.lock();
|
|
|
|
let lc = wallet_lock.lc_provider()?;
|
|
|
|
lc.close_wallet(None)?;
|
2023-08-09 20:11:44 +03:00
|
|
|
// Clear wallet info.
|
|
|
|
let mut w_info = self.info.write().unwrap();
|
|
|
|
*w_info = None;
|
|
|
|
// Mark wallet as not opened.
|
2023-08-03 00:00:23 +03:00
|
|
|
self.is_open.store(false, Ordering::Relaxed);
|
|
|
|
}
|
2023-07-28 00:00:57 +03:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Get wallet balance info.
|
2023-08-09 02:22:16 +03:00
|
|
|
pub fn get_info(&self) -> Option<WalletInfo> {
|
|
|
|
let r_info = self.info.read().unwrap();
|
|
|
|
r_info.clone()
|
2023-07-28 00:00:57 +03:00
|
|
|
}
|
2023-08-09 04:19:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Delay in seconds to update wallet info.
|
|
|
|
const INFO_UPDATE_DELAY: Duration = Duration::from_millis(20 * 1000);
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
/// Launch thread for commands handling and info updating after [`INFO_UPDATE_DELAY`].
|
|
|
|
fn start_wallet(mut wallet: Wallet, keychain_mask: Option<SecretKey>) {
|
|
|
|
// Setup initial loading values.
|
|
|
|
wallet.loading_progress.store(0, Ordering::Relaxed);
|
|
|
|
wallet.set_loading_error(false);
|
2023-08-09 04:19:15 +03:00
|
|
|
|
|
|
|
// Launch loop at separate thread to update wallet info.
|
2023-08-09 20:11:44 +03:00
|
|
|
let thread_id = wallet.new_thread_id();
|
2023-08-09 04:19:15 +03:00
|
|
|
thread::spawn(move || loop {
|
2023-08-09 20:11:44 +03:00
|
|
|
// Stop updating if wallet was closed or thread changed.
|
|
|
|
if !wallet.is_open() || thread_id != wallet.get_thread_id() {
|
2023-08-09 04:19:15 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
// Setup error when required integrated node is not enabled or skip when it's not ready.
|
|
|
|
if wallet.config.ext_conn_id.is_none() {
|
|
|
|
if !Node::is_running() {
|
|
|
|
wallet.set_loading_error(true);
|
|
|
|
} else if Node::get_sync_status() != Some(SyncStatus::NoSync) {
|
|
|
|
wallet.set_loading_error(false);
|
|
|
|
thread::sleep(Duration::from_millis(1000));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update wallet info if it was no loading error after several attempts.
|
|
|
|
if !wallet.loading_error() {
|
|
|
|
let wallet_scan = wallet.clone();
|
|
|
|
let (tx, rx) = mpsc::channel::<StatusMessage>();
|
|
|
|
// Update loading progress at separate thread.
|
|
|
|
thread::spawn(move || {
|
|
|
|
while let Ok(m) = rx.recv() {
|
|
|
|
// Stop updating if wallet was closed or maximum.
|
|
|
|
if !wallet_scan.is_open() || wallet_scan.get_thread_id() != thread_id {
|
|
|
|
return;
|
2023-08-09 04:19:15 +03:00
|
|
|
}
|
2023-08-09 20:11:44 +03:00
|
|
|
match m {
|
|
|
|
StatusMessage::UpdatingOutputs(_) => {}
|
|
|
|
StatusMessage::UpdatingTransactions(_) => {}
|
|
|
|
StatusMessage::FullScanWarn(_) => {}
|
|
|
|
StatusMessage::Scanning(_, progress) => {
|
|
|
|
wallet_scan.loading_progress.store(progress, Ordering::Relaxed);
|
|
|
|
}
|
|
|
|
StatusMessage::ScanningComplete(_) => {
|
|
|
|
wallet_scan.loading_progress.store(100, Ordering::Relaxed);
|
|
|
|
}
|
|
|
|
StatusMessage::UpdateWarning(_) => {}
|
2023-08-09 04:19:15 +03:00
|
|
|
}
|
|
|
|
}
|
2023-08-09 20:11:44 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
// Retrieve wallet info.
|
|
|
|
match retrieve_summary_info(
|
|
|
|
wallet.instance.clone(),
|
|
|
|
keychain_mask.as_ref(),
|
|
|
|
&Some(tx),
|
|
|
|
true,
|
|
|
|
wallet.config.min_confirmations
|
|
|
|
) {
|
|
|
|
Ok(info) => {
|
|
|
|
if wallet.loading_progress() != 100 {
|
|
|
|
wallet.set_loading_error(true);
|
|
|
|
} else {
|
|
|
|
let mut w_info = wallet.info.write().unwrap();
|
|
|
|
*w_info = Some(info.1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(_) => {
|
|
|
|
wallet.set_loading_error(true);
|
|
|
|
wallet.loading_progress.store(0, Ordering::Relaxed);
|
2023-08-09 04:19:15 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
// Stop updating if wallet was closed.
|
|
|
|
if !wallet.is_open() || wallet.get_thread_id() != thread_id {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-08-09 04:19:15 +03:00
|
|
|
// Repeat after default delay or after 1 second if update was not complete.
|
2023-08-09 20:11:44 +03:00
|
|
|
let delay = if wallet.loading_progress() == 100 && !wallet.loading_error() {
|
2023-08-09 04:19:15 +03:00
|
|
|
INFO_UPDATE_DELAY
|
|
|
|
} else {
|
|
|
|
Duration::from_millis(1000)
|
|
|
|
};
|
|
|
|
thread::sleep(delay);
|
|
|
|
});
|
2023-07-25 03:42:52 +03:00
|
|
|
}
|