bitcoin_hd_keys/
lib.rs

1use std::collections::HashMap;
2use std::fmt::Write;
3use std::num::{NonZeroU32, ParseIntError};
4use std::str::FromStr;
5mod bip39;
6
7use binary_utils::*;
8use bip39::WORDS;
9use bitcoin::hashes::{ripemd160, Hash};
10use bitcoin::schnorr::UntweakedPublicKey;
11use bitcoin::util::base58::check_encode_slice;
12use bitcoin::util::base58::from_check;
13use bitcoin::util::taproot::TapTweakHash;
14use bitcoin_bech32::{u5, WitnessProgram};
15use bitcoin_utils::*;
16use hmac_sha512::HMAC;
17use num_bigint::BigUint;
18use rand::{thread_rng, RngCore};
19use ring::{digest, pbkdf2};
20use secp256k1::{Scalar, Secp256k1, SecretKey};
21use sha2::{Digest, Sha256};
22
23use hex_utilities::{
24    convert_decimal_to_32_byte_hex, convert_decimal_to_8_byte_hex, convert_hex_to_decimal,
25    decode_hex, encode_hex, get_hex_string_from_byte_array,
26};
27
28// TODO: Maybe also incorporate 'h' in addition to '
29const HARDENED_DERIVATION_CHARACTER: &str = "'";
30
31#[derive(Debug, Clone)]
32pub struct SerializedExtendedKeys {
33    pub xpub: String,
34    pub xpriv: String,
35}
36
37#[derive(Debug, Clone)]
38pub struct NonMasterKeys {
39    pub private_key_hex: String,
40    pub public_key_hex: String,
41    pub chain_code_hex: String,
42    pub is_hardened: bool,
43}
44impl NonMasterKeys {
45    pub fn get_wif(&self, network: Network, should_compress: bool) -> String {
46        get_wif_from_private_key(&self.private_key_hex, network, should_compress)
47    }
48    pub fn get_address(&self, network: Network, address_type: AddressType) -> String {
49        get_address_from_pub_key(&self.public_key_hex, network, address_type)
50    }
51    pub fn serialize(
52        &self,
53        parent_public_key: String,
54        depth: u8,
55        child_index: u32,
56        network: Network,
57        bip: Bip,
58    ) -> SerializedExtendedKeys {
59        serialize_non_master_key(&self, parent_public_key, depth, child_index, network, bip)
60    }
61}
62#[derive(Debug, Clone)]
63pub struct MasterKeys {
64    pub private_key_hex: String,
65    pub public_key_hex: String,
66    pub chain_code_hex: String,
67}
68impl MasterKeys {
69    pub fn get_wif(&self, network: Network, should_compress: bool) -> String {
70        get_wif_from_private_key(&self.private_key_hex, network, should_compress)
71    }
72    pub fn get_address(&self, network: Network, address_type: AddressType) -> String {
73        get_address_from_pub_key(&self.public_key_hex, network, address_type)
74    }
75    pub fn serialize(&self, network: Network, bip: Bip) -> SerializedExtendedKeys {
76        serialize_master_key(self, network, bip)
77    }
78}
79
80#[derive(Debug, Clone)]
81pub enum Keys {
82    Master(MasterKeys),
83    NonMaster(NonMasterKeys),
84}
85
86impl Keys {
87    pub fn get_wif(&self, network: Network, should_compress: bool) -> String {
88        match &self {
89            Keys::Master(master_keys) => master_keys.get_wif(network, should_compress),
90            Keys::NonMaster(non_master_keys) => non_master_keys.get_wif(network, should_compress),
91        }
92    }
93    pub fn get_address(&self, network: Network, address_type: AddressType) -> String {
94        match &self {
95            Keys::Master(master_keys) => master_keys.get_address(network, address_type),
96            Keys::NonMaster(non_master_keys) => non_master_keys.get_address(network, address_type),
97        }
98    }
99}
100#[derive(Debug)]
101enum DerivationChild {
102    NonHardened(u32),
103    Hardened(u32),
104}
105
106#[derive(Debug, Clone)]
107pub struct DecodedExtendedSerializedPrivateKey {
108    pub version_hex: String,
109    pub depth: u8,
110    pub parent_fingerprint: String,
111    pub child_index: u32,
112    pub network: Network,
113    pub depth_fingerprint_child_index_hex: String,
114    pub chain_code_hex: String,
115    pub private_key_hex: String,
116    pub wif_compressed: String,
117    pub wif_uncompressed: String,
118    pub public_key_hex_uncompressed: String,
119    pub public_key_hex_compressed: String,
120}
121#[derive(Debug, Clone)]
122pub struct DecodedExtendedSerializedPublicKey {
123    pub version_hex: String,
124    pub depth: u8,
125    pub parent_fingerprint: String,
126    pub child_index: u32,
127    pub network: Network,
128    pub depth_fingerprint_child_index_hex: String,
129    pub chain_code_hex: String,
130    pub public_key_hex_uncompressed: String,
131}
132
133#[derive(Debug, Clone)]
134pub enum DecodedExtendedKeySerialized {
135    PrivateKey(DecodedExtendedSerializedPrivateKey),
136    PublicKey(DecodedExtendedSerializedPublicKey),
137}
138
139// Notes
140// - A hexidecimal is represetnted by only 4 bits (one byte). We use u8 here because we can't use a
141// u4.
142// - Check work here: https://iancoleman.io/bip39/
143// - https://bitcoin.stackexchange.com/questions/89814/how-does-bip-39-mnemonic-work
144
145// TODO: Use utilties from bitcoin-utils package instead
146fn sha256_entropy_hex_byte_array(hex_byte_array: &Vec<u8>) -> Vec<u8> {
147    let mut hasher = Sha256::new();
148    // write input message
149    hasher.update(&hex_byte_array);
150    // read hash digest and consume hasher
151    let sha256_result = hasher.finalize();
152    sha256_result.to_vec()
153}
154fn serialize_master_key(
155    master_keys: &MasterKeys,
156    network: Network,
157    bip: Bip,
158) -> SerializedExtendedKeys {
159    let master_xprv = serialize_key(SerializeKeyArgs {
160        keys_to_serialize: Keys::Master(master_keys.clone()).clone(),
161        parent_public_key: None,
162        is_public: false,
163        network: network,
164        depth: Some(0),
165        child_index: 0,
166        bip,
167        // Note: always false for master key
168    });
169    let master_xpub = serialize_key(SerializeKeyArgs {
170        keys_to_serialize: Keys::Master(master_keys.clone()).clone(),
171        parent_public_key: None,
172        is_public: true,
173        network: network,
174        depth: Some(0),
175        child_index: 0,
176        bip,
177        // Note: always false for master key
178    });
179    SerializedExtendedKeys {
180        xpub: master_xpub,
181        xpriv: master_xprv,
182    }
183}
184fn serialize_non_master_key(
185    non_master_keys: &NonMasterKeys,
186    parent_public_key: String,
187    depth: u8,
188    child_index: u32,
189    network: Network,
190    bip: Bip,
191) -> SerializedExtendedKeys {
192    let bip32_extended_public_key = serialize_key(SerializeKeyArgs {
193        keys_to_serialize: Keys::NonMaster(non_master_keys.clone()).clone(),
194        parent_public_key: Some(parent_public_key.clone()),
195        is_public: true,
196        network,
197        depth: Some(depth),
198        child_index: child_index as u32,
199        bip,
200    });
201    let bip32_extended_private_key = serialize_key(SerializeKeyArgs {
202        keys_to_serialize: Keys::NonMaster(non_master_keys.clone()).clone(),
203        parent_public_key: Some(parent_public_key.clone()),
204        is_public: false,
205        network,
206        depth: Some(depth),
207        child_index: child_index as u32,
208        bip,
209    });
210    SerializedExtendedKeys {
211        xpub: bip32_extended_public_key,
212        xpriv: bip32_extended_private_key,
213    }
214}
215struct SerializeKeyArgs {
216    pub keys_to_serialize: Keys,
217    pub parent_public_key: Option<String>,
218    pub is_public: bool,
219    pub network: Network,
220    pub depth: Option<u8>,
221    pub child_index: u32,
222    pub bip: Bip,
223}
224
225#[derive(Copy, Clone)]
226pub enum Bip {
227    Bip32,
228    Bip44,
229    Bip49,
230    Bip84,
231    Bip86,
232}
233
234pub fn create_fingerprint(public_key_hex: &String) -> String {
235    let sha256_result_hex = sha256_hex(public_key_hex);
236    let sha256_result_array = decode_hex(&sha256_result_hex).unwrap();
237    let ripemd160_result = ripemd160::Hash::hash(&sha256_result_array);
238    let first_four_bytes = &ripemd160_result[..4];
239    let first_four_hex = encode_hex(&first_four_bytes);
240    first_four_hex
241}
242
243fn serialize_key(args: SerializeKeyArgs) -> String {
244    let SerializeKeyArgs {
245        keys_to_serialize,
246        parent_public_key,
247        is_public,
248        network,
249        depth,
250        child_index,
251        bip,
252    } = args;
253
254    fn checksum(hex: &String) -> String {
255        let hash = double_sha256_hex(&hex);
256        let hash_byte_array = decode_hex(&hash).unwrap();
257        let first_four_bytes = &hash_byte_array[0..=3];
258        encode_hex(first_four_bytes)
259    }
260
261    fn base58_encode(hex_byte_array: Vec<u8>) -> String {
262        let encoded = bitcoin::util::base58::encode_slice(&hex_byte_array);
263        encoded
264    }
265    let public_key_hex = match &keys_to_serialize {
266        Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
267        Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
268    };
269    let private_key_hex = match &keys_to_serialize {
270        Keys::NonMaster(non_master_keys) => non_master_keys.private_key_hex.clone(),
271        Keys::Master(master_keys) => master_keys.private_key_hex.clone(),
272    };
273    let chain_code_hex = match &keys_to_serialize {
274        Keys::NonMaster(non_master_keys) => non_master_keys.chain_code_hex.clone(),
275        Keys::Master(master_keys) => master_keys.chain_code_hex.clone(),
276    };
277    let is_hardened = match &keys_to_serialize {
278        Keys::NonMaster(non_master_keys) => non_master_keys.is_hardened.clone(),
279        Keys::Master(_master_keys) => false,
280    };
281
282    // TODO: Add all versions!
283    // List of all the version possibilities: https://electrum.readthedocs.io/en/latest/xpub_version_bytes.html
284    let version = match bip {
285        Bip::Bip32 | Bip::Bip44 => {
286            if is_public {
287                match network {
288                    Network::Mainnet => "0488b21e",
289                    Network::Testnet => "043587cf",
290                }
291            } else {
292                match network {
293                    Network::Mainnet => "0488ade4",
294                    Network::Testnet => "04358394",
295                }
296            }
297        }
298        Bip::Bip49 => {
299            // Source: https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki
300            if is_public {
301                match network {
302                    Network::Mainnet => "049d7cb2",
303                    Network::Testnet => "044a5262",
304                }
305            } else {
306                match network {
307                    Network::Mainnet => "049d7878",
308                    Network::Testnet => "044a4e28",
309                }
310            }
311        }
312        Bip::Bip84 | Bip::Bip86 => {
313            // Source: https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki
314            if is_public {
315                match network {
316                    Network::Mainnet => "04b24746",
317                    Network::Testnet => "045f1cf6",
318                }
319            } else {
320                match network {
321                    Network::Mainnet => "04b2430c",
322                    Network::Testnet => "045f18bc",
323                }
324            }
325        }
326    };
327    let key = if is_public {
328        format!("{}", public_key_hex)
329    } else {
330        format!("{}{}", "00", private_key_hex)
331    };
332
333    let depth = convert_decimal_to_8_byte_hex(depth.unwrap_or(0));
334    let parent_fingerprint = match &parent_public_key {
335        Some(parent_public_key) => create_fingerprint(&parent_public_key.to_string()),
336        None => "00000000".to_string(),
337    };
338    // for child
339    // let parent_fingerprint = create_fingerprint(parent_public_key.to_string());
340    // TODO: How do we do children at other indexes other than 0. Like 1.
341    let child_index_with_hardened_factored_in = if is_hardened {
342        child_index + 2147483648 // # child index number (must between 2**31 and 2**32-1)
343    } else {
344        child_index
345    };
346    let child_number = convert_decimal_to_32_byte_hex(child_index_with_hardened_factored_in);
347    let chain_code = chain_code_hex;
348    // let key = format!("{}{}", "00", private_key);
349    let serialized = format!(
350        "{}{}{}{}{}{}",
351        version, depth, parent_fingerprint, child_number, chain_code, key
352    );
353
354    let serialized_bytes = decode_hex(&serialized).unwrap();
355    let checksum = checksum(&serialized);
356    let checksum_bytes = decode_hex(&checksum).unwrap();
357    let serialized_with_checksum = format!("{}{}", serialized, checksum);
358    let serialized_with_checksum_bytes = concat_u8(&serialized_bytes, &checksum_bytes);
359    let base58_encoded_serialized_with_checksum = base58_encode(serialized_with_checksum_bytes);
360    base58_encoded_serialized_with_checksum
361    // checksum: 7a2a2640
362    // serialized: 0488ade401018c12590000000005aae71d7c080474efaab01fa79e96f4c6cfe243237780b0df4bc36106228e310039f329fedba2a68e2a804fcd9aeea4104ace9080212a52ce8b52c1fb89850c72
363}
364
365fn get_child_extended_public_key(
366    parent_chain_code: &[u8],
367    parent_public_key: &String,
368    child_index: i32,
369) -> (String, String) {
370    let parent_chain_code = parent_chain_code;
371    let key = parent_chain_code;
372    let index: i32 = child_index;
373    let index_as_bytes = index.to_be_bytes();
374    let parent_public_key_hex = parent_public_key.clone();
375    let parent_public_key_as_bytes = decode_hex(&parent_public_key).unwrap();
376    let parent_public_key_with_index_as_bytes =
377        concat_u8(&parent_public_key_as_bytes, &index_as_bytes);
378
379    let h = HMAC::mac(parent_public_key_with_index_as_bytes, key);
380    let left = &h[0..=31];
381    let right = &h[32..];
382    // let sk = secp256k1::SecretKey::from_slice(left).expect("statistically impossible to hit");
383    // let parent_private_secret_key = SecretKey::from_str(&encode_hex(parent_private_key)).unwrap();
384
385    // let tweaked = sk
386    //     .add_tweak(&parent_private_secret_key.into())
387    //     .expect("statistically impossible to hit");
388
389    // Source: "ckd_pub" function here: https://github.com/rust-bitcoin/rust-bitcoin/blob/master/src/util/bip32.rs
390    let secp = Secp256k1::new();
391    let sk = secp256k1::SecretKey::from_str(&encode_hex(left)).unwrap();
392    let pk = secp256k1::PublicKey::from_str(&parent_public_key_hex)
393        .expect("statistically impossible to hit");
394    let tweaked = pk.add_exp_tweak(&secp, &sk.into()).unwrap();
395
396    let child_public_key: String = tweaked.to_string();
397    let child_chain_code: String = encode_hex(right);
398
399    return (child_public_key, child_chain_code);
400}
401fn get_hardened_child_extended_private_key(
402    master_chain_code: &[u8],
403    master_private_key: &[u8],
404    child_index: u32,
405) -> Keys {
406    let key = master_chain_code;
407    let index: u32 = child_index + 2147483648; // # child index number (must between 2**31 and 2**32-1)
408    let index_as_bytes = index.to_be_bytes();
409    let master_private_key_as_bytes = master_private_key;
410    let prefix_bytes = decode_hex("00").unwrap();
411    let master_private_key_with_index_as_bytes =
412        concat_u8(master_private_key_as_bytes, &index_as_bytes);
413    let master_private_key_with_index_and_prefix_as_bytes =
414        concat_u8(&prefix_bytes, &master_private_key_with_index_as_bytes);
415
416    let h = HMAC::mac(master_private_key_with_index_and_prefix_as_bytes, key);
417    let left = &h[0..=31];
418    let right = &h[32..];
419    //  Source: 'ckd_priv" function here: https://github.com/rust-bitcoin/rust-bitcoin/blob/master/src/util/bip32.rs
420    let sk = secp256k1::SecretKey::from_slice(left).expect("statistically impossible to hit");
421    let master_private_secret_key = SecretKey::from_str(&encode_hex(master_private_key)).unwrap();
422
423    let tweaked = sk
424        .add_tweak(&master_private_secret_key.into())
425        .expect("statistically impossible to hit");
426    let hardened_child_private_key: String = tweaked.display_secret().to_string();
427    let child_public_key = get_compressed_public_key_from_private_key(&hardened_child_private_key);
428
429    let child_private_key = hardened_child_private_key;
430    let child_chain_code = encode_hex(right);
431    let child_public_key = child_public_key;
432    let keys = Keys::NonMaster(NonMasterKeys {
433        private_key_hex: child_private_key,
434        public_key_hex: child_public_key,
435        chain_code_hex: child_chain_code,
436        is_hardened: true,
437    });
438    keys
439}
440fn get_child_extended_private_key(
441    master_chain_code: &[u8],
442    master_public_key: &String,
443    master_private_key: &[u8],
444    child_index: i32,
445) -> Keys {
446    //
447    let key = master_chain_code;
448    // TODO: This is the child index !
449    let index: i32 = child_index;
450    let index_as_bytes = index.to_be_bytes();
451    let master_public_key_as_bytes = master_public_key.as_bytes();
452    let master_public_key_as_bytes = decode_hex(&master_public_key).unwrap();
453    let master_public_key_with_index_as_bytes =
454        concat_u8(&master_public_key_as_bytes, &index_as_bytes);
455    let h = HMAC::mac(master_public_key_with_index_as_bytes, key);
456    let left = &h[0..=31];
457    let right = &h[32..];
458    //  Source: 'ckd_priv" function here: https://github.com/rust-bitcoin/rust-bitcoin/blob/master/src/util/bip32.rs
459    let sk = secp256k1::SecretKey::from_slice(left).expect("statistically impossible to hit");
460    // let secp = Secp256k1::new();
461    let master_private_secret_key = SecretKey::from_str(&encode_hex(master_private_key)).unwrap();
462
463    let tweaked = sk
464        .add_tweak(&master_private_secret_key.into())
465        .expect("statistically impossible to hit");
466    let child_private_key: String = tweaked.display_secret().to_string();
467    let child_public_key = get_compressed_public_key_from_private_key(&child_private_key);
468
469    let child_private_key = child_private_key;
470    let child_chain_code = encode_hex(right);
471    let child_public_key = child_public_key;
472    let keys = Keys::NonMaster(NonMasterKeys {
473        private_key_hex: child_private_key,
474        public_key_hex: child_public_key,
475        chain_code_hex: child_chain_code,
476        is_hardened: false,
477    });
478    keys
479}
480
481fn parse_derivation_path_child(derivation_path_child: &String) -> DerivationChild {
482    let child_split_into_hardened_key: Vec<&str> = derivation_path_child
483        .split(HARDENED_DERIVATION_CHARACTER)
484        .collect();
485    let is_hardened = child_split_into_hardened_key.len() == 2;
486    let child_index = child_split_into_hardened_key
487        .get(0)
488        .unwrap()
489        .parse()
490        .unwrap();
491    if is_hardened {
492        DerivationChild::Hardened(child_index)
493    } else {
494        DerivationChild::NonHardened(child_index)
495    }
496}
497fn get_child_index_from_derivation_path(derivation_path: &String) -> DerivationChild {
498    let derivation_path_split_by_dash: Vec<&str> = derivation_path.split('/').collect();
499    let first = derivation_path_split_by_dash.first().unwrap();
500    if first.to_string() != "m" {
501        panic!("derivation must start with m")
502    } else {
503        let last_item = derivation_path_split_by_dash.last().unwrap().to_string();
504        parse_derivation_path_child(&last_item)
505    }
506}
507
508fn split_derivation_path(derivation_path: String) -> Vec<String> {
509    let derivation_path_split_by_dash: Vec<&str> = derivation_path.split('/').collect();
510    let first = derivation_path_split_by_dash.first().unwrap();
511    if first.to_string() != "m" {
512        panic!("derivation must start with m")
513    } else {
514        // TODO: factor in hardened vs non-hardened keys here
515        let derivation_path_indexes: Vec<String> = derivation_path_split_by_dash[1..]
516            .iter()
517            .map(|s| s.to_string())
518            .collect();
519        derivation_path_indexes
520    }
521}
522
523fn get_child_key_from_derivation_path(derivation_path: String, master_keys: Keys) -> Keys {
524    let derivation_path_indexes = split_derivation_path(derivation_path);
525    let mut current_parent_keys = master_keys;
526    // TODO: factor in hardened vs non-hardened keys here
527    for derivation_path_item in derivation_path_indexes {
528        let derivation_child = parse_derivation_path_child(&derivation_path_item);
529
530        let child_keys = match derivation_child {
531            DerivationChild::NonHardened(child_index) => {
532                let should_harden = false;
533                get_child_key(&current_parent_keys, child_index as i32, should_harden)
534            }
535            DerivationChild::Hardened(child_index) => {
536                let should_harden = true;
537                get_child_key(&current_parent_keys, child_index as i32, should_harden)
538            }
539        };
540        //get_child_key(&current_parent_keys, i as i32, false);
541        current_parent_keys = child_keys;
542    }
543
544    current_parent_keys
545}
546fn get_children_keys_from_derivation_path(
547    derivation_path: &String,
548    master_keys: Keys,
549    children_count: i32,
550    should_be_hardened: bool,
551) -> HashMap<String, Keys> {
552    let child_key = get_child_key_from_derivation_path(derivation_path.to_string(), master_keys);
553    let child_keys = get_child_keys(&child_key, children_count, should_be_hardened);
554    child_keys
555}
556fn get_child_key(parent_keys: &Keys, child_index: i32, should_harden: bool) -> Keys {
557    let parent_chain_code_hex = match &parent_keys {
558        Keys::NonMaster(non_master_keys) => non_master_keys.chain_code_hex.clone(),
559        Keys::Master(master_keys) => master_keys.chain_code_hex.clone(),
560    };
561    let parent_private_key_hex = match parent_keys {
562        Keys::NonMaster(non_master_keys) => non_master_keys.private_key_hex.clone(),
563        Keys::Master(master_keys) => master_keys.private_key_hex.clone(),
564    };
565    let parent_public_key_hex = match parent_keys {
566        Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
567        Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
568    };
569    let parent_chain_code_bytes = decode_hex(&parent_chain_code_hex).unwrap();
570    let parent_private_key_bytes = decode_hex(&parent_private_key_hex).unwrap();
571    if should_harden {
572        get_hardened_child_extended_private_key(
573            &parent_chain_code_bytes,
574            &parent_private_key_bytes,
575            child_index as u32,
576        )
577    } else {
578        get_child_extended_private_key(
579            &parent_chain_code_bytes,
580            &parent_public_key_hex.clone(),
581            &parent_private_key_bytes,
582            child_index as i32,
583        )
584    }
585}
586fn get_child_keys(
587    parent_keys: &Keys,
588    children_count: i32,
589    should_be_hardened: bool,
590) -> HashMap<String, Keys> {
591    let mut children = HashMap::new();
592    for child_index in 0..=children_count {
593        if should_be_hardened {
594            let child_keys_hardened = get_child_key(parent_keys, child_index as i32, true);
595            let hash_key = format!("{}'", child_index);
596            children.insert(hash_key, child_keys_hardened);
597        } else {
598            let child_keys = get_child_key(parent_keys, child_index as i32, false);
599            let hash_key = format!("{}", child_index);
600            children.insert(hash_key, child_keys);
601        }
602    }
603    children
604}
605
606fn get_depth_from_derivation_path(derivation_path: &String) -> u8 {
607    let derivation_path_split_by_dash: Vec<&str> = derivation_path.split('/').collect();
608    let first = derivation_path_split_by_dash.first().unwrap();
609    if first.to_string() != "m" {
610        panic!("derivation must start with m")
611    } else {
612        let derivation_path_without_m = derivation_path_split_by_dash.get(1..).unwrap();
613        let depth = derivation_path_without_m.len() as u8;
614        depth
615    }
616}
617fn get_parent_derivation_path(derivation_path: &String) -> String {
618    let derivation_path_split_by_dash: Vec<&str> = derivation_path.split('/').collect();
619    let first = derivation_path_split_by_dash.first().unwrap();
620    if first.to_string() != "m" {
621        panic!("derivation must start with m")
622    } else {
623        derivation_path_split_by_dash
624            .get(0..=derivation_path_split_by_dash.len() - 2)
625            .unwrap()
626            .join("/")
627    }
628}
629
630// PUBLICCCC
631// Use this many bits when you want to have 12 words
632pub fn get_128_bits_of_entropy() -> [u8; 32] {
633    let mut data = [0u8; 32];
634    rand::thread_rng().fill_bytes(&mut data);
635    data
636}
637
638// Use this many bits when you want to have 24 words
639pub fn get_256_bits_of_entropy() -> [u8; 64] {
640    let mut data = [0u8; 64];
641    rand::thread_rng().fill_bytes(&mut data);
642    data
643}
644pub fn get_mnemonic_words(entropy: Vec<u8>) -> Vec<String> {
645    //let hex_string = "a4b836c41875815e8b153bc89091f1d85dd1ae47287289f5a50ff23cf41b8d21";
646    //let hex_string = "da490f7254f80aa2f7e8dcb3c63a8404";
647    let entropy_hex_string = get_hex_string_from_byte_array(&entropy);
648
649    // let entropy_hex_string = "731180c4b776f6b961da802ff55b153f".to_string();
650    let entropy_hex_byte_array = decode_hex(&entropy_hex_string).unwrap();
651
652    // 2) Calculate the SHA256 of the entropy.
653    let sha256_result = sha256_entropy_hex_byte_array(&entropy_hex_byte_array);
654    // 3) Append the first entropy_length/32 bits of the SHA256 of the entropy at the end of the entropy. For example, in our case we will append the first 4 bits of the SHA256(entropy) to the entropy since our entropy is 128 bits.
655    let entropy_hex_binary_string = get_binary_string_for_byte_array(&entropy_hex_byte_array);
656    let bits_to_append_count = (&entropy_hex_binary_string.len()) / 32;
657    let sha256_result_binary_string = get_binary_string_for_byte_array(&sha256_result);
658    let checksum_binary_string = &sha256_result_binary_string[0..bits_to_append_count];
659
660    // 4) Each word of the mnemonic represents 11 bits. Hence, if you check the wordlist you will find 2048 unique words. Now, divide the entropy + checksum into parts of 11 bits each.
661    let entropy_plus_checksum_binary =
662        format!("{}{}", entropy_hex_binary_string, checksum_binary_string);
663
664    let word_binary = split_binary_string_into_framents_of_11_bits(&entropy_plus_checksum_binary);
665
666    let words: Vec<String> = word_binary
667        .iter()
668        .map(|word_binary_string| {
669            let word_num = convert_binary_to_int(word_binary_string);
670            WORDS.get(word_num as usize).unwrap().to_string()
671        })
672        .collect();
673    words
674}
675fn get_mnemonic_sentence(mnemonic_words: &Vec<String>) -> String {
676    mnemonic_words.join(" ")
677}
678
679fn get_bip38_512_bit_private_key(words: Vec<String>, passphrase: Option<String>) -> String {
680    let mnemonic_sentence = words.join(" ");
681
682    // ===== CREATE A PRIVATE KEY (512 bit seed) ==========================
683    const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
684    let n_iter = NonZeroU32::new(2048).unwrap();
685    let rng = thread_rng();
686    // let rng = SystemRandom::new();
687
688    // Optional passphase
689    let passphrase = match passphrase {
690        Some(passphrase) => passphrase,
691        None => "".to_string(),
692    };
693    let salt = format!("{}{}", "mnemonic", passphrase);
694    let mut salt_as_bytes = salt.as_bytes().to_owned();
695    // rand::thread_rng().fill_bytes(&mut salt);
696
697    let password = mnemonic_sentence.clone();
698    let mut password_as_bytes = password.as_bytes().to_owned();
699    let mut pbkdf2_hash = [0u8; CREDENTIAL_LEN];
700
701    pbkdf2::derive(
702        pbkdf2::PBKDF2_HMAC_SHA512,
703        n_iter,
704        &salt_as_bytes,
705        password.as_bytes(),
706        &mut pbkdf2_hash,
707    );
708
709    let bip39_seed = encode_hex(&pbkdf2_hash);
710
711    // TODO: This should probably be extracted into a teest
712    let wrong_password = "Definitely not the correct password";
713    let should_fail = pbkdf2::verify(
714        pbkdf2::PBKDF2_HMAC_SHA512,
715        n_iter,
716        &salt.as_bytes(),
717        wrong_password.as_bytes(),
718        &pbkdf2_hash,
719    );
720    match should_fail {
721        Err(err) => {}
722        _ => panic!("SOULD HAVE ERRORERED"),
723    }
724
725    bip39_seed
726}
727fn get_master_keys_from_seed(bip39_seed: &String) -> MasterKeys {
728    let pbkdf2_hash = decode_hex(&bip39_seed).unwrap();
729    let key = "Bitcoin seed";
730    let h = HMAC::mac(pbkdf2_hash.to_vec(), key.as_bytes());
731    let left = &h[0..=31];
732    let master_private_key = left;
733    let master_private_key_hex = encode_hex(master_private_key);
734    let right = &h[32..];
735    let master_chain_code = right;
736
737    // How do I get master public key:
738    // https://learnmeabitcoin.com/technical/extended-keys
739    // https://learnmeabitcoin.com/technical/hd-wallets
740    let master_public_key = get_compressed_public_key_from_private_key(&master_private_key_hex);
741    let keys = MasterKeys {
742        public_key_hex: master_public_key,
743        private_key_hex: master_private_key_hex,
744        chain_code_hex: encode_hex(master_chain_code),
745    };
746    keys
747}
748fn get_bip32_root_key_from_seed(bip39_seed: &String, network: Network, bip: Bip) -> String {
749    let master_keys = get_master_keys_from_seed(&bip39_seed.to_string());
750    let serialized_extended_master_keys = master_keys.serialize(network, bip);
751
752    let master_xprv = serialized_extended_master_keys.xpriv;
753    master_xprv
754}
755fn get_bip32_root_key_from_master_keys(
756    master_keys: &MasterKeys,
757    network: Network,
758    bip: Bip,
759) -> String {
760    let serialized_extended_master_keys = master_keys.serialize(network, bip);
761
762    let master_xprv = serialized_extended_master_keys.xpriv;
763    master_xprv
764}
765fn get_bip32_extended_keys_from_derivation_path(
766    derivation_path: &String,
767    master_keys: &Keys,
768    network: Network,
769    bip: Bip,
770) -> SerializedExtendedKeys {
771    let parent_deviation_path = get_parent_derivation_path(derivation_path);
772    let derivation_child = get_child_index_from_derivation_path(derivation_path);
773    let derivation_child_index = match derivation_child {
774        DerivationChild::NonHardened(child_index) => child_index,
775        DerivationChild::Hardened(child_index) => child_index,
776    };
777    let found_child =
778        get_child_key_from_derivation_path(derivation_path.to_string(), master_keys.clone());
779    let parent_keys =
780        get_child_key_from_derivation_path(parent_deviation_path, master_keys.clone());
781    let depth = get_depth_from_derivation_path(&derivation_path.to_string());
782
783    let parent_public_key_hex = match parent_keys {
784        Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex,
785        Keys::Master(master_keys) => master_keys.public_key_hex,
786    };
787
788    let bip32_extended_keys = match found_child {
789        Keys::NonMaster(non_master_keys) => non_master_keys.serialize(
790            parent_public_key_hex,
791            depth,
792            derivation_child_index,
793            network,
794            bip,
795        ),
796        Keys::Master(master_keys) => master_keys.serialize(network, bip),
797    };
798
799    bip32_extended_keys
800}
801
802fn get_derived_addresses_for_derivation_path(
803    derivation_path: &String,
804    master_keys: &MasterKeys,
805    child_count: i32,
806    should_use_hardened_addresses: bool,
807) -> HashMap<String, Keys> {
808    let found_children = get_children_keys_from_derivation_path(
809        &derivation_path,
810        Keys::Master(master_keys.clone()),
811        child_count,
812        should_use_hardened_addresses,
813    );
814    let mut found_children_with_full_derivation_path_as_key: HashMap<String, Keys> = HashMap::new();
815    for (key, value) in found_children {
816        let full_derivation_path_with_child = format!("{}/{}", derivation_path, key);
817        found_children_with_full_derivation_path_as_key
818            .insert(full_derivation_path_with_child, value);
819    }
820    found_children_with_full_derivation_path_as_key
821}
822
823fn decode_serialized_extended_key(extended_key_serialized: &str) -> DecodedExtendedKeySerialized {
824    // Source (to check work): http://bip32.org/
825    let decoded_result = from_check(extended_key_serialized).unwrap();
826    let index_of_last_byte_of_version = 3;
827    let version_bytes = decoded_result
828        .get(0..=index_of_last_byte_of_version)
829        .unwrap();
830    let version_hex = encode_hex(version_bytes);
831    let (network, is_public) = match version_hex.as_str() {
832        // bip32 version keys
833        "0488b21e" => (Network::Mainnet, true),
834        "043587cf" => (Network::Testnet, true),
835        "0488ade4" => (Network::Mainnet, false),
836        "04358394" => (Network::Testnet, false),
837        // bip49 version keys
838        "049d7cb2" => (Network::Mainnet, true),
839        "044a5262" => (Network::Testnet, true),
840        "049d7878" => (Network::Mainnet, false),
841        "044a4e28" => (Network::Testnet, false),
842        // bip84 version keys
843        "04b24746" => (Network::Mainnet, true),
844        "045f1cf6" => (Network::Testnet, true),
845        "04b2430c" => (Network::Mainnet, false),
846        "045f18bc" => (Network::Testnet, false),
847        _ => panic!("Version  not recognized: {}", version_hex),
848    };
849
850    // Check: https://coinb.in/#verify
851    // Source:https://en.bitcoin.it/wiki/Wallet_import_format
852    // 1. decode the base58check
853    // private key is 64 characters long, and each byte is 2 characters (4 bytes each).
854    let index_where_private_key_starts = decoded_result.len() - (64 / 2);
855    let index_where_chain_code_starts = index_where_private_key_starts - (64 / 2) - 1;
856    let key_bytes = decoded_result
857        .get(index_where_private_key_starts..)
858        .unwrap();
859    // There is a byte between chain code and private key, that's why we subtract 1 here from the
860    // index where the private key starts
861    let chain_code_bytes = decoded_result
862        .get(
863            index_where_chain_code_starts
864                ..(index_where_private_key_starts - (if is_public { 0 } else { 1 })),
865        )
866        .unwrap();
867    let key_hex = encode_hex(&key_bytes);
868    let chain_code_hex = encode_hex(&chain_code_bytes);
869
870    let depth_fingerprint_child_index_bytes = decoded_result
871        .get((index_of_last_byte_of_version + 1)..index_where_chain_code_starts)
872        .unwrap();
873    let depth_fingerprint_child_index_hex = encode_hex(&depth_fingerprint_child_index_bytes);
874    let depth_byte = depth_fingerprint_child_index_bytes.get(0).unwrap().clone();
875    let depth_hex = encode_hex(&[depth_byte]);
876    let depth_decimal = convert_hex_to_decimal(&depth_hex).unwrap() as u8;
877    let depth = depth_fingerprint_child_index_bytes.get(0..=1).unwrap();
878    let depth_hex = encode_hex(&depth);
879
880    let parent_fingerprint_bytes = depth_fingerprint_child_index_bytes.get(1..=4).unwrap();
881    let parent_fingerprint_hex = encode_hex(parent_fingerprint_bytes);
882
883    let child_index_bytes = depth_fingerprint_child_index_bytes.get(5..).unwrap();
884    let child_index_hex = encode_hex(&child_index_bytes);
885    let child_index_decimal = convert_hex_to_decimal(&child_index_hex).unwrap() as u32;
886    if is_public {
887        DecodedExtendedKeySerialized::PublicKey(DecodedExtendedSerializedPublicKey {
888            version_hex,
889            network,
890            depth_fingerprint_child_index_hex,
891            depth: depth_decimal,
892            parent_fingerprint: parent_fingerprint_hex,
893            child_index: child_index_decimal,
894            chain_code_hex,
895            public_key_hex_uncompressed: key_hex,
896        })
897    } else {
898        DecodedExtendedKeySerialized::PrivateKey(DecodedExtendedSerializedPrivateKey {
899            version_hex,
900            network,
901            depth_fingerprint_child_index_hex,
902            depth: depth_decimal,
903            parent_fingerprint: parent_fingerprint_hex,
904            child_index: child_index_decimal,
905            chain_code_hex,
906            private_key_hex: key_hex.clone(),
907            wif_compressed: get_wif_from_private_key(&key_hex, network, true),
908            wif_uncompressed: get_wif_from_private_key(&key_hex, network, false),
909            public_key_hex_uncompressed: get_public_key_from_private_key(&key_hex, false),
910            public_key_hex_compressed: get_public_key_from_private_key(&key_hex, true),
911        })
912    }
913}
914fn get_master_keys_from_serialized_extended_private_master_key(
915    serialized_extended_private_key: &String,
916) -> MasterKeys {
917    let decoded_serialized_extended_key =
918        decode_serialized_extended_key(serialized_extended_private_key);
919    let decoded_xpriv_keys = match decoded_serialized_extended_key.clone() {
920        DecodedExtendedKeySerialized::PrivateKey(decoded_extended_serialized_private_key) => {
921            decoded_extended_serialized_private_key
922        }
923        DecodedExtendedKeySerialized::PublicKey(_) => panic!("shouldn happen"),
924    };
925    if decoded_xpriv_keys.depth == 0 && decoded_xpriv_keys.child_index == 0 {
926        let master_keys = MasterKeys {
927            private_key_hex: decoded_xpriv_keys.private_key_hex,
928            public_key_hex: decoded_xpriv_keys.public_key_hex_uncompressed,
929            chain_code_hex: decoded_xpriv_keys.chain_code_hex,
930        };
931        master_keys
932    } else {
933        panic!("must pass a master extended key here, not a child");
934    }
935}
936// Just a wapper for more specific naming
937fn get_master_keys_from_bip32_root_key(bip32_root_key: &String) -> MasterKeys {
938    get_master_keys_from_serialized_extended_private_master_key(bip32_root_key)
939}
940fn get_bip32_derived_addresses(
941    bip32_derivation_path: &String,
942    master_keys: &MasterKeys,
943    children_count: i32,
944    should_harden: bool,
945) -> HashMap<String, Keys> {
946    // Notice: multiple wallets use different derivation paths. Source: https://iancoleman.io/bip39/
947    // - Bitcoincore
948    // - Blockchain.info
949    // - Multibit
950    // - Coinmomi
951    // // Todo: Maybe we should have presets for different vendors?
952    let found_children = get_derived_addresses_for_derivation_path(
953        &bip32_derivation_path,
954        master_keys,
955        children_count,
956        should_harden,
957    );
958    found_children
959}
960
961#[derive(Debug, Clone)]
962pub struct DerivedAdresses {
963    pub external: HashMap<String, Keys>,
964    pub internal: HashMap<String, Keys>,
965}
966
967fn get_derived_addresses_from_5_levels(
968    purpose: u8,
969    cointype: i32,
970    account: i32,
971    // Remove
972    should_include_change_addresses: bool,
973    master_keys: &MasterKeys,
974    children_count: i32,
975    should_harden: bool,
976) -> DerivedAdresses {
977    let bip44_derivation_path_for_external_chain =
978        format!("m/{}'/{}'/{}'/0", purpose, cointype, account.to_string()).to_string(); // Must use with P2PKH
979
980    // internal chain is also known as a change address
981    let bip44_derivation_path_for_internal_chain =
982        format!("m/{}'/{}'/{}'/1", purpose, cointype, account.to_string()).to_string(); // Must use with P2PKH
983
984    // Notice: multiple wallets use different derivation paths. Source: https://iancoleman.io/bip39/
985    // - Bitcoincore
986    // - Blockchain.info
987    // - Multibit
988    // - Coinmomi
989    // // Todo: Maybe we should have presets for different vendors?
990    let found_children_for_external_chain = get_derived_addresses_for_derivation_path(
991        &bip44_derivation_path_for_external_chain,
992        &master_keys,
993        children_count,
994        should_harden,
995    );
996
997    let found_children_for_internal_chain = get_derived_addresses_for_derivation_path(
998        &bip44_derivation_path_for_internal_chain,
999        &master_keys,
1000        children_count,
1001        should_harden,
1002    );
1003
1004    DerivedAdresses {
1005        internal: found_children_for_internal_chain,
1006        external: found_children_for_external_chain,
1007    }
1008}
1009
1010// TODO: Create a function to get the Account Extended private/public keys and the bip32 extended
1011// private/public keys. See BIP44 section of: https://iancoleman.io/bip39/
1012fn get_bip44_derived_addresses(
1013    coin_type: i32,
1014    account: i32,
1015    should_include_change_addresses: bool,
1016    master_keys: &MasterKeys,
1017    children_count: i32,
1018    should_harden: bool,
1019) -> DerivedAdresses {
1020    // Source: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
1021    // External chain is used for addresses that are meant to be visible outside of the wallet (e.g. for receiving payments). Internal chain is used for addresses which are not meant to be visible outside of the wallet and is used for return transaction change.
1022    // internal chain is also known as a change address
1023    let purpose = 44;
1024    get_derived_addresses_from_5_levels(
1025        purpose,
1026        coin_type,
1027        account,
1028        should_include_change_addresses,
1029        master_keys,
1030        children_count,
1031        should_harden,
1032    )
1033}
1034// TODO: Create a function to get the Account Extended private/public keys and the bip32 extended
1035// private/public keys. See BIP49 section of: https://iancoleman.io/bip39/
1036fn get_bip49_derived_addresses(
1037    coin_type: i32,
1038    account: i32,
1039    should_include_change_addresses: bool,
1040    master_keys: &MasterKeys,
1041    children_count: i32,
1042    should_harden: bool,
1043) -> DerivedAdresses {
1044    // Source: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
1045    // External chain is used for addresses that are meant to be visible outside of the wallet (e.g. for receiving payments). Internal chain is used for addresses which are not meant to be visible outside of the wallet and is used for return transaction change.
1046    // internal chain is also known as a change address
1047    let purpose = 49;
1048    get_derived_addresses_from_5_levels(
1049        purpose,
1050        coin_type,
1051        account,
1052        should_include_change_addresses,
1053        master_keys,
1054        children_count,
1055        should_harden,
1056    )
1057}
1058// TODO: Create a function to get the Account Extended private/public keys and the bip32 extended
1059// private/public keys. See BIP49 section of: https://iancoleman.io/bip39/
1060fn get_bip84_derived_addresses(
1061    coin_type: i32,
1062    account: i32,
1063    should_include_change_addresses: bool,
1064    master_keys: &MasterKeys,
1065    children_count: i32,
1066    should_harden: bool,
1067) -> DerivedAdresses {
1068    // Source: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
1069    // External chain is used for addresses that are meant to be visible outside of the wallet (e.g. for receiving payments). Internal chain is used for addresses which are not meant to be visible outside of the wallet and is used for return transaction change.
1070    // internal chain is also known as a change address
1071    let purpose = 84;
1072    get_derived_addresses_from_5_levels(
1073        purpose,
1074        coin_type,
1075        account,
1076        should_include_change_addresses,
1077        master_keys,
1078        children_count,
1079        should_harden,
1080    )
1081}
1082// TODO: Create a function to get the Account Extended private/public keys and the bip32 extended
1083// private/public keys. See BIP49 section of: https://iancoleman.io/bip39/
1084fn get_bip86_derived_addresses(
1085    coin_type: i32,
1086    account: i32,
1087    should_include_change_addresses: bool,
1088    master_keys: &MasterKeys,
1089    children_count: i32,
1090    should_harden: bool,
1091) -> DerivedAdresses {
1092    // Source: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
1093    // External chain is used for addresses that are meant to be visible outside of the wallet (e.g. for receiving payments). Internal chain is used for addresses which are not meant to be visible outside of the wallet and is used for return transaction change.
1094    // internal chain is also known as a change address
1095    let purpose = 86;
1096    get_derived_addresses_from_5_levels(
1097        purpose,
1098        coin_type,
1099        account,
1100        should_include_change_addresses,
1101        master_keys,
1102        children_count,
1103        should_harden,
1104    )
1105}
1106
1107#[derive(Debug)]
1108struct Bip44DerivationPathInfo {
1109    account_extended_private_key: String,
1110    account_extended_public_key: String,
1111}
1112fn get_bip44_derivation_path_info(
1113    cointype: i32,
1114    account: i32,
1115    master_keys: &MasterKeys,
1116    network: Network,
1117) -> Bip44DerivationPathInfo {
1118    let purpose = 44;
1119    let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, cointype, account);
1120    let bip32_extended_keys_for_account = get_bip32_extended_keys_from_derivation_path(
1121        &account_derivation_path.to_string(),
1122        &Keys::Master(master_keys.clone()),
1123        network,
1124        Bip::Bip44,
1125    );
1126
1127    Bip44DerivationPathInfo {
1128        account_extended_private_key: bip32_extended_keys_for_account.xpriv,
1129        account_extended_public_key: bip32_extended_keys_for_account.xpub,
1130    }
1131}
1132#[derive(Debug)]
1133struct Bip49DerivationPathInfo {
1134    account_extended_private_key: String,
1135    account_extended_public_key: String,
1136}
1137fn get_bip49_derivation_path_info(
1138    coin_type: i32,
1139    account: i32,
1140    master_keys: &MasterKeys,
1141    network: Network,
1142) -> Bip49DerivationPathInfo {
1143    let purpose = 49;
1144    let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1145    let bip32_extended_keys_for_account = get_bip32_extended_keys_from_derivation_path(
1146        &account_derivation_path.to_string(),
1147        &Keys::Master(master_keys.clone()),
1148        network,
1149        Bip::Bip49,
1150    );
1151
1152    Bip49DerivationPathInfo {
1153        account_extended_private_key: bip32_extended_keys_for_account.xpriv,
1154        account_extended_public_key: bip32_extended_keys_for_account.xpub,
1155    }
1156}
1157#[derive(Debug)]
1158struct Bip84DerivationPathInfo {
1159    account_extended_private_key: String,
1160    account_extended_public_key: String,
1161}
1162fn get_bip84_derivation_path_info(
1163    coin_type: i32,
1164    account: i32,
1165    master_keys: &MasterKeys,
1166    network: Network,
1167) -> Bip84DerivationPathInfo {
1168    let purpose = 84;
1169    let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1170    let bip32_extended_keys_for_account = get_bip32_extended_keys_from_derivation_path(
1171        &account_derivation_path.to_string(),
1172        &Keys::Master(master_keys.clone()),
1173        network,
1174        Bip::Bip84,
1175    );
1176
1177    Bip84DerivationPathInfo {
1178        account_extended_private_key: bip32_extended_keys_for_account.xpriv,
1179        account_extended_public_key: bip32_extended_keys_for_account.xpub,
1180    }
1181}
1182#[derive(Debug)]
1183struct Bip86DerivationPathInfo {
1184    account_extended_private_key: String,
1185    account_extended_public_key: String,
1186}
1187fn get_bip86_derivation_path_info(
1188    coin_type: i32,
1189    account: i32,
1190    master_keys: &MasterKeys,
1191    network: Network,
1192) -> Bip86DerivationPathInfo {
1193    let purpose = 86;
1194    let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1195    let bip32_extended_keys_for_account = get_bip32_extended_keys_from_derivation_path(
1196        &account_derivation_path.to_string(),
1197        &Keys::Master(master_keys.clone()),
1198        network,
1199        Bip::Bip84,
1200    );
1201
1202    Bip86DerivationPathInfo {
1203        account_extended_private_key: bip32_extended_keys_for_account.xpriv,
1204        account_extended_public_key: bip32_extended_keys_for_account.xpub,
1205    }
1206}
1207
1208#[derive(Debug)]
1209pub struct HDWalletBip32 {
1210    pub network: Network,
1211    pub bip39_seed: String,
1212    pub master_keys: MasterKeys,
1213    pub bip32_root_key: String,
1214    pub bip32_root_pub_key: String,
1215    pub bip32_derivation_path: String,
1216    pub bip32_extended_private_key: String,
1217    pub bip32_extended_public_key: String,
1218    pub master_fingerprint: String,
1219    pub derived_addresses: HashMap<String, Keys>,
1220}
1221impl HDWalletBip32 {
1222    pub fn pretty_print_derived_addressed(
1223        &self,
1224        network: Network,
1225        address_type: AddressType,
1226    ) -> () {
1227        for (key, value) in self.derived_addresses.clone() {
1228            let should_compress = true;
1229            let public_key_hex = match &value {
1230                Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1231                Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1232            };
1233            let address = value.get_address(network, address_type);
1234            println!(
1235                "{} {}  {}   {}    {}      {}",
1236                key,
1237                address,
1238                get_public_key_hash_from_address(&address),
1239                get_public_key_hash_from_public_key(&public_key_hex),
1240                public_key_hex,
1241                value.get_wif(network, should_compress)
1242            )
1243        }
1244    }
1245}
1246
1247pub fn generate_bip32_hd_wallet_from_mnemonic_words(
1248    mnemonic_words: Vec<String>,
1249    password: Option<String>,
1250    derivation_path: String,
1251    children_count: i32,
1252    should_harden: bool,
1253    network: Network,
1254) -> HDWalletBip32 {
1255    let bip = Bip::Bip32;
1256    let passphrase = match password {
1257        Some(password) => password,
1258        None => "".to_string(),
1259    };
1260    let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1261    let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1262    // Notice we have two ways to get the master keys: -------------------------
1263    // 1) using seed
1264    let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1265    // 2) using bip32 root key (extended private master key)
1266    let master_keys_generated_from_bip32_root_key =
1267        get_master_keys_from_bip32_root_key(&bip32_root_key);
1268    let master_keys = master_keys_generated_from_seed;
1269    // ---------------------------------------------------------------------------
1270    // Can also get bip32 root key from masterkeys;
1271    let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1272    let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1273    //
1274    let serialized_extended_master_keys = master_keys.serialize(network, bip);
1275
1276    let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1277
1278    let bip32_extended_keys = get_bip32_extended_keys_from_derivation_path(
1279        &derivation_path,
1280        &Keys::Master(master_keys.clone()),
1281        network,
1282        bip,
1283    );
1284    let xpriv = &bip32_extended_keys.xpriv;
1285    let xpub = &bip32_extended_keys.xpub;
1286
1287    let found_children = get_bip32_derived_addresses(
1288        &derivation_path,
1289        &master_keys,
1290        children_count,
1291        should_harden,
1292    );
1293
1294    HDWalletBip32 {
1295        network,
1296        master_keys,
1297        bip39_seed,
1298        bip32_root_key,
1299        bip32_root_pub_key,
1300        master_fingerprint,
1301        bip32_derivation_path: derivation_path,
1302        bip32_extended_private_key: xpriv.to_string(),
1303        bip32_extended_public_key: xpub.to_string(),
1304        derived_addresses: found_children,
1305    }
1306}
1307#[derive(Debug)]
1308pub struct HDWalletBip44 {
1309    pub network: Network,
1310    pub bip39_seed: String,
1311    pub master_keys: MasterKeys,
1312    pub bip32_root_key: String,
1313    pub bip32_root_pub_key: String,
1314    pub master_fingerprint: String,
1315    pub purpose: i32,
1316    pub coin_type: i32,
1317    pub account: i32,
1318    // internal: bool,
1319    pub account_derivation_path: String,
1320    pub account_extended_private_key: String,
1321    pub account_extended_public_key: String,
1322    pub derivation_path_external: String,
1323    pub bip32_extended_private_key_for_external: String,
1324    pub bip32_extended_public_key_for_external: String,
1325    pub derivation_path_internal: String,
1326    pub bip32_extended_private_key_for_internal: String,
1327    pub bip32_extended_public_key_for_internal: String,
1328    pub derived_addresses: DerivedAdresses,
1329}
1330impl HDWalletBip44 {
1331    pub fn pretty_print_derived_addressed(&self, network: Network) -> () {
1332        let address_type = AddressType::P2PKH;
1333        for (key, value) in self.derived_addresses.external.clone() {
1334            let should_compress = true;
1335            let public_key_hex = match &value {
1336                Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1337                Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1338            };
1339            let address = value.get_address(network, address_type);
1340            println!(
1341                "{} {}  {}   {}    {}      {}",
1342                key,
1343                address,
1344                get_public_key_hash_from_address(&address),
1345                get_public_key_hash_from_public_key(&public_key_hex),
1346                public_key_hex,
1347                value.get_wif(network, should_compress)
1348            )
1349        }
1350        for (key, value) in self.derived_addresses.internal.clone() {
1351            let should_compress = true;
1352            let public_key_hex = match &value {
1353                Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1354                Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1355            };
1356            let address = value.get_address(network, address_type);
1357            println!(
1358                "{} {}  {}   {}    {}      {}",
1359                key,
1360                address,
1361                get_public_key_hash_from_address(&address),
1362                get_public_key_hash_from_public_key(&public_key_hex),
1363                public_key_hex,
1364                value.get_wif(network, should_compress)
1365            )
1366        }
1367    }
1368}
1369pub fn generate_bip44_hd_wallet_from_mnemonic_words(
1370    mnemonic_words: Vec<String>,
1371    password: Option<String>,
1372    coin_type: i32,
1373    account: i32,
1374    children_count: i32,
1375    should_harden: bool,
1376    network: Network,
1377) -> HDWalletBip44 {
1378    let bip = Bip::Bip44;
1379    let purpose = 44;
1380
1381    let passphrase = match password {
1382        Some(password) => password,
1383        None => "".to_string(),
1384    };
1385    let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1386    let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1387    // Notice we have two ways to get the master keys: -------------------------
1388    // 1) using seed
1389    let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1390    // 2) using bip32 root key (extended private master key)
1391    let master_keys_generated_from_bip32_root_key =
1392        get_master_keys_from_bip32_root_key(&bip32_root_key);
1393    let master_keys = master_keys_generated_from_seed;
1394    // ---------------------------------------------------------------------------
1395    // Can also get bip32 root key from masterkeys;
1396    let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1397    //
1398    let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1399    let serialized_extended_master_keys = master_keys.serialize(network, bip);
1400
1401    let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1402    let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1403    let derivation_path_external = format!("{}/0", account_derivation_path);
1404    let bip32_extended_keys_for_external = get_bip32_extended_keys_from_derivation_path(
1405        &derivation_path_external,
1406        &Keys::Master(master_keys.clone()),
1407        network,
1408        bip,
1409    );
1410    let bip32_extended_private_key_for_external = bip32_extended_keys_for_external.xpriv;
1411    let bip32_extended_public_key_for_external = bip32_extended_keys_for_external.xpub;
1412    // Change
1413    let derivation_path_internal = format!("{}/1", account_derivation_path);
1414    let bip32_extended_keys_for_internal = get_bip32_extended_keys_from_derivation_path(
1415        &derivation_path_internal,
1416        &Keys::Master(master_keys.clone()),
1417        network,
1418        bip,
1419    );
1420    let bip32_extended_private_key_for_internal = bip32_extended_keys_for_internal.xpriv;
1421    let bip32_extended_public_key_for_internal = bip32_extended_keys_for_internal.xpub;
1422
1423    let should_include_change_addresses = true;
1424    let found_children = get_bip44_derived_addresses(
1425        coin_type,
1426        account,
1427        should_include_change_addresses,
1428        &master_keys,
1429        children_count,
1430        should_harden,
1431    );
1432    let bip44_derivation_path_info =
1433        get_bip44_derivation_path_info(coin_type, account, &master_keys.clone(), network);
1434    // println!("{:#?}", bip84_derivation_path_info);
1435
1436    HDWalletBip44 {
1437        network,
1438        bip39_seed,
1439        master_keys,
1440        bip32_root_key,
1441        bip32_root_pub_key,
1442        master_fingerprint,
1443        purpose,
1444        coin_type,
1445        account,
1446        // internal: bool,
1447        account_derivation_path,
1448        account_extended_private_key: bip44_derivation_path_info.account_extended_private_key,
1449        account_extended_public_key: bip44_derivation_path_info.account_extended_public_key,
1450        derivation_path_external,
1451        bip32_extended_private_key_for_external,
1452        bip32_extended_public_key_for_external,
1453        derivation_path_internal,
1454        bip32_extended_private_key_for_internal,
1455        bip32_extended_public_key_for_internal,
1456        derived_addresses: found_children,
1457    }
1458}
1459#[derive(Debug)]
1460pub struct HDWalletBip49 {
1461    pub network: Network,
1462    pub master_keys: MasterKeys,
1463    pub bip39_seed: String,
1464    pub bip32_root_key: String,
1465    pub bip32_root_pub_key: String,
1466    pub master_fingerprint: String,
1467    pub purpose: i32,
1468    pub coin_type: i32,
1469    pub account: i32,
1470    // internal: bool,
1471    pub account_derivation_path: String,
1472    pub account_extended_private_key: String,
1473    pub account_extended_public_key: String,
1474    pub derivation_path_external: String,
1475    pub bip32_extended_private_key_for_external: String,
1476    pub bip32_extended_public_key_for_external: String,
1477    pub derivation_path_internal: String,
1478    pub bip32_extended_private_key_for_internal: String,
1479    pub bip32_extended_public_key_for_internal: String,
1480    pub derived_addresses: DerivedAdresses,
1481}
1482impl HDWalletBip49 {
1483    pub fn pretty_print_derived_addressed(&self, network: Network) -> () {
1484        let address_type = AddressType::P2SH;
1485        for (key, value) in self.derived_addresses.external.clone() {
1486            let should_compress = true;
1487            let public_key_hex = match &value {
1488                Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1489                Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1490            };
1491            let address = value.get_address(network, address_type);
1492            println!(
1493                "{} {}  {}   {}      {}",
1494                key,
1495                address,
1496                //get_public_key_hash_from_address(&address),
1497                get_public_key_hash_from_public_key(&public_key_hex),
1498                public_key_hex,
1499                value.get_wif(network, should_compress)
1500            )
1501        }
1502        for (key, value) in self.derived_addresses.internal.clone() {
1503            let should_compress = true;
1504            let public_key_hex = match &value {
1505                Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1506                Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1507            };
1508            let address = value.get_address(network, address_type);
1509            println!(
1510                "{} {}  {}   {}      {}",
1511                key,
1512                address,
1513                //get_public_key_hash_from_address(&address),
1514                get_public_key_hash_from_public_key(&public_key_hex),
1515                public_key_hex,
1516                value.get_wif(network, should_compress)
1517            )
1518        }
1519    }
1520}
1521pub fn generate_bip49_hd_wallet_from_mnemonic_words(
1522    mnemonic_words: Vec<String>,
1523    password: Option<String>,
1524    coin_type: i32,
1525    account: i32,
1526    children_count: i32,
1527    should_harden: bool,
1528    network: Network,
1529) -> HDWalletBip49 {
1530    let bip = Bip::Bip49;
1531    let purpose = 49;
1532
1533    let passphrase = match password {
1534        Some(password) => password,
1535        None => "".to_string(),
1536    };
1537    let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1538    let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1539    // Notice we have two ways to get the master keys: -------------------------
1540    // 1) using seed
1541    let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1542    // 2) using bip32 root key (extended private master key)
1543    let master_keys_generated_from_bip32_root_key =
1544        get_master_keys_from_bip32_root_key(&bip32_root_key);
1545    let master_keys = master_keys_generated_from_seed;
1546    // ---------------------------------------------------------------------------
1547    // Can also get bip32 root key from masterkeys;
1548    let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1549    //
1550    let serialized_extended_master_keys = master_keys.serialize(network, bip);
1551
1552    let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1553    let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1554
1555    let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1556    let derivation_path_external = format!("{}/0", account_derivation_path);
1557    let bip32_extended_keys_for_external = get_bip32_extended_keys_from_derivation_path(
1558        &derivation_path_external,
1559        &Keys::Master(master_keys.clone()),
1560        network,
1561        bip,
1562    );
1563    let bip32_extended_private_key_for_external = bip32_extended_keys_for_external.xpriv;
1564    let bip32_extended_public_key_for_external = bip32_extended_keys_for_external.xpub;
1565    // Change
1566    let derivation_path_internal = format!("{}/1", account_derivation_path);
1567    let bip32_extended_keys_for_internal = get_bip32_extended_keys_from_derivation_path(
1568        &derivation_path_internal,
1569        &Keys::Master(master_keys.clone()),
1570        network,
1571        bip,
1572    );
1573    let bip32_extended_private_key_for_internal = bip32_extended_keys_for_internal.xpriv;
1574    let bip32_extended_public_key_for_internal = bip32_extended_keys_for_internal.xpub;
1575
1576    let should_include_change_addresses = true;
1577    let found_children = get_bip49_derived_addresses(
1578        coin_type,
1579        account,
1580        should_include_change_addresses,
1581        &master_keys,
1582        children_count,
1583        should_harden,
1584    );
1585    let bip49_derivation_path_info =
1586        get_bip49_derivation_path_info(coin_type, account, &master_keys.clone(), network);
1587
1588    HDWalletBip49 {
1589        network,
1590        bip39_seed,
1591        master_keys,
1592        bip32_root_key,
1593        bip32_root_pub_key,
1594        master_fingerprint,
1595        purpose,
1596        coin_type,
1597        account,
1598        // internal: bool,
1599        account_derivation_path,
1600        account_extended_private_key: bip49_derivation_path_info.account_extended_private_key,
1601        account_extended_public_key: bip49_derivation_path_info.account_extended_public_key,
1602        derivation_path_external,
1603        bip32_extended_private_key_for_external,
1604        bip32_extended_public_key_for_external,
1605        derivation_path_internal,
1606        bip32_extended_private_key_for_internal,
1607        bip32_extended_public_key_for_internal,
1608        derived_addresses: found_children,
1609    }
1610}
1611#[derive(Debug)]
1612pub struct HDWalletBip84 {
1613    pub network: Network,
1614    pub bip39_seed: String,
1615    pub master_keys: MasterKeys,
1616    pub bip32_root_key: String,
1617    pub bip32_root_pub_key: String,
1618    pub master_fingerprint: String,
1619    pub purpose: i32,
1620    pub coin_type: i32,
1621    pub account: i32,
1622    // internal: bool,
1623    pub account_derivation_path: String,
1624    pub account_extended_private_key: String,
1625    pub account_extended_public_key: String,
1626    pub derivation_path_external: String,
1627    pub bip32_extended_private_key_for_external: String,
1628    pub bip32_extended_public_key_for_external: String,
1629    pub derivation_path_internal: String,
1630    pub bip32_extended_private_key_for_internal: String,
1631    pub bip32_extended_public_key_for_internal: String,
1632    pub derived_addresses: DerivedAdresses,
1633}
1634impl HDWalletBip84 {
1635    pub fn pretty_print_derived_addressed(&self, network: Network) -> () {
1636        let address_type = AddressType::P2WPKH;
1637        for (key, value) in self.derived_addresses.external.clone() {
1638            let should_compress = true;
1639            let public_key_hex = match &value {
1640                Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1641                Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1642            };
1643            let address = value.get_address(network, address_type);
1644            println!(
1645                "{} {}  {}   {}    {}      {}",
1646                key,
1647                address,
1648                get_public_key_hash_from_address(&address),
1649                get_public_key_hash_from_public_key(&public_key_hex),
1650                public_key_hex,
1651                value.get_wif(network, should_compress)
1652            )
1653        }
1654        for (key, value) in self.derived_addresses.internal.clone() {
1655            let should_compress = true;
1656            let public_key_hex = match &value {
1657                Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1658                Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1659            };
1660            let address = value.get_address(network, address_type);
1661            println!(
1662                "{} {}  {}   {}    {}      {}",
1663                key,
1664                address,
1665                get_public_key_hash_from_address(&address),
1666                get_public_key_hash_from_public_key(&public_key_hex),
1667                public_key_hex,
1668                value.get_wif(network, should_compress)
1669            )
1670        }
1671    }
1672}
1673pub fn generate_bip84_hd_wallet_from_mnemonic_words(
1674    mnemonic_words: Vec<String>,
1675    password: Option<String>,
1676    coin_type: i32,
1677    account: i32,
1678    children_count: i32,
1679    should_harden: bool,
1680    network: Network,
1681) -> HDWalletBip84 {
1682    let bip = Bip::Bip84;
1683    let purpose = 84;
1684
1685    let passphrase = match password {
1686        Some(password) => password,
1687        None => "".to_string(),
1688    };
1689    let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1690    let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1691    // Notice we have two ways to get the master keys: -------------------------
1692    // 1) using seed
1693    let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1694    // 2) using bip32 root key (extended private master key)
1695    let master_keys_generated_from_bip32_root_key =
1696        get_master_keys_from_bip32_root_key(&bip32_root_key);
1697    let master_keys = master_keys_generated_from_seed;
1698    // ---------------------------------------------------------------------------
1699    // Can also get bip32 root key from masterkeys;
1700    let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1701    //
1702    let serialized_extended_master_keys = master_keys.serialize(network, bip);
1703    let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1704
1705    let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1706    let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1707    let derivation_path_external = format!("{}/0", account_derivation_path);
1708    let bip32_extended_keys_for_external = get_bip32_extended_keys_from_derivation_path(
1709        &derivation_path_external,
1710        &Keys::Master(master_keys.clone()),
1711        network,
1712        bip,
1713    );
1714    let bip32_extended_private_key_for_external = bip32_extended_keys_for_external.xpriv;
1715    let bip32_extended_public_key_for_external = bip32_extended_keys_for_external.xpub;
1716    // Change
1717    let derivation_path_internal = format!("{}/1", account_derivation_path);
1718    let bip32_extended_keys_for_internal = get_bip32_extended_keys_from_derivation_path(
1719        &derivation_path_internal,
1720        &Keys::Master(master_keys.clone()),
1721        network,
1722        bip,
1723    );
1724    let bip32_extended_private_key_for_internal = bip32_extended_keys_for_internal.xpriv;
1725    let bip32_extended_public_key_for_internal = bip32_extended_keys_for_internal.xpub;
1726
1727    let should_include_change_addresses = true;
1728    let found_children = get_bip84_derived_addresses(
1729        coin_type,
1730        account,
1731        should_include_change_addresses,
1732        &master_keys,
1733        children_count,
1734        should_harden,
1735    );
1736    let bip84_derivation_path_info =
1737        get_bip84_derivation_path_info(coin_type, account, &master_keys.clone(), network);
1738
1739    HDWalletBip84 {
1740        network,
1741        bip39_seed,
1742        master_keys,
1743        bip32_root_key,
1744        bip32_root_pub_key,
1745        master_fingerprint,
1746        purpose,
1747        coin_type,
1748        account,
1749        // internal: bool,
1750        account_derivation_path,
1751        account_extended_private_key: bip84_derivation_path_info.account_extended_private_key,
1752        account_extended_public_key: bip84_derivation_path_info.account_extended_public_key,
1753        derivation_path_external,
1754        bip32_extended_private_key_for_external,
1755        bip32_extended_public_key_for_external,
1756        derivation_path_internal,
1757        bip32_extended_private_key_for_internal,
1758        bip32_extended_public_key_for_internal,
1759        derived_addresses: found_children,
1760    }
1761}
1762#[derive(Debug)]
1763pub struct HDWalletBip86 {
1764    pub network: Network,
1765    pub bip39_seed: String,
1766    pub master_keys: MasterKeys,
1767    pub bip32_root_key: String,
1768    pub bip32_root_pub_key: String,
1769    pub master_fingerprint: String,
1770    pub purpose: i32,
1771    pub coin_type: i32,
1772    pub account: i32,
1773    // internal: bool,
1774    pub account_derivation_path: String,
1775    pub account_extended_private_key: String,
1776    pub account_extended_public_key: String,
1777    pub derivation_path_external: String,
1778    pub bip32_extended_private_key_for_external: String,
1779    pub bip32_extended_public_key_for_external: String,
1780    pub derivation_path_internal: String,
1781    pub bip32_extended_private_key_for_internal: String,
1782    pub bip32_extended_public_key_for_internal: String,
1783    pub derived_addresses: DerivedAdresses,
1784}
1785impl HDWalletBip86 {
1786    pub fn pretty_print_derived_addressed(&self, network: Network) -> () {
1787        let address_type = AddressType::P2TR;
1788        for (key, value) in self.derived_addresses.internal.clone() {
1789            let should_compress = true;
1790            let public_key_hex = match &value {
1791                Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1792                Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1793            };
1794            let address = value.get_address(network, address_type);
1795            println!(
1796                "{} {}  {}    {}      {}",
1797                key,
1798                address,
1799                // get_public_key_hash_from_address(&address),
1800                get_public_key_hash_from_public_key(&public_key_hex),
1801                public_key_hex,
1802                value.get_wif(network, should_compress)
1803            )
1804        }
1805        for (key, value) in self.derived_addresses.external.clone() {
1806            let should_compress = true;
1807            let public_key_hex = match &value {
1808                Keys::NonMaster(non_master_keys) => non_master_keys.public_key_hex.clone(),
1809                Keys::Master(master_keys) => master_keys.public_key_hex.clone(),
1810            };
1811            let address = value.get_address(network, address_type);
1812            println!(
1813                "{} {}  {}    {}      {}",
1814                key,
1815                address,
1816                // get_public_key_hash_from_address(&address),
1817                get_public_key_hash_from_public_key(&public_key_hex),
1818                public_key_hex,
1819                value.get_wif(network, should_compress)
1820            )
1821        }
1822    }
1823}
1824pub fn generate_bip86_hd_wallet_from_mnemonic_words(
1825    mnemonic_words: Vec<String>,
1826    password: Option<String>,
1827    coin_type: i32,
1828    account: i32,
1829    children_count: i32,
1830    should_harden: bool,
1831    network: Network,
1832) -> HDWalletBip86 {
1833    let bip = Bip::Bip86;
1834    let purpose = 86;
1835
1836    let passphrase = match password {
1837        Some(password) => password,
1838        None => "".to_string(),
1839    };
1840    let bip39_seed = get_bip38_512_bit_private_key(mnemonic_words, Some(passphrase));
1841    let bip32_root_key = get_bip32_root_key_from_seed(&bip39_seed, network, bip);
1842    // Notice we have two ways to get the master keys: -------------------------
1843    // 1) using seed
1844    let master_keys_generated_from_seed = get_master_keys_from_seed(&bip39_seed);
1845    // 2) using bip32 root key (extended private master key)
1846    let master_keys_generated_from_bip32_root_key =
1847        get_master_keys_from_bip32_root_key(&bip32_root_key);
1848    let master_keys = master_keys_generated_from_seed;
1849    // ---------------------------------------------------------------------------
1850    // Can also get bip32 root key from masterkeys;
1851    let bip32_root_key = get_bip32_root_key_from_master_keys(&master_keys, network, bip);
1852    //
1853    let serialized_extended_master_keys = master_keys.serialize(network, bip);
1854    let master_fingerprint = create_fingerprint(&master_keys.public_key_hex);
1855
1856    let bip32_root_pub_key = serialized_extended_master_keys.xpub;
1857    let account_derivation_path = format!("m/{}'/{}'/{}'", purpose, coin_type, account);
1858    let derivation_path_external = format!("{}/0", account_derivation_path);
1859    let bip32_extended_keys_for_external = get_bip32_extended_keys_from_derivation_path(
1860        &derivation_path_external,
1861        &Keys::Master(master_keys.clone()),
1862        network,
1863        bip,
1864    );
1865    let bip32_extended_private_key_for_external = bip32_extended_keys_for_external.xpriv;
1866    let bip32_extended_public_key_for_external = bip32_extended_keys_for_external.xpub;
1867    // Change
1868    let derivation_path_internal = format!("{}/1", account_derivation_path);
1869    let bip32_extended_keys_for_internal = get_bip32_extended_keys_from_derivation_path(
1870        &derivation_path_internal,
1871        &Keys::Master(master_keys.clone()),
1872        network,
1873        bip,
1874    );
1875    let bip32_extended_private_key_for_internal = bip32_extended_keys_for_internal.xpriv;
1876    let bip32_extended_public_key_for_internal = bip32_extended_keys_for_internal.xpub;
1877
1878    let should_include_change_addresses = true;
1879    let found_children = get_bip86_derived_addresses(
1880        coin_type,
1881        account,
1882        should_include_change_addresses,
1883        &master_keys,
1884        children_count,
1885        should_harden,
1886    );
1887    let bip86_derivation_path_info =
1888        get_bip86_derivation_path_info(coin_type, account, &master_keys.clone(), network);
1889
1890    HDWalletBip86 {
1891        network,
1892        bip39_seed,
1893        master_keys,
1894        bip32_root_key,
1895        bip32_root_pub_key,
1896        master_fingerprint,
1897        purpose,
1898        coin_type,
1899        account,
1900        // internal: bool,
1901        account_derivation_path,
1902        account_extended_private_key: bip86_derivation_path_info.account_extended_private_key,
1903        account_extended_public_key: bip86_derivation_path_info.account_extended_public_key,
1904        derivation_path_external,
1905        bip32_extended_private_key_for_external,
1906        bip32_extended_public_key_for_external,
1907        derivation_path_internal,
1908        bip32_extended_private_key_for_internal,
1909        bip32_extended_public_key_for_internal,
1910        derived_addresses: found_children,
1911    }
1912}
1913pub fn generate_bip141_hd_wallet_from_mnemonic_words() {
1914    todo!("Need to implement: https://iancoleman.io/bip39/");
1915}