Skip to content

Commit

Permalink
feat: add fee rate and proper drain logic to full-wallet ex
Browse files Browse the repository at this point in the history
  • Loading branch information
riverKanies committed Jan 23, 2025
1 parent 4882001 commit c4249c8
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 9 deletions.
12 changes: 9 additions & 3 deletions docs/cookbook/full-wallet.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Next, lets use those descriptors to load up our wallet. Replace the placeholder
--8<-- "examples/rust/full-wallet/src/main.rs:descriptors"
```

We are going to run this example twice. On the first run it will do a full scan for your wallet, persist that chain data, generate a new address for you, and display your current wallet balance, it will then attempt to build a transaction, but will fail becuase we don't have any funds yet. We will use the new address (from the first run) to request funds from the [Mutinynet faucet](https://faucet.mutinynet.com/) so we can build a transaction on the second run. On the second run it will load the data from the previous run, do a light weight sync to check for updates (no need to repeat the full scan), and then build and broadcast a transaction. Let's go through this step by step.
We are going to run this example twice. On the first run it will do a full scan for your wallet, persist that chain data, generate a new address for you, and display your current wallet balance, it will then attempt to build a transaction, but will fail becuase we don't have any funds yet. We will use the new address (from the first run) to request funds from the <a href="https://faucet.mutinynet.com/" target="_blank" rel="noopener noreferrer">Mutinynet faucet</a> so we can build a transaction on the second run. On the second run it will load the data from the previous run, do a light weight sync to check for updates (no need to repeat the full scan), and then build and broadcast a transaction. Let's go through this step by step.

```rust title="examples/rust/full-wallet/src/main.rs"
--8<-- "examples/rust/full-wallet/src/main.rs:persist"
Expand All @@ -51,7 +51,7 @@ The process will then error out, indicating we don't have enough funds to send a

### Request satoshis from the Mutinynet faucet

We can now use our new address to request some sats from the [Mutinynet faucet](https://faucet.mutinynet.com/). After requesting sats, you can view the transaction in their [Mempool Explorer instance](https://mutinynet.com/) (click the link on the faucet confirmation page or put the txid in the search bar of the mempool explorer). After a minute or so you should see the transaction confirmed. We can also re-run the `full-wallet` example and see that our wallet now has some funds!
We can now use our new address to request some sats from the <a href="https://faucet.mutinynet.com/" target="_blank" rel="noopener noreferrer">Mutinynet faucet</a>. After requesting sats, you can view the transaction in their <a href="https://mutinynet.com/" target="_blank" rel="noopener noreferrer">Mempool Explorer instance</a> (click the link on the faucet confirmation page or put the txid in the search bar of the mempool explorer). After a minute or so you should see the transaction confirmed. We can also re-run the `full-wallet` example and see that our wallet now has some funds!

## Load, Sync, and Send a Transaction (Second Run)

Expand All @@ -73,12 +73,18 @@ Now that we have funds, let's prepare to send a transaction. We need to decide w
--8<-- "examples/rust/full-wallet/src/main.rs:faucet"
```

Here we are preparing to send 5000 sats back to the mutiny faucet (it's good practice to send test sats back to the faucet when you're done using them).
Here we are preparing to send 5000 sats back to the mutiny faucet, so you'll need to request at more sats than that or change this value (it's good practice to send test sats back to the faucet when you're done using them).

Finally we are ready to build, sign, and broadcast the transaction:

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

We are manually determining the fee rate to be 4 sat/vb (satoshis per virtual byte).

Again we can view the transaction in the Mutinynet explorer or re-run the `full-wallet` example to see that our wallet has less funds.

### Drain the Wallet

When you're done with the test sats that you got from the faucet, you should send the remaining funds back to the faucet by [draining the wallet](/cookbook/transactions/transaction-builder/#spend-all-funds).
4 changes: 1 addition & 3 deletions docs/cookbook/transactions/transaction-builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ Note that if you set the fee using both the fee_absolute and the fee_rate method
The transaction builder has a convenience method that will spend all UTXOs available to it (while respecting the unspendable UTXOs if any). Simple use of this method will simply increase the size of your change output, but you can combine it with the `TxBuilder::drain_to` method to ensure all funds are sent to a specific address:

```rust
let psbt = wallet.build_tx()
.drain_wallet()
.drain_to(address.script_pubkey())
--8<-- "examples/rust/full-wallet/src/main.rs:drain"
```

### Set the nSequence value
Expand Down
27 changes: 24 additions & 3 deletions examples/rust/full-wallet/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use bdk_esplora::esplora_client;
use bdk_esplora::esplora_client::Builder;
use bdk_esplora::EsploraExt;
use bdk_wallet::bitcoin::Address;
use bdk_wallet::bitcoin::{Amount, Network};
use bdk_wallet::bitcoin::{Amount, FeeRate, Network};
use bdk_wallet::chain::spk_client::{
FullScanRequestBuilder, FullScanResponse, SyncRequestBuilder, SyncResponse,
};
Expand Down Expand Up @@ -85,7 +85,7 @@ fn main() -> Result<(), anyhow::Error> {

// --8<-- [start:faucet]
// Use the Mutinynet faucet return address
let address = Address::from_str("tb1qd28npep0s8frcm3y7dxqajkcy2m40eysplyr9v")
let faucet_address = Address::from_str("tb1qd28npep0s8frcm3y7dxqajkcy2m40eysplyr9v")
.unwrap()
.require_network(Network::Signet)
.unwrap();
Expand All @@ -96,7 +96,8 @@ fn main() -> Result<(), anyhow::Error> {
// --8<-- [start:transaction]
// Transaction Logic
let mut tx_builder = wallet.build_tx();
tx_builder.add_recipient(address.script_pubkey(), send_amount);
tx_builder.fee_rate(FeeRate::from_sat_per_vb(4).unwrap());
tx_builder.add_recipient(faucet_address.script_pubkey(), send_amount);

let mut psbt = tx_builder.finish()?;
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
Expand All @@ -107,5 +108,25 @@ fn main() -> Result<(), anyhow::Error> {
println!("Tx broadcasted! Txid: {}", tx.compute_txid());
// --8<-- [end:transaction]

// Resync to see new tx in mempool
println!("Performing regular sync...");
let sync_request: SyncRequestBuilder<(KeychainKind, u32)> =
wallet.start_sync_with_revealed_spks();
let update: SyncResponse = client.sync(sync_request, PARALLEL_REQUESTS)?;
wallet.apply_update(update).unwrap();

// Drain all the remaining sats back to Mutinynet
// --8<-- [start:drain]
let mut tx_builder = wallet.build_tx();
tx_builder.drain_wallet();
tx_builder.drain_to(faucet_address.script_pubkey());
// --8<-- [end:drain]
let mut psbt = tx_builder.finish()?;
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
assert!(finalized);
let tx = psbt.extract_tx()?;
client.broadcast(&tx)?;
println!("Drain Tx broadcasted! Txid: {}", tx.compute_txid());

Ok(())
}

0 comments on commit c4249c8

Please sign in to comment.