whisky_wallet/wallet/
mod.rs

1pub mod derivation_indices;
2pub mod mnemonic;
3pub mod root_key;
4use bip39::{Language, Mnemonic};
5use derivation_indices::DerivationIndices;
6pub use mnemonic::MnemonicWallet;
7pub use root_key::RootKeyWallet;
8use whisky_common::WError;
9use whisky_csl::{
10    csl::{Bip32PrivateKey, FixedTransaction, PrivateKey, PublicKey},
11    sign_transaction,
12};
13
14pub enum WalletType {
15    MnemonicWallet(MnemonicWallet),
16    RootKeyWallet(RootKeyWallet),
17    Cli(String),
18}
19
20pub struct Wallet {
21    pub wallet_type: WalletType,
22}
23
24pub struct Account {
25    pub private_key: PrivateKey,
26    pub public_key: PublicKey,
27}
28
29impl Account {
30    pub fn sign_transaction(&self, tx_hex: &str) -> Result<String, WError> {
31        let mut tx = FixedTransaction::from_hex(tx_hex)
32            .map_err(WError::from_err("Account - failed to deserialize tx hex"))?;
33        tx.sign_and_add_vkey_signature(&self.private_key)
34            .map_err(WError::from_err("Account - failed to sign transaction"))?;
35        Ok(tx.to_hex())
36    }
37}
38
39impl Wallet {
40    pub fn new(wallet_type: WalletType) -> Self {
41        Self { wallet_type }
42    }
43
44    pub fn new_cli(cli_skey: &str) -> Self {
45        Self {
46            wallet_type: WalletType::Cli(cli_skey.to_string()),
47        }
48    }
49
50    pub fn new_mnemonic(mnemonic_phrase: &str) -> Self {
51        Self {
52            wallet_type: WalletType::MnemonicWallet(MnemonicWallet {
53                mnemonic_phrase: mnemonic_phrase.to_string(),
54                derivation_indices: DerivationIndices::default(),
55            }),
56        }
57    }
58
59    pub fn new_root_key(root_key: &str) -> Self {
60        Self {
61            wallet_type: WalletType::RootKeyWallet(RootKeyWallet {
62                root_key: root_key.to_string(),
63                derivation_indices: DerivationIndices::default(),
64            }),
65        }
66    }
67
68    pub fn payment_account(&mut self, account_index: u32, key_index: u32) -> &mut Self {
69        match &mut self.wallet_type {
70            WalletType::MnemonicWallet(mnemonic_wallet) => {
71                mnemonic_wallet.payment_account(account_index, key_index);
72            }
73            WalletType::RootKeyWallet(root_key_wallet) => {
74                root_key_wallet.payment_account(account_index, key_index);
75            }
76            _ => {}
77        }
78        self
79    }
80
81    pub fn stake_account(&mut self, account_index: u32, key_index: u32) -> &mut Self {
82        match &mut self.wallet_type {
83            WalletType::MnemonicWallet(mnemonic_wallet) => {
84                mnemonic_wallet.stake_account(account_index, key_index);
85            }
86            WalletType::RootKeyWallet(root_key_wallet) => {
87                root_key_wallet.stake_account(account_index, key_index);
88            }
89            _ => {}
90        }
91        self
92    }
93
94    pub fn drep_account(&mut self, account_index: u32, key_index: u32) -> &mut Self {
95        match &mut self.wallet_type {
96            WalletType::MnemonicWallet(mnemonic_wallet) => {
97                mnemonic_wallet.drep_account(account_index, key_index);
98            }
99            WalletType::RootKeyWallet(root_key_wallet) => {
100                root_key_wallet.drep_account(account_index, key_index);
101            }
102            _ => {}
103        }
104        self
105    }
106
107    pub fn sign_tx(&self, tx_hex: &str) -> Result<String, WError> {
108        match &self.wallet_type {
109            WalletType::Cli(cli_skey) => {
110                let signed_tx = sign_transaction(tx_hex, &[cli_skey])
111                    .map_err(WError::from_err("Wallet - sign_tx"))?;
112                Ok(signed_tx)
113            }
114            _ => {
115                let account = self
116                    .get_account()
117                    .map_err(WError::from_err("Wallet - sign_tx"))?;
118                let signed_tx = account
119                    .sign_transaction(tx_hex)
120                    .map_err(WError::from_err("Wallet - sign_tx"))?;
121                Ok(signed_tx.to_string())
122            }
123        }
124    }
125
126    pub fn get_account(&self) -> Result<Account, WError> {
127        let private_key: PrivateKey = match &self.wallet_type {
128            WalletType::MnemonicWallet(mnemonic_wallet) => {
129                let mnemonic =
130                    Mnemonic::from_phrase(&mnemonic_wallet.mnemonic_phrase, Language::English)
131                        .map_err(WError::from_err(
132                            "Wallet - get_account - failed to create mnemonic",
133                        ))?;
134                let entropy = mnemonic.entropy();
135                let mut root_key = Bip32PrivateKey::from_bip39_entropy(entropy, &[]);
136                for index in &mnemonic_wallet.derivation_indices.0 {
137                    root_key = root_key.derive(index.clone());
138                }
139                root_key.to_raw_key()
140            }
141            WalletType::RootKeyWallet(root_key_wallet) => {
142                let mut root_key = Bip32PrivateKey::from_bech32(&root_key_wallet.root_key)
143                    .map_err(WError::from_err(
144                        "Wallet - get_account - invalid root key hex",
145                    ))?;
146                for index in &root_key_wallet.derivation_indices.0 {
147                    root_key = root_key.derive(index.clone());
148                }
149                root_key.to_raw_key()
150            }
151            WalletType::Cli(private_key) => PrivateKey::from_hex(&private_key).map_err(
152                WError::from_err("Wallet - get_account - invalid private key hex"),
153            )?,
154        };
155        let public_key = private_key.to_public();
156        Ok(Account {
157            private_key,
158            public_key,
159        })
160    }
161}