Skip to content

Commit

Permalink
Add hidapi feature in remote-wallet
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric-Warehime authored and t-nelson committed Jan 13, 2022
1 parent e291342 commit b635073
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 32 deletions.
2 changes: 1 addition & 1 deletion clap-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ edition = "2021"
clap = "2.33.0"
rpassword = "5.0"
solana-perf = { path = "../perf", version = "=1.10.0" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.0" }
solana-remote-wallet = { path = "../remote-wallet", version = "=1.10.0", default-features = false}
solana-sdk = { path = "../sdk", version = "=1.10.0" }
thiserror = "1.0.30"
tiny-bip39 = "0.8.2"
Expand Down
12 changes: 0 additions & 12 deletions programs/bpf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions remote-wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand All @@ -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"]
Expand Down
25 changes: 17 additions & 8 deletions remote-wallet/src/ledger.rs
Original file line number Diff line number Diff line change
@@ -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("✅ ", "");
Expand Down Expand Up @@ -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,
Expand All @@ -90,6 +95,7 @@ impl fmt::Debug for LedgerWallet {
}
}

#[cfg(feature = "hidapi")]
impl LedgerWallet {
pub fn new(device: hidapi::HidDevice) -> Self {
Self {
Expand Down Expand Up @@ -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"
}
Expand Down
1 change: 1 addition & 0 deletions remote-wallet/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(clippy::integer_arithmetic)]
#![allow(dead_code)]
pub mod ledger;
pub mod ledger_error;
pub mod locator;
Expand Down
42 changes: 33 additions & 9 deletions remote-wallet/src/remote_wallet.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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())
Expand All @@ -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,
Expand All @@ -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()?;
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()?;
Expand Down

0 comments on commit b635073

Please sign in to comment.