Skip to content

Commit

Permalink
fix: don't push seed words in docs (it's against bdk philosophy)
Browse files Browse the repository at this point in the history
  • Loading branch information
riverKanies committed Oct 25, 2024
1 parent c929773 commit 4983809
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 137 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"rust-analyzer.linkedProjects": [
"examples/rust/quickstart/Cargo.toml",
"examples/rust/descriptors/Cargo.toml",
"examples/rust/wallet-recovery/Cargo.toml",
"examples/rust/seed-phrase/Cargo.toml",
"examples/rust/transaction/Cargo.toml"
]
}
48 changes: 28 additions & 20 deletions docs/cookbook/full-wallet.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,50 @@
# Full Wallet Example

This page will do a walk through of 3 examples to illustrate core wallet functionality including:
This page will illustrate core wallet functionality including:

- Generating seeds and keys
- Recovering a wallet with seeds
- Generating descriptors
- Recovering a wallet with descriptors
- Creating and broadcasting a transaction

## Generating seeds and keys
Note: the logic to do this is in 3 separate examples, if you're following along with the code examples you will need to copy and paste descriptors between examples.

First lets run the [descriptors](../keys-descriptors/descriptors) example to generate seeds, keys, and descriptors:
## Generating Descriptors

```rust title="examples/rust/descriptors/src/main.rs""
--8<-- "examples/rust/descriptors/src/main.rs"
First lets run the [descriptors](../keys-descriptors/descriptors) example to our descriptors which will define our HD wallet:

```rust title="examples/rust/descriptors/src/main.rs"
// ...
--8<-- "examples/rust/descriptors/src/main.rs:main"
// ...
```

## Recovering a wallet with seeds
Notice there are two types of descriptors generated: private key descriptors (with full signing capabilities) and public key descriptors (primarily for generating invoice addresses). We will be using our private key descriptors to send a transaction later.

Next lets use those seeds to recover our wallet. Put your seed phrase into the [wallet-recovery](../keys-descriptors/wallet-recovery) example and run it to sync a wallet, check the balance, and generate a new address:
## Recovering a Wallet with Descriptors

```rust title="examples/rust/wallet-recovery/src/main.rs""
--8<-- "examples/rust/wallet-recovery/src/main.rs"
```
Next lets use those descriptors to recover our wallet. Replace the descriptors in the [quickstart](./quickstart.md) example with either your private or publickey descriptors (either will work here) and run it to sync a wallet, check the balance, and generate a new invoice address:

Note: use of the term 'recover' here might be confusing since we just created the wallet, however we are not persisting any data at the moment, so we will need to recover our wallet every time we want to use it.
```rust title="examples/rust/quickstart/src/main.rs"
// ...
--8<-- "examples/rust/quickstart/src/main.rs:address"
// ...
```

### Request sats from Mutinynet Faucet
### Request Sats from Mutinynet Faucet

After recovering our wallet, we printed out a new address that funds can be sent to. Let's now hop over to the [Mutinynet Faucet](https://mutinynet.com/faucet) and request some sats. After requesting sats you can view the transaction in the [Mempool](https://mutinynet.com/) (click the link on the confirmation page or put the transaction id in the search bar). After a minute or so you should see the transaction confirmed. We can also re-run the `wallet-recovery` example and see that our wallet now has some funds!
We can now use our new invoice address to request some sats from the [Mutinynet Faucet](https://mutinynet.com/faucet). After requesting sats you can view the transaction in the [Mempool](https://mutinynet.com/) (click the link on the confirmation page or put the transaction id in the search bar). After a minute or so you should see the transaction confirmed. We can also re-run the `quickstart` example and see that our wallet now has some funds!

## Creating and broadcasting a transaction
## Creating and Broadcasting a Transaction

Finally we can test out sending some sats ourselves. Put your seed phrase into the `transaction` example and run it to create, sign, and broadcast a transaction.
Finally we can test out sending some sats ourselves. Put your private key descriptors into the `transaction` example and run it to create, sign, and broadcast a transaction.

```rust title="examples/rust/transaction/src/main.rs""
--8<-- "examples/rust/transaction/src/main.rs"
```rust title="examples/rust/transaction/src/main.rs"
// ...
--8<-- "examples/rust/transaction/src/main.rs:main"
// ...
```

Again we can view the transaction in the mempool or re-run the `wallet-recovery` example to see that our wallet has less funds. Our funds will only be reduced by the fee amount because we sent the funds back to ourselves.
Again we can view the transaction in the mempool or re-run the `quickstart` example to see that our wallet has less funds. Our funds will only be reduced by the fee amount because we sent the funds back to ourselves.



Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/keys-descriptors/descriptors.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Creating Seeds, Keys, and Descriptors
# Creating Keys and Descriptors
BDK is a descriptor-first library. This page explores how to build them and how they interact with other standards like BIP-39 recovery phrases.

