Add hidapi feature in remote-wallet

This commit is contained in:
Eric Warehime
2021-12-06 14:32:59 -08:00
committed by Trent Nelson
parent e291342c4a
commit b635073829
6 changed files with 54 additions and 32 deletions

View File

@@ -12,7 +12,7 @@ documentation = "https://docs.rs/solana-remote-wallet"
[dependencies]
console = "0.15.0"
dialoguer = "0.9.0"
hidapi = { version = "1.3.2", default-features = false }
hidapi = { version = "1.3.2", default-features = false, optional = true}
log = "0.4.14"
num-derive = { version = "0.3" }
num-traits = { version = "0.2" }
@@ -24,7 +24,7 @@ thiserror = "1.0"
uriparse = "0.6.3"
[features]
default = ["linux-static-hidraw"]
default = ["linux-static-hidraw", "hidapi"]
linux-static-libusb = ["hidapi/linux-static-libusb"]
linux-static-hidraw = ["hidapi/linux-static-hidraw"]
linux-shared-libusb = ["hidapi/linux-shared-libusb"]

View File

@@ -1,16 +1,20 @@
use {
crate::{
ledger_error::LedgerError,
locator::Manufacturer,
remote_wallet::{RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletManager},
crate::remote_wallet::{
RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletManager,
},
console::Emoji,
dialoguer::{theme::ColorfulTheme, Select},
semver::Version as FirmwareVersion,
solana_sdk::derivation_path::DerivationPath,
std::{fmt, sync::Arc},
};
#[cfg(feature = "hidapi")]
use {
crate::{ledger_error::LedgerError, locator::Manufacturer},
log::*,
num_traits::FromPrimitive,
semver::Version as FirmwareVersion,
solana_sdk::{derivation_path::DerivationPath, pubkey::Pubkey, signature::Signature},
std::{cmp::min, convert::TryFrom, fmt, sync::Arc},
solana_sdk::{pubkey::Pubkey, signature::Signature},
std::{cmp::min, convert::TryFrom},
};
static CHECK_MARK: Emoji = Emoji("", "");
@@ -79,6 +83,7 @@ pub struct LedgerSettings {
/// Ledger Wallet device
pub struct LedgerWallet {
#[cfg(feature = "hidapi")]
pub device: hidapi::HidDevice,
pub pretty_path: String,
pub version: FirmwareVersion,
@@ -90,6 +95,7 @@ impl fmt::Debug for LedgerWallet {
}
}
#[cfg(feature = "hidapi")]
impl LedgerWallet {
pub fn new(device: hidapi::HidDevice) -> Self {
Self {
@@ -347,7 +353,10 @@ impl LedgerWallet {
}
}
impl RemoteWallet for LedgerWallet {
#[cfg(not(feature = "hidapi"))]
impl RemoteWallet<Self> for LedgerWallet {}
#[cfg(feature = "hidapi")]
impl RemoteWallet<hidapi::DeviceInfo> for LedgerWallet {
fn name(&self) -> &str {
"Ledger hardware wallet"
}

View File

@@ -1,4 +1,5 @@
#![allow(clippy::integer_arithmetic)]
#![allow(dead_code)]
pub mod ledger;
pub mod ledger_error;
pub mod locator;

View File

@@ -1,11 +1,13 @@
#[cfg(feature = "hidapi")]
use {crate::ledger::is_valid_ledger, parking_lot::Mutex};
use {
crate::{
ledger::{is_valid_ledger, LedgerWallet},
ledger::LedgerWallet,
ledger_error::LedgerError,
locator::{Locator, LocatorError, Manufacturer},
},
log::*,
parking_lot::{Mutex, RwLock},
parking_lot::RwLock,
solana_sdk::{
derivation_path::{DerivationPath, DerivationPathError},
pubkey::Pubkey,
@@ -61,6 +63,7 @@ pub enum RemoteWalletError {
LocatorError(#[from] LocatorError),
}
#[cfg(feature = "hidapi")]
impl From<hidapi::HidError> for RemoteWalletError {
fn from(err: hidapi::HidError) -> RemoteWalletError {
RemoteWalletError::Hid(err.to_string())
@@ -87,12 +90,14 @@ impl From<RemoteWalletError> for SignerError {
/// Collection of connected RemoteWallets
pub struct RemoteWalletManager {
#[cfg(feature = "hidapi")]
usb: Arc<Mutex<hidapi::HidApi>>,
devices: RwLock<Vec<Device>>,
}
impl RemoteWalletManager {
/// Create a new instance.
#[cfg(feature = "hidapi")]
pub fn new(usb: Arc<Mutex<hidapi::HidApi>>) -> Arc<Self> {
Arc::new(Self {
usb,
@@ -102,6 +107,7 @@ impl RemoteWalletManager {
/// Repopulate device list
/// Note: this method iterates over and updates all devices
#[cfg(feature = "hidapi")]
pub fn update_devices(&self) -> Result<usize, RemoteWalletError> {
let mut usb = self.usb.lock();
usb.refresh_devices()?;
@@ -149,6 +155,13 @@ impl RemoteWalletManager {
Ok(num_curr_devices - num_prev_devices)
}
#[cfg(not(feature = "hidapi"))]
pub fn update_devices(&self) -> Result<usize, RemoteWalletError> {
Err(RemoteWalletError::Hid(
"hidapi crate compilation disabled in solana-remote-wallet.".to_string(),
))
}
/// List connected and acknowledged wallets
pub fn list_devices(&self) -> Vec<RemoteWalletInfo> {
self.devices.read().iter().map(|d| d.info.clone()).collect()
@@ -195,30 +208,34 @@ impl RemoteWalletManager {
}
/// `RemoteWallet` trait
pub trait RemoteWallet {
#[allow(unused_variables)]
pub trait RemoteWallet<T> {
fn name(&self) -> &str {
"remote wallet"
}
/// Parse device info and get device base pubkey
fn read_device(
&mut self,
dev_info: &hidapi::DeviceInfo,
) -> Result<RemoteWalletInfo, RemoteWalletError>;
fn read_device(&mut self, dev_info: &T) -> Result<RemoteWalletInfo, RemoteWalletError> {
unreachable!();
}
/// Get solana pubkey from a RemoteWallet
fn get_pubkey(
&self,
derivation_path: &DerivationPath,
confirm_key: bool,
) -> Result<Pubkey, RemoteWalletError>;
) -> Result<Pubkey, RemoteWalletError> {
unreachable!();
}
/// Sign transaction data with wallet managing pubkey at derivation path m/44'/501'/<account>'/<change>'.
fn sign_message(
&self,
derivation_path: &DerivationPath,
data: &[u8],
) -> Result<Signature, RemoteWalletError>;
) -> Result<Signature, RemoteWalletError> {
unreachable!();
}
}
/// `RemoteWallet` device
@@ -280,10 +297,17 @@ pub fn is_valid_hid_device(usage_page: u16, interface_number: i32) -> bool {
}
/// Helper to initialize hidapi and RemoteWalletManager
#[cfg(feature = "hidapi")]
pub fn initialize_wallet_manager() -> Result<Arc<RemoteWalletManager>, RemoteWalletError> {
let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new()?));
Ok(RemoteWalletManager::new(hidapi))
}
#[cfg(not(feature = "hidapi"))]
pub fn initialize_wallet_manager() -> Result<Arc<RemoteWalletManager>, RemoteWalletError> {
Err(RemoteWalletError::Hid(
"hidapi crate compilation disabled in solana-remote-wallet.".to_string(),
))
}
pub fn maybe_wallet_manager() -> Result<Option<Arc<RemoteWalletManager>>, RemoteWalletError> {
let wallet_manager = initialize_wallet_manager()?;