CLI: collect and deduplicate signers (#8398)
* Rename (keypair util is not a thing) * Add method to generate_unique_signers * Cli: refactor signer handling and remote-wallet init * Fixup unit tests * Fixup intergation tests * Update keypair path print statement * Remove &None * Use deterministic key in test * Retain storage-account as index * Make signer index-handling less brittle * Cache pubkey on RemoteKeypair::new * Make signer_of consistent + return pubkey * Remove &matches double references * Nonce authorities need special handling
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::remote_wallet::{
|
||||
initialize_wallet_manager, DerivationPath, RemoteWallet, RemoteWalletError, RemoteWalletInfo,
|
||||
DerivationPath, RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletManager,
|
||||
};
|
||||
use dialoguer::{theme::ColorfulTheme, Select};
|
||||
use log::*;
|
||||
@@ -378,9 +378,8 @@ fn extend_and_serialize(derivation_path: &DerivationPath) -> Vec<u8> {
|
||||
/// Choose a Ledger wallet based on matching info fields
|
||||
pub fn get_ledger_from_info(
|
||||
info: RemoteWalletInfo,
|
||||
wallet_manager: &RemoteWalletManager,
|
||||
) -> Result<Arc<LedgerWallet>, RemoteWalletError> {
|
||||
let wallet_manager = initialize_wallet_manager()?;
|
||||
let _device_count = wallet_manager.update_devices()?;
|
||||
let devices = wallet_manager.list_devices();
|
||||
let (pubkeys, device_paths): (Vec<Pubkey>, Vec<String>) = devices
|
||||
.iter()
|
||||
|
@@ -1,7 +1,8 @@
|
||||
use crate::{
|
||||
ledger::get_ledger_from_info,
|
||||
remote_wallet::{
|
||||
DerivationPath, RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletType,
|
||||
DerivationPath, RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletManager,
|
||||
RemoteWalletType,
|
||||
},
|
||||
};
|
||||
use solana_sdk::{
|
||||
@@ -12,24 +13,29 @@ use solana_sdk::{
|
||||
pub struct RemoteKeypair {
|
||||
pub wallet_type: RemoteWalletType,
|
||||
pub derivation_path: DerivationPath,
|
||||
pub pubkey: Pubkey,
|
||||
}
|
||||
|
||||
impl RemoteKeypair {
|
||||
pub fn new(wallet_type: RemoteWalletType, derivation_path: DerivationPath) -> Self {
|
||||
Self {
|
||||
pub fn new(
|
||||
wallet_type: RemoteWalletType,
|
||||
derivation_path: DerivationPath,
|
||||
) -> Result<Self, RemoteWalletError> {
|
||||
let pubkey = match &wallet_type {
|
||||
RemoteWalletType::Ledger(wallet) => wallet.get_pubkey(&derivation_path)?,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
wallet_type,
|
||||
derivation_path,
|
||||
}
|
||||
pubkey,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Signer for RemoteKeypair {
|
||||
fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
|
||||
match &self.wallet_type {
|
||||
RemoteWalletType::Ledger(wallet) => wallet
|
||||
.get_pubkey(&self.derivation_path)
|
||||
.map_err(|e| e.into()),
|
||||
}
|
||||
Ok(self.pubkey)
|
||||
}
|
||||
|
||||
fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError> {
|
||||
@@ -44,17 +50,18 @@ impl Signer for RemoteKeypair {
|
||||
pub fn generate_remote_keypair(
|
||||
path: String,
|
||||
explicit_derivation_path: Option<DerivationPath>,
|
||||
wallet_manager: &RemoteWalletManager,
|
||||
) -> Result<RemoteKeypair, RemoteWalletError> {
|
||||
let (remote_wallet_info, mut derivation_path) = RemoteWalletInfo::parse_path(path)?;
|
||||
if let Some(derivation) = explicit_derivation_path {
|
||||
derivation_path = derivation;
|
||||
}
|
||||
if remote_wallet_info.manufacturer == "ledger" {
|
||||
let ledger = get_ledger_from_info(remote_wallet_info)?;
|
||||
Ok(RemoteKeypair {
|
||||
wallet_type: RemoteWalletType::Ledger(ledger),
|
||||
let ledger = get_ledger_from_info(remote_wallet_info, wallet_manager)?;
|
||||
Ok(RemoteKeypair::new(
|
||||
RemoteWalletType::Ledger(ledger),
|
||||
derivation_path,
|
||||
})
|
||||
)?)
|
||||
} else {
|
||||
Err(RemoteWalletError::DeviceTypeMismatch)
|
||||
}
|
||||
|
@@ -299,6 +299,17 @@ pub fn initialize_wallet_manager() -> Result<Arc<RemoteWalletManager>, RemoteWal
|
||||
Ok(RemoteWalletManager::new(hidapi))
|
||||
}
|
||||
|
||||
pub fn maybe_wallet_manager() -> Result<Option<Arc<RemoteWalletManager>>, RemoteWalletError> {
|
||||
let wallet_manager = initialize_wallet_manager()?;
|
||||
let device_count = wallet_manager.update_devices()?;
|
||||
if device_count > 0 {
|
||||
Ok(Some(wallet_manager))
|
||||
} else {
|
||||
drop(wallet_manager);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
Reference in New Issue
Block a user