!!!danger
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Wallet Recovery from Seeds
# Recover Descriptors from Seeds

BDK wallets require the use of descriptors, but recovery phrases (also called seed phrases) are a common and popular backup solution. Creating descriptors from a recovery phrase is a common workflow and BDK makes this easy with its _descriptor templates_, which are offered for common descriptors ([BIP 44/49/84/86](https://docs.rs/bdk_wallet/latest/bdk_wallet/descriptor/template/index.html)).

Expand All @@ -14,5 +14,5 @@ BDK wallets require the use of descriptors, but recovery phrases (also called se
### Example

```rust
--8<-- "examples/rust/wallet-recovery/src/main.rs"
--8<-- "examples/rust/seed-phrase/src/main.rs"
```
29 changes: 12 additions & 17 deletions examples/rust/descriptors/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@ use bdk_wallet::bitcoin::bip32::Xpriv;
use bdk_wallet::bitcoin::Network;
use bdk_wallet::KeychainKind;
use bdk_wallet::template::{Bip86, DescriptorTemplate};
use bdk_wallet::keys::bip39::{Language, Mnemonic, WordCount};
use bdk_wallet::keys::{GeneratedKey, GeneratableKey};
use bdk_wallet::miniscript::Tap;
use bdk_wallet::bitcoin::secp256k1::rand;
use bdk_wallet::bitcoin::secp256k1::rand::RngCore;

fn main() -> () {
let mnemonic: GeneratedKey<_, Tap> =
Mnemonic::generate((WordCount::Words12, Language::English))
.expect("Failed to generate mnemonic");
println!("Generated Seed Words:\n{}\nNote: save these to recover your wallet later.\nWarning: this seed generation method is for example purposes only! Seeds used on MainNet should be generated using the most random method possible.\n", mnemonic.to_string());
// --8<-- [start:main]
let mut seed: [u8; 32] = [0u8; 32];
rand::thread_rng().fill_bytes(&mut seed);

let seed = mnemonic.to_seed("");
let xprv: Xpriv =
Xpriv::new_master(Network::Signet, &seed).expect("Failed to create master key");
println!("Generated Master Private Key:\n{}\nWarning: be very careful with seeds and private keys when using MainNet! We are logging these values for convenience only because this is an example on SigNet.\n", xprv);
let network: Network = Network::Signet;
let xprv: Xpriv = Xpriv::new_master(network, &seed).unwrap();
println!("Generated Master Private Key:\n{}\nWarning: be very careful with private keys when using MainNet! We are logging these values for convenience only because this is an example on SigNet.\n", xprv);

let (descriptor, key_map, _) = Bip86(xprv, KeychainKind::External)
.build(Network::Signet)
Expand All @@ -24,15 +21,13 @@ fn main() -> () {
let (change_descriptor, change_key_map, _) = Bip86(xprv, KeychainKind::Internal)
.build(Network::Signet)
.expect("Failed to build internal descriptor");

// --8<-- [end:main]

println!(
"---------------- Descriptor ------------------------------\n{:?}\n{:?}\n",
"---------------- Descriptors ------------------------------\nPrivate Key, External:\n{:?}\nPrivate Key, Internal:\n{:?}\nPublic Key, External:\n{:?}\nPublic Key, Internal:\n{:?}\n",
descriptor.to_string_with_secret(&key_map), // privkey
descriptor.to_string() // pubkey
);
println!(
"---------------- Change Descriptor -----------------------\n{:?}\n{:?}\n",
change_descriptor.to_string_with_secret(&change_key_map),
descriptor.to_string(), // pubkey
change_descriptor.to_string()
);
}
4 changes: 2 additions & 2 deletions examples/rust/quickstart/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ fn main() -> () {
println!("Wallet balance: {} sat", balance.total().to_sat());
// --8<-- [end:scan]

// --8<-- [start:address]
// Reveal a new address from your external keychain
// doing this just to show it is an HD wallet
let address: AddressInfo = wallet.reveal_next_address(KeychainKind::External);
println!("Generated address {} at index {}", address.address, address.index);

// --8<-- [end:address]

}
// --8<-- [end:file]
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ edition = "2021"

[dependencies]
bdk_wallet = { version = "=1.0.0-beta.5", features = ["keys-bip39"] }
bdk_esplora = { version = "=0.19.0", features = ["blocking"] }
32 changes: 32 additions & 0 deletions examples/rust/seed-phrase/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use bdk_wallet::bitcoin::bip32::Xpriv;
use bdk_wallet::bitcoin::Network;
use bdk_wallet::KeychainKind;
use bdk_wallet::template::{Bip86, DescriptorTemplate};
use bdk_wallet::keys::bip39::Mnemonic;

const RECOVERY_PHRASE: &str = "[your 12 word seed phrase here ...]";
// const RECOVERY_PHRASE: &str = "holiday marble tide globe license stumble rescue antenna monitor sea half sauce"; // example

fn main() -> () {
let mnemonic = Mnemonic::parse(RECOVERY_PHRASE).expect("Invalid seed! Be sure to replace the value of RECOVERY_PHRASE with your own 12 word seed phrase.");
let seed = mnemonic.to_seed("");
let xprv: Xpriv =
Xpriv::new_master(Network::Signet, &seed).expect("Failed to create master key");
println!("Generated Master Private Key:\n{}\nWarning: be very careful with seeds and private keys when using MainNet! We are logging these values for convenience only because this is an example on SigNet.\n", xprv);

let (descriptor, key_map, _) = Bip86(xprv, KeychainKind::External)
.build(Network::Signet)
.expect("Failed to build external descriptor");

let (change_descriptor, change_key_map, _) = Bip86(xprv, KeychainKind::Internal)
.build(Network::Signet)
.expect("Failed to build internal descriptor");

println!(
"---------------- Descriptors ------------------------------\nPrivate Key, External:\n{:?}\nPrivate Key, Internal:\n{:?}\nPublic Key, External:\n{:?}\nPublic Key, Internal:\n{:?}\n",
descriptor.to_string_with_secret(&key_map), // privkey
change_descriptor.to_string_with_secret(&change_key_map),
descriptor.to_string(), // pubkey
change_descriptor.to_string()
);
}
24 changes: 6 additions & 18 deletions examples/rust/transaction/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,14 @@ use bdk_esplora::EsploraExt;
use bdk_esplora::esplora_client::Builder;
use bdk_esplora::esplora_client;
use bdk_wallet::chain::spk_client::{FullScanRequestBuilder, FullScanResult};
use bdk_wallet::bitcoin::bip32::Xpriv;
use bdk_wallet::template::{Bip86, DescriptorTemplate};
use bdk_wallet::keys::bip39::Mnemonic;

const STOP_GAP: usize = 50;
const PARALLEL_REQUESTS: usize = 1;
const SEND_AMOUNT: Amount = Amount::from_sat(5000);

const RECOVERY_PHRASE: &str = "[your 12 word seed phrase here ...]";
// const RECOVERY_PHRASE: &str = "holiday marble tide globe license stumble rescue antenna monitor sea half sauce"; // example

// --8<-- [start:main]
const DESCRIPTOR_PRIVATE_EXTERNAL: &str = "[your private external descriptor here ...]";
const DESCRIPTOR_PRIVATE_INTERNAL: &str = "[your private internal descriptor here ...]";

fn main() -> Result<(), anyhow::Error> {
let (mut wallet, client) = recover_wallet();
Expand All @@ -43,20 +40,11 @@ fn main() -> Result<(), anyhow::Error> {

Ok(())
}
// --8<-- [end:main]

fn recover_wallet() -> (Wallet, esplora_client::BlockingClient) {
// see examples/rust/wallet-recovery for more details
let mnemonic = Mnemonic::parse(RECOVERY_PHRASE).expect("Invalid seed! Be sure to replace the value of RECOVERY_PHRASE with your own 12 word seed phrase.");
let seed = mnemonic.to_seed("");
let xprv: Xpriv =
Xpriv::new_master(Network::Signet, &seed).expect("Failed to create master key");
let (descriptor, key_map, _) = Bip86(xprv, KeychainKind::External)
.build(Network::Signet)
.expect("Failed to build external descriptor");
let (change_descriptor, change_key_map, _) = Bip86(xprv, KeychainKind::Internal)
.build(Network::Signet)
.expect("Failed to build internal descriptor");
let mut wallet: Wallet = Wallet::create(descriptor.to_string_with_secret(&key_map), change_descriptor.to_string_with_secret(&change_key_map))
// see examples/rust/quickstart for more details
let mut wallet: Wallet = Wallet::create(DESCRIPTOR_PRIVATE_EXTERNAL, DESCRIPTOR_PRIVATE_INTERNAL)
.network(Network::Signet)
.create_wallet_no_persist()
.unwrap();
Expand Down
74 changes: 0 additions & 74 deletions examples/rust/wallet-recovery/src/main.rs

This file was deleted.

2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ nav:
- Flat File Persistence: cookbook/persistence/flat-file.md
- Keys and Descriptors:
- Creating Descriptors: cookbook/keys-descriptors/descriptors.md
- Wallet Recovery: cookbook/keys-descriptors/wallet-recovery.md
- Seed Phrase to Descriptors: cookbook/keys-descriptors/seed-phrase.md
- Architecture:
- Overview:
- Design: architecture/design.md

0 comments on commit 4983809

Please sign in to comment.