Skip to content

refactor(key-wallet): dedupe core account types via shared trait + composition#728

Merged
xdustinface merged 3 commits into
claude/adoring-booth-151626from
claude/managed-account-dedupe
May 5, 2026
Merged

refactor(key-wallet): dedupe core account types via shared trait + composition#728
xdustinface merged 3 commits into
claude/adoring-booth-151626from
claude/managed-account-dedupe

Conversation

@QuantumExplorer

Copy link
Copy Markdown
Member

Summary

Follow-up to #711 that eliminates the near-total method duplication between ManagedCoreFundsAccount and ManagedCoreKeysAccount that the rename split introduced.

Three coordinated changes:

  1. Shared trait owns the duplicated logic. All 21 previously-duplicated methods (address-pool / key-derivation / index queries) move into ManagedAccountTrait as default impls, expressed in terms of 8 primitive accessors. The bodies now live exactly once.
  2. Funds account composes the keys account. ManagedCoreFundsAccount is now a thin wrapper: { core: ManagedCoreKeysAccount, balance, utxos, spent_outpoints }. It implements the trait by delegating the 8 primitives to core. Only funds-specific operations (transaction recording, UTXO updates, balance computation, Standard-account receive/change paths) remain inherent.
  3. Fields privatized on both structs. External access now goes through trait accessors or new inherent getters (balance(), balance_mut(), utxos(), utxos_mut(), etc.). Field accesses migrated to method calls across key-wallet, key-wallet-ffi, key-wallet-manager, and dash-spv test helpers.

The custom Deserialize impl is rewritten: it deserializes the inner core (which carries transactions) and rebuilds spent_outpoints from those inputs. Wire format changes (nested core object); serialization compatibility was explicitly out of scope per the discussion preceding this PR.

Numbers

  • managed_core_funds_account.rs: 1348 → 677 lines (-49%)
  • managed_core_keys_account.rs: 666 → 157 lines (-76%)
  • managed_account_trait.rs: 57 → 597 lines (the relocated shared logic)
  • Net: -621 lines across 24 files

Test plan

  • cargo check --workspace --all-targets — clean
  • cargo clippy --workspace --all-targets --all-features — clean (no warnings)
  • cargo test --workspace --lib — 1802 passed, 0 failed
  • cargo test -p key-wallet --lib — 461 passed, 0 failed
  • dashd integration tests in dash-spv (need setup-dashd.py; not run locally)
  • CI passes against the refactor(key-wallet): split ManagedCoreAccount into funds + keys variants #711 base

