1#![allow(clippy::too_many_arguments)]
3pub mod error;
4pub mod input;
5pub mod logger;
6pub mod wallet;
7
8use std::path::Path;
9use std::{io, net, thread};
10
11use termion::raw::IntoRawMode;
12
13use nakamoto_client::chan;
14use nakamoto_client::handle::Handle;
15use nakamoto_client::Network;
16use nakamoto_client::{Client, Config};
17use nakamoto_common::bitcoin::util::bip32::DerivationPath;
18use nakamoto_common::block::Height;
19
20use crate::error::Error;
21use crate::wallet::Db;
22use crate::wallet::Hw;
23use crate::wallet::Wallet;
24
25type Reactor = nakamoto_net_poll::Reactor<net::TcpStream>;
27
28pub fn run(
30 wallet: &Path,
31 birth: Height,
32 hd_path: DerivationPath,
33 network: Network,
34 connect: Vec<net::SocketAddr>,
35 offline: bool,
36) -> Result<(), Error> {
37 let cfg = Config {
38 network,
39 connect,
40 listen: vec![], ..Config::default()
42 };
43
44 let client = Client::<Reactor>::new()?;
46 let handle = client.handle();
47 let client_recv = handle.events();
48 let (loading_send, loading_recv) = chan::unbounded();
49
50 log::info!("Opening wallet file `{}`..", wallet.display());
51
52 let db = Db::open(wallet)?;
53 let hw = Hw::new(hd_path);
54
55 let (inputs_tx, inputs_rx) = crossbeam_channel::unbounded();
56 let (exit_tx, exit_rx) = crossbeam_channel::bounded(1);
57 let (signals_tx, signals_rx) = crossbeam_channel::unbounded();
58
59 log::info!("Spawning client threads..");
60
61 let t1 = thread::spawn(|| input::run(inputs_tx, exit_rx));
63 let t2 = thread::spawn(|| input::signals(signals_tx));
65 let t3 = thread::spawn(move || {
67 if offline {
68 Ok(())
69 } else {
70 client.load(cfg, loading_send)?.run()
71 }
72 });
73
74 log::info!("Switching to alternative screen..");
75
76 let stdout = io::stdout().into_raw_mode()?;
77 let term = termion::screen::AlternateScreen::from(termion::cursor::HideCursor::from(
78 termion::input::MouseTerminal::from(stdout),
79 ));
80
81 log::info!("Running main wallet loop..");
83 Wallet::new(handle.clone(), network, db, hw).run(
84 birth,
85 inputs_rx,
86 signals_rx,
87 loading_recv,
88 client_recv,
89 offline,
90 term,
91 )?;
92
93 log::info!("Exiting..");
95 exit_tx.send(()).unwrap();
96
97 log::info!("Shutting down client..");
99 handle.shutdown()?;
100
101 t1.join().unwrap()?;
102 t2.join().unwrap()?;
103 t3.join().unwrap()?;
104
105 Ok(())
106}