println!("LDK logs are available at <your-supplied-ldk-data-dir-path>/.ldk/logs");
println!("Local Node ID is {}.", channel_manager.get_our_node_id());
let stdin = io::stdin();
- print!("> ");
- io::stdout().flush().unwrap(); // Without flushing, the `>` doesn't print
- for line in stdin.lock().lines() {
- let line = line.unwrap();
+ let mut line_reader = stdin.lock().lines();
+ loop {
+ print!("> ");
+ io::stdout().flush().unwrap(); // Without flushing, the `>` doesn't print
+ let line = match line_reader.next() {
+ Some(l) => l.unwrap(),
+ None => break,
+ };
let mut words = line.split_whitespace();
if let Some(word) = words.next() {
match word {
let channel_value_sat = words.next();
if peer_pubkey_and_ip_addr.is_none() || channel_value_sat.is_none() {
println!("ERROR: openchannel has 2 required arguments: `openchannel pubkey@host:port channel_amt_satoshis` [--public]");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
let peer_pubkey_and_ip_addr = peer_pubkey_and_ip_addr.unwrap();
Ok(info) => info,
Err(e) => {
println!("{:?}", e.into_inner().unwrap());
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
};
let chan_amt_sat: Result<u64, _> = channel_value_sat.unwrap().parse();
if chan_amt_sat.is_err() {
println!("ERROR: channel amount must be a number");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
.await
.is_err()
{
- print!("> ");
- io::stdout().flush().unwrap();
continue;
};
Some("--public=false") => false,
Some(_) => {
println!("ERROR: invalid `--public` command format. Valid formats: `--public`, `--public=true` `--public=false`");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
None => false,
let invoice_str = words.next();
if invoice_str.is_none() {
println!("ERROR: sendpayment requires an invoice: `sendpayment <invoice>`");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
Ok(inv) => inv,
Err(e) => {
println!("ERROR: invalid invoice: {:?}", e);
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
};
Some(pk) => pk,
None => {
println!("ERROR: couldn't parse destination pubkey");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
},
None => {
println!("ERROR: keysend requires a destination pubkey: `keysend <dest_pubkey> <amt_msat>`");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
};
None => {
println!("ERROR: keysend requires an amount in millisatoshis: `keysend <dest_pubkey> <amt_msat>`");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
};
Ok(amt) => amt,
Err(e) => {
println!("ERROR: couldn't parse amount_msat: {}", e);
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
};
let amt_str = words.next();
if amt_str.is_none() {
println!("ERROR: getinvoice requires an amount in millisatoshis");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
let amt_msat: Result<u64, _> = amt_str.unwrap().parse();
if amt_msat.is_err() {
println!("ERROR: getinvoice provided payment amount was not a number");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
get_invoice(
let peer_pubkey_and_ip_addr = words.next();
if peer_pubkey_and_ip_addr.is_none() {
println!("ERROR: connectpeer requires peer connection info: `connectpeer pubkey@host:port`");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
let (pubkey, peer_addr) =
Ok(info) => info,
Err(e) => {
println!("{:?}", e.into_inner().unwrap());
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
};
let channel_id_str = words.next();
if channel_id_str.is_none() {
println!("ERROR: closechannel requires a channel ID: `closechannel <channel_id>`");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
let channel_id_vec = hex_utils::to_vec(channel_id_str.unwrap());
if channel_id_vec.is_none() {
println!("ERROR: couldn't parse channel_id as hex");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
let mut channel_id = [0; 32];
let channel_id_str = words.next();
if channel_id_str.is_none() {
println!("ERROR: forceclosechannel requires a channel ID: `forceclosechannel <channel_id>`");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
let channel_id_vec = hex_utils::to_vec(channel_id_str.unwrap());
if channel_id_vec.is_none() {
println!("ERROR: couldn't parse channel_id as hex");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
let mut channel_id = [0; 32];
const MSG_STARTPOS: usize = "signmsg".len() + 1;
if line.as_bytes().len() <= MSG_STARTPOS {
println!("ERROR: signmsg requires a message");
- print!("> ");
- io::stdout().flush().unwrap();
continue;
}
println!(
&keys_manager.get_node_secret()
)
);
- print!("> ");
- io::stdout().flush().unwrap();
}
_ => println!("Unknown command. See `\"help\" for available commands."),
}
}
- print!("> ");
- io::stdout().flush().unwrap();
}
}
fn node_info(channel_manager: Arc<ChannelManager>, peer_manager: Arc<PeerManager>) {
println!("\t{{");
println!("\t\t node_pubkey: {}", channel_manager.get_our_node_id());
- println!("\t\t num_channels: {}", channel_manager.list_channels().len());
- println!("\t\t num_usable_channels: {}", channel_manager.list_usable_channels().len());
+ let chans = channel_manager.list_channels();
+ println!("\t\t num_channels: {}", chans.len());
+ println!("\t\t num_usable_channels: {}", chans.iter().filter(|c| c.is_usable).count());
+ let local_balance_msat = chans
+ .iter()
+ .map(|c| c.unspendable_punishment_reserve.unwrap_or(0) * 1000 + c.outbound_capacity_msat)
+ .sum::<u64>();
+ println!("\t\t local_balance_msat: {}", local_balance_msat);
println!("\t\t num_peers: {}", peer_manager.get_peer_node_ids().len());
println!("\t}},");
}
return Ok(());
}
}
+ let res = do_connect_peer(pubkey, peer_addr, peer_manager).await;
+ if res.is_err() {
+ println!("ERROR: failed to connect to peer");
+ }
+ res
+}
+
+pub(crate) async fn do_connect_peer(
+ pubkey: PublicKey, peer_addr: SocketAddr, peer_manager: Arc<PeerManager>,
+) -> Result<(), ()> {
match lightning_net_tokio::connect_outbound(Arc::clone(&peer_manager), pubkey, peer_addr).await
{
Some(connection_closed_future) => {
loop {
match futures::poll!(&mut connection_closed_future) {
std::task::Poll::Ready(_) => {
- println!("ERROR: Peer disconnected before we finished the handshake");
return Err(());
}
std::task::Poll::Pending => {}
}
// Avoid blocking the tokio context by sleeping a bit
match peer_manager.get_peer_node_ids().iter().find(|id| **id == pubkey) {
- Some(_) => break,
+ Some(_) => return Ok(()),
None => tokio::time::sleep(Duration::from_millis(10)).await,
}
}
}
- None => {
- println!("ERROR: failed to connect to peer");
- return Err(());
- }
+ None => Err(()),
}
- Ok(())
}
fn open_channel(