Skip to content

Commit 06b3424

Browse files
committed
feat: add initializing wallet conf to just runner
- add config module to store and retrieve values - add toml and serde crates for desearilizing and reading values - update Justfile to create and save values in config.toml file in datadir - update utils, commands and handlers files to use values from config.toml -refactor prepare_wallet_db fn - fix clippy issues
1 parent 7a71b14 commit 06b3424

File tree

9 files changed

+364
-39
lines changed

9 files changed

+364
-39
lines changed

Cargo.lock

Lines changed: 85 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ log = "0.4"
2121
serde_json = "1.0"
2222
thiserror = "2.0.11"
2323
tokio = { version = "1", features = ["full"] }
24+
toml = "0.8.23"
25+
serde= {version = "1.0", features = ["derive"]}
2426

2527
# Optional dependencies
2628
bdk_bitcoind_rpc = { version = "0.20.0", optional = true }

Justfile

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,31 @@ descriptors private wallet=default_wallet:
9999
# run any bitcoin-cli rpc command
100100
[group('rpc')]
101101
rpc command wallet=default_wallet:
102-
bitcoin-cli -datadir={{default_datadir}} -regtest -rpcwallet={{wallet}} -rpcuser={{rpc_user}} -rpcpassword={{rpc_password}} {{command}}
102+
bitcoin-cli -datadir={{default_datadir}} -regtest -rpcwallet={{wallet}} -rpcuser={{rpc_user}} -rpcpassword={{rpc_password}} {{command}}
103+
104+
[group('wallet')]
105+
init wallet_name ext_descriptor int_descriptor client_type url database_type='sqlite' rpc_user='user' rpc_password='pass' force='false':
106+
mkdir -p {{default_datadir}}
107+
# Check if wallet configuration exists
108+
if [ "{{force}}" = "false" ] && grep -Fx "[wallets.{{wallet_name}}]" {{default_datadir}}/config.toml > /dev/null; then \
109+
echo "Error: Wallet '{{wallet_name}}' already configured in {{default_datadir}}/config.toml. Use --force to overwrite."; \
110+
exit 1; \
111+
fi
112+
# Remove existing configuration if --force is true
113+
if [ "{{force}}" = "true" ] && grep -Fx "[wallets.{{wallet_name}}]" {{default_datadir}}/config.toml > /dev/null; then \
114+
sed -i.bak '/^\[wallets\.{{wallet_name}}\]/,/^\[/d' {{default_datadir}}/config.toml; \
115+
sed -i.bak '/^\[wallets\.{{wallet_name}}\]/d' {{default_datadir}}/config.toml; \
116+
rm {{default_datadir}}/config.toml.bak; \
117+
fi
118+
# Append new configuration
119+
echo "" >> {{default_datadir}}/config.toml || touch {{default_datadir}}/config.toml
120+
echo "[wallets.{{wallet_name}}]" >> {{default_datadir}}/config.toml
121+
echo "name = \"{{wallet_name}}\"" >> {{default_datadir}}/config.toml
122+
echo "ext_descriptor = \"{{ext_descriptor}}\"" >> {{default_datadir}}/config.toml
123+
echo "int_descriptor = \"{{int_descriptor}}\"" >> {{default_datadir}}/config.toml
124+
echo "database_type = \"sqlite\"" >> {{default_datadir}}/config.toml
125+
echo "client_type = \"{{client_type}}\"" >> {{default_datadir}}/config.toml
126+
echo "server_url = \"{{url}}\"" >> {{default_datadir}}/config.toml
127+
echo "rpc_user = \"{{rpc_user}}\"" >> {{default_datadir}}/config.toml
128+
echo "rpc_password = \"{{rpc_password}}\"" >> {{default_datadir}}/config.toml
129+
echo "Wallet configuration for {{wallet_name}} added to {{default_datadir}}/config.toml"

src/commands.rs

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
1515
#![allow(clippy::large_enum_variant)]
1616

