|  | 
|  | 1 | +#[allow(dead_code)] | 
|  | 2 | +use bdk_wallet::keyring::KeyRing; | 
|  | 3 | +use bdk_wallet::Wallet; | 
|  | 4 | +use bitcoin::Network; | 
|  | 5 | +use miniscript::descriptor::DescriptorType; | 
|  | 6 | + | 
|  | 7 | +// The KeyRing holds a map of keychain identifiers (`K`) to public descriptors. These keychain | 
|  | 8 | +// identifiers can be simple (something like the `DescriptorId` or the `KeychainKind` types work | 
|  | 9 | +// well, e.g. see the `simple_keyring.rs` example), but they can also be more complex if required by | 
|  | 10 | +// the application. This example shows how the keychain identifier can be used to carry metadata | 
|  | 11 | +// about the descriptors, which could be used to select which keychain to use in different scenarios | 
|  | 12 | +// when calling methods like `Wallet::reveal_next_address`. | 
|  | 13 | + | 
|  | 14 | +// In this example, Johnny has a lot of keychains he keeps track of in his wallet. The map of | 
|  | 15 | +// KeychainIdentifier -> Descriptor uses keys that are custom-made at the application layer, and | 
|  | 16 | +// useful for its business logic (for example, choose a weekend keychain when Johnny is out partying | 
|  | 17 | +// on the weekend). | 
|  | 18 | + | 
|  | 19 | +const DESC_1: &str = "tr([5bc5d243/86'/1'/0']tpubDC72NVP1RK5qwy2QdEfWphDsUBAfBu7oiV6jEFooHP8tGQGFVUeFxhgZxuk1j6EQRJ1YsS3th2RyDgReRqCL4zqp4jtuV2z7gbiqDH2iyUS/0/*)#xh44xwsp"; | 
|  | 20 | +const DESC_2: &str = "wpkh([5bc5d243/84'/1'/0']tpubDCA4DcMLVSDifbfUxyJaVVAx57ztsVjke6DRYF95jFFgJqvzA9oENovVd7n34NNURmZxFNRB1VLGyDEqxvaZNXie3ZroEGFbeTS2xLYuaN1/0/*)#q8afsa3z"; | 
|  | 21 | +const DESC_3: &str = "pkh([5bc5d243/44'/1'/0']tpubDDNQtvd8Sg1mXtSGtxRWEcgg7PbPwUSAyAmBonDSL3HLuutthe54Yih4XDYcywVdcduwqaQonpbTAGjjSh5kcLeCj5MTjYooa9ve2Npx6ho/1/*)#g73kgtdn"; | 
|  | 22 | +const DESC_4: &str = "tr([5bc5d243/86'/1'/0']tpubDC72NVP1RK5qwy2QdEfWphDsUBAfBu7oiV6jEFooHP8tGQGFVUeFxhgZxuk1j6EQRJ1YsS3th2RyDgReRqCL4zqp4jtuV2z7gbiqDH2iyUS/42/42)"; | 
|  | 23 | +const DESC_5: &str = "sh(wpkh([5bc5d243/49'/1'/0']tpubDDd6eupua2nhRp2egUAgYGjkxHeh5jPrBDaKLExeySwRvUb1hU7s8osoeACRhXs2w1UGZSMmEpZ1FkjYJ2Pxvfsy7w6XRqYYW7Vw89Unrzr/0/*))#svvvc6el"; | 
|  | 24 | + | 
|  | 25 | +fn main() { | 
|  | 26 | +    let keychain_1 = KeychainId { | 
|  | 27 | +        number: 1, | 
|  | 28 | +        nickname: "Johnny's favorite keychain", | 
|  | 29 | +        script_type: DescriptorType::Tr, | 
|  | 30 | +        color: Color::Blue, | 
|  | 31 | +        time_of_week_keychain: DayType::WeekDay, | 
|  | 32 | +    }; | 
|  | 33 | +    let keychain_2 = KeychainId { | 
|  | 34 | +        number: 2, | 
|  | 35 | +        nickname: "Johnny's party keychain", | 
|  | 36 | +        script_type: DescriptorType::Wpkh, | 
|  | 37 | +        color: Color::Green, | 
|  | 38 | +        time_of_week_keychain: DayType::WeekEnd, | 
|  | 39 | +    }; | 
|  | 40 | +    let keychain_3 = KeychainId { | 
|  | 41 | +        number: 3, | 
|  | 42 | +        nickname: "Johnny's old P2PKH keychain", | 
|  | 43 | +        script_type: DescriptorType::Pkh, | 
|  | 44 | +        color: Color::Blue, | 
|  | 45 | +        time_of_week_keychain: DayType::AnyDay, | 
|  | 46 | +    }; | 
|  | 47 | +    let keychain_4 = KeychainId { | 
|  | 48 | +        number: 4, | 
|  | 49 | +        nickname: "Johnny's project donations keychain", | 
|  | 50 | +        script_type: DescriptorType::Tr, | 
|  | 51 | +        color: Color::Yellow, | 
|  | 52 | +        time_of_week_keychain: DayType::AnyDay, | 
|  | 53 | +    }; | 
|  | 54 | +    let keychain_5 = KeychainId { | 
|  | 55 | +        number: 5, | 
|  | 56 | +        nickname: "The secret keychain", | 
|  | 57 | +        script_type: DescriptorType::ShWpkh, | 
|  | 58 | +        color: Color::Blue, | 
|  | 59 | +        time_of_week_keychain: DayType::AnyDay, | 
|  | 60 | +    }; | 
|  | 61 | + | 
|  | 62 | +    let mut keyring: KeyRing<KeychainId> = KeyRing::new(Network::Signet, keychain_1, DESC_1); | 
|  | 63 | +    keyring.add_descriptor(keychain_2, DESC_2, false); | 
|  | 64 | +    keyring.add_descriptor(keychain_3, DESC_3, false); | 
|  | 65 | +    keyring.add_descriptor(keychain_4, DESC_4, false); | 
|  | 66 | +    keyring.add_descriptor(keychain_5, DESC_5, false); | 
|  | 67 | + | 
|  | 68 | +    // DESC_1 is the default keychain (the first one added to the keyring is automatically the | 
|  | 69 | +    // default keychain), but this can also be changed later on with the | 
|  | 70 | +    // KeyRing::set_default_keychain API. This default keychain is useful because you can use | 
|  | 71 | +    // APIs like `Wallet::reveal_next_default_address()` which will always work with your | 
|  | 72 | +    // default keychain. | 
|  | 73 | + | 
|  | 74 | +    let mut wallet = Wallet::new(keyring); | 
|  | 75 | + | 
|  | 76 | +    let address1 = wallet.reveal_next_default_address(); | 
|  | 77 | +    println!("Default keychain address: {}", address1.address); | 
|  | 78 | + | 
|  | 79 | +    let party_address = wallet.reveal_next_address(keychain_2).unwrap(); | 
|  | 80 | +    println!("Party address:            {}", party_address.address); | 
|  | 81 | + | 
|  | 82 | +    let donation_address = wallet.reveal_next_address(keychain_4).unwrap(); | 
|  | 83 | +    println!("Donation address:         {}", donation_address.address); | 
|  | 84 | +} | 
|  | 85 | + | 
|  | 86 | +#[derive(Debug, Clone, Copy)] | 
|  | 87 | +struct KeychainId { | 
|  | 88 | +    number: u32, | 
|  | 89 | +    nickname: &'static str, | 
|  | 90 | +    script_type: DescriptorType, | 
|  | 91 | +    color: Color, | 
|  | 92 | +    time_of_week_keychain: DayType, | 
|  | 93 | +} | 
|  | 94 | + | 
|  | 95 | +impl PartialEq for KeychainId { | 
|  | 96 | +    fn eq(&self, other: &Self) -> bool { | 
|  | 97 | +        self.number == other.number | 
|  | 98 | +    } | 
|  | 99 | +} | 
|  | 100 | + | 
|  | 101 | +impl Eq for KeychainId {} | 
|  | 102 | + | 
|  | 103 | +impl PartialOrd for KeychainId { | 
|  | 104 | +    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { | 
|  | 105 | +        Some(self.cmp(other)) | 
|  | 106 | +    } | 
|  | 107 | +} | 
|  | 108 | + | 
|  | 109 | +impl Ord for KeychainId { | 
|  | 110 | +    fn cmp(&self, other: &Self) -> std::cmp::Ordering { | 
|  | 111 | +        self.number.cmp(&other.number) | 
|  | 112 | +    } | 
|  | 113 | +} | 
|  | 114 | + | 
|  | 115 | +#[derive(Debug, Clone, Copy)] | 
|  | 116 | +enum Color { | 
|  | 117 | +    Blue, | 
|  | 118 | +    Green, | 
|  | 119 | +    Yellow, | 
|  | 120 | +} | 
|  | 121 | + | 
|  | 122 | +#[derive(Debug, Clone, Copy)] | 
|  | 123 | +enum DayType { | 
|  | 124 | +    AnyDay, | 
|  | 125 | +    WeekDay, | 
|  | 126 | +    WeekEnd, | 
|  | 127 | +} | 
0 commit comments