solana_remote_wallet/
remote_keypair.rs1use {
2 crate::{
3 ledger::get_ledger_from_info,
4 locator::{Locator, Manufacturer},
5 remote_wallet::{
6 RemoteWallet, RemoteWalletError, RemoteWalletInfo, RemoteWalletManager,
7 RemoteWalletType,
8 },
9 },
10 solana_derivation_path::DerivationPath,
11 solana_pubkey::Pubkey,
12 solana_signature::Signature,
13 solana_signer::{Signer, SignerError},
14};
15
16pub struct RemoteKeypair {
17 pub wallet_type: RemoteWalletType,
18 pub derivation_path: DerivationPath,
19 pub pubkey: Pubkey,
20 pub path: String,
21}
22
23impl RemoteKeypair {
24 pub fn new(
25 wallet_type: RemoteWalletType,
26 derivation_path: DerivationPath,
27 confirm_key: bool,
28 path: String,
29 ) -> Result<Self, RemoteWalletError> {
30 let pubkey = match &wallet_type {
31 RemoteWalletType::Ledger(wallet) => wallet.get_pubkey(&derivation_path, confirm_key)?,
32 };
33
34 Ok(Self {
35 wallet_type,
36 derivation_path,
37 pubkey,
38 path,
39 })
40 }
41}
42
43impl Signer for RemoteKeypair {
44 fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
45 Ok(self.pubkey)
46 }
47
48 fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError> {
49 match &self.wallet_type {
50 RemoteWalletType::Ledger(wallet) => wallet
51 .sign_message(&self.derivation_path, message)
52 .map_err(|e| e.into()),
53 }
54 }
55
56 fn is_interactive(&self) -> bool {
57 true
58 }
59}
60
61pub fn generate_remote_keypair(
62 locator: Locator,
63 derivation_path: DerivationPath,
64 wallet_manager: &RemoteWalletManager,
65 confirm_key: bool,
66 keypair_name: &str,
67) -> Result<RemoteKeypair, RemoteWalletError> {
68 let remote_wallet_info = RemoteWalletInfo::parse_locator(locator);
69 if remote_wallet_info.manufacturer == Manufacturer::Ledger {
70 let ledger = get_ledger_from_info(remote_wallet_info, keypair_name, wallet_manager)?;
71 let path = format!("{}{}", ledger.pretty_path, derivation_path.get_query());
72 Ok(RemoteKeypair::new(
73 RemoteWalletType::Ledger(ledger),
74 derivation_path,
75 confirm_key,
76 path,
77 )?)
78 } else {
79 Err(RemoteWalletError::DeviceTypeMismatch)
80 }
81}