17+
use std::path::Path;
18+
use crate::config::WalletConfig;
19+
use crate::error::BDKCliError as Error;
1720
use bdk_wallet::bitcoin::{
1821
bip32::{DerivationPath, Xpriv},
1922
Address, Network, OutPoint, ScriptBuf,
@@ -167,15 +170,15 @@ pub struct WalletOpts {
167170
feature = "rpc",
168171
feature = "cbf"
169172
))]
170-
#[arg(env = "CLIENT_TYPE", short = 'c', long, value_enum, required = true)]
171-
pub client_type: ClientType,
173+
#[arg(env = "CLIENT_TYPE", short = 'c', long, value_enum)]
174+
pub client_type: Option<ClientType>,
172175
#[cfg(feature = "sqlite")]
173-
#[arg(env = "DATABASE_TYPE", short = 'd', long, value_enum, required = true)]
174-
pub database_type: DatabaseType,
176+
#[arg(env = "DATABASE_TYPE", short = 'd', long, value_enum, default_value="sqlite")]
177+
pub database_type: Option<DatabaseType>,
175178
/// Sets the server url.
176179
#[cfg(any(feature = "electrum", feature = "esplora", feature = "rpc"))]
177-
#[arg(env = "SERVER_URL", short = 'u', long, required = true)]
178-
pub url: String,
180+
#[arg(env = "SERVER_URL", short = 'u', long)]
181+
pub url: Option<String>,
179182
/// Electrum batch size.
180183
#[cfg(feature = "electrum")]
181184
#[arg(env = "ELECTRUM_BATCH_SIZE", short = 'b', long, default_value = "10")]
@@ -198,7 +201,7 @@ pub struct WalletOpts {
198201
value_parser = parse_proxy_auth,
199202
default_value = "user:password",
200203
)]
201-
pub basic_auth: (String, String),
204+
pub basic_auth: Option<(String, String)>,
202205
#[cfg(feature = "rpc")]
203206
/// Sets an optional cookie authentication.
204207
#[arg(env = "COOKIE")]
@@ -208,6 +211,64 @@ pub struct WalletOpts {
208211
pub compactfilter_opts: CompactFilterOpts,
209212
}
210213

214+
impl WalletOpts {
215+
/// Load configuration from TOML file and merge with CLI options
216+
pub fn load_config(&mut self, wallet_name: &str, datadir: &Path) -> Result<(), Error> {
217+
if let Some(config) = WalletConfig::load(datadir)? {
218+
if let Ok(config_opts) = config.get_wallet_opts(wallet_name) {
219+
self.wallet = self.wallet.take().or(config_opts.wallet);
220+
self.verbose = self.verbose || config_opts.verbose;
221+
self.ext_descriptor = self.ext_descriptor.take().or(config_opts.ext_descriptor);
222+
self.int_descriptor = self.int_descriptor.take().or(config_opts.int_descriptor);
223+
#[cfg(any(
224+
feature = "electrum",
225+
feature = "esplora",
226+
feature = "rpc",
227+
feature = "cbf"
228+
))]
229+
{
230+
self.client_type = self.client_type.clone().or(config_opts.client_type);
231+
}
232+
#[cfg(feature = "sqlite")]
233+
{
234+
// prioritizing the config.toml value for database type as it has a default value
235+
self.database_type = config_opts.database_type.or(self.database_type.clone());
236+
}
237+
#[cfg(any(feature = "electrum", feature = "esplora", feature = "rpc"))]
238+
{
239+
self.url = self.url.take().or(config_opts.url);
240+
}
241+
#[cfg(feature = "electrum")]
242+
{
243+
self.batch_size = if self.batch_size != 10 {
244+
config_opts.batch_size
245+
} else {
246+
self.batch_size
247+
};
248+
}
249+
#[cfg(feature = "esplora")]
250+
{
251+
self.parallel_requests = if self.parallel_requests != 5 {
252+
config_opts.parallel_requests
253+
} else {
254+
self.parallel_requests
255+
};
256+
}
257+
#[cfg(feature = "rpc")]
258+
{
259+
self.basic_auth = self.basic_auth.take().or(config_opts.basic_auth);
260+
self.cookie = self.cookie.take().or(config_opts.cookie);
261+
}
262+
#[cfg(feature = "cbf")]
263+
{
264+
self.compactfilter_opts = config_opts.compactfilter_opts;
265+
}
266+
}
267+
}
268+
Ok(())
269+
}
270+
}
271+
211272
/// Options to configure a SOCKS5 proxy for a blockchain client connection.
212273
#[cfg(any(feature = "electrum", feature = "esplora"))]
213274
#[derive(Debug, Args, Clone, PartialEq, Eq)]

0 commit comments

Comments
 (0)