Skip to content

Conversation

@xdustinface
Copy link
Collaborator

@xdustinface xdustinface commented Jan 7, 2026

We currently keep track of immature balance separately from other balances with the immature_balance function. This PR drops the extra function, adds WalletBalance.immature and changes the balance tracking so that we have all balances in one place. It also fixes a mix-up between locked and immature balance in FFI.

Based on:

Summary by CodeRabbit

Release Notes

  • New Features

    • Balance breakdown now includes an immature component and exposes it in the public balance retrieval surface.
    • Added locked balance visibility alongside existing categories.
  • Tests

    • Added unit and integration tests covering immature and locked UTXO handling and coinbase maturity transitions.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 7, 2026

📝 Walkthrough

Walkthrough

Added explicit immature balance tracking: WalletBalance gained an immature field propagated through core balance logic, FFI types/signatures, managed account/wallet code, and tests; WalletInfoInterface::immature_balance was removed and balance updates now include immature computations and maturation handling.

Changes

Cohort / File(s) Summary
FFI API & Headers
key-wallet-ffi/FFI_API.md, key-wallet-ffi/include/key_wallet_ffi.h
managed_wallet_get_balance signature updated to include immature_out; FFIBalance now includes locked field; docs/safety notes updated.
FFI Implementations
key-wallet-ffi/src/managed_wallet.rs, key-wallet-ffi/src/managed_account.rs, key-wallet-ffi/src/types.rs
FFI functions now populate immature and locked; From<WalletBalance> for FFIBalance maps immature from balance.immature() and adds locked.
Core Balance Type
key-wallet/src/wallet/balance.rs
WalletBalance gained immature field, constructor updated, immature() getter added, total() and AddAssign updated, Display updated to include immature.
Balance Calculation
key-wallet/src/managed_account/mod.rs
update_balance now accumulates immature UTXOs and constructs WalletBalance with immature and locked values.
Wallet Info Interface
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
Removed immature_balance() from trait/impl; update_synced_height now triggers update_balance to refresh cached balance.
Transaction Checking & Tests
key-wallet/src/transaction_checking/wallet_checker.rs
Removed automatic cache-update import; tests adjusted to advance synced height explicitly and use balance().immature().
Unit & Integration Tests
key-wallet/src/tests/balance_tests.rs, key-wallet/src/tests/mod.rs, key-wallet-manager/tests/spv_integration_tests.rs
Added balance unit tests for immature/coinbase/locked/unconfirmed cases; added SPV integration test for coinbase maturation and a create_coinbase_transaction helper.
Test Utilities
key-wallet/src/test_utils/mod.rs, key-wallet/src/test_utils/account.rs
Added test utils module and ManagedAccount::new_test_bip44 helper for tests.

Sequence Diagram(s)

sequenceDiagram
    participant Client as FFI Caller
    participant Wallet as ManagedWallet
    participant Account as ManagedAccount
    participant UTXO as UTXO Tracker/DB

    Client->>Wallet: managed_wallet_get_balance()
    Wallet->>Account: request current WalletBalance
    Account->>UTXO: query UTXO set (confirmed, unconfirmed, immature, locked)
    UTXO-->>Account: return categorized UTXOs
    Account->>Account: compute WalletBalance {confirmed, unconfirmed, immature, locked, total}
    Account-->>Wallet: WalletBalance
    Wallet->>Client: populate out params including immature_out, locked_out, total_out
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • ZocoLini

"🐇 I hopped through UTXOs under moonlight bright,
Immature coins now wait, then see the light,
From account to FFI I nibbled each byte,
Tests hum and mature as blocks reach their height,
A carrot of balance, all tidy and right."

🚥 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 and concisely describes the main objective of the PR: unifying immature balance tracking with the other balance components in WalletBalance.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f25b0c and aa5235d.

📒 Files selected for processing (14)
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/test_utils/mod.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/test_utils/mod.rs
🧰 Additional context used
📓 Path-based instructions (6)
key-wallet/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

key-wallet/**/*.rs: Separate immutable structures (Account, Wallet) containing only identity information from mutable wrappers (ManagedAccount, ManagedWalletInfo) with state management
Never serialize or log private keys in production; use public keys or key fingerprints for identification instead
Always validate network consistency when deriving or validating addresses; never mix mainnet and testnet operations
Use BTreeMap for ordered data (accounts, transactions) and HashMap for lookups (address mappings); apply memory management strategies for old transaction data
Apply atomic state updates when managing watch-only wallets: validate that external signatures match expected pubkeys and never attempt signing operations
Use the ? operator for error propagation, provide context in error messages, never panic in library code, and return Result<T> for all fallible operations

Files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: MSRV (Minimum Supported Rust Version) is 1.89; ensure compatibility with this version for all builds
Unit tests should live alongside code with #[cfg(test)] annotation; integration tests use the tests/ directory
Use snake_case for function and variable names
Use UpperCamelCase for types and traits
Use SCREAMING_SNAKE_CASE for constants
Format code with rustfmt before commits; ensure cargo fmt --all is run
Run cargo clippy --workspace --all-targets -- -D warnings for linting; avoid warnings in CI
Prefer async/await via tokio for asynchronous operations

**/*.rs: Never hardcode network parameters, addresses, or keys in Rust code
Use proper error types (thiserror) and propagate errors appropriately in Rust
Use tokio runtime for async operations in Rust
Use conditional compilation with feature flags for optional features
Write unit tests for new functionality in Rust
Format code using cargo fmt
Run clippy with all features and all targets, treating warnings as errors
Never log or expose private keys in any code
Always validate inputs from untrusted sources in Rust
Use secure random number generation for keys

Files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
key-wallet/**/transaction_checking/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

Implement transaction classification and routing through TransactionRouter to avoid checking all accounts for every transaction

Files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
key-wallet/**/tests/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

key-wallet/**/tests/**/*.rs: Organize unit tests by functionality: separate test files for BIP32, mnemonics, addresses, derivation paths, and PSBT operations
Use deterministic testing with known test vectors and fixed seeds for reproducible results
Use property-based testing for complex invariants such as gap limit constraints

Files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
**/tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/tests/**/*.rs: Use descriptive test names (e.g., test_parse_address_mainnet)
Mark network-dependent or long-running tests with #[ignore] and run with -- --ignored

Files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
**/*test*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*test*.rs: Test both mainnet and testnet configurations
Use proptest for property-based testing where appropriate

Files:

  • key-wallet/src/tests/balance_tests.rs
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Separate immutable structures (`Account`, `Wallet`) containing only identity information from mutable wrappers (`ManagedAccount`, `ManagedWalletInfo`) with state management
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/managed_account/**/*.rs : Implement atomic state updates when processing transactions: update transactions, UTXOs, balances, and address usage state together
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Separate immutable structures (`Account`, `Wallet`) containing only identity information from mutable wrappers (`ManagedAccount`, `ManagedWalletInfo`) with state management

Applied to files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/managed_account/**/*.rs : Implement atomic state updates when processing transactions: update transactions, UTXOs, balances, and address usage state together

Applied to files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Use `BTreeMap` for ordered data (accounts, transactions) and `HashMap` for lookups (address mappings); apply memory management strategies for old transaction data

