installer: refac context
This commit is contained in:
parent
56be997d6b
commit
a2021ca326
@ -1,80 +1,26 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use minisafe::{
|
||||
config::{BitcoinConfig, BitcoindConfig, Config as MinisafeConfig},
|
||||
descriptors::InheritanceDescriptor,
|
||||
miniscript::bitcoin::Network,
|
||||
};
|
||||
use minisafe::config::Config as MinisafeConfig;
|
||||
|
||||
use serde::Serialize;
|
||||
use std::{net::SocketAddr, path::PathBuf, time::Duration};
|
||||
use super::step::Context;
|
||||
|
||||
/// Static informations we require to operate
|
||||
/// fields with default values are not present, see minisafe::config.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct Config {
|
||||
#[serde(serialize_with = "serialize_option_to_string")]
|
||||
pub main_descriptor: Option<InheritanceDescriptor>,
|
||||
pub bitcoin_config: BitcoinConfig,
|
||||
/// Everything we need to know to talk to bitcoind
|
||||
pub bitcoind_config: BitcoindConfig,
|
||||
/// An optional custom data directory
|
||||
pub data_dir: Option<PathBuf>,
|
||||
}
|
||||
pub const DEFAULT_FILE_NAME: &str = "daemon.toml";
|
||||
|
||||
impl Config {
|
||||
pub const DEFAULT_FILE_NAME: &'static str = "daemon.toml";
|
||||
/// returns a minisafed config with empty or dummy values
|
||||
pub fn new() -> Config {
|
||||
Self {
|
||||
main_descriptor: None,
|
||||
bitcoin_config: BitcoinConfig {
|
||||
network: Network::Bitcoin,
|
||||
poll_interval_secs: Duration::from_secs(30),
|
||||
},
|
||||
bitcoind_config: BitcoindConfig {
|
||||
cookie_path: PathBuf::new(),
|
||||
addr: SocketAddr::new(
|
||||
std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)),
|
||||
8080,
|
||||
),
|
||||
},
|
||||
data_dir: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize_option_to_string<T: std::fmt::Display, S: serde::Serializer>(
|
||||
field: &Option<T>,
|
||||
s: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
match field {
|
||||
Some(field) => s.serialize_str(&field.to_string()),
|
||||
None => s.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Config> for MinisafeConfig {
|
||||
impl TryFrom<Context> for MinisafeConfig {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(cfg: Config) -> Result<Self, Self::Error> {
|
||||
if cfg.main_descriptor.is_none() {
|
||||
fn try_from(ctx: Context) -> Result<Self, Self::Error> {
|
||||
if ctx.descriptor.is_none() {
|
||||
return Err("config does not have a main Descriptor");
|
||||
}
|
||||
Ok(MinisafeConfig {
|
||||
#[cfg(unix)]
|
||||
daemon: false,
|
||||
log_level: log::LevelFilter::Info,
|
||||
main_descriptor: cfg.main_descriptor.unwrap(),
|
||||
data_dir: cfg.data_dir,
|
||||
bitcoin_config: cfg.bitcoin_config,
|
||||
bitcoind_config: Some(cfg.bitcoind_config),
|
||||
main_descriptor: ctx.descriptor.unwrap(),
|
||||
data_dir: ctx.data_dir,
|
||||
bitcoin_config: ctx.bitcoin_config,
|
||||
bitcoind_config: ctx.bitcoind_config,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ use std::convert::TryInto;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{app::config as gui_config, installer::config::Config as DaemonConfig};
|
||||
use crate::{app::config as gui_config, installer::config::DEFAULT_FILE_NAME};
|
||||
|
||||
pub use message::Message;
|
||||
use step::{Context, DefineBitcoind, DefineDescriptor, Final, Step, Welcome};
|
||||
@ -24,7 +24,6 @@ pub struct Installer {
|
||||
|
||||
/// Context is data passed through each step.
|
||||
context: Context,
|
||||
config: DaemonConfig,
|
||||
}
|
||||
|
||||
impl Installer {
|
||||
@ -44,12 +43,9 @@ impl Installer {
|
||||
destination_path: PathBuf,
|
||||
network: bitcoin::Network,
|
||||
) -> (Installer, Command<Message>) {
|
||||
let mut config = DaemonConfig::new();
|
||||
config.data_dir = Some(destination_path);
|
||||
(
|
||||
Installer {
|
||||
should_exit: false,
|
||||
config,
|
||||
current: 0,
|
||||
steps: vec![
|
||||
Welcome::new(network).into(),
|
||||
@ -57,7 +53,7 @@ impl Installer {
|
||||
DefineBitcoind::new().into(),
|
||||
Final::new().into(),
|
||||
],
|
||||
context: Context::new(network),
|
||||
context: Context::new(network, Some(destination_path)),
|
||||
},
|
||||
Command::none(),
|
||||
)
|
||||
@ -82,7 +78,7 @@ impl Installer {
|
||||
.steps
|
||||
.get_mut(self.current)
|
||||
.expect("There is always a step");
|
||||
if current_step.apply(&mut self.context, &mut self.config) {
|
||||
if current_step.apply(&mut self.context) {
|
||||
self.next();
|
||||
// skip the step according to the current context.
|
||||
while self
|
||||
@ -111,10 +107,7 @@ impl Installer {
|
||||
.get_mut(self.current)
|
||||
.expect("There is always a step")
|
||||
.update(message);
|
||||
Command::perform(
|
||||
install(self.context.clone(), self.config.clone()),
|
||||
Message::Installed,
|
||||
)
|
||||
Command::perform(install(self.context.clone()), Message::Installed)
|
||||
}
|
||||
Message::Event(Event::Window(window::Event::CloseRequested)) => {
|
||||
self.stop();
|
||||
@ -136,12 +129,14 @@ impl Installer {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn install(_ctx: Context, mut cfg: DaemonConfig) -> Result<PathBuf, Error> {
|
||||
pub async fn install(ctx: Context) -> Result<PathBuf, Error> {
|
||||
let mut cfg: minisafe::config::Config = ctx
|
||||
.try_into()
|
||||
.expect("Everything should be checked at this point");
|
||||
// Start Daemon to check correctness of installation
|
||||
let daemon =
|
||||
minisafe::DaemonHandle::start_default(cfg.clone().try_into().unwrap()).map_err(|e| {
|
||||
Error::Unexpected(format!("Failed to start daemon with entered config: {}", e))
|
||||
})?;
|
||||
let daemon = minisafe::DaemonHandle::start_default(cfg.clone()).map_err(|e| {
|
||||
Error::Unexpected(format!("Failed to start daemon with entered config: {}", e))
|
||||
})?;
|
||||
daemon.shutdown();
|
||||
|
||||
cfg.data_dir =
|
||||
@ -154,7 +149,7 @@ pub async fn install(_ctx: Context, mut cfg: DaemonConfig) -> Result<PathBuf, Er
|
||||
|
||||
// create minisafed configuration file
|
||||
let mut minisafed_config_path = datadir_path.clone();
|
||||
minisafed_config_path.push(DaemonConfig::DEFAULT_FILE_NAME);
|
||||
minisafed_config_path.push(DEFAULT_FILE_NAME);
|
||||
let mut minisafed_config_file = std::fs::File::create(&minisafed_config_path)
|
||||
.map_err(|e| Error::CannotCreateFile(e.to_string()))?;
|
||||
|
||||
|
||||
@ -12,7 +12,6 @@ use minisafe::{
|
||||
use crate::{
|
||||
hw::{list_hardware_wallets, HardwareWallet},
|
||||
installer::{
|
||||
config,
|
||||
message::{self, Message},
|
||||
step::{Context, Step},
|
||||
view, Error,
|
||||
@ -101,7 +100,7 @@ impl Step for DefineDescriptor {
|
||||
Command::none()
|
||||
}
|
||||
|
||||
fn apply(&mut self, _ctx: &mut Context, config: &mut config::Config) -> bool {
|
||||
fn apply(&mut self, ctx: &mut Context) -> bool {
|
||||
// descriptor forms for import or creation cannot be both empty or filled.
|
||||
if self.imported_descriptor.value.is_empty()
|
||||
== (self.user_xpub.value.is_empty()
|
||||
@ -125,7 +124,7 @@ impl Step for DefineDescriptor {
|
||||
false
|
||||
} else if !self.imported_descriptor.value.is_empty() {
|
||||
if let Ok(desc) = InheritanceDescriptor::from_str(&self.imported_descriptor.value) {
|
||||
config.main_descriptor = Some(desc);
|
||||
ctx.descriptor = Some(desc);
|
||||
true
|
||||
} else {
|
||||
self.imported_descriptor.valid = false;
|
||||
@ -145,20 +144,20 @@ impl Step for DefineDescriptor {
|
||||
return false;
|
||||
}
|
||||
|
||||
match InheritanceDescriptor::new(
|
||||
let desc = match InheritanceDescriptor::new(
|
||||
user_key.unwrap(),
|
||||
heir_key.unwrap(),
|
||||
sequence.unwrap(),
|
||||
) {
|
||||
Ok(desc) => {
|
||||
config.main_descriptor = Some(desc);
|
||||
true
|
||||
}
|
||||
Ok(desc) => desc,
|
||||
Err(e) => {
|
||||
self.error = Some(e.to_string());
|
||||
false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ctx.descriptor = Some(desc);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,14 +3,18 @@ pub use descriptor::DefineDescriptor;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use iced::{pure::Element, Command};
|
||||
use minisafe::miniscript::bitcoin;
|
||||
use minisafe::{
|
||||
config::{BitcoinConfig, BitcoindConfig},
|
||||
descriptors::InheritanceDescriptor,
|
||||
miniscript::bitcoin,
|
||||
};
|
||||
|
||||
use crate::ui::component::form;
|
||||
|
||||
use crate::installer::{
|
||||
config,
|
||||
message::{self, Message},
|
||||
view,
|
||||
};
|
||||
@ -24,25 +28,30 @@ pub trait Step {
|
||||
fn skip(&self, _ctx: &Context) -> bool {
|
||||
false
|
||||
}
|
||||
fn apply(&mut self, _ctx: &mut Context, _config: &mut config::Config) -> bool {
|
||||
fn apply(&mut self, _ctx: &mut Context) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Context {
|
||||
pub network: bitcoin::Network,
|
||||
pub bitcoin_config: BitcoinConfig,
|
||||
pub bitcoind_config: Option<BitcoindConfig>,
|
||||
pub descriptor: Option<InheritanceDescriptor>,
|
||||
pub data_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(network: bitcoin::Network) -> Self {
|
||||
Self { network }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Context {
|
||||
fn default() -> Self {
|
||||
Self::new(bitcoin::Network::Bitcoin)
|
||||
pub fn new(network: bitcoin::Network, data_dir: Option<PathBuf>) -> Self {
|
||||
Self {
|
||||
bitcoin_config: BitcoinConfig {
|
||||
network,
|
||||
poll_interval_secs: Duration::from_secs(30),
|
||||
},
|
||||
bitcoind_config: None,
|
||||
descriptor: None,
|
||||
data_dir,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,9 +72,8 @@ impl Step for Welcome {
|
||||
}
|
||||
Command::none()
|
||||
}
|
||||
fn apply(&mut self, ctx: &mut Context, config: &mut config::Config) -> bool {
|
||||
ctx.network = self.network;
|
||||
config.bitcoin_config.network = self.network;
|
||||
fn apply(&mut self, ctx: &mut Context) -> bool {
|
||||
ctx.bitcoin_config.network = self.network;
|
||||
true
|
||||
}
|
||||
fn view(&self) -> Element<Message> {
|
||||
@ -145,10 +153,11 @@ impl DefineBitcoind {
|
||||
impl Step for DefineBitcoind {
|
||||
fn load_context(&mut self, ctx: &Context) {
|
||||
if self.cookie_path.value.is_empty() {
|
||||
self.cookie_path.value = bitcoind_default_cookie_path(&ctx.network).unwrap_or_default()
|
||||
self.cookie_path.value =
|
||||
bitcoind_default_cookie_path(&ctx.bitcoin_config.network).unwrap_or_default()
|
||||
}
|
||||
if self.address.value.is_empty() {
|
||||
self.address.value = bitcoind_default_address(&ctx.network);
|
||||
self.address.value = bitcoind_default_address(&ctx.bitcoin_config.network);
|
||||
}
|
||||
}
|
||||
fn update(&mut self, message: Message) -> Command<Message> {
|
||||
@ -167,7 +176,7 @@ impl Step for DefineBitcoind {
|
||||
Command::none()
|
||||
}
|
||||
|
||||
fn apply(&mut self, _ctx: &mut Context, config: &mut config::Config) -> bool {
|
||||
fn apply(&mut self, ctx: &mut Context) -> bool {
|
||||
match (
|
||||
PathBuf::from_str(&self.cookie_path.value),
|
||||
std::net::SocketAddr::from_str(&self.address.value),
|
||||
@ -186,8 +195,10 @@ impl Step for DefineBitcoind {
|
||||
false
|
||||
}
|
||||
(Ok(path), Ok(addr)) => {
|
||||
config.bitcoind_config.cookie_path = path;
|
||||
config.bitcoind_config.addr = addr;
|
||||
ctx.bitcoind_config = Some(BitcoindConfig {
|
||||
cookie_path: path,
|
||||
addr,
|
||||
});
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user