## TxBuilder v2 <https://github.com/bitcoindevkit/bdk-tx> <https://github.com/ValuedMammal/bdk/tree/feat/wallet-build-psbt-bak> ### Motivation 1. Enable creating transactions in a way that doesn't depend on `bdk_wallet`, for example it should be easy to build a tx using types from `rust-bitcoin`, `rust-miniscript`, etc. 2. problem: Right now the wallet comingles various options/params some of which are more relevant to coin selection, tx building, signing, finalizing, etc. The resulting implementation has a lot of moving parts and requires a lot of error handling. We want to tease apart and modularize these distinct activities. By contrast there should be relatively few ways that a user can screw up tx building. In general the tx builder should take the information you give it and use it to populate a psbt, and only fail because of an obvious mistake or logic error, while applying basic sanity checks like ensuring that the tx doesn't create more coins than it spends. 3. Currently when a TxBuilder instance is created, the wallet is effectively "locked" because the builder holds an exclusive reference to it, preventing the wallet from doing other tasks like revealing addresses. Since most of the work of tx building occurs during `finish`, passing in a wallet reference at this stage would represent a nice improvement to UX. ### Design/implementation #### `bdk_wallet` - Implement DataProvider for Wallet (or a helper struct) - Add UtxoOrdering - Workflow: - the wallet gets the available utxos, filtered by the params - set the target outputs - run coin selection and decide change - use the builder API to set inputs/outputs - use the updater API to update psbt - return the updated psbt and finalizer > src/wallet/tx_builder.rs ```rs impl TxBuilder { pub fn build_psbt_with_aux_rand(&mut self, params: TxParams, rng: &mut impl RngCore) -> Result<(Psbt, Finalizer), BuildPsbtError> { self.wallet.build_psbt(self.params, rng) } } ``` > src/wallet/mod.rs ```rs impl Wallet { fn build_psbt(&mut self, params: TxParams, rng: &mut impl RngCore) -> Result<(Psbt, Finalizer), BuildPsbtError> {} } ``` #### `bdk_tx` #### struct: - `Builder` - `PsbtUpdater` - `UpdateOptions` - `Finalizer` #### enum: - `Error` - `UpdatePsbtError` #### trait: - `DataProvider` - Updating a psbt requires some data retrieval like getting previous transaction data. This should be trivial to implement for wallet. #### API > src/builder.rs ```rs impl Builder { pub fn build_psbt<D>(self, provider: &mut D) -> Result<(Psbt, Finalizer), Error> where D: DataProvider, {} } ``` ### Backward compatibility Transaction building via `TxBuilder::finish` remains unchanged and behaves the same as before. The new implementation can be introduced as a feature. The main benefits of the new implementation are - Using miniscript `plan` in place of old policy module - Using `bdk_coin_select` to select coins instead of "legacy" coin_selection module Pros: minimal API change Cons: overall more code ### Deployment - [x] Develop `bdk_tx` library - [x] Use bdk-tx in `example_cli` - [x] In bdk_wallet add `TxBuilder::finish_psbt` - [x] Introduce `selector` module in bdk-wallet as a thin wrapper around `CoinSelector` used to facilitate tx building - [x] Devise a solution for `add_foreign_utxo`. This can be a new API in bdk-tx used for adding an "unplanned" input e.g. `add_psbt_input` - [ ] Write new tests ### Open questions github.com/bitcoindevkit/bdk-tx is in experimental phase and still unpublished. Does it make sense for it to be its own crate or a module in an existing project?