use std::io; fn convert_path_from_str(derivation: &str) -> Vec<u32> { let derivation = derivation.to_string(); let elements = derivation.split('/').skip(1).collect::<Vec<_>>(); let mut path = vec![]; for derivation_index in elements { let hardened = derivation_index.contains('\''); let mut index = derivation_index.replace('\'', "").parse::<u32>().unwrap(); if hardened { index |= 0x80000000; } path.push(index); } path } fn device_selector() -> trezor_client::Trezor { let mut devices = trezor_client::find_devices(false); if devices.is_empty() { panic!("No devices connected"); } else if devices.len() == 1 { devices.remove(0).connect().expect("connection error") } else { println!("Choose device:"); for (i, dev) in devices.iter().enumerate() { println!("{}: {}", i + 1, dev); } println!("Enter device number: "); let mut inp = String::new(); io::stdin().read_line(&mut inp).expect("stdin error"); let idx: usize = inp[..inp.len() - 1].parse().expect("invalid number"); if idx >= devices.len() { panic!("Index out of range"); } devices.remove(idx).connect().unwrap() } } fn do_main() -> Result<(), trezor_client::Error> { // init with debugging tracing_subscriber::fmt().with_max_level(tracing::Level::TRACE).init(); let mut trezor = device_selector(); trezor.init_device(None)?; let f = trezor.features().expect("no features").clone(); println!("Features:"); println!("vendor: {}", f.vendor()); println!("version: {}.{}.{}", f.major_version(), f.minor_version(), f.patch_version()); println!("device id: {}", f.device_id()); println!("label: {}", f.label()); println!("is initialized: {}", f.initialized()); println!("pin protection: {}", f.pin_protection()); println!("passphrase protection: {}", f.passphrase_protection()); println!( "{:?}", trezor.ethereum_get_address(convert_path_from_str("m/44'/60'/1'/0/0")).unwrap() ); drop(trezor); let mut trezor2 = device_selector(); trezor2.init_device(Some(f.session_id().to_vec()))?; println!( "{:?}", trezor2.ethereum_get_address(convert_path_from_str("m/44'/60'/1'/0/0")).unwrap() ); //optional bool bootloader_mode = 5; // is device in bootloader mode? //optional string language = 9; // device language //optional bytes revision = 13; // SCM revision of firmware //optional bytes bootloader_hash = 14; // hash of the bootloader //optional bool imported = 15; // was storage imported from an external source? //optional bool pin_cached = 16; // is PIN already cached in session? //optional bool passphrase_cached = 17; // is passphrase already cached in session? //optional bool firmware_present = 18; // is valid firmware loaded? //optional uint32 flags = 20; // device flags (equals // to Storage.flags) optional string model = 21; // device hardware model //optional uint32 fw_major = 22; // reported firmware version if in bootloader // mode optional uint32 fw_minor = 23; // reported firmware version if in // bootloader mode optional uint32 fw_patch = 24; // reported firmware version // if in bootloader mode optional string fw_vendor = 25; // reported firmware // vendor if in bootloader mode optional bytes fw_vendor_keys = 26; // reported // firmware vendor keys (their hash) optional bool unfinished_backup = 27; // report // unfinished backup (equals to Storage.unfinished_backup) optional bool no_backup = 28; // // report no backup (equals to Storage.no_backup) Ok(()) } fn main() { do_main().unwrap() }