Cli: Add resolve-signer subcommand (#8859)

* Expose remote-wallet device pretty path

* Add resolve-signer helpers

* Add cli resolve-signer subcommand

* Print pretty-path in waiting msg
This commit is contained in:
Tyera Eulberg
2020-03-14 20:48:41 -07:00
committed by GitHub
parent c3c4c9326b
commit 3c2aff2b5b
6 changed files with 179 additions and 5 deletions

View File

@ -55,6 +55,7 @@ mod commands {
/// Ledger Wallet device
pub struct LedgerWallet {
pub device: hidapi::HidDevice,
pub pretty_path: String,
}
impl fmt::Debug for LedgerWallet {
@ -65,7 +66,10 @@ impl fmt::Debug for LedgerWallet {
impl LedgerWallet {
pub fn new(device: hidapi::HidDevice) -> Self {
Self { device }
Self {
device,
pretty_path: String::default(),
}
}
// Transport Protocol:
@ -231,7 +235,10 @@ impl LedgerWallet {
) -> Result<Vec<u8>, RemoteWalletError> {
self.write(command, p1, p2, data)?;
if p1 == P1_CONFIRM && is_last_part(p2) {
println!("Waiting for remote wallet to approve...");
println!(
"Waiting for approval from remote wallet {}",
self.pretty_path
);
let result = self.read()?;
println!("{}Approved", CHECK_MARK);
Ok(result)

View File

@ -14,6 +14,7 @@ pub struct RemoteKeypair {
pub wallet_type: RemoteWalletType,
pub derivation_path: DerivationPath,
pub pubkey: Pubkey,
pub path: String,
}
impl RemoteKeypair {
@ -21,6 +22,7 @@ impl RemoteKeypair {
wallet_type: RemoteWalletType,
derivation_path: DerivationPath,
confirm_key: bool,
path: String,
) -> Result<Self, RemoteWalletError> {
let pubkey = match &wallet_type {
RemoteWalletType::Ledger(wallet) => wallet.get_pubkey(&derivation_path, confirm_key)?,
@ -30,6 +32,7 @@ impl RemoteKeypair {
wallet_type,
derivation_path,
pubkey,
path,
})
}
}
@ -57,10 +60,12 @@ pub fn generate_remote_keypair(
let (remote_wallet_info, derivation_path) = RemoteWalletInfo::parse_path(path)?;
if remote_wallet_info.manufacturer == "ledger" {
let ledger = get_ledger_from_info(remote_wallet_info, keypair_name, wallet_manager)?;
let path = format!("{}{}", ledger.pretty_path, derivation_path.get_query());
Ok(RemoteKeypair::new(
RemoteWalletType::Ledger(ledger),
derivation_path,
confirm_key,
path,
)?)
} else {
Err(RemoteWalletError::DeviceTypeMismatch)

View File

@ -105,8 +105,9 @@ impl RemoteWalletManager {
if is_valid_ledger(device_info.vendor_id(), device_info.product_id()) {
match usb.open_path(&device_info.path()) {
Ok(device) => {
let ledger = LedgerWallet::new(device);
let mut ledger = LedgerWallet::new(device);
if let Ok(info) = ledger.read_device(&device_info) {
ledger.pretty_path = info.get_pretty_path();
let path = device_info.path().to_str().unwrap().to_string();
trace!("Found device: {:?}", info);
v.push(Device {
@ -328,6 +329,20 @@ impl fmt::Debug for DerivationPath {
}
}
impl DerivationPath {
pub fn get_query(&self) -> String {
if let Some(account) = self.account {
if let Some(change) = self.change {
format!("?key={}/{}", account, change)
} else {
format!("?key={}", account)
}
} else {
"".to_string()
}
}
}
/// Helper to determine if a device is a valid HID
pub fn is_valid_hid_device(usage_page: u16, interface_number: i32) -> bool {
usage_page == HID_GLOBAL_USAGE_PAGE || interface_number == HID_USB_DEVICE_CLASS as i32
@ -519,4 +534,40 @@ mod tests {
test_info.pubkey = pubkey;
assert!(info.matches(&test_info));
}
#[test]
fn test_get_pretty_path() {
let pubkey = Pubkey::new_rand();
let pubkey_str = pubkey.to_string();
let remote_wallet_info = RemoteWalletInfo {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
pubkey,
error: None,
};
assert_eq!(
remote_wallet_info.get_pretty_path(),
format!("usb://ledger/nano-s/{}", pubkey_str)
);
}
#[test]
fn test_get_query() {
let derivation_path = DerivationPath {
account: None,
change: None,
};
assert_eq!(derivation_path.get_query(), "".to_string());
let derivation_path = DerivationPath {
account: Some(1),
change: None,
};
assert_eq!(derivation_path.get_query(), "?key=1".to_string());
let derivation_path = DerivationPath {
account: Some(1),
change: Some(2),
};
assert_eq!(derivation_path.get_query(), "?key=1/2".to_string());
}
}