1use std::{fs, sync::Arc};
20
21use url::Url;
22
23use darkfi::{rpc::client::RpcClient, util::path::expand_path, Error, Result};
24
25pub mod error;
27use error::{WalletDbError, WalletDbResult};
28
29pub mod rpc;
31
32pub mod transfer;
34
35pub mod swap;
37
38pub mod token;
40
41pub mod cli_util;
43
44pub mod money;
46
47pub mod dao;
49
50pub mod deploy;
52
53pub mod txs_history;
55
56pub mod scanned_blocks;
58
59pub mod walletdb;
61use walletdb::{WalletDb, WalletPtr};
62
63pub struct Drk {
65 pub wallet: WalletPtr,
67 pub rpc_client: Option<RpcClient>,
69 pub fun: bool,
71}
72
73impl Drk {
74 pub async fn new(
75 wallet_path: String,
76 wallet_pass: String,
77 endpoint: Option<Url>,
78 ex: Arc<smol::Executor<'static>>,
79 fun: bool,
80 ) -> Result<Self> {
81 let wallet_path = expand_path(&wallet_path)?;
83 if !wallet_path.exists() {
84 if let Some(parent) = wallet_path.parent() {
85 fs::create_dir_all(parent)?;
86 }
87 }
88 let Ok(wallet) = WalletDb::new(Some(wallet_path), Some(&wallet_pass)) else {
89 return Err(Error::DatabaseError(format!("{}", WalletDbError::InitializationFailed)));
90 };
91
92 let rpc_client = if let Some(endpoint) = endpoint {
94 Some(RpcClient::new(endpoint, ex).await?)
95 } else {
96 None
97 };
98
99 Ok(Self { wallet, rpc_client, fun })
100 }
101
102 pub async fn initialize_wallet(&self) -> WalletDbResult<()> {
104 self.wallet.exec_batch_sql(include_str!("../wallet.sql"))?;
106
107 Ok(())
108 }
109
110 pub async fn reset(&self) -> WalletDbResult<()> {
112 println!("Resetting full wallet state");
113 self.reset_scanned_blocks()?;
114 self.reset_money_tree().await?;
115 self.reset_money_smt()?;
116 self.reset_money_coins()?;
117 self.reset_mint_authorities()?;
118 self.reset_dao_trees().await?;
119 self.reset_daos().await?;
120 self.reset_dao_proposals().await?;
121 self.reset_dao_votes()?;
122 self.reset_tx_history()?;
123 println!("Successfully reset full wallet state");
124 Ok(())
125 }
126
127 pub async fn reset_inverse_cache(&self) -> Result<()> {
133 if let Err(e) = self.wallet.clear_inverse_cache() {
135 return Err(Error::DatabaseError(format!(
136 "[reset_inverse_cache] Clearing wallet inverse cache failed: {e:?}"
137 )))
138 }
139
140 let query = self.get_money_tree_state_query().await?;
142 if let Err(e) = self.wallet.cache_inverse(query) {
143 return Err(Error::DatabaseError(format!(
144 "[reset_inverse_cache] Inserting money query into inverse cache failed: {e:?}"
145 )))
146 }
147
148 let query = self.get_dao_trees_state_query().await?;
150 if let Err(e) = self.wallet.cache_inverse(query) {
151 return Err(Error::DatabaseError(format!(
152 "[reset_inverse_cache] Inserting DAO query into inverse cache failed: {e:?}"
153 )))
154 }
155
156 Ok(())
157 }
158
159 pub fn store_inverse_cache(&self, height: u32, hash: &str) -> Result<()> {
163 let rollback_query = match self.wallet.grab_inverse_cache_block() {
165 Ok(q) => q,
166 Err(e) => {
167 return Err(Error::DatabaseError(format!(
168 "[store_inverse_cache] Creating rollback query failed: {e:?}"
169 )))
170 }
171 };
172
173 if let Err(e) = self.put_scanned_block_record(height, hash, &rollback_query) {
175 return Err(Error::DatabaseError(format!(
176 "[store_inverse_cache] Inserting scanned blocks information record failed: {e:?}"
177 )))
178 };
179
180 if let Err(e) = self.wallet.clear_inverse_cache() {
182 return Err(Error::DatabaseError(format!(
183 "[store_inverse_cache] Clearing wallet inverse cache failed: {e:?}"
184 )))
185 };
186
187 Ok(())
188 }
189}