Skip to content

Conversation

@xdustinface
Copy link
Collaborator

@xdustinface xdustinface commented Feb 1, 2026

  • Moves parts of it out into separate functions/helpers
  • Combines the gap limit maintenance cases since the ManagedAccountType::Standard is also already handled in ManagedAccountType::address_pools_mut
  • Early return in case of an already known transaction, adding the record again and updating UTXOs is no-op if the transaction is known already.

Summary by CodeRabbit

  • New Features

    • Transaction recording with automatic wallet balance and UTXO updates for spendable accounts.
    • Mutable account access to enable direct account updates.
  • Improvements

    • Streamlined per-account transaction processing with a single summary log per transaction (includes net change, received, sent).
    • Enhanced transaction context tracking and display (confirmation state, block info, timestamps).
  • Refactor

    • Unified account lookup logic for consistent behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 1, 2026

📝 Walkthrough

Walkthrough

Refactors account lookup into a macro-backed accessor and adds a mutable getter. Adds per-account transaction recording and UTXO update helpers. Reworks WalletTransactionChecker to accept TransactionContext, delegate per-account recording, add TransactionContext helpers/Display, and consolidate transaction logging and gap-limit handling.

Changes

Cohort / File(s) Summary
Account Accessor Consolidation
key-wallet/src/managed_account/managed_account_collection.rs
Added private macro get_by_account_type_match_impl, refactored get_by_account_type_match to use it, and added pub fn get_by_account_type_match_mut(...) -> Option<&mut ManagedAccount> for mutable access.
Transaction Recording & UTXO Management
key-wallet/src/managed_account/mod.rs
Added private fn update_utxos(&mut self, tx: &Transaction, account_match: &AccountMatch, context: TransactionContext) and crate-visible pub(crate) fn record_transaction(&mut self, tx: &Transaction, account_match: &AccountMatch, context: TransactionContext) to record TransactionRecord and update UTXOs; introduced related imports (Transaction, Txid, BTreeSet).
Transaction Checking Refactor
key-wallet/src/transaction_checking/wallet_checker.rs
Changed WalletTransactionChecker::check_transaction signature to include context: TransactionContext and wallet: &mut Wallet; added Display impl and helper methods on TransactionContext; refactored flow to early-return when not updating, identify affected accounts, call get_by_account_type_match_mut() and account.record_transaction(...) per account, streamline gap-limit/address usage handling, and consolidate final logging and metadata increment.

Sequence Diagram

sequenceDiagram
    participant Checker as "WalletTransactionChecker" rect rgba(60,120,200,0.5)
    participant Account as "ManagedAccount" rect rgba(80,200,120,0.5)
    participant UTXO as "UTXO Store" rect rgba(200,160,60,0.5)

    Checker->>Checker: check_transaction(tx, context, wallet, update_state)
    alt update_state && tx relevant
        Checker->>Checker: identify affected accounts (AccountMatch)
        loop per affected account
            Checker->>Checker: get_by_account_type_match_mut(account_type_match)
            Checker->>Account: record_transaction(tx, account_match, context)
            Account->>Account: create TransactionRecord
            Account->>UTXO: update_utxos(tx, account_match, context)
            Account->>Checker: mark addresses used / update pools
        end
        Checker->>Checker: compute net_change & log final summary
        Checker->>Checker: increment wallet.metadata.total_transactions
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I nibble code and stitch a macro seam,