Applied to files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Apply atomic state updates when managing watch-only wallets: validate that external signatures match expected pubkeys and never attempt signing operations

Applied to files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/src/types.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/transaction_checking/**/*.rs : Implement transaction classification and routing through `TransactionRouter` to avoid checking all accounts for every transaction

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Always validate network consistency when deriving or validating addresses; never mix mainnet and testnet operations

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
📚 Learning: 2025-12-22T17:59:51.097Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T17:59:51.097Z
Learning: Cover critical parsing, networking, SPV, and wallet flows in tests; add regression tests for fixes; consider property tests with `proptest`

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Support multiple `KeySource` variants (Private, Public, NoKeySource) to enable both full wallets and watch-only wallets with the same interface

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
📚 Learning: 2025-06-26T16:01:37.609Z
Learnt from: DCG-Claude
Repo: dashpay/rust-dashcore PR: 0
File: :0-0
Timestamp: 2025-06-26T16:01:37.609Z
Learning: The mempool tracking infrastructure (UnconfirmedTransaction, MempoolState, configuration, and mempool_filter.rs) is fully implemented and integrated in the Dash SPV client as of this PR, including client logic, FFI APIs, and tests.

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/tests/**/*.rs : Organize unit tests by functionality: separate test files for BIP32, mnemonics, addresses, derivation paths, and PSBT operations

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Use the `?` operator for error propagation, provide context in error messages, never panic in library code, and return `Result<T>` for all fallible operations

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
📚 Learning: 2025-08-21T05:01:58.949Z
Learnt from: QuantumExplorer
Repo: dashpay/rust-dashcore PR: 108
File: key-wallet-ffi/src/wallet_manager.rs:270-318
Timestamp: 2025-08-21T05:01:58.949Z
Learning: In the key-wallet-ffi design, wallets retrieved from the wallet manager via lookup functions should return const pointers (*const FFIWallet) to enforce read-only access and prevent unintended modifications. The wallet manager should control wallet lifecycle and mutations through specific APIs rather than allowing external mutation of retrieved wallet references.

Applied to files:

  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/src/types.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/account/**/*.rs : Use enum-based type system for `AccountType` with specific variants (Standard, IdentityAuthentication, IdentityEncryption, MasternodeOperator, etc.) to provide compile-time safety and clear semantics

Applied to files:

  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Use staged gap limit management with `GapLimitStage` tracking `last_used_index` and `used_indices` to enable efficient address discovery without loading entire chains into memory

Applied to files:

  • key-wallet-ffi/src/managed_wallet.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Generate addresses in batches using gap limit and staged generation instead of unbounded address generation to prevent memory and performance issues

Applied to files:

  • key-wallet-ffi/src/managed_wallet.rs
📚 Learning: 2025-12-01T07:59:58.608Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-12-01T07:59:58.608Z
Learning: Applies to dash-spv-ffi/tests/unit/**/*.rs : Add corresponding unit tests in `tests/unit/` for each new FFI function

Applied to files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-30T22:00:57.000Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-30T22:00:57.000Z
Learning: Applies to **/*.rs : Write unit tests for new functionality in Rust

Applied to files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/tests/**/*.rs : Use property-based testing for complex invariants such as gap limit constraints

Applied to files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-16T09:03:55.811Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-16T09:03:55.811Z
Learning: Applies to dash-spv/tests/**/*.rs : Organize tests into unit tests (in-module), integration tests (tests/ directory), real network tests (with live Dash Core nodes), and performance benchmarks

Applied to files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/tests/**/*.rs : Use deterministic testing with known test vectors and fixed seeds for reproducible results

Applied to files:

  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-22T17:59:51.097Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T17:59:51.097Z
Learning: Applies to **/*.rs : Unit tests should live alongside code with `#[cfg(test)]` annotation; integration tests use the `tests/` directory

Applied to files:

  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-22T17:59:51.097Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T17:59:51.097Z
Learning: Applies to **/tests/**/*.rs : Use descriptive test names (e.g., `test_parse_address_mainnet`)

Applied to files:

  • key-wallet/src/tests/mod.rs
🧬 Code graph analysis (4)
key-wallet/src/transaction_checking/wallet_checker.rs (4)
key-wallet/src/managed_account/mod.rs (1)
  • balance (861-863)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (4)
  • balance (77-77)
  • balance (188-190)
  • get_spendable_utxos (74-74)
  • get_spendable_utxos (184-186)
key-wallet/src/managed_account/managed_account_trait.rs (1)
  • balance (36-36)
key-wallet/src/wallet/balance.rs (1)
  • immature (46-48)
key-wallet-ffi/src/managed_wallet.rs (4)
key-wallet/src/managed_account/mod.rs (2)
  • balance (861-863)
  • new (63-73)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (2)
  • balance (77-77)
  • balance (188-190)
key-wallet/src/wallet/balance.rs (5)
  • new (26-33)
  • unconfirmed (41-43)
  • immature (46-48)
  • locked (51-53)
  • total (56-58)
key-wallet/src/wallet/managed_wallet_info/mod.rs (1)
  • new (52-62)
key-wallet-ffi/src/types.rs (3)
key-wallet/src/managed_account/mod.rs (1)
  • balance (861-863)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (2)
  • balance (77-77)
  • balance (188-190)
key-wallet/src/managed_account/managed_account_trait.rs (1)
  • balance (36-36)
key-wallet-ffi/src/managed_account.rs (4)
key-wallet/src/managed_account/mod.rs (1)
  • balance (861-863)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (2)
  • balance (77-77)
  • balance (188-190)
key-wallet/src/managed_account/managed_account_trait.rs (1)
  • balance (36-36)
key-wallet/src/wallet/balance.rs (1)
  • locked (51-53)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: MSRV Check (1.89)
  • GitHub Check: fuzz (hashes_sha512_256)
  • GitHub Check: fuzz (hashes_ripemd160)
  • GitHub Check: fuzz (hashes_sha512)
  • GitHub Check: fuzz (hashes_sha256)
  • GitHub Check: fuzz (hashes_json)
  • GitHub Check: fuzz (hashes_sha1)
  • GitHub Check: fuzz (dash_deserialize_address)
  • GitHub Check: fuzz (dash_deserialize_amount)
  • GitHub Check: fuzz (dash_deserialize_script)
  • GitHub Check: fuzz (dash_deser_net_msg)
  • GitHub Check: Pre-commit (ubuntu-latest)
  • GitHub Check: Pre-commit (macos-latest)
  • GitHub Check: Pre-commit (windows-latest)
  • GitHub Check: fuzz (dash_outpoint_string)
  • GitHub Check: fuzz (dash_deserialize_block)
  • GitHub Check: fuzz (dash_deserialize_witness)
  • GitHub Check: fuzz (dash_script_bytes_to_asm_fmt)
  • GitHub Check: Thread Sanitizer
  • GitHub Check: Address Sanitizer
🔇 Additional comments (20)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (1)

262-266: LGTM! Balance refresh on height update is correct.

The addition of update_balance() ensures that balance state (including immature→spendable transitions) is refreshed when the synced height advances, which is essential for coinbase maturation tracking.

key-wallet/src/tests/mod.rs (1)

7-7: LGTM!

The new test module declaration is properly placed and follows the coding guidelines for test organization.

