Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: full wallet persisted #80

Merged

Conversation

riverKanies
Copy link
Contributor

this modifies the full-wallet page to reference a new full-wallet example project rather than referencing both the quickstart and a transaction example

it also adds persistence and variable sync logic

@riverKanies riverKanies marked this pull request as draft October 29, 2024 19:47
@riverKanies riverKanies marked this pull request as ready for review October 30, 2024 14:58
Copy link
Member

@thunderbiscuit thunderbiscuit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff! I like to see the persistence added. It's funny because it also made me realize the clunkiness of the load_wallet returning... an Option? Feels odd.

Anyway thanks for the work! There are a few small things that need fixing but overall it's looking good. One more little thing: let's add a custom fee rate on the TxBuilder (something like 4 or 8), just to showcase this fairly important/standard API.

.gitignore Outdated
@@ -7,6 +7,7 @@ dist/
drafts/
target/
*Cargo.lock
*.db
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the .sqlite3 extension on the db file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure ok

use std::str::FromStr;
use bdk_wallet::rusqlite::Connection;

const DB_PATH: &str = "full-wallet.db";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above.

// --8<-- [start:descriptors]
const DESCRIPTOR_PRIVATE_EXTERNAL: &str = "[your private external descriptor here ...]";
const DESCRIPTOR_PRIVATE_INTERNAL: &str = "[your private internal descriptor here ...]";
// Example private key descriptors
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually call those "private descriptors" rather than "private key descriptors".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, just trying to be a little extra explicit. there may be a few other files to update on this front


let send_amount: Amount = Amount::from_sat(5000);
// return all sats to mutinynet faucet
// let send_amount: Amount = Amount::from_sat(balance.total().to_sat() - 100);// min fee is 100 sat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think 100 sat would be enough here. The better way to do this is probably using the TxBuilder::drain_wallet and TxBuilder::drain_to methods on the builder.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, well I tried sending all and the error said it required 100, tried that and it worked. my understanding was that mutiny net has a hard coded min fee of 100, but that could totally be wrong, it could be variable. maybe for now I'll just remove this and the note about it and make a separate PR for this soon (as you suggest below)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good to know! I didn't know that mutinynet was using a hard-coded minimum fee. In this case it's non-standard and odd so I definitely wouldn't want to use that and make an example of it.

Note also that MutinyNet will eventually be sunset (just a hunch) and so I don't see the examples sticking to MutinyNet for the long run (but it works now and I don't want to slow down the PRs so I'm cool with using it).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there has been some talk of a bdk hosted signet, but for now mutiny works

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we'll move to full standard Signet if we can find a good and reliable faucet, or to testnet once the Testnet4 stabilizes.

- Creating and broadcasting a transaction

!!! tip
The logic for this page is broken down in in 3 separate examples in the [examples source code](https://github.com/bitcoindevkit/book-of-bdk/tree/master/examples/rust). If you are following along with the code examples you will need to copy and paste descriptors between them.
The logic for this page is split between 2 separate examples in the [examples source code](https://github.com/bitcoindevkit/book-of-bdk/tree/master/examples/rust). One to create descriptors and a second for everything else.If you are following along with the code examples you will need to copy and paste your private key descriptors you get from the first example into the second. We leave descriptor creation in a separate example because bdk does not handle private key descriptor storage, that is up to the wallet developer.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can call those descriptors "private descriptors".


Next, lets use those descriptors to load up 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 address:
Next, lets use those descriptors to load up our wallet. Replace the placeholder descriptors in the `full-wallet` example with your private key descriptors:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again "private descriptors" is the correct nomenclature here.

```

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 invoice 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 invoice 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invoice address -> address

```

Next we'll fetch data from our blockchain client. On the first run, we don't yet have any data, so we need to do a full scan. We then persist the data from the scan.
Finally, we'll print out an invoice that we can use to request funds. You should also see the current balance printed out, it should be 0 since this is a brand new wallet. Note that we persist the wallet after generating the invoice address. This is to avoid re-using the same address as that would compromise our privacy (on subsequent runs you'll notice the address index incremented).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invoice -> address


## Creating and Broadcasting a Transaction
Here we are preparing to send 5000 sats back to the mutiny faucet. When you're done testing things out with this wallet you can uncomment the bottom line here to send all the rest of your remaining funds back (we subtract 100 sats from the total wallet balance as that is the minimum transaction fee).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not exactly sure how to best provide this "send all" capability in the example without muddying it. Your proposed approach of leaving 100 sats would not work, and so I suggest we leave this for another PR (the better way is adjusting the txbuilder for this; we could add it to the example but at first glance I feel like it's a slightly more advanced use than you might want to showcase in this example).


// --8<-- [start:transaction]
// Transaction Logic
let mut tx_builder = wallet.build_tx();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you feel about adding a check on the balance here instead of letting it error out?

Something like

if balance.total().to_sat() == 0 {
    println!("No available funds to send. Send some sats to {}", address.address);
    return Ok(());
}

Copy link
Contributor Author

@riverKanies riverKanies Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the error it throws already says "Error: Insufficient funds: 0 sat available of 5042 sat needed", it seems quite good, so I saw no reason to add extra code to the example

@riverKanies riverKanies marked this pull request as draft October 30, 2024 16:55
@riverKanies riverKanies marked this pull request as ready for review October 30, 2024 17:32
Copy link
Member

@thunderbiscuit thunderbiscuit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 308fce9. 🚀

@thunderbiscuit thunderbiscuit merged commit 308fce9 into bitcoindevkit:master Oct 30, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants