/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2025 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
use std::{fs, sync::Arc};
use url::Url;
use darkfi::{rpc::client::RpcClient, util::path::expand_path, Error, Result};
/// Error codes
pub mod error;
use error::{WalletDbError, WalletDbResult};
/// darkfid JSON-RPC related methods
pub mod rpc;
/// Payment methods
pub mod transfer;
/// Swap methods
pub mod swap;
/// Token methods
pub mod token;
/// CLI utility functions
pub mod cli_util;
/// Wallet functionality related to Money
pub mod money;
/// Wallet functionality related to Dao
pub mod dao;
/// Wallet functionality related to Deployooor
pub mod deploy;
/// Wallet functionality related to transactions history
pub mod txs_history;
/// Wallet functionality related to scanned blocks
pub mod scanned_blocks;
/// Wallet database operations handler
pub mod walletdb;
use walletdb::{WalletDb, WalletPtr};
/// Blockchain cache database operations handler
pub mod cache;
use cache::Cache;
/// CLI-util structure
pub struct Drk {
/// Blockchain cache database operations handler
pub cache: Cache,
/// Wallet database operations handler
pub wallet: WalletPtr,
/// JSON-RPC client to execute requests to darkfid daemon
pub rpc_client: Option,
/// Flag indicating if fun stuff are enabled
pub fun: bool,
}
impl Drk {
pub async fn new(
cache_path: String,
wallet_path: String,
wallet_pass: String,
endpoint: Option,
ex: Arc>,
fun: bool,
) -> Result {
// Initialize blockchain cache database
let db_path = expand_path(&cache_path)?;
let sled_db = sled_overlay::sled::open(&db_path)?;
let Ok(cache) = Cache::new(&sled_db) else {
return Err(Error::DatabaseError(format!("{}", WalletDbError::InitializationFailed)));
};
// Initialize wallet
let wallet_path = expand_path(&wallet_path)?;
if !wallet_path.exists() {
if let Some(parent) = wallet_path.parent() {
fs::create_dir_all(parent)?;
}
}
let Ok(wallet) = WalletDb::new(Some(wallet_path), Some(&wallet_pass)) else {
return Err(Error::DatabaseError(format!("{}", WalletDbError::InitializationFailed)));
};
// Initialize rpc client
let rpc_client = if let Some(endpoint) = endpoint {
Some(RpcClient::new(endpoint, ex).await?)
} else {
None
};
Ok(Self { cache, wallet, rpc_client, fun })
}
/// Initialize wallet with tables for `Drk`.
pub async fn initialize_wallet(&self) -> WalletDbResult<()> {
// Initialize wallet schema
self.wallet.exec_batch_sql(include_str!("../wallet.sql"))?;
Ok(())
}
/// Auxiliary function to completely reset wallet state.
pub async fn reset(&self) -> WalletDbResult<()> {
println!("Resetting full wallet state");
self.reset_scanned_blocks()?;
self.reset_money_tree()?;
self.reset_money_smt()?;
self.reset_money_coins()?;
self.reset_mint_authorities()?;
self.reset_dao_trees().await?;
self.reset_daos().await?;
self.reset_dao_proposals().await?;
self.reset_dao_votes()?;
self.reset_tx_history()?;
println!("Successfully reset full wallet state");
Ok(())
}
/// Auxiliary function to reset `walletdb` inverse cache state.
pub async fn reset_inverse_cache(&self) -> Result<()> {
// Reset `walletdb` inverse cache
if let Err(e) = self.wallet.clear_inverse_cache() {
return Err(Error::DatabaseError(format!(
"[reset_inverse_cache] Clearing wallet inverse cache failed: {e:?}"
)))
}
Ok(())
}
}