key-wallet-ffi/src/types.rs (2)

58-64: LGTM! Clear field separation added.

The locked field addition properly separates locked balance (CoinJoin reserves) from immature balance (mining rewards), with clear documentation.


66-76: Critical bug fix: corrected immature/locked field mapping.

This fixes the mix-up mentioned in the PR description where immature was incorrectly mapped to balance.locked(). The correct mapping is now:

  • immaturebalance.immature() (mining rewards not yet mature)
  • lockedbalance.locked() (CoinJoin reserves)
key-wallet-ffi/src/managed_account.rs (2)

504-524: LGTM! Balance fields properly populated.

The function now correctly populates both immature and locked fields from the balance object, replacing the previous placeholder of 0 for immature.


1235-1250: LGTM! Test properly validates locked field.

The test correctly initializes the locked field with a sentinel value and verifies it's properly set to 0 by the balance retrieval function.

key-wallet/src/transaction_checking/wallet_checker.rs (2)

554-555: LGTM! Explicit height updates trigger balance refresh.

The explicit update_synced_height() calls are now required to trigger balance recalculation in tests, aligning with the removal of automatic balance updates from the transaction checking flow.

Also applies to: 729-730


579-579: LGTM! Unified balance API usage.

Correctly replaced immature_balance() method calls with balance().immature() accessor, aligning with the unified balance tracking approach.

Also applies to: 753-753, 783-783

key-wallet-ffi/src/managed_wallet.rs (5)

534-554: LGTM! Clear documentation of the breaking FFI change.

The addition of the immature_out parameter is well-documented with updated safety requirements. The parameter ordering (confirmed → unconfirmed → immature → locked → total) follows a logical progression from most to least liquid.


564-576: LGTM! Comprehensive null pointer validation.

The validation correctly includes immature_out in the null check alongside all other output parameters, preventing potential null pointer dereferences.


578-590: LGTM! Balance population is correct and complete.

The immature balance is correctly retrieved from balance.immature() and assigned to the output parameter, consistent with the unified balance tracking model.


1049-1078: LGTM! Test correctly validates immature balance tracking.

The test properly:

  • Creates a balance with explicit immature value (10000)
  • Passes the immature_out parameter
  • Verifies immature is correctly returned
  • Verifies total includes all balance components (1000000 + 50000 + 10000 + 25000 = 1085000)

1080-1110: LGTM! Error path tests properly validate null pointer handling.

The tests verify that null pointer validation works correctly for both the managed wallet pointer and any output parameter pointer, including the new immature_out.

key-wallet/src/tests/balance_tests.rs (4)

8-28: LGTM! Test correctly validates mixed UTXO categorization.

The test properly verifies that:

  • Regular confirmed UTXOs are spendable
  • Mature coinbase outputs (100+ confirmations) are spendable
  • Immature coinbase outputs (<100 confirmations) are tracked separately

The expected values are mathematically correct: spendable = 100k + 10M = 10.1M, immature = 20M.


30-50: LGTM! Boundary test correctly validates coinbase maturity threshold.

The test properly verifies the 100-confirmation threshold for coinbase maturity:

  • At 99 confirmations: coinbase is immature
  • At 100 confirmations: coinbase becomes spendable

This aligns with standard Dash consensus rules for coinbase maturation.


52-66: LGTM! Test correctly validates locked UTXO tracking.

The test verifies that locked UTXOs are properly categorized in the locked balance component and don't appear in spendable, unconfirmed, or immature balances.


68-81: LGTM! Test correctly validates unconfirmed UTXO tracking.

The test verifies that unconfirmed UTXOs (height=0, confirmed=false) are properly categorized in the unconfirmed balance component.

key-wallet-ffi/include/key_wallet_ffi.h (2)

509-530: LGTM! FFIBalance struct properly extended with locked field.

The struct definition is well-documented with:

  • Clear field descriptions for immature (mining rewards) and locked (CoinJoin reserves)
  • Logical field ordering that matches the getter function parameters
  • Proper alignment with the updated balance model

3073-3096: LGTM! Function declaration matches implementation.

The C function declaration is consistent with the Rust implementation:

  • Signature includes the new immature_out parameter
  • Safety documentation correctly requires all output pointers to be valid
  • Parameter ordering matches the balance component hierarchy

Note: This is a breaking API change for C consumers who must update their code to pass the additional immature_out parameter.

Based on learnings, ensure that downstream FFI consumers (Swift/Objective-C, Java/Kotlin bindings if any) are updated to handle the new parameter in managed_wallet_get_balance.

key-wallet-ffi/FFI_API.md (1)

918-925: Documentation is accurate—no changes needed.

The auto-generated documentation correctly reflects the implementation. The immature_out parameter is properly positioned between unconfirmed_out and locked_out, the mapping correctly sources from balance.immature() (not the previous incorrect source), and the safety documentation accurately documents the new parameter. All null-pointer checks are in place, and tests confirm correct behavior.


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.

@xdustinface xdustinface force-pushed the fix/unify-immature-balance branch from 7b515cd to 617282e Compare January 7, 2026 01:02
@github-actions github-actions bot added the merge-conflict The PR conflicts with the target branch. label Jan 8, 2026
@github-actions
Copy link

github-actions bot commented Jan 8, 2026

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

@xdustinface xdustinface force-pushed the fix/unify-immature-balance branch from 617282e to f6a52d9 Compare January 8, 2026 03:05
@github-actions github-actions bot removed the merge-conflict The PR conflicts with the target branch. label Jan 8, 2026
@xdustinface xdustinface force-pushed the fix/unify-immature-balance branch from f6a52d9 to 5f25b0c Compare January 8, 2026 03:31
@xdustinface xdustinface marked this pull request as ready for review January 8, 2026 03:31
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-manager/tests/spv_integration_tests.rs:
- Around line 245-321: The test
test_immature_balance_matures_during_block_processing hardcodes the 100-block
maturity; replace that literal with the COINBASE_MATURITY constant by changing
the computation to let maturity_height = coinbase_height + COINBASE_MATURITY;
and add the appropriate import for COINBASE_MATURITY (from the module where it’s
defined, e.g. dash::blockdata::constants::COINBASE_MATURITY) so the test uses
the canonical network parameter instead of a magic number.
🧹 Nitpick comments (2)
key-wallet-manager/tests/spv_integration_tests.rs (1)

202-223: Helper function correctly creates coinbase transactions.

The create_coinbase_transaction helper properly constructs a coinbase transaction with the standard pattern (zero txid, vout 0xffffffff). The TODO comment about unifying with other helpers is noted and could be addressed in a follow-up.

key-wallet/src/transaction_checking/wallet_checker.rs (1)

552-585: Immature balance and spendable UTXO flow is exercised correctly (one minor redundancy)

The tests now explicitly call update_synced_height after processing coinbase transactions and assert against balance().immature() plus get_spendable_utxos(), which matches the new centralized balance/immature logic and validates both pre- and post-maturity behavior end-to-end. That’s a solid regression guard.

There is a small redundancy: the “coinbase not mature yet” get_spendable_utxos().is_empty() assertion block appears twice back-to-back; you can drop one copy without losing coverage.

