whisky_wallet/wallet/
mod.rs1pub 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 pub account: Account,
23}
24
25pub struct Account {
26 pub private_key: PrivateKey,
27 pub public_key: PublicKey,
28}
29
30impl Account {
31 pub fn sign_transaction(&self, tx_hex: &str) -> Result<String, WError> {
32 let mut tx = FixedTransaction::from_hex(tx_hex)
33 .map_err(WError::from_err("Account - failed to deserialize tx hex"))?;
34 tx.sign_and_add_vkey_signature(&self.private_key)
35 .map_err(WError::from_err("Account - failed to sign transaction"))?;
36 Ok(tx.to_hex())
37 }
38}
39
40impl Wallet {
41 pub fn new(wallet_type: WalletType) -> Result<Self, WError> {
42 let account =
43 Wallet::get_account(&wallet_type).map_err(WError::from_err("Wallet - new"))?;
44 Ok(Self {
45 wallet_type: wallet_type,
46 account,
47 })
48 }
49
50 pub fn new_cli(cli_skey: &str) -> Result<Self, WError> {
51 let wallet_type = WalletType::Cli(cli_skey.to_string());
52 let account =
53 Wallet::get_account(&wallet_type).map_err(WError::from_err("Wallet - new"))?;
54 Ok(Self {
55 wallet_type,
56 account,
57 })
58 }
59
60 pub fn new_mnemonic(mnemonic_phrase: &str) -> Result<Self, WError> {
61 let wallet_type = WalletType::MnemonicWallet(MnemonicWallet {
62 mnemonic_phrase: mnemonic_phrase.to_string(),
63 derivation_indices: DerivationIndices::default(),
64 });
65 let account =
66 Wallet::get_account(&wallet_type).map_err(WError::from_err("Wallet - new_mnemonic"))?;
67 Ok(Self {
68 wallet_type,
69 account,
70 })
71 }
72
73 pub fn new_root_key(root_key: &str) -> Result<Self, WError> {
74 let wallet_type = WalletType::RootKeyWallet(RootKeyWallet {
75 root_key: root_key.to_string(),
76 derivation_indices: DerivationIndices::default(),
77 });
78 let account = Wallet::get_account(&wallet_type).map_err(WError::from_err(
79 "Wallet - new_root_key - failed to get account",
80 ))?;
81 Ok(Self {
82 wallet_type,
83 account,
84 })
85 }
86
87 pub fn payment_account(
88 &mut self,
89 account_index: u32,
90 key_index: u32,
91 ) -> Result<&mut Self, WError> {
92 match &mut self.wallet_type {
93 WalletType::MnemonicWallet(mnemonic_wallet) => {
94 mnemonic_wallet.payment_account(account_index, key_index);
95 }
96 WalletType::RootKeyWallet(root_key_wallet) => {
97 root_key_wallet.payment_account(account_index, key_index);
98 }
99 _ => {}
100 }
101 self.account = Wallet::get_account(&self.wallet_type).map_err(WError::from_err(
102 "Wallet - payment_account - failed to get account",
103 ))?;
104 Ok(self)
105 }
106
107 pub fn stake_account(
108 &mut self,
109 account_index: u32,
110 key_index: u32,
111 ) -> Result<&mut Self, WError> {
112 match &mut self.wallet_type {
113 WalletType::MnemonicWallet(mnemonic_wallet) => {
114 mnemonic_wallet.stake_account(account_index, key_index);
115 }
116 WalletType::RootKeyWallet(root_key_wallet) => {
117 root_key_wallet.stake_account(account_index, key_index);
118 }
119 _ => {}
120 }
121 self.account = Wallet::get_account(&self.wallet_type).map_err(WError::from_err(
122 "Wallet - stake_account - failed to get account",
123 ))?;
124 Ok(self)
125 }
126
127 pub fn drep_account(
128 &mut self,
129 account_index: u32,
130 key_index: u32,
131 ) -> Result<&mut Self, WError> {
132 match &mut self.wallet_type {
133 WalletType::MnemonicWallet(mnemonic_wallet) => {
134 mnemonic_wallet.drep_account(account_index, key_index);
135 }
136 WalletType::RootKeyWallet(root_key_wallet) => {
137 root_key_wallet.drep_account(account_index, key_index);
138 }
139 _ => {}
140 }
141 self.account = Wallet::get_account(&self.wallet_type).map_err(WError::from_err(
142 "Wallet - drep_account - failed to get account",
143 ))?;
144 Ok(self)
145 }
146
147 pub fn sign_tx(&self, tx_hex: &str) -> Result<String, WError> {
148 match &self.wallet_type {
149 WalletType::Cli(cli_skey) => {
150 let signed_tx = sign_transaction(tx_hex, &[cli_skey])
151 .map_err(WError::from_err("Wallet - sign_tx"))?;
152 Ok(signed_tx)
153 }
154 _ => {
155 let signed_tx = self
156 .account
157 .sign_transaction(tx_hex)
158 .map_err(WError::from_err("Wallet - sign_tx"))?;
159 Ok(signed_tx.to_string())
160 }
161 }
162 }
163
164 pub fn get_account(wallet_type: &WalletType) -> Result<Account, WError> {
165 let private_key: PrivateKey = match wallet_type {
166 WalletType::MnemonicWallet(mnemonic_wallet) => {
167 let mnemonic =
168 Mnemonic::from_phrase(&mnemonic_wallet.mnemonic_phrase, Language::English)
169 .map_err(WError::from_err(
170 "Wallet - get_account - failed to create mnemonic",
171 ))?;
172 let entropy = mnemonic.entropy();
173 let mut root_key = Bip32PrivateKey::from_bip39_entropy(entropy, &[]);
174 for index in &mnemonic_wallet.derivation_indices.0 {
175 root_key = root_key.derive(index.clone());
176 }
177 root_key.to_raw_key()
178 }
179 WalletType::RootKeyWallet(root_key_wallet) => {
180 let mut root_key = Bip32PrivateKey::from_bech32(&root_key_wallet.root_key)
181 .map_err(WError::from_err(
182 "Wallet - get_account - invalid root key hex",
183 ))?;
184 for index in &root_key_wallet.derivation_indices.0 {
185 root_key = root_key.derive(index.clone());
186 }
187 root_key.to_raw_key()
188 }
189 WalletType::Cli(private_key) => PrivateKey::from_hex(&private_key).map_err(
190 WError::from_err("Wallet - get_account - invalid private key hex"),
191 )?,
192 };
193 let public_key = private_key.to_public();
194 Ok(Account {
195 private_key,
196 public_key,
197 })
198 }
199}