use clap::{App, Arg};
use iota_ledger_nano::api::errors::APIError;
use iota_ledger_nano::transport::TransportTypes;
use serde::{Deserialize, Serialize};
use std::error::Error;
use std::result::Result;
use std::{thread, time::Duration};
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct LedgerApp {
pub(crate) name: String,
pub(crate) version: String,
}
impl LedgerApp {
pub fn name(&self) -> &String {
&self.name
}
pub fn version(&self) -> &String {
&self.version
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct LedgerNanoStatus {
pub(crate) connected: bool,
pub(crate) locked: bool,
pub(crate) blind_signing_enabled: bool,
pub(crate) app: Option<LedgerApp>,
pub(crate) device: Option<LedgerDeviceType>,
#[serde(rename = "bufferSize")]
pub(crate) buffer_size: Option<usize>,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum LedgerDeviceType {
#[serde(alias = "ledgerNanoS")]
LedgerNanoS,
#[serde(alias = "ledgerNanoX")]
LedgerNanoX,
#[serde(alias = "ledgerNanoSPlus")]
LedgerNanoSPlus,
}
impl TryFrom<u8> for LedgerDeviceType {
type Error = APIError;
fn try_from(device: u8) -> Result<Self, Self::Error> {
match device {
0 => Ok(Self::LedgerNanoS),
1 => Ok(Self::LedgerNanoX),
2 => Ok(Self::LedgerNanoSPlus),
_ => Err(APIError::TransportError),
}
}
}
pub fn get_ledger_nano_status(is_simulator: bool) -> LedgerNanoStatus {
log::debug!("get_ledger_nano_status");
let transport_type = if is_simulator {
TransportTypes::TCP
} else {
TransportTypes::NativeHID
};
log::debug!("get_opened_app");
let app = match iota_ledger_nano::get_opened_app(&transport_type) {
Ok((name, version)) => Some(LedgerApp { name, version }),
_ => None,
};
log::debug!("get_app_config");
let (connected_, locked, blind_signing_enabled, device) =
match iota_ledger_nano::get_app_config(&transport_type) {
Ok(config) => (
true,
config.flags & (1 << 0) != 0,
config.flags & (1 << 1) != 0,
LedgerDeviceType::try_from(config.device).ok(),
),
Err(_) => (false, false, false, None),
};
log::debug!("get_buffer_size");
let buffer_size = match iota_ledger_nano::get_buffer_size(&transport_type) {
Ok(size) => Some(size),
Err(_) => None,
};
let connected = if app.is_some() { true } else { connected_ };
LedgerNanoStatus {
connected,
locked,
blind_signing_enabled,
app,
device,
buffer_size,
}
}
pub fn main() -> Result<(), Box<dyn Error>> {
env_logger::init();
let matches = App::new("ledger iota tester")
.version("1.0")
.author("Thomas Pototschnig <microengineer18@gmail.com>")
.arg(
Arg::with_name("is-simulator")
.short("s")
.long("simulator")
.value_name("is_simulator")
.help("select the simulator as transport")
.takes_value(false),
)
.get_matches();
let is_simulator = matches.is_present("is-simulator");
loop {
let status = get_ledger_nano_status(is_simulator);
println!("{:?}", status);
thread::sleep(Duration::from_millis(1000));
}
}