Notes

  • Targets claude/adoring-booth-151626 (PR refactor(key-wallet): split ManagedCoreAccount into funds + keys variants #711's branch) so it stacks cleanly on the structural rename.
  • Wire-format change in the serde representation of ManagedCoreFundsAccount is intentional — transactions and account-type fields now sit under a core object. Persisted state from prior versions will not deserialize unmigrated; serialization compat was deemed not required.

🤖 Generated with Claude Code

…mposition

Eliminates the near-total method duplication between `ManagedCoreFundsAccount`
and `ManagedCoreKeysAccount` introduced by the rename split:

- Move all 21 shared methods (address-pool / key-derivation / index queries)
  into `ManagedAccountTrait` as default impls, expressed in terms of 8
  primitive accessors. The bodies now live exactly once.
- Restructure `ManagedCoreFundsAccount` as composition: it now wraps a
  `ManagedCoreKeysAccount` (`core` field) and adds the funds-only state
  (`balance`, `utxos`, `spent_outpoints`). It implements the trait by
  delegating the 8 primitives to `core`; only funds-specific operations
  remain as inherent methods (transaction recording, UTXO updates, balance
  computation, Standard-account receive/change paths).
- Privatize all fields on both structs. External access goes through
  the trait accessors or new inherent getters/setters (`balance()`,
  `balance_mut()`, `utxos()`, `utxos_mut()`, etc.). Field accesses across
  `key-wallet`, `key-wallet-ffi`, `key-wallet-manager`, and `dash-spv`
  test helpers migrated to method calls.
- Replace the manual `Deserialize` impl: it now deserializes the inner
  `core` (which carries `transactions`) and rebuilds `spent_outpoints`
  from those transaction inputs. Wire format changes (nested `core`
  object); serialization compatibility was explicitly out of scope.

Net diff: -621 lines across 24 files. `managed_core_funds_account.rs`
shrinks 1348 -> 677 lines; `managed_core_keys_account.rs` shrinks 666 -> 157.

Verified:
- cargo check --workspace --all-targets: clean
- cargo clippy --workspace --all-targets --all-features: clean
- cargo test --workspace --lib: 1802 passed, 0 failed
- cargo test -p key-wallet --lib: 461 passed, 0 failed
@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: be35bc3b-eb3d-4d32-8d94-91d9e57e76ad

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/managed-account-dedupe

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented May 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 52.91139% with 186 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.94%. Comparing base (425bc19) to head (3335954).

Files with missing lines Patch % Lines
...allet/src/managed_account/managed_account_trait.rs 38.17% 149 Missing ⚠️
.../src/managed_account/managed_core_funds_account.rs 76.59% 11 Missing ⚠️
key-wallet-ffi/src/address_pool.rs 0.00% 9 Missing ⚠️
key-wallet-ffi/src/managed_account.rs 30.76% 9 Missing ⚠️
.../src/managed_account/managed_account_collection.rs 33.33% 2 Missing ⚠️
...t/src/managed_account/managed_core_keys_account.rs 86.66% 2 Missing ⚠️
...wallet/src/transaction_checking/account_checker.rs 81.81% 2 Missing ⚠️
key-wallet-ffi/src/managed_wallet.rs 50.00% 1 Missing ⚠️
key-wallet-ffi/src/transaction.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@                       Coverage Diff                       @@
##           claude/adoring-booth-151626     #728      +/-   ##
===============================================================
+ Coverage                        70.28%   70.94%   +0.65%     
===============================================================
  Files                              320      320              
  Lines                            68527    68247     -280     
===============================================================
+ Hits                             48167    48417     +250     
+ Misses                           20360    19830     -530     
Flag Coverage Δ
core 75.81% <ø> (ø)
ffi 45.75% <20.00%> (+2.37%) ⬆️
rpc 20.00% <ø> (ø)
spv 87.24% <ø> (-0.08%) ⬇️
wallet 69.80% <55.13%> (+1.23%) ⬆️
Files with missing lines Coverage Δ
key-wallet-manager/src/lib.rs 62.83% <ø> (ø)
...-wallet/src/transaction_checking/wallet_checker.rs 99.39% <100.00%> (ø)
...c/wallet/managed_wallet_info/asset_lock_builder.rs 79.61% <100.00%> (ø)
...src/wallet/managed_wallet_info/managed_accounts.rs 19.85% <ø> (ø)
...allet/managed_wallet_info/wallet_info_interface.rs 81.98% <100.00%> (ø)
key-wallet-ffi/src/managed_wallet.rs 81.34% <50.00%> (+2.16%) ⬆️
key-wallet-ffi/src/transaction.rs 0.00% <0.00%> (ø)
.../src/managed_account/managed_account_collection.rs 55.66% <33.33%> (ø)
...t/src/managed_account/managed_core_keys_account.rs 55.12% <86.66%> (+55.12%) ⬆️
...wallet/src/transaction_checking/account_checker.rs 67.02% <81.81%> (ø)
... and 4 more

... and 16 files with indirect coverage changes

…fields

Per review feedback:

- Rename `ManagedCoreFundsAccount::core` -> `keys`. Method accessors
  rename `core()` / `core_mut()` -> `keys()` / `keys_mut()`. The serde
  helper struct field also renames `core` -> `keys` (changes the wire
  format again, still fine since serialization compat is out of scope).
- Make `balance` and `utxos` `pub` again on `ManagedCoreFundsAccount`.
  Drop the now-redundant `balance()` / `balance_mut()` / `utxos()` /
  `utxos_mut()` inherent methods. Call sites that had been migrated to
  method calls revert to direct field access (`account.balance`,
  `account.utxos`). `spent_outpoints` stays private — it carries an
  invariant tied to `keys.transactions()`.

Verified: cargo check + clippy clean across the workspace; all
1802 lib tests pass; key-wallet 461/461.

@QuantumExplorer QuantumExplorer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Self Reviewed

- Drop the `[`Self::record_transaction`]` link from the
  `ManagedCoreFundsAccount` doc comment; `record_transaction` is
  `pub(crate)` and rustdoc with `-D warnings` rejects intra-doc links
  from a public item to a private one.
- `cargo fmt --all` to fix import ordering (placement of the new
  `ManagedAccountTrait` use lines) and a long-line wrap in
  `account_checker.rs`.

Tests + clippy still clean locally.
@xdustinface
xdustinface merged commit 4c461c5 into claude/adoring-booth-151626 May 5, 2026
37 checks passed
@xdustinface
xdustinface deleted the claude/managed-account-dedupe branch May 5, 2026 09:21
QuantumExplorer added a commit that referenced this pull request May 5, 2026
…mposition (#728)

* refactor(key-wallet): dedupe core account types via shared trait + composition

Eliminates the near-total method duplication between `ManagedCoreFundsAccount`
and `ManagedCoreKeysAccount` introduced by the rename split:

- Move all 21 shared methods (address-pool / key-derivation / index queries)
  into `ManagedAccountTrait` as default impls, expressed in terms of 8
  primitive accessors. The bodies now live exactly once.
- Restructure `ManagedCoreFundsAccount` as composition: it now wraps a
  `ManagedCoreKeysAccount` (`core` field) and adds the funds-only state
  (`balance`, `utxos`, `spent_outpoints`). It implements the trait by
  delegating the 8 primitives to `core`; only funds-specific operations
  remain as inherent methods (transaction recording, UTXO updates, balance
  computation, Standard-account receive/change paths).
- Privatize all fields on both structs. External access goes through
  the trait accessors or new inherent getters/setters (`balance()`,
  `balance_mut()`, `utxos()`, `utxos_mut()`, etc.). Field accesses across
  `key-wallet`, `key-wallet-ffi`, `key-wallet-manager`, and `dash-spv`
  test helpers migrated to method calls.
- Replace the manual `Deserialize` impl: it now deserializes the inner
  `core` (which carries `transactions`) and rebuilds `spent_outpoints`
  from those transaction inputs. Wire format changes (nested `core`
  object); serialization compatibility was explicitly out of scope.

Net diff: -621 lines across 24 files. `managed_core_funds_account.rs`
shrinks 1348 -> 677 lines; `managed_core_keys_account.rs` shrinks 666 -> 157.

Verified:
- cargo check --workspace --all-targets: clean
- cargo clippy --workspace --all-targets --all-features: clean
- cargo test --workspace --lib: 1802 passed, 0 failed
- cargo test -p key-wallet --lib: 461 passed, 0 failed

* refactor(key-wallet): rename core->keys, expose balance/utxos as pub fields

Per review feedback:

- Rename `ManagedCoreFundsAccount::core` -> `keys`. Method accessors
  rename `core()` / `core_mut()` -> `keys()` / `keys_mut()`. The serde
  helper struct field also renames `core` -> `keys` (changes the wire
  format again, still fine since serialization compat is out of scope).
- Make `balance` and `utxos` `pub` again on `ManagedCoreFundsAccount`.
  Drop the now-redundant `balance()` / `balance_mut()` / `utxos()` /
  `utxos_mut()` inherent methods. Call sites that had been migrated to
  method calls revert to direct field access (`account.balance`,
  `account.utxos`). `spent_outpoints` stays private — it carries an
  invariant tied to `keys.transactions()`.

Verified: cargo check + clippy clean across the workspace; all
1802 lib tests pass; key-wallet 461/461.

* fix(key-wallet): satisfy CI rustfmt + drop rustdoc link to private item

- Drop the `[`Self::record_transaction`]` link from the
  `ManagedCoreFundsAccount` doc comment; `record_transaction` is
  `pub(crate)` and rustdoc with `-D warnings` rejects intra-doc links
  from a public item to a private one.
- `cargo fmt --all` to fix import ordering (placement of the new
  `ManagedAccountTrait` use lines) and a long-line wrap in
  `account_checker.rs`.

Tests + clippy still clean locally.
xdustinface pushed a commit that referenced this pull request May 5, 2026
…riants (#711)

* refactor(key-wallet): split ManagedCoreAccount into funds + keys variants

Move the existing struct out of `managed_account/mod.rs` into a dedicated
`managed_core_funds_account.rs` and rename it to `ManagedCoreFundsAccount`
to make room for a sibling `ManagedCoreKeysAccount` that omits funds-tracking
state (`balance`, `utxos`, `spent_outpoints`). The keys variant is intended
for accounts that derive special-purpose keys (identity registration, asset
locks, masternode provider keys) but is not yet wired into
`ManagedAccountCollection` — that migration follows in a subsequent PR.

This change is purely structural: `ManagedAccountCollection` continues to
store `ManagedCoreFundsAccount` for every account type and behavior is
unchanged. The C ABI is preserved — `FFIManagedCoreAccount` and the
`managed_core_account_*` C functions keep their original names and now wrap
the renamed Rust struct internally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(key-wallet): rustfmt + qualify intra-doc link to ManagedCoreFundsAccount

- Sort imports and rewrap long signatures (rustfmt fixes flagged by pre-commit)
- Qualify the `[\`ManagedCoreFundsAccount\`]` intra-doc links in
  `managed_core_keys_account.rs` to `[\`crate::managed_account::ManagedCoreFundsAccount\`]`
  so rustdoc can resolve them under `-D warnings`

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(key-wallet): fix broken receive-address example in IMPLEMENTATION_SUMMARY

The example called `get_next_receive_address()`, which is not a method on
this struct. Replace with the real `next_receive_address(...)` signature so
the snippet compiles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(key-wallet): dedupe core account types via shared trait + composition (#728)

* refactor(key-wallet): dedupe core account types via shared trait + composition

Eliminates the near-total method duplication between `ManagedCoreFundsAccount`
and `ManagedCoreKeysAccount` introduced by the rename split:

- Move all 21 shared methods (address-pool / key-derivation / index queries)
  into `ManagedAccountTrait` as default impls, expressed in terms of 8
  primitive accessors. The bodies now live exactly once.
- Restructure `ManagedCoreFundsAccount` as composition: it now wraps a
  `ManagedCoreKeysAccount` (`core` field) and adds the funds-only state
  (`balance`, `utxos`, `spent_outpoints`). It implements the trait by
  delegating the 8 primitives to `core`; only funds-specific operations
  remain as inherent methods (transaction recording, UTXO updates, balance
  computation, Standard-account receive/change paths).
- Privatize all fields on both structs. External access goes through
  the trait accessors or new inherent getters/setters (`balance()`,
  `balance_mut()`, `utxos()`, `utxos_mut()`, etc.). Field accesses across
  `key-wallet`, `key-wallet-ffi`, `key-wallet-manager`, and `dash-spv`
  test helpers migrated to method calls.
- Replace the manual `Deserialize` impl: it now deserializes the inner
  `core` (which carries `transactions`) and rebuilds `spent_outpoints`
  from those transaction inputs. Wire format changes (nested `core`
  object); serialization compatibility was explicitly out of scope.

Net diff: -621 lines across 24 files. `managed_core_funds_account.rs`
shrinks 1348 -> 677 lines; `managed_core_keys_account.rs` shrinks 666 -> 157.

Verified:
- cargo check --workspace --all-targets: clean
- cargo clippy --workspace --all-targets --all-features: clean
- cargo test --workspace --lib: 1802 passed, 0 failed
- cargo test -p key-wallet --lib: 461 passed, 0 failed

* refactor(key-wallet): rename core->keys, expose balance/utxos as pub fields

Per review feedback:

- Rename `ManagedCoreFundsAccount::core` -> `keys`. Method accessors
  rename `core()` / `core_mut()` -> `keys()` / `keys_mut()`. The serde
  helper struct field also renames `core` -> `keys` (changes the wire
  format again, still fine since serialization compat is out of scope).
- Make `balance` and `utxos` `pub` again on `ManagedCoreFundsAccount`.
  Drop the now-redundant `balance()` / `balance_mut()` / `utxos()` /
  `utxos_mut()` inherent methods. Call sites that had been migrated to
  method calls revert to direct field access (`account.balance`,
  `account.utxos`). `spent_outpoints` stays private — it carries an
  invariant tied to `keys.transactions()`.

Verified: cargo check + clippy clean across the workspace; all
1802 lib tests pass; key-wallet 461/461.

* fix(key-wallet): satisfy CI rustfmt + drop rustdoc link to private item

- Drop the `[`Self::record_transaction`]` link from the
  `ManagedCoreFundsAccount` doc comment; `record_transaction` is
  `pub(crate)` and rustdoc with `-D warnings` rejects intra-doc links
  from a public item to a private one.
- `cargo fmt --all` to fix import ordering (placement of the new
  `ManagedAccountTrait` use lines) and a long-line wrap in
  `account_checker.rs`.

Tests + clippy still clean locally.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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