Update `help` to include new commands and clean up parameters
[ldk-sample] / src / cli.rs
index d7a76bc03c9768c7f076afc1ec777fd8d296dec5..c8c14f2f6c007016bca07f63aaf77eeb0cec1ab1 100644 (file)
@@ -9,6 +9,7 @@ use bitcoin::secp256k1::key::PublicKey;
 use lightning::chain;
 use lightning::chain::keysinterface::KeysManager;
 use lightning::ln::features::InvoiceFeatures;
+use lightning::ln::msgs::NetAddress;
 use lightning::ln::{PaymentHash, PaymentSecret};
 use lightning::routing::network_graph::NetGraphMsgHandler;
 use lightning::routing::router;
@@ -18,7 +19,7 @@ use lightning_invoice::{utils, Currency, Invoice};
 use std::env;
 use std::io;
 use std::io::{BufRead, Write};
-use std::net::SocketAddr;
+use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
 use std::ops::Deref;
 use std::path::Path;
 use std::str::FromStr;
@@ -33,12 +34,14 @@ pub(crate) struct LdkUserInfo {
        pub(crate) bitcoind_rpc_host: String,
        pub(crate) ldk_storage_dir_path: String,
        pub(crate) ldk_peer_listening_port: u16,
+       pub(crate) ldk_announced_listen_addr: Option<NetAddress>,
+       pub(crate) ldk_announced_node_name: [u8; 32],
        pub(crate) network: Network,
 }
 
 pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
        if env::args().len() < 3 {
-               println!("ldk-tutorial-node requires 3 arguments: `cargo run <bitcoind-rpc-username>:<bitcoind-rpc-password>@<bitcoind-rpc-host>:<bitcoind-rpc-port> ldk_storage_directory_path [<ldk-incoming-peer-listening-port>] [bitcoin-network]`");
+               println!("ldk-tutorial-node requires 3 arguments: `cargo run <bitcoind-rpc-username>:<bitcoind-rpc-password>@<bitcoind-rpc-host>:<bitcoind-rpc-port> ldk_storage_directory_path [<ldk-incoming-peer-listening-port>] [bitcoin-network] [announced-listen-addr announced-node-name]`");
                return Err(());
        }
        let bitcoind_rpc_info = env::args().skip(1).next().unwrap();
@@ -84,6 +87,32 @@ pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
                Some(_) => panic!("Unsupported network provided. Options are: `regtest`, `testnet`"),
                None => Network::Testnet,
        };
+
+       let ldk_announced_listen_addr = match env::args().skip(arg_idx + 1).next().as_ref() {
+               Some(s) => match IpAddr::from_str(s) {
+                       Ok(IpAddr::V4(a)) => {
+                               Some(NetAddress::IPv4 { addr: a.octets(), port: ldk_peer_listening_port })
+                       }
+                       Ok(IpAddr::V6(a)) => {
+                               Some(NetAddress::IPv6 { addr: a.octets(), port: ldk_peer_listening_port })
+                       }
+                       Err(_) => panic!("Failed to parse announced-listen-addr into an IP address"),
+               },
+               None => None,
+       };
+
+       let ldk_announced_node_name = match env::args().skip(arg_idx + 2).next().as_ref() {
+               Some(s) => {
+                       if s.len() > 32 {
+                               panic!("Node Alias can not be longer than 32 bytes");
+                       }
+                       let mut bytes = [0; 32];
+                       bytes[..s.len()].copy_from_slice(s.as_bytes());
+                       bytes
+               }
+               None => [0; 32],
+       };
+
        Ok(LdkUserInfo {
                bitcoind_rpc_username,
                bitcoind_rpc_password,
@@ -91,6 +120,8 @@ pub(crate) fn parse_startup_args() -> Result<LdkUserInfo, ()> {
                bitcoind_rpc_port,
                ldk_storage_dir_path,
                ldk_peer_listening_port,
+               ldk_announced_listen_addr,
+               ldk_announced_node_name,
                network,
        })
 }
@@ -360,14 +391,16 @@ pub(crate) async fn poll_for_user_input(
 }
 
 fn help() {
-       println!("openchannel pubkey@host:port <channel_amt_satoshis>");
+       println!("openchannel pubkey@host:port <amt_satoshis>");
        println!("sendpayment <invoice>");
-       println!("getinvoice <amt_in_millisatoshis>");
+       println!("getinvoice <amt_millisatoshis>");
        println!("connectpeer pubkey@host:port");
        println!("listchannels");
        println!("listpayments");
        println!("closechannel <channel_id>");
        println!("forceclosechannel <channel_id>");
+       println!("nodeinfo");
+       println!("listpeers");
 }
 
 fn node_info(channel_manager: Arc<ChannelManager>, peer_manager: Arc<PeerManager>) {
@@ -393,20 +426,23 @@ fn list_channels(channel_manager: Arc<ChannelManager>) {
                println!("");
                println!("\t{{");
                println!("\t\tchannel_id: {},", hex_utils::hex_str(&chan_info.channel_id[..]));
+               if let Some(funding_txo) = chan_info.funding_txo {
+                       println!("\t\tfunding_txid: {},", funding_txo.txid);
+               }
                println!(
                        "\t\tpeer_pubkey: {},",
                        hex_utils::hex_str(&chan_info.remote_network_id.serialize())
                );
-               let mut pending_channel = false;
-               match chan_info.short_channel_id {
-                       Some(id) => println!("\t\tshort_channel_id: {},", id),
-                       None => {
-                               pending_channel = true;
-                       }
+               if let Some(id) = chan_info.short_channel_id {
+                       println!("\t\tshort_channel_id: {},", id);
                }
-               println!("\t\tpending_open: {},", pending_channel);
+               println!("\t\tis_confirmed_onchain: {},", chan_info.is_funding_locked);
                println!("\t\tchannel_value_satoshis: {},", chan_info.channel_value_satoshis);
-               println!("\t\tchannel_can_send_payments: {},", chan_info.is_live);
+               if chan_info.is_usable {
+                       println!("\t\tavailable_balance_for_send_msat: {},", chan_info.outbound_capacity_msat);
+                       println!("\t\tavailable_balance_for_recv_msat: {},", chan_info.inbound_capacity_msat);
+               }
+               println!("\t\tchannel_can_send_payments: {},", chan_info.is_usable);
                println!("\t}},");
        }
        println!("]");
@@ -639,12 +675,12 @@ pub(crate) fn parse_peer_info(
                return Err(std::io::Error::new(
                        std::io::ErrorKind::Other,
                        "ERROR: incorrectly formatted peer
-        info. Should be formatted as: `pubkey@host:port`",
+               info. Should be formatted as: `pubkey@host:port`",
                ));
        }
 
-       let peer_addr: Result<SocketAddr, _> = peer_addr_str.unwrap().parse();
-       if peer_addr.is_err() {
+       let peer_addr = peer_addr_str.unwrap().to_socket_addrs().map(|mut r| r.next());
+       if peer_addr.is_err() || peer_addr.as_ref().unwrap().is_none() {
                return Err(std::io::Error::new(
                        std::io::ErrorKind::Other,
                        "ERROR: couldn't parse pubkey@host:port into a socket address",
@@ -659,5 +695,5 @@ pub(crate) fn parse_peer_info(
                ));
        }
 
-       Ok((pubkey.unwrap(), peer_addr.unwrap()))
+       Ok((pubkey.unwrap(), peer_addr.unwrap().unwrap()))
 }