Based on learnings, this continues to route through TransactionRouter while only adjusting balance observation points.

Also applies to: 720-789

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 189a66d and 5f25b0c.

📒 Files selected for processing (14)
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/test_utils/mod.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
🧰 Additional context used
📓 Path-based instructions (8)
key-wallet/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

key-wallet/**/*.rs: Separate immutable structures (Account, Wallet) containing only identity information from mutable wrappers (ManagedAccount, ManagedWalletInfo) with state management
Never serialize or log private keys in production; use public keys or key fingerprints for identification instead
Always validate network consistency when deriving or validating addresses; never mix mainnet and testnet operations
Use BTreeMap for ordered data (accounts, transactions) and HashMap for lookups (address mappings); apply memory management strategies for old transaction data
Apply atomic state updates when managing watch-only wallets: validate that external signatures match expected pubkeys and never attempt signing operations
Use the ? operator for error propagation, provide context in error messages, never panic in library code, and return Result<T> for all fallible operations

Files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet/src/tests/balance_tests.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: MSRV (Minimum Supported Rust Version) is 1.89; ensure compatibility with this version for all builds
Unit tests should live alongside code with #[cfg(test)] annotation; integration tests use the tests/ directory
Use snake_case for function and variable names
Use UpperCamelCase for types and traits
Use SCREAMING_SNAKE_CASE for constants
Format code with rustfmt before commits; ensure cargo fmt --all is run
Run cargo clippy --workspace --all-targets -- -D warnings for linting; avoid warnings in CI
Prefer async/await via tokio for asynchronous operations

**/*.rs: Never hardcode network parameters, addresses, or keys in Rust code
Use proper error types (thiserror) and propagate errors appropriately in Rust
Use tokio runtime for async operations in Rust
Use conditional compilation with feature flags for optional features
Write unit tests for new functionality in Rust
Format code using cargo fmt
Run clippy with all features and all targets, treating warnings as errors
Never log or expose private keys in any code
Always validate inputs from untrusted sources in Rust
Use secure random number generation for keys

Files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/tests/balance_tests.rs
key-wallet/**/managed_account/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

Implement atomic state updates when processing transactions: update transactions, UTXOs, balances, and address usage state together

Files:

  • key-wallet/src/managed_account/mod.rs
key-wallet/**/transaction_checking/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

Implement transaction classification and routing through TransactionRouter to avoid checking all accounts for every transaction

Files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
key-wallet/**/tests/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

key-wallet/**/tests/**/*.rs: Organize unit tests by functionality: separate test files for BIP32, mnemonics, addresses, derivation paths, and PSBT operations
Use deterministic testing with known test vectors and fixed seeds for reproducible results
Use property-based testing for complex invariants such as gap limit constraints

Files:

  • key-wallet/src/tests/mod.rs
  • key-wallet/src/tests/balance_tests.rs
**/tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/tests/**/*.rs: Use descriptive test names (e.g., test_parse_address_mainnet)
Mark network-dependent or long-running tests with #[ignore] and run with -- --ignored

Files:

  • key-wallet/src/tests/mod.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/tests/balance_tests.rs
**/*integration*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Write integration tests for network operations

Files:

  • key-wallet-manager/tests/spv_integration_tests.rs
**/*test*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*test*.rs: Test both mainnet and testnet configurations
Use proptest for property-based testing where appropriate

Files:

  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/tests/balance_tests.rs
🧠 Learnings (25)
📓 Common learnings
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Separate immutable structures (`Account`, `Wallet`) containing only identity information from mutable wrappers (`ManagedAccount`, `ManagedWalletInfo`) with state management
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/managed_account/**/*.rs : Implement atomic state updates when processing transactions: update transactions, UTXOs, balances, and address usage state together
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Separate immutable structures (`Account`, `Wallet`) containing only identity information from mutable wrappers (`ManagedAccount`, `ManagedWalletInfo`) with state management

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet/src/tests/mod.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/account/**/*.rs : Use enum-based type system for `AccountType` with specific variants (Standard, IdentityAuthentication, IdentityEncryption, MasternodeOperator, etc.) to provide compile-time safety and clear semantics

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Support multiple `KeySource` variants (Private, Public, NoKeySource) to enable both full wallets and watch-only wallets with the same interface

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Use `BTreeMap` for ordered data (accounts, transactions) and `HashMap` for lookups (address mappings); apply memory management strategies for old transaction data

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_wallet.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/managed_account/**/*.rs : Implement atomic state updates when processing transactions: update transactions, UTXOs, balances, and address usage state together

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet/src/tests/mod.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Apply atomic state updates when managing watch-only wallets: validate that external signatures match expected pubkeys and never attempt signing operations

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Generate addresses in batches using gap limit and staged generation instead of unbounded address generation to prevent memory and performance issues

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet/src/test_utils/account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Pre-generate addresses in batches (typically 20-100) and store them in pools; only derive on-demand when the pool is exhausted

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet/src/test_utils/account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Always validate network consistency when deriving or validating addresses; never mix mainnet and testnet operations

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/tests/**/*.rs : Organize unit tests by functionality: separate test files for BIP32, mnemonics, addresses, derivation paths, and PSBT operations

Applied to files:

  • key-wallet/src/test_utils/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-08-21T05:01:58.949Z
Learnt from: QuantumExplorer
Repo: dashpay/rust-dashcore PR: 108
File: key-wallet-ffi/src/wallet_manager.rs:270-318
Timestamp: 2025-08-21T05:01:58.949Z
Learning: In the key-wallet-ffi design, wallets retrieved from the wallet manager via lookup functions should return const pointers (*const FFIWallet) to enforce read-only access and prevent unintended modifications. The wallet manager should control wallet lifecycle and mutations through specific APIs rather than allowing external mutation of retrieved wallet references.

Applied to files:

  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/FFI_API.md
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/tests/**/*.rs : Use property-based testing for complex invariants such as gap limit constraints

Applied to files:

  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/transaction_checking/**/*.rs : Implement transaction classification and routing through `TransactionRouter` to avoid checking all accounts for every transaction

Applied to files:

  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
📚 Learning: 2025-12-22T17:59:51.097Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T17:59:51.097Z
Learning: Cover critical parsing, networking, SPV, and wallet flows in tests; add regression tests for fixes; consider property tests with `proptest`

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Use the `?` operator for error propagation, provide context in error messages, never panic in library code, and return `Result<T>` for all fallible operations

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Use staged gap limit management with `GapLimitStage` tracking `last_used_index` and `used_indices` to enable efficient address discovery without loading entire chains into memory

Applied to files:

  • key-wallet/src/test_utils/account.rs
📚 Learning: 2025-12-30T22:00:57.000Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-30T22:00:57.000Z
Learning: Applies to **/*.rs : Write unit tests for new functionality in Rust

Applied to files:

  • key-wallet/src/tests/mod.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-12-01T07:59:58.608Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-12-01T07:59:58.608Z
Learning: Applies to dash-spv-ffi/tests/unit/**/*.rs : Add corresponding unit tests in `tests/unit/` for each new FFI function

Applied to files:

  • key-wallet/src/tests/mod.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-12-16T09:03:55.811Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-16T09:03:55.811Z
