trezorlib 0.0.2

Client library for interfacing with Trezor hardware wallet devices.
Documentation
extern crate bitcoin;
extern crate fern;
extern crate hex;
extern crate log;
extern crate trezor;

use std::io;

use bitcoin::{network::constants::Network, util::bip32, Address};

use trezor::{InputScriptType, TrezorMessage, TrezorResponse};

fn setup_logger() {
	fern::Dispatch::new()
		.format(|out, message, record| {
			out.finish(format_args!("[{}][{}] {}", record.target(), record.level(), message))
		})
		.level(log::LevelFilter::Trace)
		.chain(std::io::stderr())
		.apply()
		.unwrap();
}

fn handle_interaction<T, R: TrezorMessage>(resp: TrezorResponse<T, R>) -> T {
	match resp {
		TrezorResponse::Ok(res) => res,
		TrezorResponse::Failure(_) => resp.ok().unwrap(), // assering ok() returns the failure error
		TrezorResponse::ButtonRequest(req) => handle_interaction(req.ack().unwrap()),
		TrezorResponse::PinMatrixRequest(req) => {
			println!("Enter PIN");
			let mut pin = String::new();
			if io::stdin().read_line(&mut pin).unwrap() != 5 {
				println!("must enter pin, received: {}", pin);
			}
			// trim newline
			handle_interaction(req.ack_pin(pin[..4].to_owned()).unwrap())
		}
		TrezorResponse::PassphraseRequest(req) => {
			println!("Enter passphrase");
			let mut pass = String::new();
			io::stdin().read_line(&mut pass).unwrap();
			// trim newline
			handle_interaction(req.ack_passphrase(pass[..pass.len() - 1].to_owned()).unwrap())
		}
		TrezorResponse::PassphraseStateRequest(req) => handle_interaction(req.ack().unwrap()),
	}
}

fn main() {
	setup_logger();
	// init with debugging
	let mut trezor = trezor::unique(true).unwrap();
	trezor.init_device().unwrap();

	let pubkey = handle_interaction(
		trezor
			.get_public_key(
				vec![
					bip32::ChildNumber::from_hardened_idx(0).unwrap(),
					bip32::ChildNumber::from_hardened_idx(0).unwrap(),
					bip32::ChildNumber::from_hardened_idx(1).unwrap(),
				],
				trezor::protos::InputScriptType::SPENDADDRESS,
				Network::Testnet,
				true,
			)
			.unwrap(),
	);
	let addr = Address::p2pkh(&pubkey.public_key, Network::Testnet);
	println!("address: {}", addr);

	let (addr, signature) = handle_interaction(
		trezor
			.sign_message(
				"regel het".to_owned(),
				vec![
					bip32::ChildNumber::from_hardened_idx(0).unwrap(),
					bip32::ChildNumber::from_hardened_idx(0).unwrap(),
					bip32::ChildNumber::from_hardened_idx(1).unwrap(),
				],
				InputScriptType::SPENDADDRESS,
				Network::Testnet,
			)
			.unwrap(),
	);
	println!("Addr from device: {}", addr);
	println!("Signature: {:?}", signature);
}