automerge
This commit is contained in:
@ -87,6 +87,7 @@ pub fn signer_from_path(
|
|||||||
derivation_of(matches, "derivation_path"),
|
derivation_of(matches, "derivation_path"),
|
||||||
wallet_manager,
|
wallet_manager,
|
||||||
matches.is_present("confirm_key"),
|
matches.is_present("confirm_key"),
|
||||||
|
keypair_name,
|
||||||
)?))
|
)?))
|
||||||
} else {
|
} else {
|
||||||
Err(RemoteWalletError::NoDeviceFound.into())
|
Err(RemoteWalletError::NoDeviceFound.into())
|
||||||
|
@ -190,7 +190,9 @@ impl LedgerWallet {
|
|||||||
#[allow(clippy::match_overlapping_arm)]
|
#[allow(clippy::match_overlapping_arm)]
|
||||||
match status {
|
match status {
|
||||||
// These need to be aligned with solana Ledger app error codes, and clippy allowance removed
|
// These need to be aligned with solana Ledger app error codes, and clippy allowance removed
|
||||||
0x6700 => Err(RemoteWalletError::Protocol("Incorrect length")),
|
0x6700 => Err(RemoteWalletError::Protocol(
|
||||||
|
"Solana app not open on Ledger device",
|
||||||
|
)),
|
||||||
0x6802 => Err(RemoteWalletError::Protocol("Invalid parameter")),
|
0x6802 => Err(RemoteWalletError::Protocol("Invalid parameter")),
|
||||||
0x6803 => Err(RemoteWalletError::Protocol(
|
0x6803 => Err(RemoteWalletError::Protocol(
|
||||||
"Overflow: message longer than MAX_MESSAGE_LENGTH",
|
"Overflow: message longer than MAX_MESSAGE_LENGTH",
|
||||||
@ -265,13 +267,18 @@ impl RemoteWallet for LedgerWallet {
|
|||||||
.serial_number
|
.serial_number
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_else(|| "Unknown".to_owned());
|
.unwrap_or_else(|| "Unknown".to_owned());
|
||||||
self.get_pubkey(&DerivationPath::default(), false)
|
let pubkey_result = self.get_pubkey(&DerivationPath::default(), false);
|
||||||
.map(|pubkey| RemoteWalletInfo {
|
let (pubkey, error) = match pubkey_result {
|
||||||
model,
|
Ok(pubkey) => (pubkey, None),
|
||||||
manufacturer,
|
Err(err) => (Pubkey::default(), Some(err)),
|
||||||
serial,
|
};
|
||||||
pubkey,
|
Ok(RemoteWalletInfo {
|
||||||
})
|
model,
|
||||||
|
manufacturer,
|
||||||
|
serial,
|
||||||
|
pubkey,
|
||||||
|
error,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pubkey(
|
fn get_pubkey(
|
||||||
@ -395,12 +402,24 @@ fn extend_and_serialize(derivation_path: &DerivationPath) -> Vec<u8> {
|
|||||||
/// Choose a Ledger wallet based on matching info fields
|
/// Choose a Ledger wallet based on matching info fields
|
||||||
pub fn get_ledger_from_info(
|
pub fn get_ledger_from_info(
|
||||||
info: RemoteWalletInfo,
|
info: RemoteWalletInfo,
|
||||||
|
keypair_name: &str,
|
||||||
wallet_manager: &RemoteWalletManager,
|
wallet_manager: &RemoteWalletManager,
|
||||||
) -> Result<Arc<LedgerWallet>, RemoteWalletError> {
|
) -> Result<Arc<LedgerWallet>, RemoteWalletError> {
|
||||||
let devices = wallet_manager.list_devices();
|
let devices = wallet_manager.list_devices();
|
||||||
let (pubkeys, device_paths): (Vec<Pubkey>, Vec<String>) = devices
|
let mut matches = devices
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&device_info| device_info.matches(&info))
|
.filter(|&device_info| device_info.matches(&info));
|
||||||
|
if matches
|
||||||
|
.clone()
|
||||||
|
.all(|device_info| device_info.error.is_some())
|
||||||
|
{
|
||||||
|
let first_device = matches.next();
|
||||||
|
if let Some(device) = first_device {
|
||||||
|
return Err(device.error.clone().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let (pubkeys, device_paths): (Vec<Pubkey>, Vec<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.pubkey, device_info.get_pretty_path()))
|
||||||
.unzip();
|
.unzip();
|
||||||
if pubkeys.is_empty() {
|
if pubkeys.is_empty() {
|
||||||
@ -408,7 +427,10 @@ pub fn get_ledger_from_info(
|
|||||||
}
|
}
|
||||||
let wallet_base_pubkey = if pubkeys.len() > 1 {
|
let wallet_base_pubkey = if pubkeys.len() > 1 {
|
||||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||||
.with_prompt("Multiple hardware wallets found. Please select a device")
|
.with_prompt(&format!(
|
||||||
|
"Multiple hardware wallets found. Please select a device for {:?}",
|
||||||
|
keypair_name
|
||||||
|
))
|
||||||
.default(0)
|
.default(0)
|
||||||
.items(&device_paths[..])
|
.items(&device_paths[..])
|
||||||
.interact()
|
.interact()
|
||||||
|
@ -53,13 +53,14 @@ pub fn generate_remote_keypair(
|
|||||||
explicit_derivation_path: Option<DerivationPath>,
|
explicit_derivation_path: Option<DerivationPath>,
|
||||||
wallet_manager: &RemoteWalletManager,
|
wallet_manager: &RemoteWalletManager,
|
||||||
confirm_key: bool,
|
confirm_key: bool,
|
||||||
|
keypair_name: &str,
|
||||||
) -> Result<RemoteKeypair, RemoteWalletError> {
|
) -> Result<RemoteKeypair, RemoteWalletError> {
|
||||||
let (remote_wallet_info, mut derivation_path) = RemoteWalletInfo::parse_path(path)?;
|
let (remote_wallet_info, mut derivation_path) = RemoteWalletInfo::parse_path(path)?;
|
||||||
if let Some(derivation) = explicit_derivation_path {
|
if let Some(derivation) = explicit_derivation_path {
|
||||||
derivation_path = derivation;
|
derivation_path = derivation;
|
||||||
}
|
}
|
||||||
if remote_wallet_info.manufacturer == "ledger" {
|
if remote_wallet_info.manufacturer == "ledger" {
|
||||||
let ledger = get_ledger_from_info(remote_wallet_info, wallet_manager)?;
|
let ledger = get_ledger_from_info(remote_wallet_info, keypair_name, wallet_manager)?;
|
||||||
Ok(RemoteKeypair::new(
|
Ok(RemoteKeypair::new(
|
||||||
RemoteWalletType::Ledger(ledger),
|
RemoteWalletType::Ledger(ledger),
|
||||||
derivation_path,
|
derivation_path,
|
||||||
|
@ -18,10 +18,10 @@ const HID_GLOBAL_USAGE_PAGE: u16 = 0xFF00;
|
|||||||
const HID_USB_DEVICE_CLASS: u8 = 0;
|
const HID_USB_DEVICE_CLASS: u8 = 0;
|
||||||
|
|
||||||
/// Remote wallet error.
|
/// Remote wallet error.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum RemoteWalletError {
|
pub enum RemoteWalletError {
|
||||||
#[error("hidapi error")]
|
#[error("hidapi error")]
|
||||||
Hid(#[from] hidapi::HidError),
|
Hid(String),
|
||||||
|
|
||||||
#[error("device type mismatch")]
|
#[error("device type mismatch")]
|
||||||
DeviceTypeMismatch,
|
DeviceTypeMismatch,
|
||||||
@ -51,12 +51,16 @@ pub enum RemoteWalletError {
|
|||||||
UserCancel,
|
UserCancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<hidapi::HidError> for RemoteWalletError {
|
||||||
|
fn from(err: hidapi::HidError) -> RemoteWalletError {
|
||||||
|
RemoteWalletError::Hid(err.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<RemoteWalletError> for SignerError {
|
impl From<RemoteWalletError> for SignerError {
|
||||||
fn from(err: RemoteWalletError) -> SignerError {
|
fn from(err: RemoteWalletError) -> SignerError {
|
||||||
match err {
|
match err {
|
||||||
RemoteWalletError::Hid(hid_error) => {
|
RemoteWalletError::Hid(hid_error) => SignerError::ConnectionError(hid_error),
|
||||||
SignerError::ConnectionError(hid_error.to_string())
|
|
||||||
}
|
|
||||||
RemoteWalletError::DeviceTypeMismatch => SignerError::ConnectionError(err.to_string()),
|
RemoteWalletError::DeviceTypeMismatch => SignerError::ConnectionError(err.to_string()),
|
||||||
RemoteWalletError::InvalidDevice => SignerError::ConnectionError(err.to_string()),
|
RemoteWalletError::InvalidDevice => SignerError::ConnectionError(err.to_string()),
|
||||||
RemoteWalletError::InvalidInput(input) => SignerError::InvalidInput(input),
|
RemoteWalletError::InvalidInput(input) => SignerError::InvalidInput(input),
|
||||||
@ -215,6 +219,8 @@ pub struct RemoteWalletInfo {
|
|||||||
pub serial: String,
|
pub serial: String,
|
||||||
/// Base pubkey of device at Solana derivation path
|
/// Base pubkey of device at Solana derivation path
|
||||||
pub pubkey: Pubkey,
|
pub pubkey: Pubkey,
|
||||||
|
/// Initial read error
|
||||||
|
pub error: Option<RemoteWalletError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RemoteWalletInfo {
|
impl RemoteWalletInfo {
|
||||||
@ -360,6 +366,7 @@ mod tests {
|
|||||||
manufacturer: "ledger".to_string(),
|
manufacturer: "ledger".to_string(),
|
||||||
serial: "".to_string(),
|
serial: "".to_string(),
|
||||||
pubkey,
|
pubkey,
|
||||||
|
error: None,
|
||||||
}));
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_path,
|
derivation_path,
|
||||||
@ -376,6 +383,7 @@ mod tests {
|
|||||||
manufacturer: "ledger".to_string(),
|
manufacturer: "ledger".to_string(),
|
||||||
serial: "".to_string(),
|
serial: "".to_string(),
|
||||||
pubkey,
|
pubkey,
|
||||||
|
error: None,
|
||||||
}));
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_path,
|
derivation_path,
|
||||||
@ -392,6 +400,7 @@ mod tests {
|
|||||||
manufacturer: "ledger".to_string(),
|
manufacturer: "ledger".to_string(),
|
||||||
serial: "".to_string(),
|
serial: "".to_string(),
|
||||||
pubkey,
|
pubkey,
|
||||||
|
error: None,
|
||||||
}));
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_path,
|
derivation_path,
|
||||||
@ -408,6 +417,7 @@ mod tests {
|
|||||||
manufacturer: "ledger".to_string(),
|
manufacturer: "ledger".to_string(),
|
||||||
serial: "".to_string(),
|
serial: "".to_string(),
|
||||||
pubkey,
|
pubkey,
|
||||||
|
error: None,
|
||||||
}));
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_path,
|
derivation_path,
|
||||||
@ -424,6 +434,7 @@ mod tests {
|
|||||||
manufacturer: "ledger".to_string(),
|
manufacturer: "ledger".to_string(),
|
||||||
serial: "".to_string(),
|
serial: "".to_string(),
|
||||||
pubkey,
|
pubkey,
|
||||||
|
error: None,
|
||||||
}));
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_path,
|
derivation_path,
|
||||||
@ -441,6 +452,7 @@ mod tests {
|
|||||||
manufacturer: "ledger".to_string(),
|
manufacturer: "ledger".to_string(),
|
||||||
serial: "".to_string(),
|
serial: "".to_string(),
|
||||||
pubkey: Pubkey::default(),
|
pubkey: Pubkey::default(),
|
||||||
|
error: None,
|
||||||
}));
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_path,
|
derivation_path,
|
||||||
@ -456,6 +468,7 @@ mod tests {
|
|||||||
manufacturer: "ledger".to_string(),
|
manufacturer: "ledger".to_string(),
|
||||||
serial: "".to_string(),
|
serial: "".to_string(),
|
||||||
pubkey: Pubkey::default(),
|
pubkey: Pubkey::default(),
|
||||||
|
error: None,
|
||||||
}));
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
derivation_path,
|
derivation_path,
|
||||||
@ -490,6 +503,7 @@ mod tests {
|
|||||||
model: "Nano S".to_string(),
|
model: "Nano S".to_string(),
|
||||||
serial: "0001".to_string(),
|
serial: "0001".to_string(),
|
||||||
pubkey: pubkey.clone(),
|
pubkey: pubkey.clone(),
|
||||||
|
error: None,
|
||||||
};
|
};
|
||||||
let mut test_info = RemoteWalletInfo::default();
|
let mut test_info = RemoteWalletInfo::default();
|
||||||
test_info.manufacturer = "Not Ledger".to_string();
|
test_info.manufacturer = "Not Ledger".to_string();
|
||||||
|
Reference in New Issue
Block a user