Learning: Applies to dash-spv/tests/**/*.rs : Organize tests into unit tests (in-module), integration tests (tests/ directory), real network tests (with live Dash Core nodes), and performance benchmarks

Applied to files:

  • key-wallet/src/tests/mod.rs
  • key-wallet/src/tests/balance_tests.rs
📚 Learning: 2025-12-22T17:59:51.097Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T17:59:51.097Z
Learning: Applies to **/*.rs : Unit tests should live alongside code with `#[cfg(test)]` annotation; integration tests use the `tests/` directory

Applied to files:

  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/tests/**/*.rs : Use deterministic testing with known test vectors and fixed seeds for reproducible results

Applied to files:

  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-16T09:03:55.811Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-16T09:03:55.811Z
Learning: When adding new features, define traits for abstractions, implement concrete types following existing patterns, add comprehensive unit tests, add integration tests for network interaction, and update error types in error.rs

Applied to files:

  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-22T17:59:51.097Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T17:59:51.097Z
Learning: Applies to **/tests/**/*.rs : Use descriptive test names (e.g., `test_parse_address_mainnet`)

Applied to files:

  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-06-26T16:01:37.609Z
Learnt from: DCG-Claude
Repo: dashpay/rust-dashcore PR: 0
File: :0-0
Timestamp: 2025-06-26T16:01:37.609Z
Learning: The mempool tracking infrastructure (UnconfirmedTransaction, MempoolState, configuration, and mempool_filter.rs) is fully implemented and integrated in the Dash SPV client as of this PR, including client logic, FFI APIs, and tests.

Applied to files:

  • key-wallet-manager/tests/spv_integration_tests.rs
🧬 Code graph analysis (7)
key-wallet/src/test_utils/mod.rs (1)
key-wallet/src/derivation.rs (1)
  • account (230-233)
key-wallet-ffi/src/types.rs (3)
key-wallet/src/managed_account/mod.rs (1)
  • balance (861-863)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (2)
  • balance (77-77)
  • balance (188-190)
key-wallet/src/managed_account/managed_account_trait.rs (1)
  • balance (36-36)
key-wallet/src/managed_account/mod.rs (1)
key-wallet/src/wallet/balance.rs (5)
  • immature (46-48)
  • locked (51-53)
  • spendable (36-38)
  • unconfirmed (41-43)
  • new (26-33)
key-wallet-ffi/src/managed_account.rs (4)
key-wallet/src/managed_account/mod.rs (1)
  • balance (861-863)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (2)
  • balance (77-77)
  • balance (188-190)
key-wallet/src/managed_account/managed_account_trait.rs (1)
  • balance (36-36)
key-wallet/src/wallet/balance.rs (1)
  • locked (51-53)
key-wallet-ffi/src/managed_wallet.rs (1)
key-wallet/src/wallet/balance.rs (5)
  • new (26-33)
  • unconfirmed (41-43)
  • immature (46-48)
  • locked (51-53)
  • total (56-58)
key-wallet/src/test_utils/account.rs (2)
key-wallet/src/managed_account/mod.rs (3)
  • network (845-847)
  • new (63-73)
  • account_type (837-839)
key-wallet/src/bip32.rs (1)
  • master (1302-1304)
key-wallet-manager/tests/spv_integration_tests.rs (4)
key-wallet/src/wallet/balance.rs (2)
  • new (26-33)
  • immature (46-48)
key-wallet/src/wallet/managed_wallet_info/mod.rs (1)
  • new (52-62)
key-wallet-manager/src/wallet_manager/mod.rs (1)
  • new (79-86)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (6)
  • wallet_id (35-35)
  • wallet_id (125-127)
  • immature_transactions (92-92)
  • immature_transactions (218-240)
  • balance (77-77)
  • balance (188-190)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Ubuntu ARM / tools
  • GitHub Check: MSRV Check (1.89)
  • GitHub Check: Documentation
  • GitHub Check: fuzz (dash_outpoint_string)
  • GitHub Check: fuzz (dash_script_bytes_to_asm_fmt)
  • GitHub Check: fuzz (dash_deser_net_msg)
  • GitHub Check: Pre-commit (macos-latest)
  • GitHub Check: Pre-commit (ubuntu-latest)
  • GitHub Check: Pre-commit (windows-latest)
  • GitHub Check: Address Sanitizer
  • GitHub Check: Thread Sanitizer
🔇 Additional comments (18)
key-wallet/src/test_utils/mod.rs (1)

1-1: LGTM! Test utility module added.

The new internal account module follows the established pattern for organizing test utilities and supports the new balance testing scenarios introduced in this PR.

key-wallet/src/managed_account/mod.rs (1)

268-287: Balance tracking correctly updated to include immature category.

The balance calculation now properly categorizes UTXOs with immature coinbase outputs tracked separately. The categorization order (locked → immature → spendable → unconfirmed) ensures each UTXO is counted exactly once in the appropriate category.

Based on learnings, this implements atomic state updates when processing transactions by maintaining all balance components in a unified calculation.

key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (1)

262-266: Balance recalculation on height update ensures immature UTXOs mature correctly.

The addition of update_balance() when updating synced height is essential for this PR's objective. As the chain height advances, previously immature coinbase UTXOs mature and need to be reclassified. This ensures the cached balance reflects the current chain state.

Based on learnings, this maintains atomic state updates by ensuring balance state is consistent with the synced height.

key-wallet/src/tests/mod.rs (1)

7-7: LGTM! New balance test module follows established organization.

The addition of balance_tests module aligns with the guideline to organize unit tests by functionality and provides dedicated coverage for the new immature and locked balance features.

Based on learnings, organizing tests by functionality (separate test files for different concerns) improves maintainability.

key-wallet-ffi/src/managed_wallet.rs (2)

532-587: FFI balance accessor now cleanly exposes immature component

The extended signature, null-pointer validation, and assignment from balance.immature()/balance.locked() all line up with the updated WalletBalance model and avoid the previous immature/locked mix-up. This keeps the FFI contract explicit and backward-safe for callers that update to the new signature.


1024-1118: Tests exercise immature_out plumbing and error paths thoroughly

The updated balance test covers all four buckets (spendable, unconfirmed, immature, locked), verifies the new total, and asserts both null-managed-wallet and null-output-pointer error handling, which is exactly what this FFI surface needs.

key-wallet/src/tests/balance_tests.rs (4)

8-28: Good coverage of mixed UTXO categories in balance aggregation

This test nicely exercises spendable, immature coinbase, and regular confirmed outputs together and validates the combined WalletBalance::new(spendable, unconfirmed, immature, locked) after a height update, which should guard future refactors of update_balance().


30-50: Coinbase maturity boundary test guards off-by-one errors

The two-step height progression (1099 → 1100) around a single coinbase UTXO clearly encodes the intended immature→spendable transition, which is valuable documentation and regression protection for the maturity logic.


52-66: Locked UTXOs correctly segregated into locked balance

Marking the UTXO as locked and asserting that only the locked bucket is populated (with zero spendable/unconfirmed/immature) gives a precise signal that locking semantics are wired into balance calculation rather than just filtering at spend time.


68-81: Unconfirmed UTXO test cleanly isolates the unconfirmed bucket