I fold new getters into the stream.
I tally coins and mark the spent,
I hop through logs — each tx well sent.
Hooray, the ledger hums in green!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective of the PR, which is to refactor and cleanup the WalletTransactionChecker::check_transaction method by extracting logic into separate functions and simplifying the implementation.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/check-transaction

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@key-wallet/src/managed_account/managed_account_collection.rs`:
- Around line 23-105: The PlatformPayment branch in the
get_by_account_type_match_impl! macro currently returns None and must instead
build a PlatformPaymentAccountKey from AccountTypeMatch::PlatformPayment's
account_index and key_class and use the same accessor to look it up; update the
AccountTypeMatch::PlatformPayment arm to construct PlatformPaymentAccountKey {
account: *account_index, key_class: *key_class } and call
$self.platform_payment_accounts.$get(&key) (mirroring the Dashpay arms) so
platform_payment_accounts are properly returned by
get_by_account_type_match_impl!.
🧹 Nitpick comments (2)
key-wallet/src/transaction_checking/wallet_checker.rs (2)

162-197: Per-account processing looks correct, but silently skipping gap limit maintenance warrants logging.

The flow properly:

  1. Records the transaction and updates UTXOs via account.record_transaction
  2. Marks involved addresses as used
  3. Maintains gap limits for address pools

However, when extended_public_key_for_account_type returns None (lines 176-181), the code silently continues without maintaining gap limits. This could leave address pools in an inconsistent state for watch-only wallets or accounts without xpub access.

Consider logging when gap limit maintenance is skipped
             let Some(xpub) = wallet.extended_public_key_for_account_type(
                 &account_match.account_type_match.to_account_type_to_check(),
                 account_match.account_type_match.account_index(),
             ) else {
+                tracing::debug!(
+                    account_index = ?account_match.account_type_match.account_index(),
+                    "Skipping gap limit maintenance: no xpub available for account"
+                );
                 continue;
             };

163-163: Clone of affected_accounts is necessary but could be documented.

The .clone() is required because result.new_addresses is mutated during iteration (line 186). This is correct but not immediately obvious.

Optional: Add a brief comment explaining the clone
-        for account_match in result.affected_accounts.clone() {
+        // Clone required: we modify result.new_addresses while iterating
+        for account_match in result.affected_accounts.clone() {

@xdustinface xdustinface force-pushed the refactor/check-transaction branch from 1b3de48 to a36ee4e Compare February 1, 2026 12:29
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@key-wallet/src/transaction_checking/wallet_checker.rs`:
- Around line 74-75: Update the doc comment for the wallet_checker::block_hash
method: it currently reads "Get the block height if confirmed" but the function
returns an Option<BlockHash>, so change the comment to accurately describe that
it returns the block hash if the transaction is confirmed (e.g., "Get the block
hash if confirmed" or similar). Ensure the corrected doc refers to the block
hash and the Option return semantics for the block_hash method.
🧹 Nitpick comments (2)
key-wallet/src/transaction_checking/wallet_checker.rs (2)

162-197: Consider documenting partial-update behavior for multi-account transactions.

The per-account processing loop can partially succeed: if maintain_gap_limit fails for one account, other accounts have already been updated via record_transaction. This isn't necessarily wrong, but the non-atomic behavior across multiple affected accounts should be documented or considered.

The error logging on lines 188-193 is appropriate for observability, but callers may not be aware that a transaction could be recorded in some accounts but not have proper gap-limit maintenance in others.

💡 Optional: Add a comment documenting the behavior
         // Process each affected account
+        // Note: Processing is best-effort per account. If gap-limit maintenance fails
+        // for one account, other accounts will still have been updated.
         for account_match in result.affected_accounts.clone() {

176-181: Silent skip when extended public key is unavailable.

When extended_public_key_for_account_type returns None, the loop continues without logging. This could mask configuration issues for accounts that should have an xpub. Consider adding a debug/trace log for observability.

📋 Optional: Add trace logging
             let Some(xpub) = wallet.extended_public_key_for_account_type(
                 &account_match.account_type_match.to_account_type_to_check(),
                 account_match.account_type_match.account_index(),
             ) else {
+                tracing::trace!(
+                    account_type = ?account_match.account_type_match,
+                    "Skipping gap limit maintenance - no extended public key available"
+                );
                 continue;
             };

- Moves parts of it out into separate functions/helpers
- Combines the gap limit maintenance cases since the `ManagedAccountType::Standard` is also already handled in `ManagedAccountType::address_pools_mut`
- Early return in case of an already known transaction, adding the record again and updating UTXOs is no-op if the transaction is known already.
@xdustinface xdustinface force-pushed the refactor/check-transaction branch from a36ee4e to 330a8ea Compare February 1, 2026 12:36
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