Skip to content

Commit

Permalink
feat: delete basics.md, wip new full-wallet example
Browse files Browse the repository at this point in the history
  • Loading branch information
riverKanies committed Oct 21, 2024
1 parent 82624dd commit 413c4cf
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 207 deletions.
7 changes: 2 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ drafts/
target/
*Cargo.lock

# Tests
tests/Cargo.lock
tests/target
tests/src
tests/config.txt
# MacOS
*.DS_Store

# Python virtual environments
venv/
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"rust-analyzer.linkedProjects": [
"examples/descriptors/Cargo.toml",
"examples/rust/quickstart/Cargo.toml"
"examples/rust/quickstart/Cargo.toml",
"examples/rust/full-wallet/Cargo.toml"
]
}
193 changes: 0 additions & 193 deletions docs/cookbook/basics.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/cookbook/starter.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ First we need some <a href="https://github.com/bitcoin/bitcoin/blob/master/doc/d
```kotlin
--8<-- "examples/kotlin/quickstart/main.kt:descriptors"
```
These are taproot `tr()` descriptors using a public key on testnet (or signet) `tpub` as described in <a href="https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki" target="_blank">BIP86</a>. The `EXTERNAL_DESCRIPTOR` is an HD wallet with a path for generating addresses to give out externally for payment. We also have a second `INTERNAL_DESCRIPTOR` that we can use to generate addresses to pay ourseves change when sending payments (remeber that <a href="https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch06_transactions.adoc#outpoint" target="_blank">UTXOs</a> must be spent if full, so you often want to make change).
These are taproot `tr()` descriptors using a public key on testnet (or signet) `tpub` as described in <a href="https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki" target="_blank">BIP86</a>. The `descriptor` is an HD wallet with a path for generating addresses to give out externally for payment. We also have a second `change_descriptor` that we can use to generate addresses to pay ourseves change when sending payments (remeber that <a href="https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch06_transactions.adoc#outpoint" target="_blank">UTXOs</a> must be spent if full, so you often want to make change).

## Blockchain Client and Network

Expand Down
4 changes: 4 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ Alternatively, you can use cargo to run the examples directly using something li
cd syncing/<cratename>
cargo run --bin <cratename>
```


### rust-analyzer vscode extention
To enable rust-analyzer features for a rust example in the project you must add the path to the `Cargo.toml` file for the example to `.vscode/settings.json`
10 changes: 10 additions & 0 deletions examples/kotlin/full-wallet/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
repositories {
mavenCentral()
}

dependencies {
// for jvm
implementation 'org.bitcoindevkit:bdk-jvm:<version>'
// OR for android
implementation 'org.bitcoindevkit:bdk-android:<version>'
}
46 changes: 46 additions & 0 deletions examples/kotlin/full-wallet/main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// --8<-- [start:file]

val mnemonic = Mnemonic(WordCount.WORDS12)
val secretKey = DescriptorSecretKey(
Network.SIGNET,
mnemonic,
null
)

val descriptor = Descriptor.newBip86(
descriptorSecretKey,
KeychainKind.EXTERNAL,
Network.SIGNET
)
val changeDescriptor = Descriptor.newBip86(
secretKey,
KeychainKind.INTERNAL,
Network.SIGNET
)

val wallet = Wallet(
descriptor,
changeDescriptor,
Network.SIGNET
)

val addressInfo = wallet.revealNextAddress(KeychainKind.EXTERNAL)


// --8<-- [start:client]
val esploraClient: EsploraClient = EsploraClient("https://mutinynet.com/api")
// --8<-- [end:client]

// --8<-- [start:scan]
val syncRequest = wallet.startSyncWithRevealedSpks()
val update = try esploraClient.sync(
syncRequest,
5uL
)
wallet.applyUpdate(update)
val balance = wallet.balance()
// --8<-- [end:scan]

// TODO: tx build + broadcast, recovery, storage, etc.

// --8<-- [end:file]
8 changes: 8 additions & 0 deletions examples/rust/full-wallet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "full-wallet"
version = "0.1.0"
edition = "2021"

[dependencies]
bdk_wallet = { version = "=1.0.0-beta.5", features = ["keys-bip39"] }
bdk_esplora = { version = "=0.19.0", features = ["blocking"] }
73 changes: 73 additions & 0 deletions examples/rust/full-wallet/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// detailed documentation for this code can be found at https://bitcoindevkit.github.io/book-of-bdk/cookbook/starter/
// --8<-- [start:file]
use bdk_wallet::AddressInfo;
use bdk_wallet::KeychainKind;
use bdk_wallet::bitcoin::Network;
use bdk_wallet::Wallet;
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::keys::bip39::{Language, Mnemonic, WordCount};
use bdk_wallet::keys::{GeneratedKey, GeneratableKey};
use bdk_wallet::miniscript::Tap;
use bdk_wallet::bitcoin::bip32::Xpriv;
use bdk_wallet::template::{Bip86, DescriptorTemplate};

const STOP_GAP: usize = 50;
const PARALLEL_REQUESTS: usize = 1;


fn main() -> () {

let mnemonic: GeneratedKey<_, Tap> =
Mnemonic::generate((WordCount::Words12, Language::English))
.expect("Failed to generate mnemonic");
println!("generated Seed Words:");
println!("{}", mnemonic.to_string());
println!("save these to recover your wallet later");

let seed = mnemonic.to_seed("");
let xprv: Xpriv =
Xpriv::new_master(Network::Signet, &seed).expect("Failed to create master key");
println!("created Master Private Key:");
println!("{}", xprv);

let (descriptor, _key_map, _) = Bip86(xprv, KeychainKind::External)
.build(Network::Signet)
.expect("Failed to build external descriptor");
println!("external descriptor: {}", descriptor);

let (change_descriptor, _change_key_map, _) = Bip86(xprv, KeychainKind::Internal)
.build(Network::Signet)
.expect("Failed to build internal descriptor");
println!("internal descriptor: {}", change_descriptor);

// Create the wallet
let mut wallet: Wallet = Wallet::create(descriptor, change_descriptor)
.network(Network::Signet)
.create_wallet_no_persist()
.unwrap();

// 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);

// Sync the wallet
// --8<-- [start:client]
let client: esplora_client::BlockingClient = Builder::new("http://signet.bitcoindevkit.net").build_blocking();
// --8<-- [end:client]

// --8<-- [start:scan]
let full_scan_request: FullScanRequestBuilder<KeychainKind> = wallet.start_full_scan();
let update: FullScanResult<KeychainKind> = client.full_scan(full_scan_request, STOP_GAP, PARALLEL_REQUESTS).unwrap();
// Apply the update from the full scan to the wallet
wallet.apply_update(update).unwrap();
let balance = wallet.balance();
println!("Wallet balance: {} sat", balance.total().to_sat());
// --8<-- [end:scan]

// TODO: tx build + broadcast, recovery, storage, etc.
}
// --8<-- [end:file]
Loading

0 comments on commit 413c4cf

Please sign in to comment.