The use of a 0-height, unconfirmed UTXO and a large synced height, with expectations confined to WalletBalance::new(0, amount, 0, 0), makes the unconfirmed-path behavior explicit and easy to reason about.

key-wallet-ffi/FFI_API.md (1)

915-925: FFI docs correctly updated for immature_out and balance breakdown

The documented managed_wallet_get_balance signature and safety text now match the Rust implementation and header, explicitly covering confirmed, unconfirmed, immature, locked, and total outputs, which keeps downstream consumers aligned with the new balance model.

key-wallet/src/wallet/balance.rs (3)

10-58: Immature component is integrated consistently into WalletBalance core API

Adding the immature field, threading it through new, the getter, and total() keeps the balance representation coherent and makes the immature bucket a first-class part of the model alongside spendable, unconfirmed, and locked.


61-73: Display output remains clear after adding immature balance

Including the immature amount in the formatted string, in a stable field order, keeps debug/UX output aligned with the internal structure and avoids ambiguity about what contributes to the reported total.


75-137: AddAssign and tests correctly account for immature amounts

Extending AddAssign to accumulate immature and updating the unit tests (creation/getters, overflow, Display, and add-assign) to use the four-argument new and the new getter ensures arithmetic and presentation stay correct as balances are combined. Based on learnings, this aligns with treating WalletBalance as a simple value type with clear state semantics.

key-wallet/src/test_utils/account.rs (1)

1-39: Test helper for BIP44 managed account looks consistent

The helper cleanly wires up standard BIP44 managed accounts with external/internal pools and consistent network handling; use of KeySource::NoKeySource and expect is appropriate for test utilities.

key-wallet-ffi/src/types.rs (1)

58-63: Corrected FFIBalance mapping for immature vs locked balances

The FFI struct layout and the From<WalletBalance> impl now correctly expose immature() and locked() separately, with field order matching the C header. This resolves the previous locked/immature mix-up and keeps total delegated to balance.total().

Also applies to: 71-73

key-wallet-ffi/include/key_wallet_ffi.h (1)

519-529: FFI header now accurately exposes immature and locked wallet balances

The C FFIBalance struct and managed_wallet_get_balance prototype are in sync with the Rust side: immature and locked are documented and added in the same field order as the repr(C) Rust struct, and the balance getter now returns immature_out alongside locked_out and total_out. This is a breaking FFI change, so downstream callers will need to add the extra parameter and, if they use FFIBalance directly, handle the new locked field.

Also applies to: 3074-3095

key-wallet-ffi/src/managed_account.rs (1)

512-521: Managed account FFI balance now matches WalletBalance semantics and is well tested

managed_account_get_balance correctly forwards spendable, unconfirmed, immature, locked, and total from the underlying WalletBalance, and the updated test ensures all fields—including the new locked one—are fully overwritten and start at zero for a fresh account. This keeps the managed-account balance FFI in line with the global FFIBalance mapping.

Also applies to: 1235-1250

