Skip to content

Commit 4a04a88

Browse files
committed
feat: Add optional storage path configuration for wallet initialization
1 parent 1d0f986 commit 4a04a88

File tree

8 files changed

+65
-23
lines changed

8 files changed

+65
-23
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl KaspaCli {
103103
}
104104

105105
pub async fn try_new_arc(options: Options) -> Result<Arc<Self>> {
106-
let wallet = Arc::new(Wallet::try_new(Wallet::local_store()?, Some(Resolver::default()), None)?);
106+
let wallet = Arc::new(Wallet::try_new(Wallet::local_store(None)?, Some(Resolver::default()), None)?);
107107

108108
let kaspa_cli = Arc::new(KaspaCli {
109109
term: Arc::new(Mutex::new(None)),

wallet/core/src/storage/local/interface.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,10 @@ pub(crate) struct LocalStore {
289289
}
290290

291291
impl LocalStore {
292-
pub fn try_new(is_resident: bool) -> Result<Self> {
292+
pub fn try_new(is_resident: bool, path: Option<PathBuf>) -> Result<Self> {
293+
let location = if let Some(path) = path { Location::new(path.to_str().unwrap()) } else { Location::default() };
293294
Ok(Self {
294-
location: Arc::new(Mutex::new(Some(Arc::new(Location::default())))),
295+
location: Arc::new(Mutex::new(Some(Arc::new(location)))),
295296
inner: Arc::new(Mutex::new(None)),
296297
is_resident,
297298
batch: Arc::new(AtomicBool::new(false)),

wallet/core/src/wallet/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
pub mod api;
1313
pub mod args;
1414
pub mod maps;
15+
1516
pub use args::*;
17+
use std::path::PathBuf;
1618

1719
use crate::account::ScanNotifier;
1820
use crate::api::traits::WalletApi;
@@ -123,18 +125,18 @@ pub struct Wallet {
123125

124126
impl Default for Wallet {
125127
fn default() -> Self {
126-
let storage = Wallet::local_store().expect("Unable to initialize local storage");
128+
let storage = Wallet::local_store(None).expect("Unable to initialize local storage");
127129
Wallet::try_new(storage, None, None).unwrap()
128130
}
129131
}
130132

131133
impl Wallet {
132-
pub fn local_store() -> Result<Arc<dyn Interface>> {
133-
Ok(Arc::new(LocalStore::try_new(false)?))
134+
pub fn local_store(path: Option<PathBuf>) -> Result<Arc<dyn Interface>> {
135+
Ok(Arc::new(LocalStore::try_new(false, path)?))
134136
}
135137

136138
pub fn resident_store() -> Result<Arc<dyn Interface>> {
137-
Ok(Arc::new(LocalStore::try_new(true)?))
139+
Ok(Arc::new(LocalStore::try_new(true, None)?))
138140
}
139141

140142
pub fn try_new(storage: Arc<dyn Interface>, resolver: Option<Resolver>, network_id: Option<NetworkId>) -> Result<Wallet> {

wallet/core/src/wasm/wallet/wallet.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl Wallet {
147147
pub fn constructor(config: IWalletConfig) -> Result<Wallet> {
148148
let WalletCtorArgs { resident, network_id, encoding, url, resolver } = WalletCtorArgs::try_from(JsValue::from(config))?;
149149

150-
let store = Arc::new(LocalStore::try_new(resident)?);
150+
let store = Arc::new(LocalStore::try_new(resident, None)?);
151151

152152
let rpc_config = RpcConfig { url, resolver, encoding, network_id };
153153

wallet/daemon/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,8 @@ workflow-terminal.workspace = true
2929
clap.workspace = true
3030
futures-util.workspace = true
3131

32+
[dev-dependencies]
33+
tempfile.workspace = true
34+
3235
[lints]
3336
workspace = true

wallet/daemon/src/args.rs

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use clap::{Arg, Command};
22
use kaspa_core::kaspad_env::version;
3+
use std::io;
34
use std::net::SocketAddr;
5+
use std::path::PathBuf;
46

57
pub struct Args {
68
pub password: String,
@@ -9,23 +11,26 @@ pub struct Args {
911
pub network_id: Option<String>,
1012
pub listen_address: SocketAddr,
1113
pub ecdsa: bool,
14+
pub location: Option<PathBuf>,
1215
}
1316

1417
impl Args {
15-
pub fn parse() -> Self {
18+
pub fn parse() -> Result<Self, Box<dyn std::error::Error>> {
1619
let matches = cli().get_matches();
17-
18-
Args {
20+
let key_file = matches.get_one::<PathBuf>("keys-file").cloned();
21+
let (name, location) = parse_keys_file_arg(key_file)?;
22+
Ok(Args {
1923
password: matches.get_one::<String>("password").cloned().expect("Password argument is missing."),
20-
name: matches.get_one::<String>("name").cloned(),
24+
name,
2125
rpc_server: matches.get_one::<String>("rpc-server").cloned(),
2226
network_id: matches.get_one::<String>("network-id").cloned(),
2327
listen_address: matches
2428
.get_one::<SocketAddr>("listen-address")
2529
.cloned()
2630
.unwrap_or_else(|| "127.0.0.1:8082".parse().unwrap()),
2731
ecdsa: matches.get_one::<bool>("ecdsa").cloned().unwrap_or(false),
28-
}
32+
location,
33+
})
2934
}
3035
}
3136

@@ -34,14 +39,6 @@ pub fn cli() -> Command {
3439
.about(format!("{} (kaspawalletd) v{}", env!("CARGO_PKG_DESCRIPTION"), version()))
3540
.version(env!("CARGO_PKG_VERSION"))
3641
.arg(Arg::new("password").long("password").short('p').value_name("password").help("Path of password file").required(true))
37-
.arg(
38-
Arg::new("name")
39-
.long("name")
40-
.short('n')
41-
.value_name("name")
42-
.value_parser(clap::value_parser!(String))
43-
.help("Name of wallet"),
44-
)
4542
.arg(
4643
Arg::new("rpc-server")
4744
.long("rpc-server")
@@ -72,4 +69,42 @@ pub fn cli() -> Command {
7269
.value_parser(clap::value_parser!(bool))
7370
.help("Use ecdsa for transactions broadcast"),
7471
)
72+
.arg(Arg::new("keys-file").long("keys-file").short('f').value_name("keys-file").help("Keys file location"))
73+
}
74+
75+
fn parse_keys_file_arg(keys_file: Option<PathBuf>) -> Result<(Option<String>, Option<PathBuf>), Box<dyn std::error::Error>> {
76+
if let Some(keys_file) = keys_file {
77+
if keys_file.is_dir() {
78+
Ok((None, Some(keys_file)))
79+
} else {
80+
let name = keys_file
81+
.file_name()
82+
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Invalid wallet file path"))?
83+
.to_str()
84+
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Wallet file path is not valid UTF-8"))?
85+
.to_owned();
86+
Ok((Some(name), keys_file.parent().map(|p| p.to_owned())))
87+
}
88+
} else {
89+
Ok((None, None))
90+
}
91+
}
92+
93+
#[cfg(test)]
94+
mod tests {
95+
use super::*;
96+
use tempfile::NamedTempFile;
97+
98+
#[test]
99+
fn test_parse_keys_file() {
100+
// arrange
101+
let tmp_keys_file = NamedTempFile::new().unwrap();
102+
103+
// act
104+
let (name, location) = parse_keys_file_arg(Some(tmp_keys_file.path().to_path_buf())).unwrap();
105+
106+
// assert
107+
assert_eq!(name, Some(tmp_keys_file.path().file_name().unwrap().to_str().unwrap().to_owned()));
108+
assert_eq!(location, Some(tmp_keys_file.path().parent().unwrap().to_path_buf()));
109+
}
75110
}

wallet/daemon/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ use tonic::transport::Server;
1717
#[tokio::main]
1818
async fn main() -> Result<(), Box<dyn Error>> {
1919
kaspa_core::log::init_logger(None, "");
20-
let args = Args::parse();
20+
let args = Args::parse()?;
2121

22-
let wallet = Arc::new(Wallet::try_new(Wallet::local_store()?, Some(Resolver::default()), None)?);
22+
let wallet = Arc::new(Wallet::try_new(Wallet::local_store(args.location)?, Some(Resolver::default()), None)?);
2323
wallet.clone().wallet_open(args.password.into(), args.name, false, false).await?;
2424
info!("Wallet path: {}", wallet.store().location()?);
2525

0 commit comments

Comments
 (0)