|
| 1 | +// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers |
| 2 | +// |
| 3 | +// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE |
| 4 | +// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 5 | +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option. |
| 6 | +// You may not use this file except in accordance with one or both of these |
| 7 | +// licenses. |
| 8 | + |
| 9 | +use bdk::bitcoin::secp256k1::Secp256k1; |
| 10 | +use bdk::bitcoin::util::bip32::DerivationPath; |
| 11 | +use bdk::bitcoin::Network; |
| 12 | +use bdk::keys::bip39::{Language, Mnemonic, WordCount}; |
| 13 | +use bdk::keys::DescriptorKey::Secret; |
| 14 | +use bdk::keys::KeyError::Message; |
| 15 | +use bdk::keys::{ |
| 16 | + DerivableKey, DescriptorKey, ExtendedKey, GeneratableKey, GeneratedKey, IntoDescriptorKey, |
| 17 | +}; |
| 18 | +use bdk::miniscript::Segwitv0; |
| 19 | +use bdk::Error as BDK_Error; |
| 20 | +use std::error::Error; |
| 21 | +use std::str::FromStr; |
| 22 | + |
| 23 | +/// This example demonstrates how to generate a mnemonic phrase |
| 24 | +/// using BDK and use that to generate a master extended private key. |
| 25 | +/// It then uses the master extended private key with a derivation |
| 26 | +/// path to generate child extended private and public keys. Finally, |
| 27 | +/// it uses the derivation path and these keys to get the descriptors. |
| 28 | +fn main() -> Result<(), Box<dyn Error>> { |
| 29 | + let secp = Secp256k1::new(); |
| 30 | + |
| 31 | + // In this example we are generating a 12 words mnemonic phrase |
| 32 | + // but it is also possible generate 15, 18, 21 and 24 words |
| 33 | + // using their respective `WordCount` variant. |
| 34 | + let mnemonic: GeneratedKey<_, Segwitv0> = |
| 35 | + Mnemonic::generate((WordCount::Words12, Language::English)) |
| 36 | + .map_err(|_| BDK_Error::Generic("Mnemonic generation error".to_string()))?; |
| 37 | + |
| 38 | + let mnemonic = mnemonic.into_key(); |
| 39 | + |
| 40 | + // We don't want a passphrase on the mnemonic so we use None |
| 41 | + let xkey: ExtendedKey = (mnemonic.clone(), None).into_extended_key()?; |
| 42 | + let master_xprv = xkey.into_xprv(Network::Testnet).ok_or_else(|| { |
| 43 | + BDK_Error::Generic("Privatekey info not found (should not happen)".to_string()) |
| 44 | + })?; |
| 45 | + |
| 46 | + let fingerprint = master_xprv.fingerprint(&secp); |
| 47 | + let phrase = mnemonic.to_string(); |
| 48 | + |
| 49 | + println!("Mnemonic phrase: {}", phrase); |
| 50 | + println!("Xprv fingerprint: {}", fingerprint); |
| 51 | + |
| 52 | + // You can replace this derivation path with one of your choosing |
| 53 | + let path = DerivationPath::from_str("m/84h/0h/0h").unwrap(); |
| 54 | + |
| 55 | + // The second item in the mnemonic tuple represents the passphrase. |
| 56 | + let derived_xprv_desc_key: DescriptorKey<Segwitv0> = |
| 57 | + ((mnemonic, None), path).into_descriptor_key()?; |
| 58 | + |
| 59 | + if let Secret(desc_seckey, _, _) = derived_xprv_desc_key { |
| 60 | + let desc_pubkey = desc_seckey |
| 61 | + .as_public(&secp) |
| 62 | + .map_err(|e| BDK_Error::Generic(e.to_string()))?; |
| 63 | + println!("xpub {}", desc_pubkey); |
| 64 | + println!("xprv {}", desc_seckey); |
| 65 | + } else { |
| 66 | + return Err(Box::new(BDK_Error::Key(Message( |
| 67 | + "Invalid key variant".to_string(), |
| 68 | + )))); |
| 69 | + } |
| 70 | + |
| 71 | + Ok(()) |
| 72 | +} |
0 commit comments