[package]
name = "magical-bitcoin-wallet"
version = "0.1.0"
+edition = "2018"
authors = ["Riccardo Casatta <riccardo@casatta.it>", "Alekos Filini <alekos.filini@gmail.com>"]
[dependencies]
serde = { version = "^1.0", features = ["derive"] }
serde_json = { version = "^1.0" }
base64 = "^0.11"
+async-trait = "0.1"
# Optional dependencies
sled = { version = "0.31.0", optional = true }
-electrum-client = { version = "0.1.0-beta.5", optional = true }
-reqwest = { version = "0.10", optional = true, features = ["blocking", "json"] }
+electrum-client = { git = "https://github.com/MagicalBitcoin/rust-electrum-client.git", optional = true }
+reqwest = { version = "0.10", optional = true, features = ["json"] }
+futures = { version = "0.3", optional = true }
[features]
minimal = []
compiler = ["miniscript/compiler"]
default = ["key-value-db", "electrum"]
electrum = ["electrum-client"]
-esplora = ["reqwest"]
+esplora = ["reqwest", "futures"]
key-value-db = ["sled"]
[dev-dependencies]
+tokio = { version = "0.2", features = ["macros"] }
lazy_static = "1.4"
rustyline = "5.0" # newer version requires 2018 edition
clap = "2.33"
use std::fs;
use std::path::PathBuf;
use std::str::FromStr;
+use std::sync::Arc;
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
parse_outpoint(&s).map(|_| ())
}
-fn main() {
+#[tokio::main]
+async fn main() {
env_logger::init();
let app = App::new("Magical Bitcoin Wallet")
.unwrap();
debug!("database opened successfully");
- let client = Client::new(matches.value_of("server").unwrap()).unwrap();
+ let client = Client::new(matches.value_of("server").unwrap())
+ .await
+ .unwrap();
let wallet = Wallet::new(
descriptor,
change_descriptor,
tree,
ElectrumBlockchain::from(client),
)
+ .await
.unwrap();
+ let wallet = Arc::new(wallet);
// TODO: print errors in a nice way
- let handle_matches = |matches: ArgMatches<'_>| {
+ async fn handle_matches<C, D>(wallet: Arc<Wallet<C, D>>, matches: ArgMatches<'_>)
+ where
+ C: magical_bitcoin_wallet::blockchain::OnlineBlockchain,
+ D: magical_bitcoin_wallet::database::BatchDatabase,
+ {
if let Some(_sub_matches) = matches.subcommand_matches("get_new_address") {
println!("{}", wallet.get_new_address().unwrap().to_string());
} else if let Some(_sub_matches) = matches.subcommand_matches("sync") {
- wallet.sync(None, None).unwrap();
+ wallet.sync(None, None).await.unwrap();
} else if let Some(_sub_matches) = matches.subcommand_matches("list_unspent") {
for utxo in wallet.list_unspent().unwrap() {
println!("{} value {} SAT", utxo.outpoint, utxo.txout.value);
} else if let Some(sub_matches) = matches.subcommand_matches("broadcast") {
let psbt = base64::decode(sub_matches.value_of("psbt").unwrap()).unwrap();
let psbt: PartiallySignedTransaction = deserialize(&psbt).unwrap();
- let (txid, _) = wallet.broadcast(psbt).unwrap();
+ let (txid, _) = wallet.broadcast(psbt).await.unwrap();
println!("TXID: {}", txid);
}
continue;
}
- handle_matches(matches.unwrap());
+ handle_matches(Arc::clone(&wallet), matches.unwrap()).await;
}
Err(ReadlineError::Interrupted) => continue,
Err(ReadlineError::Eof) => break,
// rl.save_history("history.txt").unwrap();
} else {
- handle_matches(matches);
+ handle_matches(wallet, matches).await;
}
}