remote-wallet: Select hardware wallets based on host device path

This commit is contained in:
Trent Nelson 2020-10-07 20:02:02 -06:00 committed by Trent Nelson
parent 2c38865e70
commit 8e3353d9ef
2 changed files with 27 additions and 9 deletions

View File

@ -339,6 +339,7 @@ impl RemoteWallet for LedgerWallet {
.clone()
.unwrap_or("Unknown")
.to_string();
let host_device_path = dev_info.path().to_string_lossy().to_string();
let version = self.get_firmware_version()?;
self.version = version;
let pubkey_result = self.get_pubkey(&DerivationPath::default(), false);
@ -350,6 +351,7 @@ impl RemoteWallet for LedgerWallet {
model,
manufacturer,
serial,
host_device_path,
pubkey,
error,
})
@ -521,17 +523,17 @@ pub fn get_ledger_from_info(
return Err(device.error.clone().unwrap());
}
}
let mut matches: Vec<(Pubkey, String)> = matches
let mut matches: Vec<(String, String)> = matches
.filter(|&device_info| device_info.error.is_none())
.map(|device_info| (device_info.pubkey, device_info.get_pretty_path()))
.map(|device_info| (device_info.host_device_path.clone(), device_info.get_pretty_path()))
.collect();
if matches.is_empty() {
return Err(RemoteWalletError::NoDeviceFound);
}
matches.sort_by(|a, b| a.1.cmp(&b.1));
let (pubkeys, device_paths): (Vec<Pubkey>, Vec<String>) = matches.into_iter().unzip();
let (host_device_paths, device_paths): (Vec<Pubkey>, Vec<String>) = matches.into_iter().unzip();
let wallet_base_pubkey = if pubkeys.len() > 1 {
let wallet_host_device_path = if host_device_paths.len() > 1 {
let selection = Select::with_theme(&ColorfulTheme::default())
.with_prompt(&format!(
"Multiple hardware wallets found. Please select a device for {:?}",
@ -541,11 +543,11 @@ pub fn get_ledger_from_info(
.items(&device_paths[..])
.interact()
.unwrap();
pubkeys[selection]
&host_device_paths[selection]
} else {
pubkeys[0]
&host_device_paths[0]
};
wallet_manager.get_ledger(&wallet_base_pubkey)
wallet_manager.get_ledger(wallet_host_device_path)
}
//

View File

@ -152,11 +152,14 @@ impl RemoteWalletManager {
/// Get a particular wallet
#[allow(unreachable_patterns)]
pub fn get_ledger(&self, pubkey: &Pubkey) -> Result<Arc<LedgerWallet>, RemoteWalletError> {
pub fn get_ledger(
&self,
host_device_path: &str,
) -> Result<Arc<LedgerWallet>, RemoteWalletError> {
self.devices
.read()
.iter()
.find(|device| &device.info.pubkey == pubkey)
.find(|device| device.info.host_device_path == host_device_path)
.ok_or(RemoteWalletError::PubkeyNotFound)
.and_then(|device| match &device.wallet_type {
RemoteWalletType::Ledger(ledger) => Ok(ledger.clone()),
@ -237,6 +240,8 @@ pub struct RemoteWalletInfo {
pub manufacturer: String,
/// RemoteWallet device serial number
pub serial: String,
/// RemoteWallet host device path
pub host_device_path: String,
/// Base pubkey of device at Solana derivation path
pub pubkey: Pubkey,
/// Initial read error
@ -449,6 +454,7 @@ mod tests {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
host_device_path: "/host/device/path".to_string(),
pubkey,
error: None,
}));
@ -465,6 +471,7 @@ mod tests {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
host_device_path: "/host/device/path".to_string(),
pubkey,
error: None,
}));
@ -481,6 +488,7 @@ mod tests {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
host_device_path: "/host/device/path".to_string(),
pubkey,
error: None,
}));
@ -497,6 +505,7 @@ mod tests {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
host_device_path: "/host/device/path".to_string(),
pubkey,
error: None,
}));
@ -513,6 +522,7 @@ mod tests {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
host_device_path: "/host/device/path".to_string(),
pubkey,
error: None,
}));
@ -531,6 +541,7 @@ mod tests {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
host_device_path: "/host/device/path".to_string(),
pubkey: Pubkey::default(),
error: None,
}));
@ -547,6 +558,7 @@ mod tests {
model: "".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
host_device_path: "/host/device/path".to_string(),
pubkey: Pubkey::default(),
error: None,
}));
@ -581,6 +593,7 @@ mod tests {
manufacturer: "Ledger".to_string(),
model: "Nano S".to_string(),
serial: "0001".to_string(),
host_device_path: "/host/device/path".to_string(),
pubkey,
error: None,
};
@ -593,6 +606,8 @@ mod tests {
assert!(info.matches(&test_info));
test_info.model = "Nano S".to_string();
assert!(info.matches(&test_info));
test_info.host_device_path = "/host/device/path".to_string();
assert!(info.matches(&test_info));
let another_pubkey = Pubkey::new_rand();
test_info.pubkey = another_pubkey;
assert!(!info.matches(&test_info));
@ -608,6 +623,7 @@ mod tests {
model: "nano-s".to_string(),
manufacturer: "ledger".to_string(),
serial: "".to_string(),
host_device_path: "/host/device/path".to_string(),
pubkey,
error: None,
};