Refactor bdk-cli structure #278
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #278 +/- ##
==========================================
- Coverage 26.97% 24.79% -2.18%
==========================================
Files 10 22 +12
Lines 3882 3678 -204
==========================================
- Hits 1047 912 -135
+ Misses 2835 2766 -69
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
8fc06d8 to
2ce28b2
Compare
|
concept ACK, this is a big change might be a good idea to do a live walk through some time on discord to help with the review process. |
Alright, anytime we are chanced. Also, I would want most of the PRs to get in before this one because it will be challenging for others to rebase and fix conflicts. |
04dd213 to
de1fc98
Compare
53a6566 to
0c89aea
Compare
- move all blockchain clients code into the backend subdirectory - move commands.rs content into commands subdirectory
- split util fns into `descriptors` and `common`
- move persister into wallet subdirectory - update imports in payjoin module
- split handlers into top level commands config, key and descriptors
- move handler fns into offline, online, wallets modules
- split handler fns into repl - add entry point to the handlers subdir - add wallet subdir entry point
- add trait for formatting outputs - add types for presenting data to the output - refactor offline mod to use types
- add types for descriptor, key and wallets mods
- add simple table helper fn for creating tables - refactor types to use simple table helper - add type defs for key, wallets and descriptors
- rebase master for bip322 feature - update types to use simple table helper
notmandatory
left a comment
There was a problem hiding this comment.
ACK 188e68d
I like the new structure and added generic/context type safety for adding new commands. It's a big change but certainly also a big improvement.
As discussed on the walk-through today I know you still have some other PRs that need to be merged before this one and then incorporated, but once those are in it looks ready to go.
I focused my review on the overall design and did a simple manual smoke test: generate descriptors, config wallet, get new address, send btc to wallet, sync wallet, send btc from wallet.
- Update bdk_wallet to v2.4.0 and other deps - Add wallet events to RPC, electrum, esplora and kyoto clients
- add compile taproot descriptor with randomized unspendable internal key
- Adds payjoin persistence
de36eee to
b7abe68
Compare
b7abe68 to
b3fe860
Compare
sdmg15
left a comment
There was a problem hiding this comment.
Overall looks good.
So far I have two questions:
-
Why does
payjoinrequires a folder, couldn't things inside it falls either underutilsorhandlers? Because for me when having it as a separate folder it feels like most of the features would also have their own dedicated folders which isn't the case. -
Most of the
.rsaren't exported in the module tree which makes rust-analyzer unable to find those symbols. Is this intentional?
| ))] | ||
| mod payjoin; | ||
| #[cfg(any(feature = "sqlite", feature = "redb"))] | ||
| mod persister; |
There was a problem hiding this comment.
Why is this not feature-gated anymore?
There was a problem hiding this comment.
Because I moved the new_wallet fn into the module, which the db gating does not apply to.
|
|
||
| cmd.execute(&mut ctx)?.write_out(std::io::stdout())?; | ||
| } | ||
| CliSubCommand::Completions { shell: _ } => unimplemented!(), |
There was a problem hiding this comment.
I think there's missing implementation of this?
There was a problem hiding this comment.
I have added it in the new updated push
| Ok(RuntimeWallet::Standard(Box::new(new_wallet( | ||
| self.network, | ||
| &self.wallet_opts, | ||
| )?))) |
There was a problem hiding this comment.
Is this additional check needed? Doesn't the one on lines 94-97 covers this?
There was a problem hiding this comment.
Thank you for catching this
| }; | ||
|
|
||
| impl OfflineWalletSubCommand { | ||
| pub fn execute(&self, ctx: &mut AppContext<OfflineOperations<'_>>) -> Result<(), Error> { |
There was a problem hiding this comment.
Just a nit: can we have an alias in the form of type OfflineCtx<'a> = AppContext<OfflineOperations<'a>>; something similar to Online.
There was a problem hiding this comment.
Okay. I will revisit this after the merge.
The |
I don't want to hold this back but I'm wondering what can stay at top level of the My thoughts were that components that belong to the same functionalities will logically fall into For example for the DNS feature you just added I was expecting a structure similar to: Likewise for the payjoin: I think this helps grouping related files of a feature together. |
Good suggestion. I will implement. Thank you |
Done. |
24710d7 to
e86b45b
Compare
- migrate dns payment instruction feature
e3b3355 to
a08225e
Compare
|
@sdmg15 if you are satisfied, you can ack so I will merge. Thank you |
| } | ||
|
|
||
| #[derive(Parser, Debug, Clone, PartialEq)] | ||
| pub struct NewAddressCommand {} |
There was a problem hiding this comment.
Non blocking: I think there's unneeded braces for all theses unit type structs.
There was a problem hiding this comment.
Removed the braces for all unit types
- remove braces for unit type structs
a08225e to
63f769a
Compare
6000dd5 test: Add tests for dns payment instn feature (Vihiga Tyonum) b4e1081 fix(Justfile): fix test-threads to max 2 (Vihiga Tyonum) f809a7e test: add more tests for createtx, bip322 (Vihiga Tyonum) a993315 test: Add sp createtx test (Vihiga Tyonum) d710838 test: add test for multiple recipients and sp code (Vihiga Tyonum) a040a55 test: add tests for repl, transactions & send_all (Vihiga Tyonum) f17a7ef fix(repl): Remove null printed after repl output (Vihiga Tyonum) d425f5b test: split tests according to typestate (Vihiga Tyonum) 3293764 fix(proxy_opts): add saving and reading proxy_opts (Vihiga Tyonum) 3465513 ref(verbose): Drop `verbose` flag from tests (Vihiga Tyonum) 702d259 test(online): Add test transaction full cycle (Vihiga Tyonum) c013da0 test: Add integration tests for offline wallet ops (Vihiga Tyonum) 0d3c1a9 test: Add wallets, descriptor, compile & config (Vihiga Tyonum) d8e2887 test: Add helper fns & integration tests for key (Vihiga Tyonum) Pull request description: <!-- You can erase any parts of this template not applicable to your Pull Request. --> ### Description <!-- Describe the purpose of this PR, what's being adding and/or fixed --> This PR builds on #278 and introduces integration tests for bdk-cli. It replaces manual `std::process::Command` boilerplate with the `assert_cmd` library, allowing us to perform black-box testing against the compiled binary. Features covered so far include: - key: generate, derive, and restore - wallets: list wallets - wallet config: save config, read config. - descriptor: generate descriptor - compile: policy compiler - offline wallet operations: new_address, unused_address, balance, unspent, transactions, policies, public_descriptor, create_tx, combine_psbt ### Notes to the reviewers <!-- In this section you can include notes directed to the reviewers, like explaining why some parts of the PR were done in a specific way --> ## Changelog notice <!-- Notice the release manager should include in the release tag message changelog --> <!-- See https://keepachangelog.com/en/1.0.0/ for examples --> - Introduces the BdkCli helper struct to inject context state into base commands. - Dropped `verbose` flag from wallets as it was applicable to only `Pbst` ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk-cli/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing Top commit has no ACKs. Tree-SHA512: ea4adf734310f4ec494564f75b904835520b4625547859bf25c529b96f2f7fef823dc220dbe4eaf4856e2dd6fe06daa9f97bddc7a565f5e19185fdeea963202e
Description
This PR restructures the bdk-cli codebase to move away from a monolithic handling model towards a modular architecture. The primary goal is to improve code readability, simplify the addition of new features, and decouple core logic into smaller modules.
Fixes #273
Notes to the reviewers
While trying to achieve the above-stated goal, I took maximum care to avoid introducing new bugs. As a result, the existing execution logic was preserved as much as possible.
This PR introduces two new subdirectories under
src:config,descriptor,key,offline,onlineandreplmodules. They each contain structures for the subcommand, execution logic, and implementation of the top-level enum.typesmodule that defines response structures.Other notable changes
clientmodule, and it defines the enum that holds all the available clients, as well as implements the functionalities such as broadcasting transactions and syncing operations.AppCommandtrait that defines how each subcommand should be structured and theexecutemethod they should implement.AppContextstruct that holds the universal parameters that subcommands may need. Each subcommand'sexecutemethod accepts this struct and uses the params for its execution.FormatOutputtrait, which is implemented by alltypespresenting data response to the user.walletsubdirectory into thepersistermodule that defines all structures and functionalities related to persistence.Init,OfflineOperationsandOnlineOperationsstate structs were introduced, and AppContext is generic over these states. This moved the validation from runtime to compile time.FormatOutput::write_outand made it generic over the Write trait to allow for flexibility in testingruntimemodule. Also, added theRuntimeWalletenum to return options of a persisted wallet and a standard non-persisted wallet. The WalletRuntime struct is a wrapper that determines the type of wallet needed and initialises it and handles loading of a wallet from config.Request-Response Cycle
The following outlines how requests are handled and responses are generated after introducing changes to the structure:
When a user enters a set of commands, those commands are received and parsed by the Clap library into Rust structures, such as
CliOpts,WalletOpts, and subcommands. This process takes place in thecommandsmodule.The parsed request is then passed to the
mainmodule. The main module uses theruntimemodule to interpret the request and initialize any necessary resources (such as wallets, databases, and clients) needed to fulfill the request. It then routes the request to the appropriate handler for execution.Once a particular handler receives the request along with all the required resources, it processes the specific command using the
AppContextand prepares a response.After processing is complete, the handler calls the
outputmodule to format the result, serialize it into JSON, and return it to the terminal.Changelog notice
key derivesubcommand, when printing help message, the clap arg for env=“PATH” often pull all system and displays all system paths. This has been changed to derivation_path I.e. env=“DERIVATION_PATH” to prevent clap from picking the system paths and rendering itChecklists
All Submissions:
cargo fmtandcargo clippybefore committing