Merge #294: gui: store descriptor in wallet module
b177f190d144986c1268c640075c89399f4c599d gui: store descriptor in wallet module (edouard)
Pull request description:
A new module wallet is introduced that contains the main_descriptor retrieved from `getinfo`.
It removes the requirement for the `Daemon` trait to provide the demon config in the other components of the application.
Actually BitcoindSettings cannot be edited if the gui is connected to an external daemon, this PR just remove the display of the Bitcoind Settings section.
ACKs for top commit:
edouardparis:
Self-ACK b177f190d144986c1268c640075c89399f4c599d
Tree-SHA512: 1b5d00b9406a96d51e2b974d850322ea6046d8232fdd061d4e79ac7a8529c1459815fa022b5e35156664c27aedc0b08ad94d9cbf6984af09ee3c2bdd44ebe2f6
This commit is contained in:
commit
2985cbcba0
@ -4,6 +4,7 @@ pub mod menu;
|
||||
pub mod message;
|
||||
pub mod state;
|
||||
pub mod view;
|
||||
pub mod wallet;
|
||||
|
||||
mod error;
|
||||
|
||||
@ -22,7 +23,7 @@ pub use message::Message;
|
||||
use state::{CoinsPanel, CreateSpendPanel, Home, ReceivePanel, RecoveryPanel, SpendPanel, State};
|
||||
|
||||
use crate::{
|
||||
app::{cache::Cache, error::Error, menu::Menu},
|
||||
app::{cache::Cache, error::Error, menu::Menu, wallet::Wallet},
|
||||
daemon::Daemon,
|
||||
};
|
||||
|
||||
@ -30,16 +31,18 @@ pub struct App {
|
||||
state: Box<dyn State>,
|
||||
cache: Cache,
|
||||
config: Config,
|
||||
wallet: Wallet,
|
||||
daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(
|
||||
cache: Cache,
|
||||
wallet: Wallet,
|
||||
config: Config,
|
||||
daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
) -> (App, Command<Message>) {
|
||||
let state: Box<dyn State> = Home::new(&cache.coins).into();
|
||||
let state: Box<dyn State> = Home::new(wallet.clone(), &cache.coins).into();
|
||||
let cmd = state.load(daemon.clone());
|
||||
(
|
||||
Self {
|
||||
@ -47,6 +50,7 @@ impl App {
|
||||
cache,
|
||||
config,
|
||||
daemon,
|
||||
wallet,
|
||||
},
|
||||
cmd,
|
||||
)
|
||||
@ -55,31 +59,36 @@ impl App {
|
||||
fn load_state(&mut self, menu: &Menu) -> Command<Message> {
|
||||
self.state = match menu {
|
||||
menu::Menu::Settings => state::SettingsState::new(
|
||||
self.daemon.config().clone(),
|
||||
self.daemon.config().cloned(),
|
||||
&self.cache,
|
||||
self.daemon.is_external(),
|
||||
)
|
||||
.into(),
|
||||
menu::Menu::Home => Home::new(&self.cache.coins).into(),
|
||||
menu::Menu::Home => Home::new(self.wallet.clone(), &self.cache.coins).into(),
|
||||
menu::Menu::Coins => CoinsPanel::new(
|
||||
&self.cache.coins,
|
||||
self.daemon.config().main_descriptor.timelock_value(),
|
||||
self.wallet.main_descriptor.timelock_value(),
|
||||
)
|
||||
.into(),
|
||||
menu::Menu::Recovery => RecoveryPanel::new(
|
||||
self.wallet.clone(),
|
||||
self.config.clone(),
|
||||
&self.cache.coins,
|
||||
self.daemon.config().main_descriptor.timelock_value(),
|
||||
self.wallet.main_descriptor.timelock_value(),
|
||||
self.cache.blockheight as u32,
|
||||
)
|
||||
.into(),
|
||||
menu::Menu::Receive => ReceivePanel::default().into(),
|
||||
menu::Menu::Spend => SpendPanel::new(self.config.clone(), &self.cache.spend_txs).into(),
|
||||
menu::Menu::CreateSpendTx => CreateSpendPanel::new(
|
||||
menu::Menu::Spend => SpendPanel::new(
|
||||
self.wallet.clone(),
|
||||
self.config.clone(),
|
||||
&self.cache.spend_txs,
|
||||
)
|
||||
.into(),
|
||||
menu::Menu::CreateSpendTx => CreateSpendPanel::new(
|
||||
self.wallet.clone(),
|
||||
self.config.clone(),
|
||||
self.daemon.config().main_descriptor.clone(),
|
||||
&self.cache.coins,
|
||||
self.daemon.config().main_descriptor.timelock_value(),
|
||||
self.cache.blockheight as u32,
|
||||
)
|
||||
.into(),
|
||||
|
||||
@ -11,7 +11,7 @@ use iced::{widget::qr_code, Command, Subscription};
|
||||
use iced::{widget::Column, Element};
|
||||
use liana::miniscript::bitcoin::{Address, Amount};
|
||||
|
||||
use super::{cache::Cache, error::Error, menu::Menu, message::Message, view};
|
||||
use super::{cache::Cache, error::Error, menu::Menu, message::Message, view, wallet::Wallet};
|
||||
|
||||
use crate::daemon::{
|
||||
model::{remaining_sequence, Coin, HistoryTransaction},
|
||||
@ -39,6 +39,7 @@ pub trait State {
|
||||
}
|
||||
|
||||
pub struct Home {
|
||||
wallet: Wallet,
|
||||
balance: Amount,
|
||||
recovery_warning: Option<(Amount, usize)>,
|
||||
recovery_alert: Option<(Amount, usize)>,
|
||||
@ -49,8 +50,9 @@ pub struct Home {
|
||||
}
|
||||
|
||||
impl Home {
|
||||
pub fn new(coins: &[Coin]) -> Self {
|
||||
pub fn new(wallet: Wallet, coins: &[Coin]) -> Self {
|
||||
Self {
|
||||
wallet,
|
||||
balance: Amount::from_sat(
|
||||
coins
|
||||
.iter()
|
||||
@ -120,7 +122,7 @@ impl State for Home {
|
||||
for coin in coins {
|
||||
if coin.spend_info.is_none() && coin.block_height.is_some() {
|
||||
self.balance += coin.amount;
|
||||
let timelock = daemon.config().main_descriptor.timelock_value();
|
||||
let timelock = self.wallet.main_descriptor.timelock_value();
|
||||
let seq = remaining_sequence(&coin, cache.blockheight as u32, timelock);
|
||||
if seq == 0 {
|
||||
recovery_alert.0 += coin.amount;
|
||||
@ -327,10 +329,7 @@ mod tests {
|
||||
client::{Lianad, Request},
|
||||
model::*,
|
||||
},
|
||||
utils::{
|
||||
mock::{fake_daemon_config, Daemon},
|
||||
sandbox::Sandbox,
|
||||
},
|
||||
utils::{mock::Daemon, sandbox::Sandbox},
|
||||
};
|
||||
|
||||
use liana::miniscript::bitcoin::Address;
|
||||
@ -350,7 +349,7 @@ mod tests {
|
||||
)]);
|
||||
|
||||
let sandbox: Sandbox<ReceivePanel> = Sandbox::new(ReceivePanel::default());
|
||||
let client = Arc::new(Lianad::new(daemon.run(), fake_daemon_config()));
|
||||
let client = Arc::new(Lianad::new(daemon.run()));
|
||||
let sandbox = sandbox.load(client, &Cache::default()).await;
|
||||
|
||||
let panel = sandbox.state();
|
||||
|
||||
@ -12,6 +12,7 @@ use crate::{
|
||||
message::Message,
|
||||
state::{redirect, State},
|
||||
view,
|
||||
wallet::Wallet,
|
||||
},
|
||||
daemon::{
|
||||
model::{remaining_sequence, Coin},
|
||||
@ -24,6 +25,7 @@ use crate::{
|
||||
use liana::miniscript::bitcoin::{util::psbt::Psbt, Address, Amount, Network};
|
||||
|
||||
pub struct RecoveryPanel {
|
||||
wallet: Wallet,
|
||||
config: Config,
|
||||
locked_coins: (usize, Amount),
|
||||
recoverable_coins: (usize, Amount),
|
||||
@ -39,7 +41,13 @@ pub struct RecoveryPanel {
|
||||
}
|
||||
|
||||
impl RecoveryPanel {
|
||||
pub fn new(config: Config, coins: &[Coin], timelock: u32, blockheight: u32) -> Self {
|
||||
pub fn new(
|
||||
wallet: Wallet,
|
||||
config: Config,
|
||||
coins: &[Coin],
|
||||
timelock: u32,
|
||||
blockheight: u32,
|
||||
) -> Self {
|
||||
let mut locked_coins = (0, Amount::from_sat(0));
|
||||
let mut recoverable_coins = (0, Amount::from_sat(0));
|
||||
for coin in coins {
|
||||
@ -55,6 +63,7 @@ impl RecoveryPanel {
|
||||
}
|
||||
}
|
||||
Self {
|
||||
wallet,
|
||||
config,
|
||||
locked_coins,
|
||||
recoverable_coins,
|
||||
@ -195,7 +204,7 @@ impl State for RecoveryPanel {
|
||||
|
||||
fn load(&self, daemon: Arc<dyn Daemon + Sync + Send>) -> Command<Message> {
|
||||
let config = self.config.clone();
|
||||
let desc = daemon.config().main_descriptor.to_string();
|
||||
let desc = self.wallet.main_descriptor.to_string();
|
||||
let daemon = daemon.clone();
|
||||
Command::batch(vec![
|
||||
Command::perform(
|
||||
@ -208,7 +217,7 @@ impl State for RecoveryPanel {
|
||||
Message::Coins,
|
||||
),
|
||||
Command::perform(
|
||||
list_hws(config, "Liana".to_string(), desc),
|
||||
list_hws(config, self.wallet.name.clone(), desc),
|
||||
Message::ConnectedHardwareWallets,
|
||||
),
|
||||
])
|
||||
|
||||
@ -7,7 +7,7 @@ use std::sync::Arc;
|
||||
use chrono::prelude::*;
|
||||
use iced::{Command, Element};
|
||||
|
||||
use liana::config::Config;
|
||||
use liana::config::{BitcoinConfig, BitcoindConfig, Config};
|
||||
|
||||
use crate::{
|
||||
app::{cache::Cache, error::Error, message::Message, state::State, view},
|
||||
@ -23,19 +23,13 @@ trait Setting: std::fmt::Debug {
|
||||
cache: &Cache,
|
||||
message: view::SettingsMessage,
|
||||
) -> Command<Message>;
|
||||
fn view<'a>(
|
||||
&self,
|
||||
cfg: &'a Config,
|
||||
cache: &'a Cache,
|
||||
can_edit: bool,
|
||||
) -> Element<'a, view::SettingsMessage>;
|
||||
fn view<'a>(&self, cache: &'a Cache, can_edit: bool) -> Element<'a, view::SettingsMessage>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SettingsState {
|
||||
warning: Option<Error>,
|
||||
config_updated: bool,
|
||||
config: Config,
|
||||
daemon_is_external: bool,
|
||||
|
||||
settings: Vec<Box<dyn Setting>>,
|
||||
@ -43,17 +37,24 @@ pub struct SettingsState {
|
||||
}
|
||||
|
||||
impl SettingsState {
|
||||
pub fn new(config: Config, cache: &Cache, daemon_is_external: bool) -> Self {
|
||||
let settings = vec![
|
||||
BitcoindSettings::new(&config).into(),
|
||||
RescanSetting::new(cache.rescan_progress).into(),
|
||||
];
|
||||
pub fn new(config: Option<Config>, cache: &Cache, daemon_is_external: bool) -> Self {
|
||||
let settings = if let Some(config) = &config {
|
||||
vec![
|
||||
BitcoindSettings::new(
|
||||
config.bitcoin_config.clone(),
|
||||
config.bitcoind_config.clone().unwrap(),
|
||||
)
|
||||
.into(),
|
||||
RescanSetting::new(cache.rescan_progress).into(),
|
||||
]
|
||||
} else {
|
||||
vec![RescanSetting::new(cache.rescan_progress).into()]
|
||||
};
|
||||
|
||||
SettingsState {
|
||||
daemon_is_external,
|
||||
warning: None,
|
||||
config_updated: false,
|
||||
config,
|
||||
settings,
|
||||
// If a scan is running, the current setting edited is the Rescan panel.
|
||||
current: cache.rescan_progress.map(|_| 1),
|
||||
@ -123,7 +124,7 @@ impl State for SettingsState {
|
||||
.enumerate()
|
||||
.map(|(i, setting)| {
|
||||
setting
|
||||
.view(&self.config, cache, can_edit)
|
||||
.view(cache, can_edit)
|
||||
.map(move |msg| view::Message::Settings(i, msg))
|
||||
})
|
||||
.collect(),
|
||||
@ -139,6 +140,8 @@ impl From<SettingsState> for Box<dyn State> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BitcoindSettings {
|
||||
bitcoind_config: BitcoindConfig,
|
||||
bitcoin_config: BitcoinConfig,
|
||||
edit: bool,
|
||||
processing: bool,
|
||||
cookie_path: form::Value<String>,
|
||||
@ -152,18 +155,21 @@ impl From<BitcoindSettings> for Box<dyn Setting> {
|
||||
}
|
||||
|
||||
impl BitcoindSettings {
|
||||
fn new(cfg: &Config) -> BitcoindSettings {
|
||||
let cfg = cfg.bitcoind_config.as_ref().unwrap();
|
||||
fn new(bitcoin_config: BitcoinConfig, bitcoind_config: BitcoindConfig) -> BitcoindSettings {
|
||||
let path = bitcoind_config.cookie_path.to_str().unwrap().to_string();
|
||||
let addr = bitcoind_config.addr.to_string();
|
||||
BitcoindSettings {
|
||||
bitcoind_config,
|
||||
bitcoin_config,
|
||||
edit: false,
|
||||
processing: false,
|
||||
cookie_path: form::Value {
|
||||
valid: true,
|
||||
value: cfg.cookie_path.to_str().unwrap().to_string(),
|
||||
value: path,
|
||||
},
|
||||
addr: form::Value {
|
||||
valid: true,
|
||||
value: cfg.addr.to_string(),
|
||||
value: addr,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -210,7 +216,7 @@ impl Setting for BitcoindSettings {
|
||||
self.cookie_path.valid = new_path.is_ok();
|
||||
|
||||
if self.addr.valid & self.cookie_path.valid {
|
||||
let mut daemon_config = daemon.config().clone();
|
||||
let mut daemon_config = daemon.config().cloned().unwrap();
|
||||
daemon_config.bitcoind_config = Some(liana::config::BitcoindConfig {
|
||||
cookie_path: new_path.unwrap(),
|
||||
addr: new_addr.unwrap(),
|
||||
@ -225,15 +231,10 @@ impl Setting for BitcoindSettings {
|
||||
Command::none()
|
||||
}
|
||||
|
||||
fn view<'a>(
|
||||
&self,
|
||||
config: &'a Config,
|
||||
cache: &'a Cache,
|
||||
can_edit: bool,
|
||||
) -> Element<'a, view::SettingsMessage> {
|
||||
fn view<'a>(&self, cache: &'a Cache, can_edit: bool) -> Element<'a, view::SettingsMessage> {
|
||||
if self.edit {
|
||||
view::settings::bitcoind_edit(
|
||||
config.bitcoin_config.network,
|
||||
self.bitcoin_config.network,
|
||||
cache.blockheight,
|
||||
&self.addr,
|
||||
&self.cookie_path,
|
||||
@ -241,8 +242,8 @@ impl Setting for BitcoindSettings {
|
||||
)
|
||||
} else {
|
||||
view::settings::bitcoind(
|
||||
config.bitcoin_config.network,
|
||||
config.bitcoind_config.as_ref().unwrap(),
|
||||
self.bitcoin_config.network,
|
||||
&self.bitcoind_config,
|
||||
cache.blockheight,
|
||||
Some(cache.blockheight != 0),
|
||||
can_edit,
|
||||
@ -328,12 +329,7 @@ impl Setting for RescanSetting {
|
||||
Command::none()
|
||||
}
|
||||
|
||||
fn view<'a>(
|
||||
&self,
|
||||
_config: &'a Config,
|
||||
cache: &'a Cache,
|
||||
can_edit: bool,
|
||||
) -> Element<'a, view::SettingsMessage> {
|
||||
fn view<'a>(&self, cache: &'a Cache, can_edit: bool) -> Element<'a, view::SettingsMessage> {
|
||||
view::settings::rescan(
|
||||
&self.year,
|
||||
&self.month,
|
||||
|
||||
@ -9,6 +9,7 @@ use liana::miniscript::bitcoin::{
|
||||
use crate::{
|
||||
app::{
|
||||
cache::Cache, config::Config, error::Error, message::Message, view, view::spend::detail,
|
||||
wallet::Wallet,
|
||||
},
|
||||
daemon::{
|
||||
model::{SpendStatus, SpendTx},
|
||||
@ -22,13 +23,13 @@ trait Action {
|
||||
fn warning(&self) -> Option<&Error> {
|
||||
None
|
||||
}
|
||||
fn load(&self, _daemon: Arc<dyn Daemon + Sync + Send>) -> Command<Message> {
|
||||
fn load(&self, _wallet: &Wallet, _daemon: Arc<dyn Daemon + Sync + Send>) -> Command<Message> {
|
||||
Command::none()
|
||||
}
|
||||
fn update(
|
||||
&mut self,
|
||||
_wallet: &Wallet,
|
||||
_daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
_cache: &Cache,
|
||||
_message: Message,
|
||||
_tx: &mut SpendTx,
|
||||
) -> Command<Message> {
|
||||
@ -38,6 +39,7 @@ trait Action {
|
||||
}
|
||||
|
||||
pub struct SpendTxState {
|
||||
wallet: Wallet,
|
||||
config: Config,
|
||||
tx: SpendTx,
|
||||
saved: bool,
|
||||
@ -45,8 +47,9 @@ pub struct SpendTxState {
|
||||
}
|
||||
|
||||
impl SpendTxState {
|
||||
pub fn new(config: Config, tx: SpendTx, saved: bool) -> Self {
|
||||
pub fn new(wallet: Wallet, config: Config, tx: SpendTx, saved: bool) -> Self {
|
||||
Self {
|
||||
wallet,
|
||||
action: None,
|
||||
config,
|
||||
tx,
|
||||
@ -56,7 +59,7 @@ impl SpendTxState {
|
||||
|
||||
pub fn load(&self, daemon: Arc<dyn Daemon + Sync + Send>) -> Command<Message> {
|
||||
if let Some(action) = &self.action {
|
||||
action.load(daemon)
|
||||
action.load(&self.wallet, daemon)
|
||||
} else {
|
||||
Command::none()
|
||||
}
|
||||
@ -65,7 +68,7 @@ impl SpendTxState {
|
||||
pub fn update(
|
||||
&mut self,
|
||||
daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
cache: &Cache,
|
||||
_cache: &Cache,
|
||||
message: Message,
|
||||
) -> Command<Message> {
|
||||
match &message {
|
||||
@ -78,13 +81,13 @@ impl SpendTxState {
|
||||
}
|
||||
view::SpendTxMessage::Sign => {
|
||||
let action = SignAction::new(self.config.clone());
|
||||
let cmd = action.load(daemon);
|
||||
let cmd = action.load(&self.wallet, daemon);
|
||||
self.action = Some(Box::new(action));
|
||||
return cmd;
|
||||
}
|
||||
view::SpendTxMessage::EditPsbt => {
|
||||
let action = UpdateAction::new(self.tx.psbt.to_string());
|
||||
let cmd = action.load(daemon);
|
||||
let cmd = action.load(&self.wallet, daemon);
|
||||
self.action = Some(Box::new(action));
|
||||
return cmd;
|
||||
}
|
||||
@ -96,19 +99,19 @@ impl SpendTxState {
|
||||
}
|
||||
_ => {
|
||||
if let Some(action) = self.action.as_mut() {
|
||||
return action.update(daemon.clone(), cache, message, &mut self.tx);
|
||||
return action.update(&self.wallet, daemon.clone(), message, &mut self.tx);
|
||||
}
|
||||
}
|
||||
},
|
||||
Message::Updated(Ok(_)) => {
|
||||
self.saved = true;
|
||||
if let Some(action) = self.action.as_mut() {
|
||||
return action.update(daemon.clone(), cache, message, &mut self.tx);
|
||||
return action.update(&self.wallet, daemon.clone(), message, &mut self.tx);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if let Some(action) = self.action.as_mut() {
|
||||
return action.update(daemon.clone(), cache, message, &mut self.tx);
|
||||
return action.update(&self.wallet, daemon.clone(), message, &mut self.tx);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -136,8 +139,8 @@ pub struct SaveAction {
|
||||
impl Action for SaveAction {
|
||||
fn update(
|
||||
&mut self,
|
||||
_wallet: &Wallet,
|
||||
daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
_cache: &Cache,
|
||||
message: Message,
|
||||
tx: &mut SpendTx,
|
||||
) -> Command<Message> {
|
||||
@ -172,8 +175,8 @@ pub struct BroadcastAction {
|
||||
impl Action for BroadcastAction {
|
||||
fn update(
|
||||
&mut self,
|
||||
_wallet: &Wallet,
|
||||
daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
_cache: &Cache,
|
||||
message: Message,
|
||||
tx: &mut SpendTx,
|
||||
) -> Command<Message> {
|
||||
@ -216,8 +219,8 @@ pub struct DeleteAction {
|
||||
impl Action for DeleteAction {
|
||||
fn update(
|
||||
&mut self,
|
||||
_wallet: &Wallet,
|
||||
daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
_cache: &Cache,
|
||||
message: Message,
|
||||
tx: &mut SpendTx,
|
||||
) -> Command<Message> {
|
||||
@ -275,18 +278,19 @@ impl Action for SignAction {
|
||||
self.error.as_ref()
|
||||
}
|
||||
|
||||
fn load(&self, daemon: Arc<dyn Daemon + Sync + Send>) -> Command<Message> {
|
||||
fn load(&self, wallet: &Wallet, _daemon: Arc<dyn Daemon + Sync + Send>) -> Command<Message> {
|
||||
let config = self.config.clone();
|
||||
let desc = daemon.config().main_descriptor.to_string();
|
||||
let desc = wallet.main_descriptor.to_string();
|
||||
let name = wallet.name.clone();
|
||||
Command::perform(
|
||||
list_hws(config, "Liana".to_string(), desc),
|
||||
list_hws(config, name, desc),
|
||||
Message::ConnectedHardwareWallets,
|
||||
)
|
||||
}
|
||||
fn update(
|
||||
&mut self,
|
||||
wallet: &Wallet,
|
||||
daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
_cache: &Cache,
|
||||
message: Message,
|
||||
tx: &mut SpendTx,
|
||||
) -> Command<Message> {
|
||||
@ -329,7 +333,7 @@ impl Action for SignAction {
|
||||
}
|
||||
}
|
||||
Message::View(view::Message::Reload) => {
|
||||
return self.load(daemon);
|
||||
return self.load(wallet, daemon);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
@ -395,8 +399,8 @@ impl Action for UpdateAction {
|
||||
|
||||
fn update(
|
||||
&mut self,
|
||||
_wallet: &Wallet,
|
||||
daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
_cache: &Cache,
|
||||
message: Message,
|
||||
tx: &mut SpendTx,
|
||||
) -> Command<Message> {
|
||||
|
||||
@ -4,14 +4,14 @@ use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
|
||||
use liana::{
|
||||
descriptors::MultipathDescriptor,
|
||||
miniscript::bitcoin::{consensus, util::psbt::Psbt},
|
||||
};
|
||||
use liana::miniscript::bitcoin::{consensus, util::psbt::Psbt};
|
||||
|
||||
use super::{redirect, State};
|
||||
use crate::{
|
||||
app::{cache::Cache, config::Config, error::Error, menu::Menu, message::Message, view},
|
||||
app::{
|
||||
cache::Cache, config::Config, error::Error, menu::Menu, message::Message, view,
|
||||
wallet::Wallet,
|
||||
},
|
||||
daemon::{
|
||||
model::{Coin, SpendTx},
|
||||
Daemon,
|
||||
@ -20,6 +20,7 @@ use crate::{
|
||||
};
|
||||
|
||||
pub struct SpendPanel {
|
||||
wallet: Wallet,
|
||||
config: Config,
|
||||
selected_tx: Option<detail::SpendTxState>,
|
||||
spend_txs: Vec<SpendTx>,
|
||||
@ -28,8 +29,9 @@ pub struct SpendPanel {
|
||||
}
|
||||
|
||||
impl SpendPanel {
|
||||
pub fn new(config: Config, spend_txs: &[SpendTx]) -> Self {
|
||||
pub fn new(wallet: Wallet, config: Config, spend_txs: &[SpendTx]) -> Self {
|
||||
Self {
|
||||
wallet,
|
||||
config,
|
||||
spend_txs: spend_txs.to_vec(),
|
||||
warning: None,
|
||||
@ -95,7 +97,12 @@ impl State for SpendPanel {
|
||||
}
|
||||
Message::View(view::Message::Select(i)) => {
|
||||
if let Some(tx) = self.spend_txs.get(i) {
|
||||
let tx = detail::SpendTxState::new(self.config.clone(), tx.clone(), true);
|
||||
let tx = detail::SpendTxState::new(
|
||||
self.wallet.clone(),
|
||||
self.config.clone(),
|
||||
tx.clone(),
|
||||
true,
|
||||
);
|
||||
let cmd = tx.load(daemon);
|
||||
self.selected_tx = Some(tx);
|
||||
return cmd;
|
||||
@ -136,13 +143,9 @@ pub struct CreateSpendPanel {
|
||||
}
|
||||
|
||||
impl CreateSpendPanel {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
descriptor: MultipathDescriptor,
|
||||
coins: &[Coin],
|
||||
timelock: u32,
|
||||
blockheight: u32,
|
||||
) -> Self {
|
||||
pub fn new(wallet: Wallet, config: Config, coins: &[Coin], blockheight: u32) -> Self {
|
||||
let descriptor = wallet.main_descriptor.clone();
|
||||
let timelock = descriptor.timelock_value();
|
||||
Self {
|
||||
draft: step::TransactionDraft::default(),
|
||||
current: 0,
|
||||
@ -154,7 +157,7 @@ impl CreateSpendPanel {
|
||||
timelock,
|
||||
blockheight,
|
||||
)),
|
||||
Box::new(step::SaveSpend::new(config)),
|
||||
Box::new(step::SaveSpend::new(wallet, config)),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ use liana::{
|
||||
use crate::{
|
||||
app::{
|
||||
cache::Cache, config::Config, error::Error, message::Message, state::spend::detail, view,
|
||||
wallet::Wallet,
|
||||
},
|
||||
daemon::{
|
||||
model::{remaining_sequence, Coin, SpendTx},
|
||||
@ -88,8 +89,8 @@ impl ChooseRecipients {
|
||||
impl Step for ChooseRecipients {
|
||||
fn update(
|
||||
&mut self,
|
||||
daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
_cache: &Cache,
|
||||
_daemon: Arc<dyn Daemon + Sync + Send>,
|
||||
cache: &Cache,
|
||||
_draft: &TransactionDraft,
|
||||
message: Message,
|
||||
) -> Command<Message> {
|
||||
@ -105,7 +106,7 @@ impl Step for ChooseRecipients {
|
||||
self.recipients
|
||||
.get_mut(*i)
|
||||
.unwrap()
|
||||
.update(daemon.config().bitcoin_config.network, msg);
|
||||
.update(cache.network, msg);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -429,13 +430,15 @@ impl Step for ChooseCoins {
|
||||
}
|
||||
|
||||
pub struct SaveSpend {
|
||||
wallet: Wallet,
|
||||
config: Config,
|
||||
spend: Option<detail::SpendTxState>,
|
||||
}
|
||||
|
||||
impl SaveSpend {
|
||||
pub fn new(config: Config) -> Self {
|
||||
pub fn new(wallet: Wallet, config: Config) -> Self {
|
||||
Self {
|
||||
wallet,
|
||||
config,
|
||||
spend: None,
|
||||
}
|
||||
@ -445,6 +448,7 @@ impl SaveSpend {
|
||||
impl Step for SaveSpend {
|
||||
fn load(&mut self, draft: &TransactionDraft) {
|
||||
self.spend = Some(detail::SpendTxState::new(
|
||||
self.wallet.clone(),
|
||||
self.config.clone(),
|
||||
SpendTx::new(draft.generated.clone().unwrap(), draft.inputs.clone()),
|
||||
false,
|
||||
|
||||
16
gui/src/app/wallet.rs
Normal file
16
gui/src/app/wallet.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use liana::descriptors::MultipathDescriptor;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Wallet {
|
||||
pub name: String,
|
||||
pub main_descriptor: MultipathDescriptor,
|
||||
}
|
||||
|
||||
impl Wallet {
|
||||
pub fn new(main_descriptor: MultipathDescriptor) -> Self {
|
||||
Self {
|
||||
name: "Liana".to_string(),
|
||||
main_descriptor,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -27,13 +27,12 @@ pub trait Client {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Lianad<C: Client> {
|
||||
config: Config,
|
||||
client: C,
|
||||
}
|
||||
|
||||
impl<C: Client> Lianad<C> {
|
||||
pub fn new(client: C, config: Config) -> Lianad<C> {
|
||||
Lianad { client, config }
|
||||
pub fn new(client: C) -> Lianad<C> {
|
||||
Lianad { client }
|
||||
}
|
||||
|
||||
/// Generic call function for RPC calls.
|
||||
@ -55,8 +54,8 @@ impl<C: Client + Debug> Daemon for Lianad<C> {
|
||||
true
|
||||
}
|
||||
|
||||
fn config(&self) -> &Config {
|
||||
&self.config
|
||||
fn config(&self) -> Option<&Config> {
|
||||
None
|
||||
}
|
||||
|
||||
fn stop(&mut self) -> Result<(), DaemonError> {
|
||||
|
||||
@ -51,8 +51,8 @@ impl Daemon for EmbeddedDaemon {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config(&self) -> &Config {
|
||||
&self.config
|
||||
fn config(&self) -> Option<&Config> {
|
||||
Some(&self.config)
|
||||
}
|
||||
|
||||
fn stop(&mut self) -> Result<(), DaemonError> {
|
||||
|
||||
@ -46,7 +46,7 @@ pub trait Daemon: Debug {
|
||||
fn load_config(&mut self, _cfg: Config) -> Result<(), DaemonError> {
|
||||
Ok(())
|
||||
}
|
||||
fn config(&self) -> &Config;
|
||||
fn config(&self) -> Option<&Config>;
|
||||
fn stop(&mut self) -> Result<(), DaemonError>;
|
||||
fn get_info(&self) -> Result<model::GetInfoResult, DaemonError>;
|
||||
fn get_new_address(&self) -> Result<model::GetAddressResult, DaemonError>;
|
||||
|
||||
@ -296,10 +296,10 @@ pub fn cover<'a, T: 'a + Clone, C: Into<Element<'a, T>>>(
|
||||
|
||||
async fn connect(
|
||||
socket_path: PathBuf,
|
||||
config: Config,
|
||||
_config: Config,
|
||||
) -> Result<Arc<dyn Daemon + Sync + Send>, Error> {
|
||||
let client = client::jsonrpc::JsonRPCClient::new(socket_path);
|
||||
let daemon = Lianad::new(client, config);
|
||||
let daemon = Lianad::new(client);
|
||||
|
||||
debug!("Searching for external daemon");
|
||||
daemon.get_info()?;
|
||||
|
||||
@ -13,6 +13,7 @@ use liana_gui::{
|
||||
self,
|
||||
cache::Cache,
|
||||
config::{default_datadir, ConfigError},
|
||||
wallet::Wallet,
|
||||
App,
|
||||
},
|
||||
installer::{self, Installer},
|
||||
@ -206,14 +207,16 @@ impl Application for GUI {
|
||||
}
|
||||
loader::Message::Synced(info, coins, spend_txs, daemon) => {
|
||||
let cache = Cache {
|
||||
network: daemon.config().bitcoin_config.network,
|
||||
network: info.network,
|
||||
blockheight: info.block_height,
|
||||
coins,
|
||||
spend_txs,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let (app, command) = App::new(cache, loader.gui_config.clone(), daemon);
|
||||
let wallet = Wallet::new(info.descriptors.main);
|
||||
|
||||
let (app, command) = App::new(cache, wallet, loader.gui_config.clone(), daemon);
|
||||
self.state = State::App(app);
|
||||
command.map(|msg| Message::Run(Box::new(msg)))
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use crate::daemon::{client::Client, DaemonError};
|
||||
use liana::config::Config;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use std::fmt::Debug;
|
||||
@ -76,20 +75,3 @@ impl Daemon {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fake_daemon_config() -> Config {
|
||||
toml::from_str(
|
||||
r#"
|
||||
data_dir = "/home/edouard/code/revault/demo/liana/datadir"
|
||||
main_descriptor = "wsh(or_d(pk(tpubDCbK3Ysvk8HjcF6mPyrgMu3KgLiaaP19RjKpNezd8GrbAbNg6v5BtWLaCt8FNm6QkLseopKLf5MNYQFtochDTKHdfgG6iqJ8cqnLNAwtXuP/<0;1>/*),and_v(v:pkh(tpubDDtb2WPYwEWw2WWDV7reLV348iJHw2HmhzvPysKKrJw3hYmvrd4jasyoioVPdKGQqjyaBMEvTn1HvHWDSVqQ6amyyxRZ5YjpPBBGjJ8yu8S/<0;1>/*),older(100))))#9sx3g3pv"
|
||||
|
||||
[bitcoin_config]
|
||||
network = "regtest"
|
||||
poll_interval_secs = 30
|
||||
|
||||
[bitcoind_config]
|
||||
addr = "127.0.0.1:9001"
|
||||
cookie_path = "/home/edouard/code/revault/demo/liana/regtest/bcdir1/regtest/.cookie"
|
||||
"#
|
||||
).unwrap()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user