diff --git a/.codecov.yml b/.codecov.yml index 00e17af7a..d6dcd543c 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -32,7 +32,6 @@ flags: wallet: paths: - key-wallet/src/ - - key-wallet-manager/src/ ffi: paths: - dash-spv-ffi/src/ diff --git a/.github/ci-groups.yml b/.github/ci-groups.yml index eb99bb958..9c042fb4e 100644 --- a/.github/ci-groups.yml +++ b/.github/ci-groups.yml @@ -12,7 +12,6 @@ groups: wallet: - key-wallet - - key-wallet-manager ffi: - dash-spv-ffi diff --git a/Cargo.toml b/Cargo.toml index 52eec3292..1f20cf7c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["dash", "hashes", "internals", "fuzz", "rpc-client", "rpc-json", "rpc-integration-test", "key-wallet", "key-wallet-ffi", "key-wallet-manager", "dash-spv", "dash-spv-ffi"] +members = ["dash", "hashes", "internals", "fuzz", "rpc-client", "rpc-json", "rpc-integration-test", "key-wallet", "key-wallet-ffi", "dash-spv", "dash-spv-ffi"] resolver = "2" [workspace.package] diff --git a/README.md b/README.md index 694a0a48f..2e2c22474 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ |-------|--------|----------| | core | dashcore, dashcore_hashes, dashcore-private | [![codecov](https://codecov.io/gh/dashpay/rust-dashcore/graph/badge.svg?flag=core)](https://codecov.io/gh/dashpay/rust-dashcore?flags[0]=core) | | spv | dash-spv | [![codecov](https://codecov.io/gh/dashpay/rust-dashcore/graph/badge.svg?flag=spv)](https://codecov.io/gh/dashpay/rust-dashcore?flags[0]=spv) | -| wallet | key-wallet, key-wallet-manager | [![codecov](https://codecov.io/gh/dashpay/rust-dashcore/graph/badge.svg?flag=wallet)](https://codecov.io/gh/dashpay/rust-dashcore?flags[0]=wallet) | +| wallet | key-wallet | [![codecov](https://codecov.io/gh/dashpay/rust-dashcore/graph/badge.svg?flag=wallet)](https://codecov.io/gh/dashpay/rust-dashcore?flags[0]=wallet) | | ffi | dash-spv-ffi, key-wallet-ffi | [![codecov](https://codecov.io/gh/dashpay/rust-dashcore/graph/badge.svg?flag=ffi)](https://codecov.io/gh/dashpay/rust-dashcore?flags[0]=ffi) | | rpc | dashcore-rpc, dashcore-rpc-json | [![codecov](https://codecov.io/gh/dashpay/rust-dashcore/graph/badge.svg?flag=rpc)](https://codecov.io/gh/dashpay/rust-dashcore?flags[0]=rpc) | @@ -46,7 +46,7 @@ Supports (or should support) * Pay-to-contract support as in Appendix A of the [Blockstream sidechains whitepaper](https://www.blockstream.com/sidechains.pdf) * JSONRPC interaction with Dash Core * FFI bindings for C/Swift integration (dash-spv-ffi, key-wallet-ffi) -* [High-level wallet management](key-wallet-manager/README.md) with transaction building and UTXO management +* High-level wallet management with transaction building and UTXO management # Known limitations @@ -98,13 +98,10 @@ See `client/examples/` for more usage examples. This library provides comprehensive wallet functionality through multiple components: -* **key-wallet**: Low-level cryptographic primitives for HD wallets, mnemonic generation, and key derivation -* **[key-wallet-manager](key-wallet-manager/README.md)**: High-level wallet management with transaction building, UTXO tracking, and coin selection +* **key-wallet**: Low-level cryptographic primitives for HD wallets, mnemonic generation, and key derivation; and high-level wallet management with transaction building, UTXO tracking, and coin selection * **key-wallet-ffi**: C/Swift FFI bindings for mobile integration * **dash-spv**: SPV (Simplified Payment Verification) client implementation -For most applications, start with [key-wallet-manager](key-wallet-manager/README.md) which provides a complete, easy-to-use interface for wallet operations. - # Supported Dash Core Versions The following versions are officially supported: * 0.18.x @@ -122,10 +119,6 @@ This workspace compiles on Rust 1.89 or newer. Crates use mixed editions (2021 a Documentation can be found on [dashcore.readme.io/docs](https://dashcore.readme.io/docs). -## Component Documentation - -* **[key-wallet-manager](key-wallet-manager/README.md)** - High-level wallet management guide - # Contributing Contributions are generally welcome. If you intend to make larger changes please diff --git a/dash-spv-ffi/Cargo.toml b/dash-spv-ffi/Cargo.toml index da11bea58..17c2687b2 100644 --- a/dash-spv-ffi/Cargo.toml +++ b/dash-spv-ffi/Cargo.toml @@ -28,7 +28,6 @@ tracing = "0.1" key-wallet-ffi = { path = "../key-wallet-ffi" } # Still need these for SPV client internals (not for FFI types) key-wallet = { path = "../key-wallet" } -key-wallet-manager = { path = "../key-wallet-manager" } rand = "0.8" clap = { version = "4.5", features = ["derive"] } diff --git a/dash-spv-ffi/src/callbacks.rs b/dash-spv-ffi/src/callbacks.rs index 97ce9028e..90012ee9b 100644 --- a/dash-spv-ffi/src/callbacks.rs +++ b/dash-spv-ffi/src/callbacks.rs @@ -8,6 +8,7 @@ use crate::{dash_spv_ffi_sync_progress_destroy, FFISyncProgress}; use dashcore::hashes::Hash; +use key_wallet::manager::WalletEvent; use std::ffi::CString; use std::os::raw::{c_char, c_void}; @@ -619,9 +620,7 @@ impl FFIClientErrorCallback { impl FFIWalletEventCallbacks { /// Dispatch a WalletEvent to the appropriate callback. - pub fn dispatch(&self, event: &key_wallet_manager::WalletEvent) { - use key_wallet_manager::WalletEvent; - + pub fn dispatch(&self, event: &WalletEvent) { match event { WalletEvent::TransactionReceived { wallet_id, diff --git a/dash-spv-ffi/src/client.rs b/dash-spv-ffi/src/client.rs index 13e791cda..41ef3a069 100644 --- a/dash-spv-ffi/src/client.rs +++ b/dash-spv-ffi/src/client.rs @@ -106,9 +106,7 @@ where /// FFI wrapper around `DashSpvClient`. type InnerClient = DashSpvClient< - key_wallet_manager::wallet_manager::WalletManager< - key_wallet::wallet::managed_wallet_info::ManagedWalletInfo, - >, + key_wallet::manager::WalletManager, dash_spv::network::PeerNetworkManager, DiskStorageManager, >; @@ -166,7 +164,7 @@ pub unsafe extern "C" fn dash_spv_ffi_client_new( // Construct concrete implementations for generics let network = dash_spv::network::PeerNetworkManager::new(&client_config).await; let storage = DiskStorageManager::new(&client_config).await; - let wallet = key_wallet_manager::wallet_manager::WalletManager::< + let wallet = key_wallet::manager::WalletManager::< key_wallet::wallet::managed_wallet_info::ManagedWalletInfo, >::new(client_config.network); let wallet = std::sync::Arc::new(tokio::sync::RwLock::new(wallet)); diff --git a/dash-spv-ffi/tests/test_wallet_manager.rs b/dash-spv-ffi/tests/test_wallet_manager.rs index 26b71e249..1edce9598 100644 --- a/dash-spv-ffi/tests/test_wallet_manager.rs +++ b/dash-spv-ffi/tests/test_wallet_manager.rs @@ -1,6 +1,7 @@ #[cfg(test)] mod tests { use dash_spv_ffi::*; + use key_wallet::manager::WalletManager; use key_wallet::wallet::initialization::WalletAccountCreationOptions; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; use key_wallet_ffi::{ @@ -10,7 +11,6 @@ mod tests { }, FFIError, FFINetwork, FFIWalletManager, }; - use key_wallet_manager::wallet_manager::WalletManager; use std::ffi::{CStr, CString}; use tempfile::TempDir; diff --git a/dash-spv/Cargo.toml b/dash-spv/Cargo.toml index dd00740ea..8cffc11fc 100644 --- a/dash-spv/Cargo.toml +++ b/dash-spv/Cargo.toml @@ -13,7 +13,6 @@ rust-version = "1.89" dashcore = { path = "../dash", features = ["std", "serde", "core-block-hash-use-x11", "message_verification", "bls", "quorum_validation"] } dashcore_hashes = { path = "../hashes" } key-wallet = { path = "../key-wallet" } -key-wallet-manager = { path = "../key-wallet-manager" } # BLS signatures blsful = { git = "https://github.com/dashpay/agora-blsful", rev = "0c34a7a488a0bd1c9a9a2196e793b303ad35c900" } @@ -64,7 +63,7 @@ log = "0.4" [dev-dependencies] dash-spv = { path = ".", features = ["test-utils"] } dashcore = { path = "../dash", features = ["test-utils"] } -key-wallet-manager = { path = "../key-wallet-manager", features = ["test-utils"] } +key-wallet = { path = "../key-wallet", features = ["test-utils"] } criterion = { version = "0.8.1", features = ["async_tokio"] } tempfile = "3.0" tokio-test = "0.4" diff --git a/dash-spv/examples/filter_sync.rs b/dash-spv/examples/filter_sync.rs index 9b89490f8..955400f30 100644 --- a/dash-spv/examples/filter_sync.rs +++ b/dash-spv/examples/filter_sync.rs @@ -4,8 +4,8 @@ use dash_spv::network::PeerNetworkManager; use dash_spv::storage::DiskStorageManager; use dash_spv::{init_console_logging, ClientConfig, DashSpvClient, LevelFilter}; use dashcore::Address; +use key_wallet::manager::WalletManager; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_manager::WalletManager; use std::str::FromStr; use std::sync::Arc; use tokio::sync::RwLock; diff --git a/dash-spv/examples/simple_sync.rs b/dash-spv/examples/simple_sync.rs index a5f601609..8fd1cbbbc 100644 --- a/dash-spv/examples/simple_sync.rs +++ b/dash-spv/examples/simple_sync.rs @@ -5,7 +5,7 @@ use dash_spv::storage::DiskStorageManager; use dash_spv::{init_console_logging, ClientConfig, DashSpvClient, LevelFilter}; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_manager::WalletManager; +use key_wallet::manager::WalletManager; use std::sync::Arc; use tokio::sync::RwLock; use tokio_util::sync::CancellationToken; diff --git a/dash-spv/examples/spv_with_wallet.rs b/dash-spv/examples/spv_with_wallet.rs index 8d5f5c591..31e6d4ffe 100644 --- a/dash-spv/examples/spv_with_wallet.rs +++ b/dash-spv/examples/spv_with_wallet.rs @@ -5,8 +5,8 @@ use dash_spv::network::PeerNetworkManager; use dash_spv::storage::DiskStorageManager; use dash_spv::{ClientConfig, DashSpvClient, LevelFilter}; +use key_wallet::manager::WalletManager; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_manager::WalletManager; use std::sync::Arc; use tokio::sync::RwLock; use tokio_util::sync::CancellationToken; diff --git a/dash-spv/src/client/core.rs b/dash-spv/src/client/core.rs index 3e82a36ef..fa9ebda92 100644 --- a/dash-spv/src/client/core.rs +++ b/dash-spv/src/client/core.rs @@ -22,7 +22,7 @@ use crate::storage::{ }; use crate::sync::SyncCoordinator; use crate::types::MempoolState; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; pub(super) type PersistentSyncCoordinator = SyncCoordinator< PersistentBlockHeaderStorage, diff --git a/dash-spv/src/client/events.rs b/dash-spv/src/client/events.rs index 160116b2c..7f5388afd 100644 --- a/dash-spv/src/client/events.rs +++ b/dash-spv/src/client/events.rs @@ -9,7 +9,7 @@ use tokio::sync::watch; use crate::network::{NetworkEvent, NetworkManager}; use crate::storage::StorageManager; use crate::sync::{SyncEvent, SyncProgress}; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; use tokio::sync::broadcast; use super::DashSpvClient; diff --git a/dash-spv/src/client/lifecycle.rs b/dash-spv/src/client/lifecycle.rs index 6c6c9f333..3cb959c8f 100644 --- a/dash-spv/src/client/lifecycle.rs +++ b/dash-spv/src/client/lifecycle.rs @@ -28,7 +28,7 @@ use crate::sync::{ use crate::types::MempoolState; use dashcore::sml::masternode_list_engine::MasternodeListEngine; use dashcore_hashes::Hash; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; impl DashSpvClient { /// Create a new SPV client with the given configuration, network, storage, and wallet. diff --git a/dash-spv/src/client/mempool.rs b/dash-spv/src/client/mempool.rs index d351c2a01..6296c3c5f 100644 --- a/dash-spv/src/client/mempool.rs +++ b/dash-spv/src/client/mempool.rs @@ -13,7 +13,7 @@ use crate::error::Result; use crate::mempool_filter::MempoolFilter; use crate::network::NetworkManager; use crate::storage::StorageManager; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; use super::DashSpvClient; diff --git a/dash-spv/src/client/mod.rs b/dash-spv/src/client/mod.rs index 846e47881..f9cb8848e 100644 --- a/dash-spv/src/client/mod.rs +++ b/dash-spv/src/client/mod.rs @@ -50,8 +50,8 @@ mod tests { use crate::storage::DiskStorageManager; use crate::{test_utils::MockNetworkManager, types::UnconfirmedTransaction}; use dashcore::{Address, Amount, Transaction, TxOut}; + use key_wallet::manager::WalletManager; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; - use key_wallet_manager::wallet_manager::WalletManager; use std::sync::Arc; use tempfile::TempDir; use tokio::sync::RwLock; diff --git a/dash-spv/src/client/queries.rs b/dash-spv/src/client/queries.rs index 203094431..90b72ad9a 100644 --- a/dash-spv/src/client/queries.rs +++ b/dash-spv/src/client/queries.rs @@ -13,7 +13,7 @@ use dashcore::sml::llmq_type::LLMQType; use dashcore::sml::masternode_list_engine::MasternodeListEngine; use dashcore::sml::quorum_entry::qualified_quorum_entry::QualifiedQuorumEntry; use dashcore::QuorumHash; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; use std::sync::Arc; use tokio::sync::RwLock; diff --git a/dash-spv/src/client/sync_coordinator.rs b/dash-spv/src/client/sync_coordinator.rs index da1fe444d..127cca3d2 100644 --- a/dash-spv/src/client/sync_coordinator.rs +++ b/dash-spv/src/client/sync_coordinator.rs @@ -5,7 +5,7 @@ use crate::error::Result; use crate::network::NetworkManager; use crate::storage::StorageManager; use crate::sync::SyncProgress; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; use std::time::Duration; use tokio_util::sync::CancellationToken; diff --git a/dash-spv/src/client/transactions.rs b/dash-spv/src/client/transactions.rs index f2e2b2d2f..9442e3853 100644 --- a/dash-spv/src/client/transactions.rs +++ b/dash-spv/src/client/transactions.rs @@ -4,7 +4,7 @@ use crate::error::{Result, SpvError}; use crate::network::NetworkManager; use crate::storage::StorageManager; use dashcore::network::message::NetworkMessage; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; use super::DashSpvClient; diff --git a/dash-spv/src/lib.rs b/dash-spv/src/lib.rs index 87398b720..a5634d81d 100644 --- a/dash-spv/src/lib.rs +++ b/dash-spv/src/lib.rs @@ -17,7 +17,7 @@ //! use dash_spv::storage::DiskStorageManager; //! use dashcore::Network; //! use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -//! use key_wallet_manager::wallet_manager::WalletManager; +//! use key_wallet::manager::WalletManager; //! use std::sync::Arc; //! use tokio::sync::RwLock; //! use tokio_util::sync::CancellationToken; diff --git a/dash-spv/src/main.rs b/dash-spv/src/main.rs index 919bdaac6..1caeeb3f3 100644 --- a/dash-spv/src/main.rs +++ b/dash-spv/src/main.rs @@ -7,8 +7,8 @@ use std::sync::Arc; use clap::{Arg, Command}; use dash_spv::{ClientConfig, DashSpvClient, LevelFilter, Network}; +use key_wallet::manager::WalletManager; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_manager::WalletManager; use tokio_util::sync::CancellationToken; #[tokio::main] diff --git a/dash-spv/src/sync/blocks/manager.rs b/dash-spv/src/sync/blocks/manager.rs index 34771d9e9..585e346de 100644 --- a/dash-spv/src/sync/blocks/manager.rs +++ b/dash-spv/src/sync/blocks/manager.rs @@ -12,7 +12,7 @@ use crate::error::SyncResult; use crate::network::RequestSender; use crate::storage::{BlockHeaderStorage, BlockStorage}; use crate::sync::{BlocksProgress, SyncEvent, SyncManager, SyncState}; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; /// Blocks manager for downloading and processing matching blocks. /// @@ -164,8 +164,8 @@ mod tests { }; use crate::sync::{ManagerIdentifier, SyncEvent, SyncManagerProgress}; use crate::test_utils::MockNetworkManager; - use key_wallet_manager::test_utils::MockWallet; - use key_wallet_manager::wallet_manager::FilterMatchKey; + use key_wallet::manager::FilterMatchKey; + use key_wallet::test_utils::MockWallet; use std::collections::BTreeSet; type TestBlocksManager = diff --git a/dash-spv/src/sync/blocks/pipeline.rs b/dash-spv/src/sync/blocks/pipeline.rs index 819a798f5..a431f1032 100644 --- a/dash-spv/src/sync/blocks/pipeline.rs +++ b/dash-spv/src/sync/blocks/pipeline.rs @@ -11,7 +11,7 @@ use crate::network::RequestSender; use crate::sync::download_coordinator::{DownloadConfig, DownloadCoordinator}; use dashcore::blockdata::block::Block; use dashcore::BlockHash; -use key_wallet_manager::wallet_manager::FilterMatchKey; +use key_wallet::manager::FilterMatchKey; /// Maximum number of concurrent block downloads. const MAX_CONCURRENT_BLOCK_DOWNLOADS: usize = 20; diff --git a/dash-spv/src/sync/blocks/sync_manager.rs b/dash-spv/src/sync/blocks/sync_manager.rs index d869b5d2b..beeeb279a 100644 --- a/dash-spv/src/sync/blocks/sync_manager.rs +++ b/dash-spv/src/sync/blocks/sync_manager.rs @@ -10,7 +10,7 @@ use crate::types::HashedBlock; use crate::SyncError; use async_trait::async_trait; use dashcore::network::message::NetworkMessage; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; #[async_trait] impl SyncManager diff --git a/dash-spv/src/sync/events.rs b/dash-spv/src/sync/events.rs index c5da811b2..5089c5102 100644 --- a/dash-spv/src/sync/events.rs +++ b/dash-spv/src/sync/events.rs @@ -2,7 +2,7 @@ use crate::sync::ManagerIdentifier; use dashcore::ephemerealdata::chain_lock::ChainLock; use dashcore::ephemerealdata::instant_lock::InstantLock; use dashcore::{Address, BlockHash}; -use key_wallet_manager::wallet_manager::FilterMatchKey; +use key_wallet::manager::FilterMatchKey; use std::collections::BTreeSet; /// Events that managers can emit and subscribe to. diff --git a/dash-spv/src/sync/filters/batch.rs b/dash-spv/src/sync/filters/batch.rs index 687c641f0..202d169d9 100644 --- a/dash-spv/src/sync/filters/batch.rs +++ b/dash-spv/src/sync/filters/batch.rs @@ -1,6 +1,6 @@ use dashcore::bip158::BlockFilter; use dashcore::Address; -use key_wallet_manager::wallet_manager::FilterMatchKey; +use key_wallet::manager::FilterMatchKey; use std::collections::{HashMap, HashSet}; /// A completed batch of compact block filters ready for verification. @@ -134,7 +134,7 @@ mod tests { use crate::sync::filters::batch::FiltersBatch; use dashcore::bip158::BlockFilter; use dashcore::Header; - use key_wallet_manager::wallet_manager::FilterMatchKey; + use key_wallet::manager::FilterMatchKey; use std::collections::{BTreeSet, HashMap}; #[test] diff --git a/dash-spv/src/sync/filters/batch_tracker.rs b/dash-spv/src/sync/filters/batch_tracker.rs index 2a535e103..ceae6b731 100644 --- a/dash-spv/src/sync/filters/batch_tracker.rs +++ b/dash-spv/src/sync/filters/batch_tracker.rs @@ -1,6 +1,6 @@ use dashcore::bip158::BlockFilter; use dashcore::BlockHash; -use key_wallet_manager::wallet_manager::FilterMatchKey; +use key_wallet::manager::FilterMatchKey; use std::collections::{HashMap, HashSet}; /// Tracks individual filters within a batch. diff --git a/dash-spv/src/sync/filters/manager.rs b/dash-spv/src/sync/filters/manager.rs index b3d5e04f6..5080af045 100644 --- a/dash-spv/src/sync/filters/manager.rs +++ b/dash-spv/src/sync/filters/manager.rs @@ -21,8 +21,8 @@ use crate::validation::{FilterValidationInput, FilterValidator, Validator}; use crate::sync::progress::ProgressPercentage; use dashcore::hash_types::FilterHeader; -use key_wallet_manager::wallet_interface::WalletInterface; -use key_wallet_manager::wallet_manager::{check_compact_filters_for_addresses, FilterMatchKey}; +use key_wallet::manager::WalletInterface; +use key_wallet::manager::{check_compact_filters_for_addresses, FilterMatchKey}; use tokio::sync::RwLock; /// Batch size for processing filters. @@ -771,7 +771,7 @@ mod tests { PersistentFilterStorage, StorageManager, }; use crate::sync::{ManagerIdentifier, SyncManagerProgress}; - use key_wallet_manager::test_utils::MockWallet; + use key_wallet::test_utils::MockWallet; use tokio::sync::mpsc::unbounded_channel; type TestFiltersManager = FiltersManager< diff --git a/dash-spv/src/sync/filters/pipeline.rs b/dash-spv/src/sync/filters/pipeline.rs index 6906afef1..ce1da1336 100644 --- a/dash-spv/src/sync/filters/pipeline.rs +++ b/dash-spv/src/sync/filters/pipeline.rs @@ -279,7 +279,7 @@ mod tests { use dashcore::block::Header; use dashcore::network::message::NetworkMessage; use dashcore_hashes::Hash; - use key_wallet_manager::wallet_manager::FilterMatchKey; + use key_wallet::manager::FilterMatchKey; use std::time::Duration; use tempfile::TempDir; use tokio::sync::mpsc::unbounded_channel; diff --git a/dash-spv/src/sync/filters/sync_manager.rs b/dash-spv/src/sync/filters/sync_manager.rs index f888c51b1..a9423ee1b 100644 --- a/dash-spv/src/sync/filters/sync_manager.rs +++ b/dash-spv/src/sync/filters/sync_manager.rs @@ -9,7 +9,7 @@ use crate::sync::{ }; use async_trait::async_trait; use dashcore::network::message::NetworkMessage; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; #[async_trait] impl< diff --git a/dash-spv/src/sync/sync_coordinator.rs b/dash-spv/src/sync/sync_coordinator.rs index 17a8ef9d3..cd53058a9 100644 --- a/dash-spv/src/sync/sync_coordinator.rs +++ b/dash-spv/src/sync/sync_coordinator.rs @@ -24,7 +24,7 @@ use crate::sync::{ SyncManagerProgress, SyncManagerTaskContext, SyncProgress, }; use crate::SyncError; -use key_wallet_manager::wallet_interface::WalletInterface; +use key_wallet::manager::WalletInterface; const TASK_JOIN_TIMEOUT: Duration = Duration::from_secs(5); const DEFAULT_SYNC_EVENT_CAPACITY: usize = 10000; diff --git a/dash-spv/src/validation/filter.rs b/dash-spv/src/validation/filter.rs index 2947e22fa..45b3dd6c1 100644 --- a/dash-spv/src/validation/filter.rs +++ b/dash-spv/src/validation/filter.rs @@ -7,7 +7,7 @@ use std::collections::HashMap; use dashcore::bip158::BlockFilter; use dashcore::hash_types::FilterHeader; -use key_wallet_manager::wallet_manager::FilterMatchKey; +use key_wallet::manager::FilterMatchKey; use rayon::prelude::*; use crate::error::{ValidationError, ValidationResult}; @@ -132,7 +132,7 @@ mod tests { use dashcore::bip158::BlockFilter; use dashcore::BlockHash; use dashcore_hashes::Hash; - use key_wallet_manager::wallet_manager::FilterMatchKey; + use key_wallet::manager::FilterMatchKey; use super::*; diff --git a/dash-spv/tests/dashd_sync/helpers.rs b/dash-spv/tests/dashd_sync/helpers.rs index 533984e77..4bc05f8e9 100644 --- a/dash-spv/tests/dashd_sync/helpers.rs +++ b/dash-spv/tests/dashd_sync/helpers.rs @@ -1,9 +1,9 @@ use dash_spv::network::NetworkEvent; use dash_spv::sync::{ProgressPercentage, SyncEvent, SyncProgress}; use dash_spv::test_utils::DashCoreNode; +use key_wallet::manager::{WalletId, WalletManager}; use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_manager::{WalletId, WalletManager}; use std::collections::HashSet; use std::sync::Arc; use std::time::Duration; diff --git a/dash-spv/tests/dashd_sync/setup.rs b/dash-spv/tests/dashd_sync/setup.rs index 1715bbc21..6c3c29f9a 100644 --- a/dash-spv/tests/dashd_sync/setup.rs +++ b/dash-spv/tests/dashd_sync/setup.rs @@ -11,10 +11,10 @@ use dash_spv::{ use dashcore::network::address::AddrV2Message; use dashcore::network::constants::ServiceFlags; use key_wallet::managed_account::managed_account_type::ManagedAccountType; +use key_wallet::manager::{WalletId, WalletManager}; use key_wallet::wallet::initialization::WalletAccountCreationOptions; use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_manager::{WalletId, WalletManager}; use std::collections::{BTreeSet, HashSet}; use std::path::PathBuf; use std::sync::Arc; diff --git a/dash-spv/tests/dashd_sync/tests_basic.rs b/dash-spv/tests/dashd_sync/tests_basic.rs index f91745fec..8b17c0b4d 100644 --- a/dash-spv/tests/dashd_sync/tests_basic.rs +++ b/dash-spv/tests/dashd_sync/tests_basic.rs @@ -1,5 +1,5 @@ +use key_wallet::manager::WalletManager; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_manager::WalletManager; use std::sync::Arc; use tokio::sync::RwLock; diff --git a/dash-spv/tests/peer_test.rs b/dash-spv/tests/peer_test.rs index 683ce34c0..b741e41ce 100644 --- a/dash-spv/tests/peer_test.rs +++ b/dash-spv/tests/peer_test.rs @@ -13,8 +13,8 @@ use dash_spv::network::PeerNetworkManager; use dash_spv::storage::DiskStorageManager; use dash_spv::types::ValidationMode; use dashcore::Network; +use key_wallet::manager::WalletManager; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_manager::WalletManager; /// Create a test configuration with the given network fn create_test_config(network: Network) -> ClientConfig { let mut config = ClientConfig::new(network); diff --git a/dash-spv/tests/wallet_integration_test.rs b/dash-spv/tests/wallet_integration_test.rs index 6f9ffe20d..518ff78c2 100644 --- a/dash-spv/tests/wallet_integration_test.rs +++ b/dash-spv/tests/wallet_integration_test.rs @@ -12,8 +12,8 @@ use dash_spv::network::PeerNetworkManager; use dash_spv::storage::DiskStorageManager; use dash_spv::{ClientConfig, DashSpvClient}; use dashcore::Network; +use key_wallet::manager::WalletManager; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_manager::WalletManager; /// Create a test SPV client with memory storage for integration testing. async fn create_test_client( ) -> DashSpvClient, PeerNetworkManager, DiskStorageManager> { @@ -83,6 +83,3 @@ async fn test_wallet_manager_basic_operations() { let balance = wallet_manager.get_total_balance(); assert_eq!(balance, 0); } - -// Note: More comprehensive wallet tests should be in the key-wallet-manager crate -// since that's where the wallet logic now resides diff --git a/key-wallet-ffi/Cargo.toml b/key-wallet-ffi/Cargo.toml index 0b0fbd7fb..01306af39 100644 --- a/key-wallet-ffi/Cargo.toml +++ b/key-wallet-ffi/Cargo.toml @@ -15,13 +15,12 @@ crate-type = ["cdylib", "staticlib", "lib"] [features] default = ["bincode", "eddsa", "bls", "bip38"] bip38 = ["key-wallet/bip38"] -bincode = ["key-wallet-manager/bincode", "key-wallet/bincode"] +bincode = ["key-wallet/bincode"] eddsa = ["dashcore/eddsa", "key-wallet/eddsa"] bls = ["dashcore/bls", "key-wallet/bls"] [dependencies] key-wallet = { path = "../key-wallet", default-features = false, features = ["std"] } -key-wallet-manager = { path = "../key-wallet-manager", features = ["std"] } dashcore = { path = "../dash", features = ["std"] } secp256k1 = { version = "0.30.0", features = ["global-context"] } tokio = { version = "1.32", features = ["rt-multi-thread", "sync"] } diff --git a/key-wallet-ffi/src/error.rs b/key-wallet-ffi/src/error.rs index a8ca15af8..3654e163c 100644 --- a/key-wallet-ffi/src/error.rs +++ b/key-wallet-ffi/src/error.rs @@ -191,10 +191,9 @@ impl From for FFIError { } } -/// Convert key_wallet_manager::WalletError to FFIError -impl From for FFIError { - fn from(err: key_wallet_manager::wallet_manager::WalletError) -> Self { - use key_wallet_manager::wallet_manager::WalletError; +impl From for FFIError { + fn from(err: key_wallet::manager::WalletError) -> Self { + use key_wallet::manager::WalletError; let (code, msg) = match &err { WalletError::WalletCreation(msg) => { diff --git a/key-wallet-ffi/src/transaction.rs b/key-wallet-ffi/src/transaction.rs index 531d4ced8..881acb659 100644 --- a/key-wallet-ffi/src/transaction.rs +++ b/key-wallet-ffi/src/transaction.rs @@ -9,8 +9,8 @@ use dashcore::{ consensus, hashes::Hash, sighash::SighashCache, EcdsaSighashType, Network, OutPoint, Script, ScriptBuf, Transaction, TxIn, TxOut, Txid, }; +use key_wallet::wallet::managed_wallet_info::fee::FeeRate; use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; -use key_wallet_manager::FeeRate; use secp256k1::{Message, Secp256k1, SecretKey}; use crate::error::{FFIError, FFIErrorCode}; diff --git a/key-wallet-ffi/src/wallet_manager.rs b/key-wallet-ffi/src/wallet_manager.rs index e209af61f..5406a3db9 100644 --- a/key-wallet-ffi/src/wallet_manager.rs +++ b/key-wallet-ffi/src/wallet_manager.rs @@ -1,4 +1,4 @@ -//! FFI bindings for WalletManager from key-wallet-manager crate +//! FFI bindings for WalletManager #[cfg(test)] #[path = "wallet_manager_tests.rs"] @@ -16,9 +16,9 @@ use tokio::sync::RwLock; use crate::error::{FFIError, FFIErrorCode}; use crate::FFINetwork; +use key_wallet::manager::WalletInterface; +use key_wallet::manager::WalletManager; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; -use key_wallet_manager::wallet_interface::WalletInterface; -use key_wallet_manager::wallet_manager::WalletManager; /// FFI wrapper for WalletManager /// @@ -470,14 +470,14 @@ pub unsafe extern "C" fn wallet_manager_import_wallet_from_bytes( Err(e) => { // Convert the error to FFI error match e { - key_wallet_manager::wallet_manager::WalletError::WalletExists(_) => { + key_wallet::manager::WalletError::WalletExists(_) => { FFIError::set_error( error, FFIErrorCode::InvalidState, "Wallet already exists in the manager".to_string(), ); } - key_wallet_manager::wallet_manager::WalletError::InvalidParameter(msg) => { + key_wallet::manager::WalletError::InvalidParameter(msg) => { FFIError::set_error( error, FFIErrorCode::SerializationError, diff --git a/key-wallet-ffi/src/wallet_manager_tests.rs b/key-wallet-ffi/src/wallet_manager_tests.rs index d1f9720e5..6997c237f 100644 --- a/key-wallet-ffi/src/wallet_manager_tests.rs +++ b/key-wallet-ffi/src/wallet_manager_tests.rs @@ -5,7 +5,7 @@ mod tests { use crate::error::{FFIError, FFIErrorCode}; use crate::{wallet, wallet_manager, FFINetwork}; - use key_wallet_manager::wallet_interface::WalletInterface; + use key_wallet::manager::WalletInterface; use std::ffi::{CStr, CString}; use std::ptr; use std::slice; diff --git a/key-wallet-ffi/tests/test_error_conversions.rs b/key-wallet-ffi/tests/test_error_conversions.rs index 7a2a832ae..dbeefcd97 100644 --- a/key-wallet-ffi/tests/test_error_conversions.rs +++ b/key-wallet-ffi/tests/test_error_conversions.rs @@ -55,7 +55,7 @@ fn test_key_wallet_error_to_ffi_error() { #[test] fn test_wallet_manager_error_to_ffi_error() { - use key_wallet_manager::wallet_manager::WalletError; + use key_wallet::manager::WalletError; // Test WalletNotFound conversion let wallet_id = [0u8; 32]; @@ -105,8 +105,8 @@ fn test_wallet_manager_error_to_ffi_error() { #[test] fn test_key_wallet_error_to_wallet_manager_error() { + use key_wallet::manager::WalletError; use key_wallet::Error as KeyWalletError; - use key_wallet_manager::wallet_manager::WalletError; // Test InvalidMnemonic conversion let err = KeyWalletError::InvalidMnemonic("bad mnemonic".to_string()); @@ -172,8 +172,8 @@ fn test_key_wallet_error_to_wallet_manager_error() { #[test] fn test_error_message_consistency() { + use key_wallet::manager::WalletError; use key_wallet::Error as KeyWalletError; - use key_wallet_manager::wallet_manager::WalletError; // Test that error messages are preserved through conversions let original_msg = "This is a test error message"; diff --git a/key-wallet-manager/Cargo.toml b/key-wallet-manager/Cargo.toml deleted file mode 100644 index 78e7bbe6c..000000000 --- a/key-wallet-manager/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "key-wallet-manager" -version = { workspace = true } -authors = ["The Dash Core Developers"] -edition = "2021" -description = "High-level wallet management for Dash using key-wallet primitives" -keywords = ["dash", "wallet", "transaction", "utxo", "hdwallet"] -readme = "README.md" -license = "CC0-1.0" - -[features] -default = ["std", "bincode"] -std = ["key-wallet/std", "dashcore/std", "dashcore_hashes/std", "secp256k1/std"] -serde = ["dep:serde", "key-wallet/serde", "dashcore/serde"] -getrandom = ["key-wallet/getrandom"] -bincode = ["dep:bincode", "key-wallet/bincode"] -test-utils = [] - -[dependencies] -key-wallet = { path = "../key-wallet", default-features = false } -dashcore = { path = "../dash", default-features = false } -dashcore_hashes = { path = "../hashes", default-features = false } -secp256k1 = { version = "0.30.0", default-features = false, features = ["recovery"] } -serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } -async-trait = "0.1" -bincode = { version = "2.0.1", optional = true } -zeroize = { version = "1.8", features = ["derive"] } -rayon = "1.11" -tokio = { version = "1.32", features = ["full"] } - -[dev-dependencies] -dashcore = { path = "../dash", features = ["test-utils"] } -hex = "0.4" -serde_json = "1.0" - -[lints.rust] -unexpected_cfgs = { level = "allow", check-cfg = ['cfg(bench)', 'cfg(fuzzing)'] } diff --git a/key-wallet-manager/README.md b/key-wallet-manager/README.md deleted file mode 100644 index 1e82d0779..000000000 --- a/key-wallet-manager/README.md +++ /dev/null @@ -1,455 +0,0 @@ -# key-wallet-manager - -High-level wallet management for Dash using key-wallet primitives and dashcore transaction types. - -## Overview - -`key-wallet-manager` provides a comprehensive, high-level interface for managing Dash wallets, building transactions, and handling UTXOs. It bridges the gap between low-level cryptographic primitives in `key-wallet` and the transaction structures in `dashcore`. - -### Architecture - -- **Multi-wallet management**: Manages multiple wallets, each containing multiple accounts -- **High-level operations**: Transaction building, fee management, coin selection -- **UTXO management**: Track and manage unspent transaction outputs per wallet -- **Integration layer**: Seamlessly combines `key-wallet` and `dashcore` types -- **No circular dependencies**: Clean separation from low-level wallet primitives - -## Features - -- 🔑 **Wallet Management**: Create, configure, and manage HD wallets -- 💰 **Transaction Building**: Construct, sign, and broadcast Dash transactions -- 🎯 **Coin Selection**: Multiple strategies (smallest first, largest first, optimal) -- 📊 **UTXO Tracking**: Comprehensive unspent output management -- 💸 **Fee Management**: Dynamic fee calculation and levels -- 🔒 **Watch-Only Support**: Monitor addresses without private keys -- 🌐 **Multi-Account**: BIP44 account management -- ⚡ **Optimized**: Efficient algorithms for large transaction sets - -## Quick Start - -### Add Dependency - -```toml -[dependencies] -key-wallet-manager = { path = "../key-wallet-manager" } -``` - -### Basic Usage - -```rust -use key_wallet_manager::{ - WalletManager, TransactionBuilder, FeeLevel, - CoinSelector, SelectionStrategy -}; - -// Create a new wallet manager -let mut wallet_manager = WalletManager::new(Network::Testnet); - -// Create a wallet -let wallet = wallet_manager.create_wallet_from_mnemonic( - "my_wallet".to_string(), - "My Main Wallet".to_string(), - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", - "", // passphrase - None, // use default network -)?; - -// Add an account to the wallet -wallet_manager.create_account("my_wallet", 0, AccountType::BIP44)?; - -// Get a receive address from the wallet and account -let address = wallet_manager.get_receive_address("my_wallet", 0)?; -println!("Send funds to: {}", address); - -// Build a transaction -let recipient = "yNsWkgPLN1u7p1dfAXnpRPqPsWg6uqhqBr".parse()?; -let amount = 100_000; // 0.001 DASH in duffs - -let tx = wallet_manager.send_transaction( - "my_wallet", - 0, // account index - vec![(recipient, amount)], - FeeLevel::Normal, -)?; - -println!("Transaction built: {}", tx.txid()); -``` - -## Core Components - -### WalletManager - -The main interface for managing multiple wallets: - -```rust -use key_wallet_manager::WalletManager; - -// Create a wallet manager -let mut wallet_manager = WalletManager::new(Network::Testnet); - -// Create wallet from mnemonic -let wallet = wallet_manager.create_wallet_from_mnemonic( - "wallet1".to_string(), - "My Main Wallet".to_string(), - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", - "password", - None, -)?; - -// Or create new empty wallet -let wallet2 = wallet_manager.create_wallet( - "wallet2".to_string(), - "My Second Wallet".to_string(), - None, -)?; - -// Account management -wallet_manager.create_account("wallet1", 0, AccountType::BIP44)?; -let accounts = wallet_manager.get_accounts("wallet1")?; - -// Address generation -let receive_addr = wallet_manager.get_receive_address("wallet1", 0)?; -let change_addr = wallet_manager.get_change_address("wallet1", 0)?; - -// Transaction history -let all_history = wallet_manager.transaction_history(); -let wallet_history = wallet_manager.wallet_transaction_history("wallet1")?; -``` - -### TransactionBuilder - -Construct and sign transactions: - -```rust -use key_wallet_manager::{TransactionBuilder, FeeLevel}; - -let mut builder = TransactionBuilder::new(Network::Testnet); - -// Add recipients -builder.add_recipient("yNsWkgPLN1u7p1dfAXnpRPqPsWg6uqhqBr".parse()?, 50_000)?; -builder.add_recipient("yTtGbtjKJay7r4KdRWQ4aKM8bMFsQ3xvp2".parse()?, 75_000)?; - -// Set fee strategy -builder.set_fee_level(FeeLevel::High); -// Or manual fee rate -builder.set_fee_rate(FeeRate::from_sat_per_vb(10)?); - -// Add data (OP_RETURN) -builder.add_data(b"Hello Dash!")?; - -// Send transaction from wallet and account -let transaction = wallet_manager.send_transaction( - "wallet1", - 0, // account index - vec![(recipient, amount)], - FeeLevel::Normal, -)?; -``` - -### Coin Selection - -Choose optimal UTXOs for transactions: - -```rust -use key_wallet_manager::{CoinSelector, SelectionStrategy}; - -let selector = CoinSelector::new(); - -// Different strategies -// Get UTXOs for a wallet -let wallet_utxos = wallet_manager.get_wallet_utxos("wallet1")?; - -// Add UTXOs to a wallet -let utxo = Utxo::new(outpoint, txout, address, height, false); -wallet_manager.add_utxo("wallet1", utxo)?; - -let selection = selector.select_coins( - &utxo_set, - 100_000, - SelectionStrategy::LargestFirst -)?; - -let selection = selector.select_coins( - &utxo_set, - 100_000, - SelectionStrategy::BranchAndBound -)?; - -// Use selected coins -for utxo in selection.selected_utxos { - builder.add_input(utxo, None)?; // None = unsigned -} -``` - -### Watch-Only Wallets - -Monitor addresses without private keys: - -```rust -use key_wallet::{WatchOnlyWallet, WatchOnlyWalletBuilder}; - -// Create from extended public key -let xpub = "xpub6CUGRUonZSQ4TWtTMmzXdrXDtypWKiKrhko4egpiMZbpiaQL2jkwSB1icqYh2cfDfVxdx4df189oLKnC5fSwqPfgyP3hooxujYzAu3fDVmz"; - -let watch_wallet = WatchOnlyWalletBuilder::new() - .xpub_string(xpub)? - .network(Network::Testnet) - .name("Watch Wallet") - .index(0) - .build()?; - -// Generate addresses to monitor -let addr1 = watch_wallet.get_next_receive_address()?; -let addr2 = watch_wallet.get_next_receive_address()?; - -// Check for activity -let result = watch_wallet.scan_for_activity(|addr| { - // Your logic to check if address has been used - check_address_on_blockchain(addr) -}); -``` - -## Fee Management - -### Fee Levels - -```rust -use key_wallet_manager::{FeeLevel, FeeRate}; - -// Predefined levels -builder.set_fee_level(FeeLevel::Low); // ~1-3 blocks -builder.set_fee_level(FeeLevel::Normal); // Next block -builder.set_fee_level(FeeLevel::High); // Priority - -// Custom fee rate -builder.set_fee_rate(FeeRate::from_sat_per_vb(5)?); -builder.set_fee_rate(FeeRate::from_sat_per_kvb(1000)?); -``` - -### Fee Estimation - -```rust -// Estimate fees before building -let estimated_fee = builder.estimate_fee(&utxo_set)?; -println!("Estimated fee: {} duffs", estimated_fee); - -// Check if amount is dust -if builder.is_dust_amount(546) { - println!("Amount too small to spend efficiently"); -} -``` - -## Advanced Usage - -### Multi-Account Operations - -```rust -// Create multiple accounts -for i in 0..5 { - wallet.create_account(i, AccountType::BIP44)?; -} - -// Send from specific wallet and account -let tx = wallet_manager.send_transaction( - "wallet1", - 2, // account index - vec![(recipient, amount)], - FeeLevel::Normal, -)?; - -// Get wallet balance -let balance = wallet_manager.get_wallet_balance("wallet1")?; -println!("Wallet balance: {} DASH", balance / 100_000_000); - -// List all wallets -for wallet_id in wallet_manager.list_wallets() { - let balance = wallet_manager.get_wallet_balance(wallet_id)?; - println!("Wallet {}: {} DASH", wallet_id, balance / 100_000_000); -} -``` - -### Transaction Serialization - -```rust -// Get raw transaction bytes -let raw_tx = transaction.serialize(); - -// Broadcast ready hex -let hex = transaction.serialize().to_hex(); -println!("Broadcast: {}", hex); - -// Parse from hex -let parsed_tx = Transaction::deserialize(&Vec::from_hex(&hex)?)?; -``` - -### Error Handling - -```rust -use key_wallet_manager::{WalletError, BuilderError}; - -match wallet_manager.create_account("wallet1", 0, AccountType::BIP44) { - Ok(()) => println!("Account created"), - Err(WalletError::WalletNotFound(id)) => { - println!("Wallet {} not found", id); - } - Err(WalletError::InvalidNetwork) => { - println!("Network configuration error"); - } - Err(e) => println!("Other error: {}", e), -} - -match wallet_manager.send_transaction("wallet1", 0, recipients, FeeLevel::Normal) { - Ok(tx) => println!("Transaction built: {}", tx.txid()), - Err(WalletError::WalletNotFound(id)) => { - println!("Wallet {} not found", id); - } - Err(WalletError::AccountNotFound(index)) => { - println!("Account {} not found", index); - } - Err(e) => println!("Transaction error: {}", e), -} -``` - -## Best Practices - -### Security - -- **Never log private keys**: WalletManager redacts sensitive data in Debug output -- **Use strong passphrases**: For mnemonic-based wallets -- **Validate addresses**: Always verify recipient addresses -- **Check transaction fees**: Avoid overpaying due to fee calculation errors - -### Performance - -- **Batch operations**: Group multiple recipients in single transaction -- **Optimize coin selection**: Use appropriate strategy for your use case -- **Cache address pools**: Avoid regenerating addresses unnecessarily - -### Transaction Building - -```rust -// Good: Send to multiple recipients -let recipients = vec![ - (addr1, 50_000), - (addr2, 25_000), -]; -let tx = wallet_manager.send_transaction( - "wallet1", - 0, - recipients, - FeeLevel::Normal, -)?; - -// Avoid: Partial transactions that may fail to build -``` - -### UTXO Management - -```rust -// Add UTXOs to wallets -wallet_manager.add_utxo("wallet1", new_utxo)?; - -// Get wallet balances -let total_balance = wallet_manager.get_total_balance(); -let wallet_balance = wallet_manager.get_wallet_balance("wallet1")?; - -// Update wallet metadata -wallet_manager.update_wallet_metadata( - "wallet1", - Some("Updated Name".to_string()), - Some("Updated description".to_string()), -)?; -``` - -## Integration Examples - -### With dashcore-rpc - -```rust -// Assuming you have an RPC client -let tx = builder.build_and_sign(&wallet, 0)?; -let txid = rpc.send_raw_transaction(&tx.serialize())?; -println!("Broadcast transaction: {}", txid); -``` - -### With electrum client - -```rust -// Update UTXO set from electrum -let script_hash = address.script_pubkey().to_script_hash(); -let utxos = electrum.script_get_list_unspent(&script_hash)?; - -for utxo in utxos { - let outpoint = OutPoint::new(utxo.tx_hash, utxo.tx_pos); - utxo_set.add_utxo(Utxo::new(outpoint, utxo.value, address.clone(), utxo.height)); -} -``` - -## Testing - -Run the test suite: - -```bash -# Run all tests -cargo test -p key-wallet-manager - -# Run specific test modules -cargo test -p key-wallet-manager transaction_builder -cargo test -p key-wallet-manager utxo_management - -# Run with output -cargo test -p key-wallet-manager -- --nocapture -``` - -## Examples - -See the `examples/` directory for complete working examples: - -- `basic_wallet.rs` - Simple wallet creation and transaction -- `multi_account.rs` - Multi-account management -- `watch_only.rs` - Watch-only wallet setup -- `coin_selection.rs` - Different coin selection strategies -- `fee_estimation.rs` - Fee calculation examples - -## Error Types - -| Error | Description | Common Causes | -|-------|-------------|---------------| -| `WalletNotFound` | Wallet doesn't exist | Wrong wallet ID, wallet not created | -| `WalletExists` | Wallet already exists | Duplicate wallet ID | -| `AccountNotFound` | Account doesn't exist | Wrong index, account not created | -| `InvalidMnemonic` | Invalid mnemonic phrase | Wrong words, invalid checksum | -| `InvalidNetwork` | Network mismatch | Testnet key on mainnet, etc. | -| `AddressGeneration` | Address creation failed | Derivation error, invalid keys | -| `TransactionBuild` | Transaction building error | Insufficient funds, invalid inputs | - -## Compatibility - -- **Rust**: 1.70.0+ -- **Networks**: Mainnet, Testnet, Devnet, Regtest -- **Standards**: BIP32, BIP39, BIP44, DIP9 -- **Dependencies**: `key-wallet`, `dashcore`, `secp256k1` - -## Contributing - -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/amazing-feature`) -3. Make changes and add tests -4. Run tests (`cargo test -p key-wallet-manager`) -5. Commit changes (`git commit -am 'Add amazing feature'`) -6. Push to branch (`git push origin feature/amazing-feature`) -7. Create a Pull Request - -## License - -This project is licensed under CC0-1.0 - see the [LICENSE](../LICENSE) file for details. - -## Support - -- 📖 **Documentation**: Run `cargo doc --open -p key-wallet-manager` -- 🐛 **Issues**: Report bugs via GitHub Issues -- 💬 **Discussions**: Community discussions on GitHub - ---- - -Built with ❤️ for the Dash ecosystem diff --git a/key-wallet-manager/src/lib.rs b/key-wallet-manager/src/lib.rs deleted file mode 100644 index 53c608e9e..000000000 --- a/key-wallet-manager/src/lib.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! High-level wallet management for Dash -//! -//! This crate provides high-level wallet functionality that builds on top of -//! the low-level primitives in `key-wallet` and uses transaction types from -//! `dashcore`. -//! -//! ## Features -//! -//! - Multiple wallet management -//! - BIP 157/158 compact block filter support -//! - Transaction processing and matching -//! - UTXO tracking and management -//! - Address generation and gap limit handling -//! - Blockchain synchronization -//! - Transaction building and signing - -#![cfg_attr(not(feature = "std"), no_std)] - -extern crate alloc; - -#[cfg(feature = "std")] -extern crate std; - -#[cfg(any(test, feature = "test-utils"))] -pub mod test_utils; - -pub mod events; -pub mod wallet_interface; -pub mod wallet_manager; - -// Re-export key-wallet types -pub use key_wallet::{ - Account, AccountType, Address, AddressType, ChildNumber, DerivationPath, ExtendedPrivKey, - ExtendedPubKey, Mnemonic, Network, Utxo, Wallet, -}; - -// Re-export dashcore transaction types -pub use dashcore::blockdata::transaction::Transaction; -pub use dashcore::{OutPoint, TxIn, TxOut}; - -// Export our high-level types -pub use events::WalletEvent; -pub use key_wallet::wallet::managed_wallet_info::coin_selection::{ - CoinSelector, SelectionResult, SelectionStrategy, -}; -pub use key_wallet::wallet::managed_wallet_info::fee::FeeRate; -pub use key_wallet::wallet::managed_wallet_info::transaction_builder::TransactionBuilder; -pub use wallet_interface::BlockProcessingResult; -pub use wallet_manager::{WalletError, WalletManager}; diff --git a/key-wallet-manager/src/test_utils/mod.rs b/key-wallet-manager/src/test_utils/mod.rs deleted file mode 100644 index 8308f4c78..000000000 --- a/key-wallet-manager/src/test_utils/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod wallet; - -pub use wallet::{MockWallet, NonMatchingMockWallet}; diff --git a/key-wallet-manager/src/test_utils/wallet.rs b/key-wallet-manager/src/test_utils/wallet.rs deleted file mode 100644 index ea2ed378a..000000000 --- a/key-wallet-manager/src/test_utils/wallet.rs +++ /dev/null @@ -1,120 +0,0 @@ -use crate::{wallet_interface::WalletInterface, BlockProcessingResult}; -use dashcore::prelude::CoreBlockHeight; -use dashcore::{Address, Block, Transaction, Txid}; -use std::{collections::BTreeMap, sync::Arc}; -use tokio::sync::Mutex; - -// Type alias for transaction effects map -type TransactionEffectsMap = Arc)>>>; - -#[derive(Default)] -pub struct MockWallet { - processed_blocks: Arc>>, - processed_transactions: Arc>>, - // Map txid -> (net_amount, addresses) - effects: TransactionEffectsMap, - synced_height: CoreBlockHeight, -} - -impl MockWallet { - pub fn new() -> Self { - Self { - processed_blocks: Arc::new(Mutex::new(Vec::new())), - processed_transactions: Arc::new(Mutex::new(Vec::new())), - effects: Arc::new(Mutex::new(BTreeMap::new())), - synced_height: 0, - } - } - - pub async fn set_effect(&self, txid: dashcore::Txid, net: i64, addresses: Vec) { - let mut map = self.effects.lock().await; - map.insert(txid, (net, addresses)); - } - - pub fn processed_blocks(&self) -> Arc>> { - self.processed_blocks.clone() - } - - pub fn processed_transactions(&self) -> Arc>> { - self.processed_transactions.clone() - } -} - -#[async_trait::async_trait] -impl WalletInterface for MockWallet { - async fn process_block(&mut self, block: &Block, height: u32) -> BlockProcessingResult { - let mut processed = self.processed_blocks.lock().await; - processed.push((block.block_hash(), height)); - - BlockProcessingResult { - new_txids: block.txdata.iter().map(|tx| tx.txid()).collect(), - existing_txids: Vec::new(), - new_addresses: Vec::new(), - } - } - - async fn process_mempool_transaction(&mut self, tx: &Transaction) { - let mut processed = self.processed_transactions.lock().await; - processed.push(tx.txid()); - } - - async fn describe(&self) -> String { - "MockWallet (test implementation)".to_string() - } - - async fn transaction_effect(&self, tx: &Transaction) -> Option<(i64, Vec)> { - let map = self.effects.lock().await; - map.get(&tx.txid()).cloned() - } - - fn monitored_addresses(&self) -> Vec
{ - Vec::new() - } - - fn synced_height(&self) -> CoreBlockHeight { - self.synced_height - } - - fn update_synced_height(&mut self, height: CoreBlockHeight) { - self.synced_height = height; - } -} - -/// Mock wallet that returns false for filter checks -#[derive(Default)] -pub struct NonMatchingMockWallet { - synced_height: CoreBlockHeight, -} - -impl NonMatchingMockWallet { - pub fn new() -> Self { - Self { - synced_height: 0, - } - } -} - -#[async_trait::async_trait] -impl WalletInterface for NonMatchingMockWallet { - async fn process_block(&mut self, _block: &Block, _height: u32) -> BlockProcessingResult { - BlockProcessingResult::default() - } - - async fn process_mempool_transaction(&mut self, _tx: &Transaction) {} - - fn monitored_addresses(&self) -> Vec
{ - Vec::new() - } - - fn synced_height(&self) -> CoreBlockHeight { - self.synced_height - } - - fn update_synced_height(&mut self, height: CoreBlockHeight) { - self.synced_height = height; - } - - async fn describe(&self) -> String { - "NonMatchingWallet (test implementation)".to_string() - } -} diff --git a/key-wallet/Cargo.toml b/key-wallet/Cargo.toml index e514ae10f..a5d04a6c3 100644 --- a/key-wallet/Cargo.toml +++ b/key-wallet/Cargo.toml @@ -44,10 +44,11 @@ hkdf = { version = "0.12", default-features = false } zeroize = { version = "1.8", features = ["derive"] } tracing = "0.1" async-trait = "0.1" +tokio = { version = "1", features = ["macros", "rt", "sync"] } +rayon = { version = "1.11" } [dev-dependencies] dashcore = { path="../dash", features = ["test-utils"] } hex = "0.4" key-wallet = { path = ".", features = ["test-utils", "bip38", "serde", "bincode", "eddsa", "bls"] } -tokio = { version = "1", features = ["macros", "rt"] } test-case = "3.3" diff --git a/key-wallet/README.md b/key-wallet/README.md index dd774d383..c35d7a7f6 100644 --- a/key-wallet/README.md +++ b/key-wallet/README.md @@ -19,6 +19,7 @@ The key-wallet crate is a core component of the rust-dashcore ecosystem, offerin The library is organized into several key modules: - **Core Wallet Management**: Complete wallet lifecycle including creation, backup, and recovery +- **Multi-wallet management**: Manages multiple wallets, each containing multiple accounts - **Account System**: Multi-account support with different account types for various use cases - **Address Pools**: Efficient address generation and management with gap limit tracking - **Transaction Processing**: Transaction checking, UTXO tracking, and balance calculation @@ -32,6 +33,18 @@ The library is organized into several key modules: - **BIP38**: Encrypted private key support (optional feature) - **SLIP-10**: Ed25519 key derivation for Platform identities +### Transactions +- **Transaction Building**: Construct, sign, and broadcast Dash transactions +- **Coin Selection**: Multiple strategies (smallest first, largest first, optimal) +- **UTXO Tracking**: Comprehensive unspent output management +- **Fee Management**: Dynamic fee calculation and levels + +### Wallet Manager +- **Wallet Management**: Create, configure, and manage HD wallets +- **Watch-Only Support**: Monitor addresses without private keys +- **Multi-Account**: BIP44 account management +- **Optimized**: Efficient algorithms for large transaction sets + ### Dash-Specific Features (DIP9) - **Standard Accounts**: BIP44-compliant accounts for regular transactions - **CoinJoin Accounts**: Privacy-enhanced mixing accounts diff --git a/key-wallet-manager/TODO.md b/key-wallet/TODO.md similarity index 72% rename from key-wallet-manager/TODO.md rename to key-wallet/TODO.md index ad96c2d0b..8742212c7 100644 --- a/key-wallet-manager/TODO.md +++ b/key-wallet/TODO.md @@ -21,55 +21,6 @@ - Add support for writing into a writer for key-source - Implement Proof of reserves commitment -## Key-Wallet-Manager Library - -### 1. ManagedAccount Integration for Address Generation -**Location**: `wallet_manager.rs` lines 282, 296 -**Priority**: HIGH -**Description**: Address generation methods are currently disabled and return errors. - -**Methods affected**: -- `get_receive_address()` - Returns error, needs ManagedAccount -- `get_change_address()` - Returns error, needs ManagedAccount -- `send_transaction()` - Partially broken due to address generation - -**What needs to be done**: -```rust -// Current (broken): -pub fn get_receive_address(&mut self, wallet_id: &WalletId, account_index: u32) - -> Result { - Err(WalletError::AddressGeneration("...")) -} - -// Needed: -// 1. Get the Account from Wallet -// 2. Get or create ManagedAccount with address pools -// 3. Generate next address using derivation path -// 4. Update address pool state -// 5. Return the address -``` - -### 2. Transaction Building Completion -**Location**: `wallet_manager.rs` line 336 -**Priority**: HIGH -**Description**: Transaction building is incomplete with `unimplemented!()` macro. - -**Issues**: -- Need to get actual addresses from ManagedAccount -- Need to properly select UTXOs for spending -- Need to sign transactions with private keys -- Fee calculation needs to be accurate - -### 3. Fee Calculation -**Location**: `wallet_manager.rs` line 348 -**Priority**: MEDIUM -**Description**: Fee calculation is currently set to `None` and needs proper implementation. - -### 4. Coin Selection Improvements -**Location**: `coin_selection.rs` -**Priority**: LOW -**Description**: Random shuffling for privacy is not implemented in coin selection. - ## Enhanced Wallet Manager ### 1. Real Address Derivation diff --git a/key-wallet-manager/examples/wallet_creation.rs b/key-wallet/examples/wallet_creation.rs similarity index 97% rename from key-wallet-manager/examples/wallet_creation.rs rename to key-wallet/examples/wallet_creation.rs index b609234b1..5d0943cf0 100644 --- a/key-wallet-manager/examples/wallet_creation.rs +++ b/key-wallet/examples/wallet_creation.rs @@ -6,12 +6,12 @@ //! - Managing wallet accounts and addresses use key_wallet::account::StandardAccountType; +use key_wallet::manager::WalletInterface; +use key_wallet::manager::WalletManager; use key_wallet::wallet::initialization::WalletAccountCreationOptions; use key_wallet::wallet::managed_wallet_info::transaction_building::AccountTypePreference; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; use key_wallet::{AccountType, Network}; -use key_wallet_manager::wallet_interface::WalletInterface; -use key_wallet_manager::wallet_manager::WalletManager; fn main() { println!("=== Wallet Creation Example ===\n"); diff --git a/key-wallet-manager/missing_tests.md b/key-wallet/missing_tests.md similarity index 98% rename from key-wallet-manager/missing_tests.md rename to key-wallet/missing_tests.md index 0228d1db8..e0866f30a 100644 --- a/key-wallet-manager/missing_tests.md +++ b/key-wallet/missing_tests.md @@ -1,6 +1,6 @@ -# Missing Tests in key-wallet-manager +# Missing Tests in key-wallet -## 1. WalletManager Multi-Wallet Tests (`wallet_manager.rs`) +## 1. WalletManager Multi-Wallet Tests ### Multi-Wallet Management - `test_create_multiple_wallets` - Create and manage multiple wallets diff --git a/key-wallet/src/lib.rs b/key-wallet/src/lib.rs index db1496b58..b08372884 100644 --- a/key-wallet/src/lib.rs +++ b/key-wallet/src/lib.rs @@ -43,6 +43,7 @@ pub mod dip9; pub mod error; pub mod gap_limit; pub mod managed_account; +pub mod manager; pub mod mnemonic; pub mod psbt; pub mod seed; diff --git a/key-wallet-manager/src/events.rs b/key-wallet/src/manager/events.rs similarity index 98% rename from key-wallet-manager/src/events.rs rename to key-wallet/src/manager/events.rs index 47a67d6c4..9eeaf7ed5 100644 --- a/key-wallet-manager/src/events.rs +++ b/key-wallet/src/manager/events.rs @@ -3,7 +3,7 @@ //! These events are emitted by the WalletManager when significant wallet //! operations occur, allowing consumers to receive push-based notifications. -use crate::wallet_manager::WalletId; +use crate::manager::WalletId; use alloc::string::String; use alloc::vec::Vec; use dashcore::{Address, Txid}; diff --git a/key-wallet-manager/src/wallet_manager/matching.rs b/key-wallet/src/manager/matching.rs similarity index 100% rename from key-wallet-manager/src/wallet_manager/matching.rs rename to key-wallet/src/manager/matching.rs diff --git a/key-wallet-manager/src/wallet_manager/mod.rs b/key-wallet/src/manager/mod.rs similarity index 95% rename from key-wallet-manager/src/wallet_manager/mod.rs rename to key-wallet/src/manager/mod.rs index 944a16b0c..3f0c07a17 100644 --- a/key-wallet-manager/src/wallet_manager/mod.rs +++ b/key-wallet/src/manager/mod.rs @@ -1,32 +1,39 @@ -//! High-level wallet management -//! -//! This module provides a high-level interface for managing multiple wallets, -//! each of which can have multiple accounts. This follows the architecture -//! pattern where a manager oversees multiple distinct wallets. - +/// High-level wallet management for Dash +/// +/// This module provides high-level wallet functionality that builds on top of +/// the low-level primitives in `key-wallet` +/// +/// ## Features +/// +/// - Multiple wallet management +/// - BIP 157/158 compact block filter support +/// - Address generation and gap limit handling +/// - Blockchain synchronization +mod events; mod matching; mod process_block; - -pub use crate::wallet_manager::matching::{check_compact_filters_for_addresses, FilterMatchKey}; +mod wallet_interface; + +pub use events::WalletEvent; +pub use matching::{check_compact_filters_for_addresses, FilterMatchKey}; +pub use wallet_interface::{BlockProcessingResult, WalletInterface}; + +use crate::account::AccountCollection; +use crate::transaction_checking::TransactionContext; +use crate::wallet::managed_wallet_info::transaction_building::AccountTypePreference; +use crate::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; +use crate::wallet::managed_wallet_info::{ManagedWalletInfo, TransactionRecord}; +use crate::Utxo; +use crate::{Account, AccountType, Address, ExtendedPrivKey, Mnemonic, Network, Wallet}; +use crate::{ExtendedPubKey, WalletCoreBalance}; use alloc::collections::BTreeMap; use alloc::string::String; use alloc::vec::Vec; use dashcore::blockdata::transaction::Transaction; use dashcore::prelude::CoreBlockHeight; -use key_wallet::account::AccountCollection; -use key_wallet::transaction_checking::TransactionContext; -use key_wallet::wallet::managed_wallet_info::transaction_building::AccountTypePreference; -use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; -use key_wallet::wallet::managed_wallet_info::{ManagedWalletInfo, TransactionRecord}; -use key_wallet::wallet::WalletType; -use key_wallet::Utxo; -use key_wallet::{Account, AccountType, Address, ExtendedPrivKey, Mnemonic, Network, Wallet}; -use key_wallet::{ExtendedPubKey, WalletCoreBalance}; use std::collections::BTreeSet; use std::str::FromStr; -use zeroize::Zeroize; -use crate::WalletEvent; #[cfg(feature = "std")] use tokio::sync::broadcast; @@ -125,9 +132,9 @@ impl WalletManager { mnemonic: &str, passphrase: &str, birth_height: CoreBlockHeight, - account_creation_options: key_wallet::wallet::initialization::WalletAccountCreationOptions, + account_creation_options: crate::wallet::initialization::WalletAccountCreationOptions, ) -> Result { - let mnemonic_obj = Mnemonic::from_phrase(mnemonic, key_wallet::mnemonic::Language::English) + let mnemonic_obj = Mnemonic::from_phrase(mnemonic, crate::mnemonic::Language::English) .map_err(|e| WalletError::InvalidMnemonic(e.to_string()))?; // Use appropriate wallet creation method based on whether a passphrase is provided @@ -200,11 +207,14 @@ impl WalletManager { mnemonic: &str, passphrase: &str, birth_height: CoreBlockHeight, - account_creation_options: key_wallet::wallet::initialization::WalletAccountCreationOptions, + account_creation_options: crate::wallet::initialization::WalletAccountCreationOptions, downgrade_to_pubkey_wallet: bool, allow_external_signing: bool, ) -> Result<(Vec, WalletId), WalletError> { - let mnemonic_obj = Mnemonic::from_phrase(mnemonic, key_wallet::mnemonic::Language::English) + use crate::wallet::WalletType; + use zeroize::Zeroize; + + let mnemonic_obj = Mnemonic::from_phrase(mnemonic, crate::mnemonic::Language::English) .map_err(|e| WalletError::InvalidMnemonic(e.to_string()))?; // Create the initial wallet from mnemonic @@ -280,13 +290,12 @@ impl WalletManager { /// Returns the generated wallet ID pub fn create_wallet_with_random_mnemonic( &mut self, - account_creation_options: key_wallet::wallet::initialization::WalletAccountCreationOptions, + account_creation_options: crate::wallet::initialization::WalletAccountCreationOptions, ) -> Result { // Generate a random mnemonic (24 words for maximum security) - let mnemonic = - Mnemonic::generate(24, key_wallet::mnemonic::Language::English).map_err(|e| { - WalletError::WalletCreation(format!("Failed to generate mnemonic: {}", e)) - })?; + let mnemonic = Mnemonic::generate(24, crate::mnemonic::Language::English).map_err(|e| { + WalletError::WalletCreation(format!("Failed to generate mnemonic: {}", e)) + })?; let wallet = Wallet::from_mnemonic(mnemonic, self.network, account_creation_options) .map_err(|e| WalletError::WalletCreation(e.to_string()))?; @@ -373,7 +382,7 @@ impl WalletManager { pub fn import_wallet_from_extended_priv_key( &mut self, xprv: &str, - account_creation_options: key_wallet::wallet::initialization::WalletAccountCreationOptions, + account_creation_options: crate::wallet::initialization::WalletAccountCreationOptions, ) -> Result { // Parse the extended private key let extended_priv_key = ExtendedPrivKey::from_str(xprv) @@ -1092,10 +1101,10 @@ fn current_timestamp() -> u64 { #[cfg(feature = "std")] impl std::error::Error for WalletError {} -/// Conversion from key_wallet::Error to WalletError -impl From for WalletError { - fn from(err: key_wallet::Error) -> Self { - use key_wallet::Error; +/// Conversion from crate::Error to WalletError +impl From for WalletError { + fn from(err: crate::Error) -> Self { + use crate::Error; match err { Error::InvalidMnemonic(msg) => WalletError::InvalidMnemonic(msg), diff --git a/key-wallet-manager/src/wallet_manager/process_block.rs b/key-wallet/src/manager/process_block.rs similarity index 93% rename from key-wallet-manager/src/wallet_manager/process_block.rs rename to key-wallet/src/manager/process_block.rs index 052709503..4a7549cd0 100644 --- a/key-wallet-manager/src/wallet_manager/process_block.rs +++ b/key-wallet/src/manager/process_block.rs @@ -1,14 +1,14 @@ -use crate::wallet_interface::{BlockProcessingResult, WalletInterface}; -use crate::WalletManager; +use crate::manager::wallet_interface::{BlockProcessingResult, WalletInterface}; +use crate::manager::WalletManager; +use crate::transaction_checking::transaction_router::TransactionRouter; +use crate::transaction_checking::TransactionContext; +use crate::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; use alloc::string::String; use alloc::vec::Vec; use async_trait::async_trait; use core::fmt::Write as _; use dashcore::prelude::CoreBlockHeight; use dashcore::{Address, Block, Transaction}; -use key_wallet::transaction_checking::transaction_router::TransactionRouter; -use key_wallet::transaction_checking::TransactionContext; -use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; #[async_trait] impl WalletInterface for WalletManager { @@ -121,7 +121,7 @@ impl WalletInterface for WalletM // Emit event if balance changed #[cfg(feature = "std")] if old_balance != new_balance { - let event = crate::WalletEvent::BalanceUpdated { + let event = crate::manager::WalletEvent::BalanceUpdated { wallet_id: *wallet_id, spendable: new_balance.spendable(), unconfirmed: new_balance.unconfirmed(), @@ -177,8 +177,8 @@ impl WalletInterface for WalletM #[cfg(test)] mod tests { use super::*; + use crate::wallet::managed_wallet_info::ManagedWalletInfo; use dashcore::Network; - use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; #[tokio::test] async fn test_synced_height() { diff --git a/key-wallet-manager/src/wallet_interface.rs b/key-wallet/src/manager/wallet_interface.rs similarity index 100% rename from key-wallet-manager/src/wallet_interface.rs rename to key-wallet/src/manager/wallet_interface.rs diff --git a/key-wallet/src/missing_tests.md b/key-wallet/src/missing_tests.md index 402922b67..c4e458055 100644 --- a/key-wallet/src/missing_tests.md +++ b/key-wallet/src/missing_tests.md @@ -124,14 +124,3 @@ 1. **High Priority**: Mnemonic handling, key derivation, address generation 2. **Medium Priority**: Multi-language mnemonics, BIP38, gap limit edge cases 3. **Low Priority**: Performance tests, CoinJoin, migration tests - -## Note - -High-level tests involving: -- Transaction building and signing -- UTXO management and coin selection -- Fee calculation and management -- Multi-wallet operations -- Balance tracking - -Have been moved to `key-wallet-manager/missing_tests.md` diff --git a/key-wallet/src/test_utils/mod.rs b/key-wallet/src/test_utils/mod.rs index 5f69fe1d6..67ac8617e 100644 --- a/key-wallet/src/test_utils/mod.rs +++ b/key-wallet/src/test_utils/mod.rs @@ -1,3 +1,5 @@ mod account; mod utxo; mod wallet; + +pub use wallet::{MockWallet, NonMatchingMockWallet}; diff --git a/key-wallet/src/test_utils/wallet.rs b/key-wallet/src/test_utils/wallet.rs index 653e17bb6..04f78e5c9 100644 --- a/key-wallet/src/test_utils/wallet.rs +++ b/key-wallet/src/test_utils/wallet.rs @@ -1,9 +1,130 @@ -use dashcore::Network; +use std::{collections::BTreeMap, sync::Arc}; -use crate::wallet::ManagedWalletInfo; +use dashcore::{prelude::CoreBlockHeight, Address, Block, Network, Transaction, Txid}; +use tokio::sync::Mutex; + +use crate::{ + manager::{BlockProcessingResult, WalletInterface}, + wallet::ManagedWalletInfo, +}; impl ManagedWalletInfo { pub fn dummy(id: u8) -> Self { ManagedWalletInfo::new(Network::Regtest, [id; 32]) } } + +// Type alias for transaction effects map +type TransactionEffectsMap = Arc)>>>; + +#[derive(Default)] +pub struct MockWallet { + processed_blocks: Arc>>, + processed_transactions: Arc>>, + // Map txid -> (net_amount, addresses) + effects: TransactionEffectsMap, + synced_height: CoreBlockHeight, +} + +impl MockWallet { + pub fn new() -> Self { + Self { + processed_blocks: Arc::new(Mutex::new(Vec::new())), + processed_transactions: Arc::new(Mutex::new(Vec::new())), + effects: Arc::new(Mutex::new(BTreeMap::new())), + synced_height: 0, + } + } + + pub async fn set_effect(&self, txid: dashcore::Txid, net: i64, addresses: Vec) { + let mut map = self.effects.lock().await; + map.insert(txid, (net, addresses)); + } + + pub fn processed_blocks(&self) -> Arc>> { + self.processed_blocks.clone() + } + + pub fn processed_transactions(&self) -> Arc>> { + self.processed_transactions.clone() + } +} + +#[async_trait::async_trait] +impl WalletInterface for MockWallet { + async fn process_block(&mut self, block: &Block, height: u32) -> BlockProcessingResult { + let mut processed = self.processed_blocks.lock().await; + processed.push((block.block_hash(), height)); + + BlockProcessingResult { + new_txids: block.txdata.iter().map(|tx| tx.txid()).collect(), + existing_txids: Vec::new(), + new_addresses: Vec::new(), + } + } + + async fn process_mempool_transaction(&mut self, tx: &Transaction) { + let mut processed = self.processed_transactions.lock().await; + processed.push(tx.txid()); + } + + async fn describe(&self) -> String { + "MockWallet (test implementation)".to_string() + } + + async fn transaction_effect(&self, tx: &Transaction) -> Option<(i64, Vec)> { + let map = self.effects.lock().await; + map.get(&tx.txid()).cloned() + } + + fn monitored_addresses(&self) -> Vec
{ + Vec::new() + } + + fn synced_height(&self) -> CoreBlockHeight { + self.synced_height + } + + fn update_synced_height(&mut self, height: CoreBlockHeight) { + self.synced_height = height; + } +} + +/// Mock wallet that returns false for filter checks +#[derive(Default)] +pub struct NonMatchingMockWallet { + synced_height: CoreBlockHeight, +} + +impl NonMatchingMockWallet { + pub fn new() -> Self { + Self { + synced_height: 0, + } + } +} + +#[async_trait::async_trait] +impl WalletInterface for NonMatchingMockWallet { + async fn process_block(&mut self, _block: &Block, _height: u32) -> BlockProcessingResult { + BlockProcessingResult::default() + } + + async fn process_mempool_transaction(&mut self, _tx: &Transaction) {} + + fn monitored_addresses(&self) -> Vec
{ + Vec::new() + } + + fn synced_height(&self) -> CoreBlockHeight { + self.synced_height + } + + fn update_synced_height(&mut self, height: CoreBlockHeight) { + self.synced_height = height; + } + + async fn describe(&self) -> String { + "NonMatchingWallet (test implementation)".to_string() + } +} diff --git a/key-wallet-manager/tests/integration_test.rs b/key-wallet/tests/integration_test.rs similarity index 97% rename from key-wallet-manager/tests/integration_test.rs rename to key-wallet/tests/integration_test.rs index 3c1700405..e3bcff52b 100644 --- a/key-wallet-manager/tests/integration_test.rs +++ b/key-wallet/tests/integration_test.rs @@ -1,15 +1,15 @@ -//! Integration tests for key-wallet-manager +//! Integration tests for the wallet manager //! //! These tests verify that the high-level wallet management functionality //! works correctly with the low-level key-wallet primitives. +use key_wallet::manager::WalletInterface; +use key_wallet::manager::{WalletError, WalletManager}; use key_wallet::wallet::initialization::WalletAccountCreationOptions; use key_wallet::wallet::managed_wallet_info::transaction_building::AccountTypePreference; use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; use key_wallet::{mnemonic::Language, Mnemonic, Network}; -use key_wallet_manager::wallet_interface::WalletInterface; -use key_wallet_manager::wallet_manager::{WalletError, WalletManager}; #[test] fn test_wallet_manager_creation() { diff --git a/key-wallet-manager/tests/spv_integration_tests.rs b/key-wallet/tests/spv_integration_tests.rs similarity index 98% rename from key-wallet-manager/tests/spv_integration_tests.rs rename to key-wallet/tests/spv_integration_tests.rs index 2ce763687..d3fd99655 100644 --- a/key-wallet-manager/tests/spv_integration_tests.rs +++ b/key-wallet/tests/spv_integration_tests.rs @@ -4,12 +4,12 @@ use dashcore::blockdata::block::Block; use dashcore::blockdata::transaction::Transaction; use dashcore::constants::COINBASE_MATURITY; use dashcore::Address; +use key_wallet::manager::WalletInterface; +use key_wallet::manager::WalletManager; use key_wallet::wallet::initialization::WalletAccountCreationOptions; use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; use key_wallet::Network; -use key_wallet_manager::wallet_interface::WalletInterface; -use key_wallet_manager::wallet_manager::WalletManager; #[tokio::test] async fn test_block_processing() { diff --git a/key-wallet-manager/tests/test_serialized_wallets.rs b/key-wallet/tests/test_serialized_wallets.rs similarity index 98% rename from key-wallet-manager/tests/test_serialized_wallets.rs rename to key-wallet/tests/test_serialized_wallets.rs index 4ef1ea9cc..0dd9b8f44 100644 --- a/key-wallet-manager/tests/test_serialized_wallets.rs +++ b/key-wallet/tests/test_serialized_wallets.rs @@ -1,10 +1,10 @@ #[cfg(feature = "bincode")] #[cfg(test)] mod tests { + use key_wallet::manager::WalletManager; use key_wallet::wallet::initialization::WalletAccountCreationOptions; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; use key_wallet::Network; - use key_wallet_manager::wallet_manager::WalletManager; #[test] fn test_create_wallet_return_serialized_bytes() {