diff --git a/Cargo.lock b/Cargo.lock index f5703840374..d5813be584a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,7 +120,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -131,7 +131,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1568,7 +1568,7 @@ dependencies = [ [[package]] name = "dash-network" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "bincode", "bincode_derive", @@ -1579,7 +1579,7 @@ dependencies = [ [[package]] name = "dash-network-seeds" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "dash-network", ] @@ -1656,7 +1656,7 @@ dependencies = [ [[package]] name = "dash-spv" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "async-trait", "chrono", @@ -1684,7 +1684,7 @@ dependencies = [ [[package]] name = "dash-spv-ffi" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "cbindgen 0.29.2", "clap", @@ -1703,7 +1703,7 @@ dependencies = [ [[package]] name = "dashcore" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "anyhow", "base64-compat", @@ -1729,12 +1729,12 @@ dependencies = [ [[package]] name = "dashcore-private" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" [[package]] name = "dashcore-rpc" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "dashcore-rpc-json", "hex", @@ -1747,7 +1747,7 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "bincode", "dashcore", @@ -1762,7 +1762,7 @@ dependencies = [ [[package]] name = "dashcore_hashes" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "bincode", "dashcore-private", @@ -3811,7 +3811,7 @@ dependencies = [ [[package]] name = "key-wallet" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "aes", "async-trait", @@ -3839,7 +3839,7 @@ dependencies = [ [[package]] name = "key-wallet-ffi" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "cbindgen 0.29.2", "dash-network", @@ -3855,7 +3855,7 @@ dependencies = [ [[package]] name = "key-wallet-manager" version = "0.42.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=fe2476611fcf72d6f36f1154a39a2f9af3b6a248#fe2476611fcf72d6f36f1154a39a2f9af3b6a248" +source = "git+https://github.com/dashpay/rust-dashcore?rev=d6dd5da14902dca4332036c5ef4db03734934eb3#d6dd5da14902dca4332036c5ef4db03734934eb3" dependencies = [ "async-trait", "bincode", @@ -5338,7 +5338,7 @@ dependencies = [ "once_cell", "socket2 0.5.10", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -6714,7 +6714,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -8457,15 +8457,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -8499,30 +8490,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -8535,12 +8509,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -8553,12 +8521,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -8571,24 +8533,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -8601,12 +8551,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -8619,12 +8563,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -8637,12 +8575,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -8655,12 +8587,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "0.5.40" diff --git a/Cargo.toml b/Cargo.toml index b645caa087b..d78558b6a63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,15 +49,15 @@ members = [ ] [workspace.dependencies] -dashcore = { git = "https://github.com/dashpay/rust-dashcore", rev = "fe2476611fcf72d6f36f1154a39a2f9af3b6a248" } -dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", rev = "fe2476611fcf72d6f36f1154a39a2f9af3b6a248" } -dash-spv = { git = "https://github.com/dashpay/rust-dashcore", rev = "fe2476611fcf72d6f36f1154a39a2f9af3b6a248" } -dash-spv-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "fe2476611fcf72d6f36f1154a39a2f9af3b6a248" } -key-wallet = { git = "https://github.com/dashpay/rust-dashcore", rev = "fe2476611fcf72d6f36f1154a39a2f9af3b6a248" } -key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "fe2476611fcf72d6f36f1154a39a2f9af3b6a248" } -key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", rev = "fe2476611fcf72d6f36f1154a39a2f9af3b6a248" } -dash-network = { git = "https://github.com/dashpay/rust-dashcore", rev = "fe2476611fcf72d6f36f1154a39a2f9af3b6a248" } -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", rev = "fe2476611fcf72d6f36f1154a39a2f9af3b6a248" } +dashcore = { git = "https://github.com/dashpay/rust-dashcore", rev = "d6dd5da14902dca4332036c5ef4db03734934eb3" } +dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", rev = "d6dd5da14902dca4332036c5ef4db03734934eb3" } +dash-spv = { git = "https://github.com/dashpay/rust-dashcore", rev = "d6dd5da14902dca4332036c5ef4db03734934eb3" } +dash-spv-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "d6dd5da14902dca4332036c5ef4db03734934eb3" } +key-wallet = { git = "https://github.com/dashpay/rust-dashcore", rev = "d6dd5da14902dca4332036c5ef4db03734934eb3" } +key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "d6dd5da14902dca4332036c5ef4db03734934eb3" } +key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", rev = "d6dd5da14902dca4332036c5ef4db03734934eb3" } +dash-network = { git = "https://github.com/dashpay/rust-dashcore", rev = "d6dd5da14902dca4332036c5ef4db03734934eb3" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", rev = "d6dd5da14902dca4332036c5ef4db03734934eb3" } # Optimize heavy crypto crates even in dev/test builds so that # Halo 2 proof generation and verification run at near-release speed. diff --git a/packages/rs-platform-wallet/Cargo.toml b/packages/rs-platform-wallet/Cargo.toml index 13d0ccb00af..05e5eb0547c 100644 --- a/packages/rs-platform-wallet/Cargo.toml +++ b/packages/rs-platform-wallet/Cargo.toml @@ -65,3 +65,15 @@ default = ["bls", "eddsa"] bls = ["key-wallet/bls", "key-wallet-manager/bls"] eddsa = ["key-wallet/eddsa", "key-wallet-manager/eddsa"] shielded = ["dep:grovedb-commitment-tree", "dep:zip32", "dash-sdk/shielded", "dpp/shielded-client"] +# Forward to the upstream `key-wallet` / `key-wallet-manager` +# `keep-finalized-transactions` feature. With it OFF (the default), +# chainlocked transactions are evicted from the in-memory +# `transactions` map and only their txids are kept (in +# `finalized_txids`) for dedup; tx history is delivered through the +# event channel. Turn ON to keep the full `TransactionRecord` for +# finalized transactions in memory for the wallet's lifetime — useful +# for debug surfaces that page through history. +keep-finalized-transactions = [ + "key-wallet/keep-finalized-transactions", + "key-wallet-manager/keep-finalized-transactions", +] diff --git a/packages/rs-platform-wallet/src/changeset/core_bridge.rs b/packages/rs-platform-wallet/src/changeset/core_bridge.rs index 53aeb80dcc6..b2d9761ac2b 100644 --- a/packages/rs-platform-wallet/src/changeset/core_bridge.rs +++ b/packages/rs-platform-wallet/src/changeset/core_bridge.rs @@ -211,12 +211,12 @@ async fn is_chain_locked( }; // Walk every account; if any holds an in-memory record for this // txid, the chain-lock determination falls out of its - // `TransactionContext`. With `keep_txs_in_memory` off (the default) - // `get_transaction` returns `None` regardless of state — chain-lock - // delivery is event-driven in that mode, and this helper just - // reports "no record locally" by returning false. + // `TransactionContext`. With `keep-finalized-transactions` off + // (the default) `transactions()` returns an empty map regardless + // of state — chain-lock delivery is event-driven in that mode, and + // this helper just reports "no record locally" by returning false. for account in info.core_wallet.accounts.all_accounts() { - if let Some(record) = account.get_transaction(txid) { + if let Some(record) = account.transactions().get(txid) { return matches!(record.context, TransactionContext::InChainLockedBlock(_)); } } diff --git a/packages/rs-platform-wallet/src/manager/accessors.rs b/packages/rs-platform-wallet/src/manager/accessors.rs index 8b4d4810ff5..172667098af 100644 --- a/packages/rs-platform-wallet/src/manager/accessors.rs +++ b/packages/rs-platform-wallet/src/manager/accessors.rs @@ -547,17 +547,18 @@ impl PlatformWalletManager

{ .iter() .find(|a| &a.managed_account_type().to_account_type() == target)?; // Funds-only fields (`utxos`) live on the funds variant; the - // ref-enum delegates the rest. `transactions_iter()` returns an - // empty iterator when `keep_txs_in_memory` is off (the default - // — tx history is event-driven), so `total_transactions` reads - // 0 in production builds. Both behaviors are intentional. + // ref-enum delegates the rest. `transactions()` returns an + // empty map when `keep-finalized-transactions` is off (the + // default — tx history is event-driven), so + // `total_transactions` reads 0 in production builds. Both + // behaviors are intentional. let funds = account.as_funds(); Some(AccountMetadataSnapshot { - // `transactions_iter()` returns empty when - // `keep_txs_in_memory` is off (the default — tx history is - // event-driven), so `total_transactions` reads 0 in - // production builds. - total_transactions: account.transactions_iter().count() as u64, + // `transactions()` is empty when + // `keep-finalized-transactions` is off (the default — tx + // history is event-driven), so `total_transactions` reads + // 0 in production builds. + total_transactions: account.transactions().len() as u64, total_utxos: funds.map(|a| a.utxos.len() as u64).unwrap_or(0), monitor_revision: account.monitor_revision(), }) @@ -657,17 +658,14 @@ impl PlatformWalletManager

{ else { return Vec::new(); }; - // `transactions_iter` is the variant-agnostic walk and returns - // an empty iterator when `keep_txs_in_memory` is disabled — the - // default. Tx history is delivered through the event channel, - // not stored in-memory, so a paged readout here is effectively - // a debug surface for builds that flip the feature on. We - // collapse `(Txid, &TransactionRecord)` to just records, since - // the snapshot type carries the txid as a field of its own. - let iter = account - .transactions_iter() - .map(|(_, record)| record) - .skip(page_offset); + // `transactions()` returns an empty map when + // `keep-finalized-transactions` is disabled — the default. Tx + // history is delivered through the event channel, not stored + // in-memory, so a paged readout here is effectively a debug + // surface for builds that flip the feature on. The snapshot + // type carries the txid as a field of its own, so we walk + // values only. + let iter = account.transactions().values().skip(page_offset); let take = if page_limit == 0 { usize::MAX } else { diff --git a/packages/rs-platform-wallet/src/wallet/asset_lock/build.rs b/packages/rs-platform-wallet/src/wallet/asset_lock/build.rs index 1fadb3fb290..e8ad52ffe23 100644 --- a/packages/rs-platform-wallet/src/wallet/asset_lock/build.rs +++ b/packages/rs-platform-wallet/src/wallet/asset_lock/build.rs @@ -8,6 +8,7 @@ use std::time::Duration; use dashcore::Address as DashAddress; use dashcore::{OutPoint, PrivateKey, Transaction, TxOut}; +use key_wallet::managed_account::managed_account_trait::ManagedAccountTrait; use key_wallet::wallet::managed_wallet_info::asset_lock_builder::{ AssetLockFundingType, CreditOutputFunding, }; diff --git a/packages/rs-platform-wallet/src/wallet/asset_lock/sync/proof.rs b/packages/rs-platform-wallet/src/wallet/asset_lock/sync/proof.rs index 7d937438a17..36f69719b2d 100644 --- a/packages/rs-platform-wallet/src/wallet/asset_lock/sync/proof.rs +++ b/packages/rs-platform-wallet/src/wallet/asset_lock/sync/proof.rs @@ -4,6 +4,7 @@ use crate::broadcaster::TransactionBroadcaster; use std::time::Duration; use dashcore::OutPoint; +use key_wallet::managed_account::managed_account_trait::ManagedAccountTrait; use crate::error::PlatformWalletError; @@ -45,7 +46,7 @@ impl AssetLockManager { .accounts .standard_bip44_accounts .get(&account_index) - .and_then(|a| a.transactions.get(&out_point.txid)) + .and_then(|a| a.transactions().get(&out_point.txid)) .ok_or_else(|| { PlatformWalletError::AssetLockProofWait(format!( "Transaction {} not found in account {}", @@ -139,7 +140,7 @@ impl AssetLockManager { .accounts .standard_bip44_accounts .get(&account_index) - .and_then(|a| a.transactions.get(&txid)) + .and_then(|a| a.transactions().get(&txid)) .ok_or_else(|| { PlatformWalletError::AssetLockProofWait(format!( "Transaction {} not found in account {}", @@ -223,7 +224,7 @@ impl AssetLockManager { .accounts .standard_bip44_accounts .get(&account_index) - .and_then(|a| a.transactions.get(&out_point.txid)) + .and_then(|a| a.transactions().get(&out_point.txid)) { if matches!(record.context, TransactionContext::InChainLockedBlock(_)) { if let Some(h) = record.height() { @@ -294,7 +295,7 @@ impl AssetLockManager { .accounts .standard_bip44_accounts .get(&account_index) - .and_then(|a| a.transactions.get(&out_point.txid)) + .and_then(|a| a.transactions().get(&out_point.txid)) { match &record.context { TransactionContext::InstantSend(instant_lock) => { diff --git a/packages/rs-platform-wallet/src/wallet/asset_lock/sync/recovery.rs b/packages/rs-platform-wallet/src/wallet/asset_lock/sync/recovery.rs index 7cb5f7e450f..f7052041bea 100644 --- a/packages/rs-platform-wallet/src/wallet/asset_lock/sync/recovery.rs +++ b/packages/rs-platform-wallet/src/wallet/asset_lock/sync/recovery.rs @@ -9,6 +9,7 @@ use std::time::Duration; use dashcore::Address as DashAddress; use dashcore::{OutPoint, PrivateKey}; +use key_wallet::managed_account::managed_account_trait::ManagedAccountTrait; use key_wallet::wallet::managed_wallet_info::asset_lock_builder::AssetLockFundingType; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; @@ -105,7 +106,7 @@ impl AssetLockManager { .accounts .standard_bip44_accounts .get(&account_index) - .and_then(|a| a.transactions.get(&out_point.txid)); + .and_then(|a| a.transactions().get(&out_point.txid)); match record { Some(record) => match &record.context { diff --git a/packages/rs-platform-wallet/src/wallet/core/broadcast.rs b/packages/rs-platform-wallet/src/wallet/core/broadcast.rs index 10578a7a682..4484ff5748b 100644 --- a/packages/rs-platform-wallet/src/wallet/core/broadcast.rs +++ b/packages/rs-platform-wallet/src/wallet/core/broadcast.rs @@ -1,5 +1,6 @@ use dashcore::{Address as DashAddress, Transaction}; use key_wallet::account::account_type::StandardAccountType; +use key_wallet::managed_account::managed_account_trait::ManagedAccountTrait; use crate::broadcaster::TransactionBroadcaster; use crate::{CoreWallet, PlatformWalletError}; @@ -116,7 +117,15 @@ impl CoreWallet { current_height, |utxo| { for account in info.core_wallet.accounts.all_accounts() { - if let Some(path) = account.address_derivation_path(&utxo.address) { + // Address pools live on the keys variant + // after the funds/keys split; the funds + // account composes a keys account, and + // `keys_account()` exposes it for both + // `ManagedAccountRef` variants. + if let Some(path) = account + .keys_account() + .address_derivation_path(&utxo.address) + { if let Ok(key) = wallet.derive_private_key(&path) { return Some(key); } diff --git a/packages/rs-platform-wallet/src/wallet/identity/network/contacts.rs b/packages/rs-platform-wallet/src/wallet/identity/network/contacts.rs index 1ac523757e9..8a3479043bf 100644 --- a/packages/rs-platform-wallet/src/wallet/identity/network/contacts.rs +++ b/packages/rs-platform-wallet/src/wallet/identity/network/contacts.rs @@ -5,6 +5,7 @@ use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV use dpp::identity::Identity; use dpp::prelude::Identifier; use key_wallet::account::AccountType; +use key_wallet::managed_account::managed_account_trait::ManagedAccountTrait; use super::*; use crate::broadcaster::TransactionBroadcaster; @@ -139,12 +140,12 @@ impl IdentityWallet { .get_wallet_info_mut(&self.wallet_id) .ok_or_else(|| PlatformWalletError::WalletNotFound(hex::encode(self.wallet_id)))?; // DashPay accounts are funds-bearing; use the typed - // `insert_funds` API exposed by the post-split collection - // rather than wrapping in `OwnedManagedCoreAccount`. + // `insert_funds_bearing_account` API exposed by the post-split + // collection rather than wrapping in `OwnedManagedCoreAccount`. let managed = key_wallet::managed_account::ManagedCoreFundsAccount::from_account(&account); info.core_wallet .accounts - .insert_funds(managed) + .insert_funds_bearing_account(managed) .map_err(|e| { PlatformWalletError::InvalidIdentityData(format!( "Failed to register contact account: {e}" @@ -231,7 +232,7 @@ impl IdentityWallet { user_identity_id, friend_identity_id, .. - } = &account.managed_account_type + } = account.managed_account_type() else { // Routing invariant: dashpay_receival_accounts must // only contain DashpayReceivingFunds. If this ever @@ -497,7 +498,7 @@ impl IdentityWallet { // (b) Insert ManagedCoreFundsAccount for address-pool tracking. info.core_wallet .accounts - .insert_funds(managed) + .insert_funds_bearing_account(managed) .map_err(|e| { PlatformWalletError::InvalidIdentityData(format!( "Failed to register external contact account: {}", diff --git a/packages/rs-platform-wallet/src/wallet/identity/network/payments.rs b/packages/rs-platform-wallet/src/wallet/identity/network/payments.rs index 5186cd5fc61..3a44ae1e805 100644 --- a/packages/rs-platform-wallet/src/wallet/identity/network/payments.rs +++ b/packages/rs-platform-wallet/src/wallet/identity/network/payments.rs @@ -1,6 +1,7 @@ //! DashPay payment recording and send-to-contact flows. use dpp::prelude::Identifier; +use key_wallet::managed_account::managed_account_trait::ManagedAccountTrait; use super::*; use crate::broadcaster::TransactionBroadcaster; @@ -223,7 +224,15 @@ impl IdentityWallet { current_height, |utxo| { for account in info.core_wallet.accounts.all_accounts() { - if let Some(path) = account.address_derivation_path(&utxo.address) { + // Address pools live on the keys variant + // after the funds/keys split; the funds + // account composes a keys account, and + // `keys_account()` exposes it for both + // `ManagedAccountRef` variants. + if let Some(path) = account + .keys_account() + .address_derivation_path(&utxo.address) + { if let Ok(key) = wallet.derive_private_key(&path) { return Some(key); } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyWallet.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyWallet.swift index 4b459cc9d7b..47541039840 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyWallet.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyWallet.swift @@ -22,10 +22,6 @@ import Foundation /// let mnemonic = try Mnemonic.generate() /// let wallet = try Wallet(mnemonic: mnemonic, network: .testnet) /// -/// // Get a receive address -/// let managed = try ManagedWallet(wallet: wallet) -/// let address = try managed.getNextReceiveAddress(wallet: wallet) -/// /// // Check wallet balance /// let balance = try wallet.getBalance() /// print("Confirmed: \(balance.confirmed), Unconfirmed: \(balance.unconfirmed)") @@ -49,7 +45,6 @@ public class KeyWallet { // Re-export all public types for convenience public typealias KeyWalletWallet = Wallet public typealias KeyWalletAccount = Account -public typealias KeyWalletManagedWallet = ManagedWallet public typealias KeyWalletManager = WalletManager public typealias KeyWalletMnemonic = Mnemonic public typealias KeyWalletTransaction = Transaction diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift index 8b3a3746adb..af2a7dd54db 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift @@ -41,75 +41,20 @@ public class ManagedAccount { return managed_core_account_get_index(handle) } - /// Get the transaction count - public var transactionCount: UInt32 { - return managed_core_account_get_transaction_count(handle) - } - /// Get the UTXO count public var utxoCount: UInt32 { return managed_core_account_get_utxo_count(handle) } - // MARK: - Transactions - - /// Get all transactions for this account - /// - Returns: Array of transactions - public func getTransactions() -> [WalletTransaction] { - var ptr: UnsafeMutablePointer? - var count: size_t = 0 - - let success = managed_core_account_get_transactions(handle, &ptr, &count) - - guard success else { - preconditionFailure( - "Invalid state: managed_core_account_get_transactions can only fail if any pointer is nil" - ) - } - - // Handle empty case - guard count > 0, let ptr else { - return [] - } - - defer { - managed_core_account_free_transactions(ptr, count) - } - - // Convert FFI transactions to Swift transactions - var transactions: [WalletTransaction] = [] - transactions.reserveCapacity(count) - - for i in 0.. 0 ? ffiTx.fee : nil, - isOurs: true // direction-based, inferred from net_amount sign - ) - - transactions.append(transaction) - } - - return transactions - } + // `transactionCount` and `getTransactions()` accessors were removed + // in lockstep with upstream gating + // `managed_core_account_get_transaction_count` / + // `managed_core_account_get_transactions` behind the + // `keep-finalized-transactions` Cargo feature (off by default). + // The production model delivers tx history through the + // platform-wallet event channel, not from the in-memory + // per-account map. Consumers that need history should subscribe + // to wallet events on the Rust side. // MARK: - Balance diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedWallet.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedWallet.swift deleted file mode 100644 index 4bb6175c2f1..00000000000 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedWallet.swift +++ /dev/null @@ -1,430 +0,0 @@ -import Foundation -import DashSDKFFI - -/// Swift wrapper for managed wallet with address pool management and transaction checking -public class ManagedWallet { - private let handle: UnsafeMutablePointer - - /// Create a managed wallet wrapper from a regular wallet - /// - Parameter wallet: The wallet to manage - public init(wallet: Wallet) throws { - var error = FFIError() - guard let managedPointer = wallet_create_managed_wallet(wallet.ffiHandle, &error) else { - defer { - if error.message != nil { - error_message_free(error.message) - } - } - throw KeyWalletError(ffiError: error) - } - - self.handle = managedPointer - } - - deinit { - ffi_managed_wallet_free(handle) - } - - // MARK: - Address Generation - - /// Get the next unused receive address for a BIP44 account - /// - Parameters: - /// - wallet: The wallet for key derivation - /// - accountIndex: The account index - /// - Returns: The next receive address - public func getNextReceiveAddress(wallet: Wallet, accountIndex: UInt32 = 0) throws -> String { - var error = FFIError() - - guard let infoHandle = getInfoHandle() else { - throw KeyWalletError.invalidState("Failed to get managed wallet info") - } - - let addressPtr = managed_wallet_get_next_bip44_receive_address( - infoHandle, wallet.ffiHandle, accountIndex, &error) - - defer { - if error.message != nil { - error_message_free(error.message) - } - } - - guard let ptr = addressPtr else { - throw KeyWalletError(ffiError: error) - } - - let address = String(cString: ptr) - address_free(ptr) - - return address - } - - /// Get the next unused change address for a BIP44 account - /// - Parameters: - /// - wallet: The wallet for key derivation - /// - accountIndex: The account index - /// - Returns: The next change address - public func getNextChangeAddress(wallet: Wallet, accountIndex: UInt32 = 0) throws -> String { - var error = FFIError() - - guard let infoHandle = getInfoHandle() else { - throw KeyWalletError.invalidState("Failed to get managed wallet info") - } - - let addressPtr = managed_wallet_get_next_bip44_change_address( - infoHandle, wallet.ffiHandle, accountIndex, &error) - - defer { - if error.message != nil { - error_message_free(error.message) - } - } - - guard let ptr = addressPtr else { - throw KeyWalletError(ffiError: error) - } - - let address = String(cString: ptr) - address_free(ptr) - - return address - } - - /// Get a range of external (receive) addresses - /// - Parameters: - /// - wallet: The wallet for key derivation - /// - accountIndex: The account index - /// - startIndex: Starting index (inclusive) - /// - endIndex: Ending index (exclusive) - /// - Returns: Array of addresses - public func getExternalAddressRange(wallet: Wallet, accountIndex: UInt32 = 0, - startIndex: UInt32, endIndex: UInt32) throws -> [String] { - guard endIndex > startIndex else { - throw KeyWalletError.invalidInput("End index must be greater than start index") - } - - var error = FFIError() - var addressesPtr: UnsafeMutablePointer?>? - var count: size_t = 0 - - guard let infoHandle = getInfoHandle() else { - throw KeyWalletError.invalidState("Failed to get managed wallet info") - } - - let success = managed_wallet_get_bip_44_external_address_range( - infoHandle, wallet.ffiHandle, accountIndex, - startIndex, endIndex, &addressesPtr, &count, &error) - - defer { - if error.message != nil { - error_message_free(error.message) - } - if let ptr = addressesPtr { - address_array_free(ptr, count) - } - } - - guard success, let ptr = addressesPtr else { - throw KeyWalletError(ffiError: error) - } - - var addresses: [String] = [] - for i in 0.. [String] { - guard endIndex > startIndex else { - throw KeyWalletError.invalidInput("End index must be greater than start index") - } - - var error = FFIError() - var addressesPtr: UnsafeMutablePointer?>? - var count: size_t = 0 - - guard let infoHandle = getInfoHandle() else { - throw KeyWalletError.invalidState("Failed to get managed wallet info") - } - - let success = managed_wallet_get_bip_44_internal_address_range( - infoHandle, wallet.ffiHandle, accountIndex, - startIndex, endIndex, &addressesPtr, &count, &error) - - defer { - if error.message != nil { - error_message_free(error.message) - } - if let ptr = addressesPtr { - address_array_free(ptr, count) - } - } - - guard success, let ptr = addressesPtr else { - throw KeyWalletError(ffiError: error) - } - - var addresses: [String] = [] - for i in 0.. AddressPoolInfo { - var error = FFIError() - var ffiInfo = FFIAddressPoolInfo() - - let success = managed_wallet_get_address_pool_info( - handle, accountType.ffiValue, accountIndex, - poolType.ffiValue, &ffiInfo, &error) - - defer { - if error.message != nil { - error_message_free(error.message) - } - } - - guard success else { - throw KeyWalletError(ffiError: error) - } - - return AddressPoolInfo(ffiInfo: ffiInfo) - } - - /// Set the gap limit for an address pool - /// - Parameters: - /// - accountType: The account type - /// - accountIndex: The account index - /// - poolType: The address pool type - /// - gapLimit: The new gap limit - public func setGapLimit(accountType: AccountType, accountIndex: UInt32 = 0, - poolType: AddressPoolType, gapLimit: UInt32) throws { - var error = FFIError() - - let success = managed_wallet_set_gap_limit( - handle, accountType.ffiValue, accountIndex, - poolType.ffiValue, gapLimit, &error) - - defer { - if error.message != nil { - error_message_free(error.message) - } - } - - guard success else { - throw KeyWalletError(ffiError: error) - } - } - - /// Generate addresses up to a specific index - /// - Parameters: - /// - wallet: The wallet for key derivation - /// - accountType: The account type - /// - accountIndex: The account index - /// - poolType: The address pool type - /// - targetIndex: The target index to generate up to - public func generateAddressesToIndex(wallet: Wallet, accountType: AccountType, - accountIndex: UInt32 = 0, - poolType: AddressPoolType, - targetIndex: UInt32) throws { - var error = FFIError() - - let success = managed_wallet_generate_addresses_to_index( - handle, wallet.ffiHandle, accountType.ffiValue, - accountIndex, poolType.ffiValue, targetIndex, &error) - - defer { - if error.message != nil { - error_message_free(error.message) - } - } - - guard success else { - throw KeyWalletError(ffiError: error) - } - } - - /// Mark an address as used - /// - Parameter address: The address to mark as used - public func markAddressUsed(_ address: String) throws { - var error = FFIError() - - let success = address.withCString { addressCStr in - managed_wallet_mark_address_used(handle, addressCStr, &error) - } - - defer { - if error.message != nil { - error_message_free(error.message) - } - } - - guard success else { - throw KeyWalletError(ffiError: error) - } - } - - // MARK: - Transaction Checking - - /// Check if a transaction belongs to the wallet - /// - Parameters: - /// - wallet: The wallet to check against - /// - transactionData: The transaction bytes - /// - context: The transaction context - /// - blockHeight: The block height (0 for mempool) - /// - blockHash: The block hash (nil for mempool) - /// - timestamp: The timestamp - /// - updateState: Whether to update wallet state if transaction is relevant - /// - Returns: Transaction check result - public func checkTransaction(wallet: Wallet, transactionData: Data, - context: TransactionContextType = .mempool, - blockHeight: UInt32 = 0, - blockHash: Data? = nil, - timestamp: UInt32 = 0, - updateState: Bool = true) throws -> TransactionCheckResult { - var error = FFIError() - var result = FFITransactionCheckResult() - - // Build FFIBlockInfo - var blockInfo = FFIBlockInfo() - blockInfo.height = blockHeight - blockInfo.timestamp = timestamp - if let hash = blockHash, hash.count == 32 { - hash.withUnsafeBytes { buf in - withUnsafeMutableBytes(of: &blockInfo.block_hash) { dst in - dst.copyBytes(from: buf.prefix(32)) - } - } - } - - let contextType = FFITransactionContextType(rawValue: context.rawValue) - - let success = transactionData.withUnsafeBytes { txBytes in - let txPtr = txBytes.bindMemory(to: UInt8.self).baseAddress - - return managed_wallet_check_transaction( - handle, wallet.ffiHandle, - txPtr, transactionData.count, - contextType, blockInfo, - nil, 0, // islock_data, islock_len - updateState, &result, &error) - } - - defer { - if error.message != nil { - error_message_free(error.message) - } - transaction_check_result_free(&result) - } - - guard success else { - throw KeyWalletError(ffiError: error) - } - - return TransactionCheckResult(ffiResult: result) - } - - // MARK: - Balance and UTXOs - - /// Get the wallet balance from managed wallet info - public func getBalance() throws -> Balance { - guard let infoHandle = getInfoHandle() else { - throw KeyWalletError.invalidState("Failed to get managed wallet info") - } - - var error = FFIError() - var confirmed: UInt64 = 0 - var unconfirmed: UInt64 = 0 - var immature: UInt64 = 0 - var locked: UInt64 = 0 - var total: UInt64 = 0 - - let success = managed_wallet_get_balance( - infoHandle, &confirmed, &unconfirmed, &immature, &locked, &total, &error) - - defer { - if error.message != nil { - error_message_free(error.message) - } - } - - guard success else { - throw KeyWalletError(ffiError: error) - } - - let ffiBalance = FFIBalance( - confirmed: confirmed, - unconfirmed: unconfirmed, - immature: immature, - locked: locked, - total: total - ) - - return Balance(ffiBalance: ffiBalance) - } - - /// Get all UTXOs from the managed wallet - public func getUTXOs() throws -> [UTXO] { - guard let infoHandle = getInfoHandle() else { - throw KeyWalletError.invalidState("Failed to get managed wallet info") - } - - var error = FFIError() - var utxosPtr: UnsafeMutablePointer? - var count: size_t = 0 - - let success = managed_wallet_get_utxos( - infoHandle, &utxosPtr, &count, &error) - - defer { - if error.message != nil { - error_message_free(error.message) - } - if let ptr = utxosPtr { - utxo_array_free(ptr, count) - } - } - - guard success, let ptr = utxosPtr else { - throw KeyWalletError(ffiError: error) - } - - var utxos: [UTXO] = [] - for i in 0.. UnsafeMutablePointer? { - // The handle is an FFIManagedWalletInfo* (opaque C handle) - return handle - } -}