if utxo.is_locked {
locked += value;
} else if !utxo.is_mature(synced_height) {
immature += value;
Copy link
Collaborator

@ZocoLini ZocoLini Jan 8, 2026

Choose a reason for hiding this comment

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

Originally the check for immature balance was

fn immature_balance(&self) -> u64 {
        self.utxos()
            .iter()
            .filter(|utxo| utxo.is_coinbase && !utxo.is_mature(self.synced_height()))
            .map(|utxo| utxo.value())
            .sum()
    }

Is it safe to skip the utxo.is_coinbase check??

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah it's implied. Basically only coinbase can be immature and there is a is_coinbase check inside is_mature.

We currently keep track of immature balance separately from other balances with the `immature_balance` function. This PR drops the extra function, adds `WalletBalance.immature` and changes the balance tracking so that we have all balances in one place. It also fixes a mix-up between locked and immature balance in FFI.
@xdustinface xdustinface force-pushed the fix/unify-immature-balance branch from 5f25b0c to aa5235d Compare January 8, 2026 23:13
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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
key-wallet/src/transaction_checking/wallet_checker.rs (1)

755-765: Minor: duplicate assertion detected.

Lines 761-765 appear to duplicate the assertion from lines 755-759. Consider removing the duplicate check:

🧹 Suggested cleanup
         // Immature balance should reflect the coinbase value
         assert_eq!(managed_wallet.balance().immature(), 5_000_000_000);
 
         // Spendable UTXOs should be empty (coinbase not mature yet)
         assert!(
             managed_wallet.get_spendable_utxos().is_empty(),
             "No spendable UTXOs while coinbase is immature"
         );
-
-        // Spendable UTXOs should be empty (coinbase not mature yet)
-        assert!(
-            managed_wallet.get_spendable_utxos().is_empty(),
-            "No spendable UTXOs while coinbase is immature"
-        );
 
         // Now advance the chain height past maturity (100 blocks)
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f25b0c and aa5235d.

📒 Files selected for processing (14)
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/test_utils/mod.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • key-wallet/src/wallet/balance.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet-manager/tests/spv_integration_tests.rs
  • key-wallet/src/test_utils/mod.rs
🧰 Additional context used
📓 Path-based instructions (6)
key-wallet/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

key-wallet/**/*.rs: Separate immutable structures (Account, Wallet) containing only identity information from mutable wrappers (ManagedAccount, ManagedWalletInfo) with state management
Never serialize or log private keys in production; use public keys or key fingerprints for identification instead
Always validate network consistency when deriving or validating addresses; never mix mainnet and testnet operations
Use BTreeMap for ordered data (accounts, transactions) and HashMap for lookups (address mappings); apply memory management strategies for old transaction data
Apply atomic state updates when managing watch-only wallets: validate that external signatures match expected pubkeys and never attempt signing operations
Use the ? operator for error propagation, provide context in error messages, never panic in library code, and return Result<T> for all fallible operations

Files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: MSRV (Minimum Supported Rust Version) is 1.89; ensure compatibility with this version for all builds
Unit tests should live alongside code with #[cfg(test)] annotation; integration tests use the tests/ directory
Use snake_case for function and variable names
Use UpperCamelCase for types and traits
Use SCREAMING_SNAKE_CASE for constants
Format code with rustfmt before commits; ensure cargo fmt --all is run
Run cargo clippy --workspace --all-targets -- -D warnings for linting; avoid warnings in CI
Prefer async/await via tokio for asynchronous operations

**/*.rs: Never hardcode network parameters, addresses, or keys in Rust code
Use proper error types (thiserror) and propagate errors appropriately in Rust
Use tokio runtime for async operations in Rust
Use conditional compilation with feature flags for optional features
Write unit tests for new functionality in Rust
Format code using cargo fmt
Run clippy with all features and all targets, treating warnings as errors
Never log or expose private keys in any code
Always validate inputs from untrusted sources in Rust
Use secure random number generation for keys

Files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
key-wallet/**/transaction_checking/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

Implement transaction classification and routing through TransactionRouter to avoid checking all accounts for every transaction

Files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
key-wallet/**/tests/**/*.rs

📄 CodeRabbit inference engine (key-wallet/CLAUDE.md)

key-wallet/**/tests/**/*.rs: Organize unit tests by functionality: separate test files for BIP32, mnemonics, addresses, derivation paths, and PSBT operations
Use deterministic testing with known test vectors and fixed seeds for reproducible results
Use property-based testing for complex invariants such as gap limit constraints

Files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
**/tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/tests/**/*.rs: Use descriptive test names (e.g., test_parse_address_mainnet)
Mark network-dependent or long-running tests with #[ignore] and run with -- --ignored

Files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
**/*test*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*test*.rs: Test both mainnet and testnet configurations
Use proptest for property-based testing where appropriate

Files:

  • key-wallet/src/tests/balance_tests.rs
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Separate immutable structures (`Account`, `Wallet`) containing only identity information from mutable wrappers (`ManagedAccount`, `ManagedWalletInfo`) with state management
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/managed_account/**/*.rs : Implement atomic state updates when processing transactions: update transactions, UTXOs, balances, and address usage state together
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Separate immutable structures (`Account`, `Wallet`) containing only identity information from mutable wrappers (`ManagedAccount`, `ManagedWalletInfo`) with state management

Applied to files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/managed_account/**/*.rs : Implement atomic state updates when processing transactions: update transactions, UTXOs, balances, and address usage state together

Applied to files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Use `BTreeMap` for ordered data (accounts, transactions) and `HashMap` for lookups (address mappings); apply memory management strategies for old transaction data

Applied to files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Apply atomic state updates when managing watch-only wallets: validate that external signatures match expected pubkeys and never attempt signing operations

Applied to files:

  • key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/src/types.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/transaction_checking/**/*.rs : Implement transaction classification and routing through `TransactionRouter` to avoid checking all accounts for every transaction

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Always validate network consistency when deriving or validating addresses; never mix mainnet and testnet operations

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
📚 Learning: 2025-12-22T17:59:51.097Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T17:59:51.097Z
Learning: Cover critical parsing, networking, SPV, and wallet flows in tests; add regression tests for fixes; consider property tests with `proptest`

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Support multiple `KeySource` variants (Private, Public, NoKeySource) to enable both full wallets and watch-only wallets with the same interface

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
📚 Learning: 2025-06-26T16:01:37.609Z
Learnt from: DCG-Claude
Repo: dashpay/rust-dashcore PR: 0
File: :0-0
Timestamp: 2025-06-26T16:01:37.609Z
Learning: The mempool tracking infrastructure (UnconfirmedTransaction, MempoolState, configuration, and mempool_filter.rs) is fully implemented and integrated in the Dash SPV client as of this PR, including client logic, FFI APIs, and tests.

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/tests/**/*.rs : Organize unit tests by functionality: separate test files for BIP32, mnemonics, addresses, derivation paths, and PSBT operations

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/*.rs : Use the `?` operator for error propagation, provide context in error messages, never panic in library code, and return `Result<T>` for all fallible operations

Applied to files:

  • key-wallet/src/transaction_checking/wallet_checker.rs
📚 Learning: 2025-08-21T05:01:58.949Z
Learnt from: QuantumExplorer
Repo: dashpay/rust-dashcore PR: 108
File: key-wallet-ffi/src/wallet_manager.rs:270-318
Timestamp: 2025-08-21T05:01:58.949Z
Learning: In the key-wallet-ffi design, wallets retrieved from the wallet manager via lookup functions should return const pointers (*const FFIWallet) to enforce read-only access and prevent unintended modifications. The wallet manager should control wallet lifecycle and mutations through specific APIs rather than allowing external mutation of retrieved wallet references.

Applied to files:

  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet-ffi/src/types.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/account/**/*.rs : Use enum-based type system for `AccountType` with specific variants (Standard, IdentityAuthentication, IdentityEncryption, MasternodeOperator, etc.) to provide compile-time safety and clear semantics

Applied to files:

  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet-ffi/FFI_API.md
  • key-wallet/src/tests/mod.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/managed_account.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Use staged gap limit management with `GapLimitStage` tracking `last_used_index` and `used_indices` to enable efficient address discovery without loading entire chains into memory

Applied to files:

  • key-wallet-ffi/src/managed_wallet.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/address_pool/**/*.rs : Generate addresses in batches using gap limit and staged generation instead of unbounded address generation to prevent memory and performance issues

Applied to files:

  • key-wallet-ffi/src/managed_wallet.rs
📚 Learning: 2025-12-01T07:59:58.608Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv-ffi/CLAUDE.md:0-0
Timestamp: 2025-12-01T07:59:58.608Z
Learning: Applies to dash-spv-ffi/tests/unit/**/*.rs : Add corresponding unit tests in `tests/unit/` for each new FFI function

Applied to files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-30T22:00:57.000Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-30T22:00:57.000Z
Learning: Applies to **/*.rs : Write unit tests for new functionality in Rust

Applied to files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/tests/**/*.rs : Use property-based testing for complex invariants such as gap limit constraints

Applied to files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-16T09:03:55.811Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: dash-spv/CLAUDE.md:0-0
Timestamp: 2025-12-16T09:03:55.811Z
Learning: Applies to dash-spv/tests/**/*.rs : Organize tests into unit tests (in-module), integration tests (tests/ directory), real network tests (with live Dash Core nodes), and performance benchmarks

Applied to files:

  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-19T00:07:22.904Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: key-wallet/CLAUDE.md:0-0
Timestamp: 2025-12-19T00:07:22.904Z
Learning: Applies to key-wallet/**/tests/**/*.rs : Use deterministic testing with known test vectors and fixed seeds for reproducible results

Applied to files:

  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-22T17:59:51.097Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T17:59:51.097Z
Learning: Applies to **/*.rs : Unit tests should live alongside code with `#[cfg(test)]` annotation; integration tests use the `tests/` directory

Applied to files:

  • key-wallet/src/tests/mod.rs
📚 Learning: 2025-12-22T17:59:51.097Z
Learnt from: CR
Repo: dashpay/rust-dashcore PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T17:59:51.097Z
Learning: Applies to **/tests/**/*.rs : Use descriptive test names (e.g., `test_parse_address_mainnet`)

Applied to files:

  • key-wallet/src/tests/mod.rs
🧬 Code graph analysis (4)
key-wallet/src/transaction_checking/wallet_checker.rs (4)
key-wallet/src/managed_account/mod.rs (1)
  • balance (861-863)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (4)
  • balance (77-77)
  • balance (188-190)
  • get_spendable_utxos (74-74)
  • get_spendable_utxos (184-186)
key-wallet/src/managed_account/managed_account_trait.rs (1)
  • balance (36-36)
key-wallet/src/wallet/balance.rs (1)
  • immature (46-48)
key-wallet-ffi/src/managed_wallet.rs (4)
key-wallet/src/managed_account/mod.rs (2)
  • balance (861-863)
  • new (63-73)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (2)
  • balance (77-77)
  • balance (188-190)
key-wallet/src/wallet/balance.rs (5)
  • new (26-33)
  • unconfirmed (41-43)
  • immature (46-48)
  • locked (51-53)
  • total (56-58)
key-wallet/src/wallet/managed_wallet_info/mod.rs (1)
  • new (52-62)
key-wallet-ffi/src/types.rs (3)
key-wallet/src/managed_account/mod.rs (1)
  • balance (861-863)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (2)
  • balance (77-77)
  • balance (188-190)
key-wallet/src/managed_account/managed_account_trait.rs (1)
  • balance (36-36)
key-wallet-ffi/src/managed_account.rs (4)
key-wallet/src/managed_account/mod.rs (1)
  • balance (861-863)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (2)
  • balance (77-77)
  • balance (188-190)
key-wallet/src/managed_account/managed_account_trait.rs (1)
  • balance (36-36)
key-wallet/src/wallet/balance.rs (1)
  • locked (51-53)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: MSRV Check (1.89)
  • GitHub Check: fuzz (hashes_sha512_256)
  • GitHub Check: fuzz (hashes_ripemd160)
  • GitHub Check: fuzz (hashes_sha512)
  • GitHub Check: fuzz (hashes_sha256)
  • GitHub Check: fuzz (hashes_json)
  • GitHub Check: fuzz (hashes_sha1)
  • GitHub Check: fuzz (dash_deserialize_address)
  • GitHub Check: fuzz (dash_deserialize_amount)
  • GitHub Check: fuzz (dash_deserialize_script)
  • GitHub Check: fuzz (dash_deser_net_msg)
  • GitHub Check: Pre-commit (ubuntu-latest)
  • GitHub Check: Pre-commit (macos-latest)
  • GitHub Check: Pre-commit (windows-latest)
  • GitHub Check: fuzz (dash_outpoint_string)
  • GitHub Check: fuzz (dash_deserialize_block)
  • GitHub Check: fuzz (dash_deserialize_witness)
  • GitHub Check: fuzz (dash_script_bytes_to_asm_fmt)
  • GitHub Check: Thread Sanitizer
  • GitHub Check: Address Sanitizer
🔇 Additional comments (20)
key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs (1)

262-266: LGTM! Balance refresh on height update is correct.

The addition of update_balance() ensures that balance state (including immature→spendable transitions) is refreshed when the synced height advances, which is essential for coinbase maturation tracking.

key-wallet/src/tests/mod.rs (1)

7-7: LGTM!

The new test module declaration is properly placed and follows the coding guidelines for test organization.

key-wallet-ffi/src/types.rs (2)

58-64: LGTM! Clear field separation added.

The locked field addition properly separates locked balance (CoinJoin reserves) from immature balance (mining rewards), with clear documentation.


66-76: Critical bug fix: corrected immature/locked field mapping.

This fixes the mix-up mentioned in the PR description where immature was incorrectly mapped to balance.locked(). The correct mapping is now:

  • immaturebalance.immature() (mining rewards not yet mature)
  • lockedbalance.locked() (CoinJoin reserves)
key-wallet-ffi/src/managed_account.rs (2)

504-524: LGTM! Balance fields properly populated.

The function now correctly populates both immature and locked fields from the balance object, replacing the previous placeholder of 0 for immature.


1235-1250: LGTM! Test properly validates locked field.

The test correctly initializes the locked field with a sentinel value and verifies it's properly set to 0 by the balance retrieval function.

key-wallet/src/transaction_checking/wallet_checker.rs (2)

554-555: LGTM! Explicit height updates trigger balance refresh.

The explicit update_synced_height() calls are now required to trigger balance recalculation in tests, aligning with the removal of automatic balance updates from the transaction checking flow.

Also applies to: 729-730


579-579: LGTM! Unified balance API usage.

Correctly replaced immature_balance() method calls with balance().immature() accessor, aligning with the unified balance tracking approach.

Also applies to: 753-753, 783-783

key-wallet-ffi/src/managed_wallet.rs (5)

534-554: LGTM! Clear documentation of the breaking FFI change.

The addition of the immature_out parameter is well-documented with updated safety requirements. The parameter ordering (confirmed → unconfirmed → immature → locked → total) follows a logical progression from most to least liquid.


564-576: LGTM! Comprehensive null pointer validation.

The validation correctly includes immature_out in the null check alongside all other output parameters, preventing potential null pointer dereferences.


578-590: LGTM! Balance population is correct and complete.

The immature balance is correctly retrieved from balance.immature() and assigned to the output parameter, consistent with the unified balance tracking model.


1049-1078: LGTM! Test correctly validates immature balance tracking.

The test properly:

  • Creates a balance with explicit immature value (10000)
  • Passes the immature_out parameter
  • Verifies immature is correctly returned
  • Verifies total includes all balance components (1000000 + 50000 + 10000 + 25000 = 1085000)

1080-1110: LGTM! Error path tests properly validate null pointer handling.

The tests verify that null pointer validation works correctly for both the managed wallet pointer and any output parameter pointer, including the new immature_out.

key-wallet/src/tests/balance_tests.rs (4)

8-28: LGTM! Test correctly validates mixed UTXO categorization.

The test properly verifies that:

  • Regular confirmed UTXOs are spendable
  • Mature coinbase outputs (100+ confirmations) are spendable
  • Immature coinbase outputs (<100 confirmations) are tracked separately

The expected values are mathematically correct: spendable = 100k + 10M = 10.1M, immature = 20M.


30-50: LGTM! Boundary test correctly validates coinbase maturity threshold.

The test properly verifies the 100-confirmation threshold for coinbase maturity:

  • At 99 confirmations: coinbase is immature
  • At 100 confirmations: coinbase becomes spendable

This aligns with standard Dash consensus rules for coinbase maturation.


52-66: LGTM! Test correctly validates locked UTXO tracking.

The test verifies that locked UTXOs are properly categorized in the locked balance component and don't appear in spendable, unconfirmed, or immature balances.


68-81: LGTM! Test correctly validates unconfirmed UTXO tracking.

The test verifies that unconfirmed UTXOs (height=0, confirmed=false) are properly categorized in the unconfirmed balance component.

key-wallet-ffi/include/key_wallet_ffi.h (2)

509-530: LGTM! FFIBalance struct properly extended with locked field.

The struct definition is well-documented with:

  • Clear field descriptions for immature (mining rewards) and locked (CoinJoin reserves)
  • Logical field ordering that matches the getter function parameters
  • Proper alignment with the updated balance model

3073-3096: LGTM! Function declaration matches implementation.

The C function declaration is consistent with the Rust implementation:

  • Signature includes the new immature_out parameter
  • Safety documentation correctly requires all output pointers to be valid
  • Parameter ordering matches the balance component hierarchy

Note: This is a breaking API change for C consumers who must update their code to pass the additional immature_out parameter.

Based on learnings, ensure that downstream FFI consumers (Swift/Objective-C, Java/Kotlin bindings if any) are updated to handle the new parameter in managed_wallet_get_balance.

key-wallet-ffi/FFI_API.md (1)

918-925: Documentation is accurate—no changes needed.

The auto-generated documentation correctly reflects the implementation. The immature_out parameter is properly positioned between unconfirmed_out and locked_out, the mapping correctly sources from balance.immature() (not the previous incorrect source), and the safety documentation accurately documents the new parameter. All null-pointer checks are in place, and tests confirm correct behavior.

@xdustinface xdustinface requested a review from ZocoLini January 8, 2026 23:25
@xdustinface xdustinface merged commit 742715d into v0.42-dev Jan 9, 2026
53 checks passed
@xdustinface xdustinface deleted the fix/unify-immature-balance branch January 9, 2026 01:40
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.

3 participants