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