source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+[[package]]
+name = "ahash"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98"
+dependencies = [
+ "getrandom 0.2.6",
+ "once_cell",
+ "version_check",
+]
+
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00fa2bcfe9debe57f32285ef56cb218b2e0dbf91e476ad22f61a745d4c032a18"
dependencies = [
+ "ahash",
"async-trait",
"bdk-macros",
"bip39",
"rand",
"reqwest",
"rocksdb",
+ "rusqlite",
"serde",
"serde_json",
"sled",
"str-buf",
]
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
+[[package]]
+name = "fallible-streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
+
[[package]]
name = "fastrand"
version = "1.7.0"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
+dependencies = [
+ "hashbrown",
+]
[[package]]
name = "heck"
"libc",
]
+[[package]]
+name = "libsqlite3-sys"
+version = "0.22.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d"
+dependencies = [
+ "pkg-config",
+ "vcpkg",
+]
+
[[package]]
name = "lock_api"
version = "0.4.7"
"librocksdb-sys",
]
+[[package]]
+name = "rusqlite"
+version = "0.25.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c4b1eaf239b47034fb450ee9cdedd7d0226571689d8823030c4b6c2cb407152"
+dependencies = [
+ "bitflags",
+ "fallible-iterator",
+ "fallible-streaming-iterator",
+ "hashlink",
+ "libsqlite3-sys",
+ "memchr",
+ "smallvec 1.8.0",
+]
+
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
[[package]]
name = "vec_map"
version = "0.8.2"
electrsd = { version= "0.12", features = ["trigger", "bitcoind_22_0"], optional = true}
[features]
-default = ["cli", "repl"]
-cli = ["bdk/key-value-db", "clap", "dirs-next", "env_logger"]
+default = ["cli", "repl", "key-value-db"]
+cli = ["clap", "dirs-next", "env_logger"]
repl = ["regex", "rustyline", "fd-lock"]
+key-value-db = ["bdk/key-value-db"]
+sqlite-db = ["bdk/sqlite"]
electrum = ["bdk/electrum"]
esplora = []
esplora-ureq = ["esplora", "bdk/use-esplora-ureq"]
#[cfg(feature = "rpc")]
use bdk::blockchain::rpc::{Auth, RpcConfig};
-use bdk::database::BatchDatabase;
-use bdk::sled;
-use bdk::sled::Tree;
+#[cfg(feature = "key-value-db")]
+use bdk::database::any::SledDbConfiguration;
+#[cfg(feature = "sqlite-db")]
+use bdk::database::any::SqliteDbConfiguration;
+use bdk::database::{AnyDatabase, AnyDatabaseConfig, BatchDatabase, ConfigurableDatabase};
use bdk::wallet::wallet_name_from_descriptor;
use bdk::Wallet;
use bdk::{bitcoin, Error};
Exit,
}
-fn prepare_home_dir() -> Result<PathBuf, Error> {
+/// prepare bdk_cli home and wallet directory
+fn prepare_home_wallet_dir(wallet_name: &String) -> Result<PathBuf, Error> {
let mut dir = PathBuf::new();
dir.push(
&dirs_next::home_dir().ok_or_else(|| Error::Generic("home dir not found".to_string()))?,
fs::create_dir(&dir).map_err(|e| Error::Generic(e.to_string()))?;
}
- #[cfg(not(feature = "compact_filters"))]
- dir.push("database.sled");
+ dir.push(wallet_name);
+
+ if !dir.exists() {
+ info!("Creating wallet directory {}", dir.as_path().display());
+ fs::create_dir(&dir).map_err(|e| Error::Generic(e.to_string()))?;
+ }
- #[cfg(feature = "compact_filters")]
- dir.push("compact_filters");
Ok(dir)
}
-fn open_database(wallet_opts: &WalletOpts) -> Result<Tree, Error> {
- let mut database_path = prepare_home_dir()?;
- let wallet_name = wallet_opts
- .wallet
- .as_deref()
- .expect("We should always have a wallet name at this point");
- database_path.push(wallet_name);
- let database = sled::open(database_path)?;
- let tree = database.open_tree(&wallet_name)?;
+/// Prepare wallet database directory
+fn prepare_wallet_db_dir(wallet_name: &String) -> Result<PathBuf, Error> {
+ let mut db_dir = prepare_home_wallet_dir(wallet_name)?;
+
+ #[cfg(feature = "key-value-db")]
+ db_dir.push("wallet.sled");
+
+ #[cfg(feature = "sqlite-db")]
+ db_dir.push("wallet.sqlite");
+
+ #[cfg(not(feature = "sqlite-db"))]
+ if !db_dir.exists() {
+ info!("Creating database directory {}", db_dir.as_path().display());
+ fs::create_dir(&db_dir).map_err(|e| Error::Generic(e.to_string()))?;
+ }
+
+ Ok(db_dir)
+}
+
+/// Prepare blockchain data directory (for compact filters)
+#[cfg(feature = "compact_filters")]
+fn prepare_bc_dir(wallet_name: &String) -> Result<PathBuf, Error> {
+ let mut bc_dir = prepare_home_wallet_dir(wallet_name)?;
+
+ bc_dir.push("compact_filters");
+
+ if !bc_dir.exists() {
+ info!(
+ "Creating blockchain directory {}",
+ bc_dir.as_path().display()
+ );
+ fs::create_dir(&bc_dir).map_err(|e| Error::Generic(e.to_string()))?;
+ }
+
+ Ok(bc_dir)
+}
+
+fn open_database(wallet_opts: &WalletOpts) -> Result<AnyDatabase, Error> {
+ let wallet_name = wallet_opts.wallet.as_ref().expect("wallet name");
+ let database_path = prepare_wallet_db_dir(wallet_name)?;
+
+ #[cfg(feature = "key-value-db")]
+ let config = AnyDatabaseConfig::Sled(SledDbConfiguration {
+ path: database_path
+ .into_os_string()
+ .into_string()
+ .expect("path string"),
+ tree_name: wallet_name.to_string(),
+ });
+ #[cfg(feature = "sqlite-db")]
+ let config = AnyDatabaseConfig::Sqlite(SqliteDbConfiguration {
+ path: database_path
+ .into_os_string()
+ .into_string()
+ .expect("path string"),
+ });
+ let database = AnyDatabase::from_config(&config)?;
debug!("database opened successfully");
- Ok(tree)
+ Ok(database)
}
#[allow(dead_code)]
}
}
+ let wallet_name = wallet_opts.wallet.as_ref().expect("wallet name");
AnyBlockchainConfig::CompactFilters(CompactFiltersBlockchainConfig {
peers,
network: _network,
- storage_dir: prepare_home_dir()?
+ storage_dir: prepare_bc_dir(wallet_name)?
.into_os_string()
.into_string()
.map_err(|_| Error::Generic("Internal OS_String conversion error".to_string()))?,