# Multi-Keychain Wallet [#318](https://github.com/bitcoindevkit/bdk_wallet/pull/318)
<br>
## Todo
- [ ] 1. `Wallet::create_with_params` allowed to create a wallet with a custom genesis block. Should this come in the keyring?
- [x] 2. On `Wallet::create_with_params`, the docs say `The genesis_hash (if not specified) will be inferred from keyring.network`. What if it's specified but conflicts with the keyring's network? It might be better to have this defined and checked in one place.
- [ ] 3. The `Wallet::load` and `Wallet::create_with_params` are still kind of messy. They achieve similar goals to the keyring. Needs cleanup on the design. Can `CreateParams` be made free of the generic?
- [ ] 4. Handle all `// TODO PR #318: ...` comments.
- [x] 5. Remove `KeyRingError` variants corresponding to default. Same for `LoadError`. Remove default keychain field of `LoadParams` too.
- [ ] 6. `KeyRing::new_with_descriptors` may not be needed now.
- [ ] 7. `wallet_name_from_desc` should be fixed?
- [ ] 8. Add a helper function to revert back to 2.3.0 wallet from multi-keychain wallet and use this in migration examples.
<br>
## Old PR Todo List
- [ ] Fix up the `Wallet` API docs (`K` needs to be `Ord` for example)
- [ ] Should the create_with_params take a struct of params?
- [x] `Wallet::new` should call `Wallet::create_with_params`
- [x] Wallet persistence
- [ ] Customizing genesis hash: throw if KeyRing is on Mainnet, ok otherwise.
- [x] Fix up the wallet `ChangeSet`.
- [x] Add persistence example.
- [ ] Restore tests if applicable
- [ ] Add wallet migration example from a 2.3.0 wallet
<br>
## Design Questions/Decisions
1. Should `KeyRing::new` take in a descriptor?
2. Should mismatch/missing load errors reside in `LoadError`?
3. Should `LoadMismatch` be removed?
4. `KeyRing` should have a minimal public API
<br>
## Impact on Public API
72 functions are part of the public API. This is how they are impacted by this PR.
| # | Current Wallet Impacted Methods | Changes |
| --- | ----------------------------------------- | ------------------------------------------------------------------------------------------------ |
| 1 | `Wallet::create_single` | Removed |
| 2 | `Wallet::create_from_two_path_descriptor` | Removed |
| 3 | `Wallet::create` | Now takes a `KeyRing`. |
| 4 | `Wallet::create_with_params` | The `CreateParams` type is a bit different. |
| 5 | `Wallet::load` | The `LoadParams` type is a bit different. |
| 6 | `Wallet::load_with_params` | The `LoadParams` type is a bit different. |
| 7 | `Wallet::keychains` | Very similar but now returns a map of keychains. |
| 8 | `Wallet::peek_address` | Now takes generic `K` and returns an `Option`. |
| 9 | `Wallet::reveal_next_address` | Now takes generic `K` and returns an `Option`. |
| 10 | `Wallet::reveal_addresses_to` | Now takes generic `K` and returns an `Option`. |
| 11 | `Wallet::next_unused_address` | Now takes generic `K` and returns an `Option`. |
| 12 | `Wallet::mark_used` | Now takes generic `K`. Needs work. |
| 13 | `Wallet::unmark_used` | Now takes generic `K`. Needs work. |
| 14 | `Wallet::list_unused_addresses` | Now takes generic `K` and returns an `Option`. Needs work. |
| 15 | `Wallet::derivation_of_spk` | Now returns the generic `K` keychain. |
| 16 | `Wallet::all_unbounded_spk_iters` | The keys on the map are now the generic `K`. |
| 17 | `Wallet::unbounded_spk_iters` | Now takes generic `K` and returns an `Option`. |
| 18 | `Wallet::public_descriptor` | Replaced by the `Wallet::keychains` method which returns a Map<K, PubDescriptor> |
| 19 | `Wallet::derivation_index` | Now takes generic `K`. |
| 20 | `Wallet::next_derivation_index` | Now takes generic `K` and returns an `Option`. |
| 21 | `Wallet::descriptor_checksum` | Now takes generic `K` and returns an `Option`. |
<br>
| # | Unimpacted Methods |
| --- | ------------------------------------------ |
| 1 | `Wallet::network` |
| 2 | `Wallet::is_mine` |
| 3 | `Wallet::list_unspent` |
| 4 | `Wallet::tx_details` |
| 5 | `Wallet::list_output` |
| 6 | `Wallet::checkpoints` |
| 7 | `Wallet::latest_checkpoint` |
| 8 | `Wallet::get_utxo` |
| 9 | `Wallet::insert_txout` |
| 10 | `Wallet::calculate_fee` |
| 11 | `Wallet::calculate_fee_rate` |
| 12 | `Wallet::sent_and_received` |
| 13 | `Wallet::get_tx` |
| 14 | `Wallet::transactions` |
| 15 | `Wallet::transactions_sort_by` |
| 16 | `Wallet::balance` |
| 17 | `Wallet::finalize_psbt` |
| 18 | `Wallet::cancel_tx` |
| 19 | `Wallet::get_psbt_input` |
| 20 | `Wallet::apply_update` |
| 21 | `Wallet::apply_update_events` |
| 22 | `Wallet::staged` |
| 23 | `Wallet::staged_mut` |
| 24 | `Wallet::take_staged` |
| 25 | `Wallet::tx_graph` |
| 26 | `Wallet::spk_index` |
| 27 | `Wallet::local_chain` |
| 28 | `Wallet::list_locked_outpoints` |
| 29 | `Wallet::list_locked_unspent` |
| 30 | `Wallet::is_outpoint_locked` |
| 31 | `Wallet::lock_outpoint` |
| 32 | `Wallet::unlock_outpoint` |
| 33 | `Wallet::apply_block` |
| 34 | `Wallet::apply_block_events` |
| 35 | `Wallet::apply_block_connected_to` |
| 36 | `Wallet::apply_block_connected_to_events` |
| 37 | `Wallet::apply_unconfirmed_txs` |
| 38 | `Wallet::apply_evicted_txs` |
| 39 | `Wallet::start_sync_with_revealed_spks_at` |
| 40 | `Wallet::start_sync_with_revealed_spks` |
| 41 | `Wallet::start_full_scan` |
| 42 | `Wallet::start_full_scan_at` |
<br>
| # | Will Be Removed Before Multi-Keychain |
| --- | ------------------------------------- |
| 1 | `Wallet::add_signer` |
| 2 | `Wallet::set_keymap` |
| 3 | `Wallet::set_keymaps` |
| 4 | `Wallet::get_signers` |
| 5 | `Wallet::build_tx` |
| 6 | `Wallet::build_fee_bump` |
| 7 | `Wallet::sign` |
| 8 | `Wallet::policies` |
| 9 | `Wallet::secp_ctx` |
## Follow-Ups
1. Example showcasing maintaining a default keychain?
2. Example emulating wallet creation in bitcoin-cli.
3. 2-Keychain wrapper around wallet?