diff --git a/Cargo.lock b/Cargo.lock index 0e309a219d..7e207a19f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4886,6 +4886,7 @@ dependencies = [ "bincode", "bs58", "cbindgen 0.27.0", + "dash-network", "dash-sdk", "dashcore", "dpp", @@ -5891,6 +5892,7 @@ dependencies = [ "bs58", "cbindgen 0.27.0", "dash-async", + "dash-network", "dash-sdk", "dotenvy", "drive-proof-verifier", @@ -5938,6 +5940,7 @@ dependencies = [ name = "rs-unified-sdk-ffi" version = "3.1.0-dev.1" dependencies = [ + "dash-network", "dash-spv-ffi", "key-wallet-ffi", "platform-wallet-ffi", diff --git a/Cargo.toml b/Cargo.toml index c4ddb2882f..7b7bd60964 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ dash-spv-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "8fe9ea key-wallet = { git = "https://github.com/dashpay/rust-dashcore", rev = "8fe9ea394306e5f9282505b24d09092ab9a33738" } key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "8fe9ea394306e5f9282505b24d09092ab9a33738" } key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", rev = "8fe9ea394306e5f9282505b24d09092ab9a33738" } +dash-network = { git = "https://github.com/dashpay/rust-dashcore", rev = "8fe9ea394306e5f9282505b24d09092ab9a33738" } dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", rev = "8fe9ea394306e5f9282505b24d09092ab9a33738" } # Optimize heavy crypto crates even in dev/test builds so that diff --git a/packages/rs-platform-wallet-ffi/Cargo.toml b/packages/rs-platform-wallet-ffi/Cargo.toml index 43c195e360..5e2b46da44 100644 --- a/packages/rs-platform-wallet-ffi/Cargo.toml +++ b/packages/rs-platform-wallet-ffi/Cargo.toml @@ -27,6 +27,7 @@ tokio = { version = "1", features = ["rt-multi-thread"] } # Core dependencies (for Network type) dashcore = { workspace = true } key-wallet = { workspace = true, features = ["bincode"] } +dash-network = { workspace = true, features = ["ffi"] } # Bincode used to serialize RootExtendedPubKey / ExtendedPubKey across # FFI for watch-only restore. Same version pinned elsewhere in workspace. diff --git a/packages/rs-platform-wallet-ffi/src/core_wallet/wallet.rs b/packages/rs-platform-wallet-ffi/src/core_wallet/wallet.rs index 694c9d2da9..3267c83a24 100644 --- a/packages/rs-platform-wallet-ffi/src/core_wallet/wallet.rs +++ b/packages/rs-platform-wallet-ffi/src/core_wallet/wallet.rs @@ -2,6 +2,7 @@ use crate::error::*; use crate::handle::*; +use crate::types::FFINetwork; /// Destroy a CoreWallet handle. #[no_mangle] @@ -46,12 +47,10 @@ pub unsafe extern "C" fn core_wallet_get_balance( } /// Get the network this wallet operates on. -/// -/// Returns: 0 = Mainnet, 1 = Testnet, 2 = Devnet, 3 = Regtest. #[no_mangle] pub unsafe extern "C" fn core_wallet_get_network( handle: Handle, - out_network: *mut u32, + out_network: *mut FFINetwork, _out_error: *mut PlatformWalletFFIError, ) -> PlatformWalletFFIResult { if out_network.is_null() { @@ -60,12 +59,7 @@ pub unsafe extern "C" fn core_wallet_get_network( CORE_WALLET_STORAGE .with_item(handle, |wallet| { - *out_network = match wallet.network() { - key_wallet::Network::Mainnet => 0, - key_wallet::Network::Testnet => 1, - key_wallet::Network::Devnet => 2, - key_wallet::Network::Regtest => 3, - }; + *out_network = wallet.network().into(); PlatformWalletFFIResult::Success }) .unwrap_or(PlatformWalletFFIResult::ErrorInvalidHandle) diff --git a/packages/rs-platform-wallet-ffi/src/derivation.rs b/packages/rs-platform-wallet-ffi/src/derivation.rs index e1548df16a..c9ef8342be 100644 --- a/packages/rs-platform-wallet-ffi/src/derivation.rs +++ b/packages/rs-platform-wallet-ffi/src/derivation.rs @@ -19,10 +19,10 @@ use std::str::FromStr; use dashcore::secp256k1::Secp256k1; use key_wallet::bip32::{DerivationPath, ExtendedPrivKey}; use key_wallet::mnemonic::{Language, Mnemonic}; -use key_wallet::Network; use zeroize::Zeroizing; use crate::error::*; +use crate::types::{FFINetwork, Network}; /// Parse a BIP-39 mnemonic against every supported wordlist in turn, /// returning the first language that yields a valid mnemonic. @@ -67,8 +67,7 @@ fn parse_mnemonic_any_language(phrase: &str) -> Result { /// * `mnemonic` — UTF-8 null-terminated BIP-39 mnemonic phrase. /// * `passphrase` — optional UTF-8 null-terminated BIP-39 passphrase. /// Pass `null` for no passphrase. -/// * `network` — `0` = Mainnet, `1` = Testnet, `2` = Devnet, `3` = -/// Regtest. Drives the xpriv version bytes; the derived secret +/// * `network` — Drives the xpriv version bytes; the derived secret /// key itself is network-independent but the master key's chain /// code derivation uses the HD seed directly. /// * `path_utf8` — UTF-8 null-terminated BIP-32 path string, e.g. @@ -95,7 +94,7 @@ fn parse_mnemonic_any_language(phrase: &str) -> Result { pub unsafe extern "C" fn platform_wallet_derive_ext_priv_key_from_mnemonic( mnemonic: *const c_char, passphrase: *const c_char, - network: u32, + network: FFINetwork, path_utf8: *const c_char, out_secret_key: *mut u8, out_chain_code: *mut u8, @@ -159,21 +158,7 @@ pub unsafe extern "C" fn platform_wallet_derive_ext_priv_key_from_mnemonic( } }; - let network = match network { - 0 => Network::Mainnet, - 1 => Network::Testnet, - 2 => Network::Devnet, - 3 => Network::Regtest, - _ => { - if !out_error.is_null() { - *out_error = PlatformWalletFFIError::new( - PlatformWalletFFIResult::ErrorInvalidParameter, - "invalid network (expected 0..=3)", - ); - } - return PlatformWalletFFIResult::ErrorInvalidParameter; - } - }; + let network: Network = network.into(); let path = match DerivationPath::from_str(path_str) { Ok(p) => p, diff --git a/packages/rs-platform-wallet-ffi/src/derive_identity_key_at_slot.rs b/packages/rs-platform-wallet-ffi/src/derive_identity_key_at_slot.rs index c9a28feaac..0e923ce2fe 100644 --- a/packages/rs-platform-wallet-ffi/src/derive_identity_key_at_slot.rs +++ b/packages/rs-platform-wallet-ffi/src/derive_identity_key_at_slot.rs @@ -22,10 +22,10 @@ use std::ffi::{c_void, CString}; use std::os::raw::c_char; +use crate::types::{FFINetwork, Network}; use dashcore::PrivateKey as DashPrivateKey; use key_wallet::bip32::ExtendedPrivKey; use platform_wallet::wallet::identity::network::derive_ecdsa_identity_auth_keypair_from_master; -use rs_sdk_ffi::DashSDKNetwork; use zeroize::Zeroizing; use crate::derive_and_persist_callbacks::{ @@ -33,7 +33,7 @@ use crate::derive_and_persist_callbacks::{ }; use crate::error::*; use crate::identity_key_preview::IdentityKeyPreviewFFI; -use crate::identity_keys_from_mnemonic::{map_network, parse_mnemonic_any_language}; +use crate::identity_keys_from_mnemonic::parse_mnemonic_any_language; /// Derive a single ECDSA identity-authentication keypair at /// `(identity_index, key_index)` from a BIP-39 mnemonic. Returns @@ -72,7 +72,7 @@ use crate::identity_keys_from_mnemonic::{map_network, parse_mnemonic_any_languag pub unsafe extern "C" fn dash_sdk_derive_identity_key_at_slot( mnemonic_cstr: *const std::os::raw::c_char, passphrase_cstr: *const std::os::raw::c_char, - network: DashSDKNetwork, + network: FFINetwork, identity_index: u32, key_index: u32, out_row: *mut IdentityKeyPreviewFFI, @@ -151,7 +151,7 @@ pub unsafe extern "C" fn dash_sdk_derive_identity_key_at_slot( unsafe fn derive_at_slot_inner( mnemonic_str: &str, passphrase_str: &str, - network: DashSDKNetwork, + network: FFINetwork, identity_index: u32, key_index: u32, out_row: *mut IdentityKeyPreviewFFI, @@ -175,7 +175,7 @@ unsafe fn derive_at_slot_inner( let seed: Zeroizing<[u8; 64]> = Zeroizing::new(mnemonic.to_seed(passphrase_str)); // ---- Master xpriv -------------------------------------------------------- - let kw_network = map_network(network); + let kw_network: Network = network.into(); let master = match ExtendedPrivKey::new_master(kw_network, seed.as_ref()) { Ok(m) => m, Err(e) => { @@ -338,7 +338,7 @@ unsafe fn derive_at_slot_inner( /// - `out_error` may be NULL. #[no_mangle] pub unsafe extern "C" fn dash_sdk_derive_identity_key_at_slot_with_resolver( - network: DashSDKNetwork, + network: FFINetwork, wallet_id_bytes: *const u8, mnemonic_resolver_handle: *mut MnemonicResolverHandle, identity_index: u32, diff --git a/packages/rs-platform-wallet-ffi/src/identity_derive_and_persist.rs b/packages/rs-platform-wallet-ffi/src/identity_derive_and_persist.rs index e146a85ae5..5f2deec124 100644 --- a/packages/rs-platform-wallet-ffi/src/identity_derive_and_persist.rs +++ b/packages/rs-platform-wallet-ffi/src/identity_derive_and_persist.rs @@ -76,10 +76,10 @@ use std::ffi::{c_void, CString}; use std::os::raw::c_char; use std::ptr; +use crate::types::{FFINetwork, Network}; use dashcore::hashes::Hash; use dashcore::secp256k1::Secp256k1; use key_wallet::bip32::{ExtendedPrivKey, ExtendedPubKey}; -use rs_sdk_ffi::DashSDKNetwork; use zeroize::{Zeroize, Zeroizing}; use crate::derive_and_persist_callbacks::{ @@ -89,7 +89,7 @@ use crate::derive_and_persist_callbacks::{ use crate::error::*; use crate::identity_key_preview::IdentityKeyPreviewFFI; use crate::identity_keys_from_mnemonic::{ - identity_auth_derivation_path, map_network, parse_mnemonic_any_language, + identity_auth_derivation_path, parse_mnemonic_any_language, }; use crate::identity_registration_with_signer::IdentityRegistrationKeyDerivationsFFI; @@ -158,7 +158,7 @@ const SECURITY_LEVEL_HIGH: u8 = 2; #[no_mangle] #[allow(clippy::too_many_arguments)] pub unsafe extern "C" fn dash_sdk_derive_and_persist_identity_keys( - network: DashSDKNetwork, + network: FFINetwork, wallet_id_bytes: *const u8, identity_index: u32, key_count: u32, @@ -281,7 +281,7 @@ pub unsafe extern "C" fn dash_sdk_derive_and_persist_identity_keys( // (non-zeroized) `String` storage early. drop(mnemonic); - let kw_network = map_network(network); + let kw_network: Network = network.into(); let master = match ExtendedPrivKey::new_master(kw_network, seed.as_ref()) { Ok(m) => m, Err(e) => { @@ -629,7 +629,7 @@ mod tests { let mut err = PlatformWalletFFIError::success(); let rc = unsafe { dash_sdk_derive_and_persist_identity_keys( - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, wallet_id.as_ptr(), 7, // identity_index 3, // key_count @@ -695,7 +695,7 @@ mod tests { let mut err = PlatformWalletFFIError::success(); let rc = unsafe { dash_sdk_derive_and_persist_identity_keys( - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, wallet_id.as_ptr(), 0, 2, @@ -722,7 +722,7 @@ mod tests { // Null out_pubkeys. let rc = unsafe { dash_sdk_derive_and_persist_identity_keys( - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, wallet_id.as_ptr(), 0, 1, @@ -741,7 +741,7 @@ mod tests { }; let rc = unsafe { dash_sdk_derive_and_persist_identity_keys( - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, std::ptr::null(), 0, 1, @@ -770,7 +770,7 @@ mod tests { let mut err = PlatformWalletFFIError::success(); let rc = unsafe { dash_sdk_derive_and_persist_identity_keys( - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, wallet_id.as_ptr(), 0, 0, diff --git a/packages/rs-platform-wallet-ffi/src/identity_keys_from_mnemonic.rs b/packages/rs-platform-wallet-ffi/src/identity_keys_from_mnemonic.rs index 019bc42d68..b0fd2e7ae9 100644 --- a/packages/rs-platform-wallet-ffi/src/identity_keys_from_mnemonic.rs +++ b/packages/rs-platform-wallet-ffi/src/identity_keys_from_mnemonic.rs @@ -45,12 +45,12 @@ use key_wallet::dip9::{ IDENTITY_AUTHENTICATION_PATH_MAINNET, IDENTITY_AUTHENTICATION_PATH_TESTNET, }; use key_wallet::mnemonic::{Language, Mnemonic}; -use rs_sdk_ffi::DashSDKNetwork; use zeroize::Zeroizing; use crate::error::*; use crate::identity_key_preview::IdentityKeyPreviewFFI; use crate::identity_registration_with_signer::IdentityRegistrationKeyDerivationsFFI; +use crate::types::{FFINetwork, Network}; /// Parse a BIP-39 mnemonic against every supported wordlist. /// @@ -81,20 +81,6 @@ pub(crate) fn parse_mnemonic_any_language(phrase: &str) -> Result key_wallet::Network { - match network { - DashSDKNetwork::SDKMainnet => key_wallet::Network::Mainnet, - DashSDKNetwork::SDKTestnet => key_wallet::Network::Testnet, - DashSDKNetwork::SDKRegtest => key_wallet::Network::Regtest, - DashSDKNetwork::SDKDevnet => key_wallet::Network::Devnet, - DashSDKNetwork::SDKLocal => key_wallet::Network::Regtest, - } -} - /// Build the DIP-9 identity-authentication derivation path /// `m/9'/coin'/5'/0'/0'/identity_index'/key_index'`. /// @@ -109,12 +95,12 @@ pub(crate) fn map_network(network: DashSDKNetwork) -> key_wallet::Network { /// `platform_wallet::identity_auth_derivation_path` is `pub(crate)` and /// this entry point sits outside that crate. pub(crate) fn identity_auth_derivation_path( - network: key_wallet::Network, + network: Network, identity_index: u32, key_index: u32, ) -> Result { let base_path: DerivationPath = match network { - key_wallet::Network::Mainnet => IDENTITY_AUTHENTICATION_PATH_MAINNET, + Network::Mainnet => IDENTITY_AUTHENTICATION_PATH_MAINNET, _ => IDENTITY_AUTHENTICATION_PATH_TESTNET, } .into(); @@ -191,7 +177,7 @@ pub(crate) fn identity_auth_derivation_path( pub unsafe extern "C" fn dash_sdk_derive_identity_keys_from_mnemonic( mnemonic_cstr: *const std::os::raw::c_char, passphrase_cstr: *const std::os::raw::c_char, - network: DashSDKNetwork, + network: FFINetwork, identity_index: u32, key_count: u32, out_rows: *mut IdentityRegistrationKeyDerivationsFFI, @@ -278,7 +264,7 @@ pub unsafe extern "C" fn dash_sdk_derive_identity_keys_from_mnemonic( let seed: Zeroizing<[u8; 64]> = Zeroizing::new(mnemonic.to_seed(passphrase_str)); // ---- Master xpriv -------------------------------------------------------- - let kw_network = map_network(network); + let kw_network: Network = network.into(); let master = match ExtendedPrivKey::new_master(kw_network, seed.as_ref()) { Ok(m) => m, Err(e) => { @@ -513,7 +499,7 @@ mod tests { dash_sdk_derive_identity_keys_from_mnemonic( mnemonic.as_ptr(), std::ptr::null(), // empty passphrase - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, 7, 3, &mut out, @@ -574,7 +560,7 @@ mod tests { dash_sdk_derive_identity_keys_from_mnemonic( mnemonic.as_ptr(), std::ptr::null(), - DashSDKNetwork::SDKMainnet, + FFINetwork::Mainnet, 0, 1, &mut out, @@ -606,7 +592,7 @@ mod tests { dash_sdk_derive_identity_keys_from_mnemonic( mnemonic.as_ptr(), std::ptr::null(), - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, 0, 0, &mut out, @@ -634,7 +620,7 @@ mod tests { dash_sdk_derive_identity_keys_from_mnemonic( mnemonic.as_ptr(), std::ptr::null(), - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, 0, 3, &mut out, diff --git a/packages/rs-platform-wallet-ffi/src/manager.rs b/packages/rs-platform-wallet-ffi/src/manager.rs index df43838fcb..29804e3403 100644 --- a/packages/rs-platform-wallet-ffi/src/manager.rs +++ b/packages/rs-platform-wallet-ffi/src/manager.rs @@ -5,10 +5,10 @@ use crate::event_handler::{EventHandlerCallbacks, FFIEventHandler}; use crate::handle::*; use crate::persistence::{FFIPersister, PersistenceCallbacks}; use crate::runtime::runtime; +use crate::types::{FFINetwork, Network}; use dash_sdk::Sdk; use key_wallet::wallet::initialization::WalletAccountCreationOptions; -use key_wallet::Network; use platform_wallet::PlatformWalletManager; use std::os::raw::c_void; use std::sync::Arc; @@ -74,7 +74,7 @@ pub unsafe extern "C" fn platform_wallet_manager_create( #[no_mangle] pub unsafe extern "C" fn platform_wallet_manager_create_wallet_from_seed( manager_handle: Handle, - network: u32, + network: FFINetwork, seed_bytes: *const u8, seed_len: usize, account_options: u32, @@ -95,21 +95,7 @@ pub unsafe extern "C" fn platform_wallet_manager_create_wallet_from_seed( return PlatformWalletFFIResult::ErrorInvalidParameter; } - let network = match network { - 0 => Network::Mainnet, - 1 => Network::Testnet, - 2 => Network::Devnet, - 3 => Network::Regtest, - _ => { - if !out_error.is_null() { - *out_error = PlatformWalletFFIError::new( - PlatformWalletFFIResult::ErrorInvalidNetwork, - format!("Unknown network: {}", network), - ); - } - return PlatformWalletFFIResult::ErrorInvalidNetwork; - } - }; + let network: Network = network.into(); let mut seed = [0u8; 64]; std::ptr::copy_nonoverlapping(seed_bytes, seed.as_mut_ptr(), 64); @@ -153,7 +139,7 @@ pub unsafe extern "C" fn platform_wallet_manager_create_wallet_from_seed( pub unsafe extern "C" fn platform_wallet_manager_create_wallet_from_mnemonic( manager_handle: Handle, mnemonic: *const std::os::raw::c_char, - network: u32, + network: FFINetwork, account_options: u32, out_wallet_handle: *mut Handle, out_wallet_id: *mut [u8; 32], @@ -176,21 +162,7 @@ pub unsafe extern "C" fn platform_wallet_manager_create_wallet_from_mnemonic( } }; - let network = match network { - 0 => Network::Mainnet, - 1 => Network::Testnet, - 2 => Network::Devnet, - 3 => Network::Regtest, - _ => { - if !out_error.is_null() { - *out_error = PlatformWalletFFIError::new( - PlatformWalletFFIResult::ErrorInvalidNetwork, - format!("Unknown network: {}", network), - ); - } - return PlatformWalletFFIResult::ErrorInvalidNetwork; - } - }; + let network: Network = network.into(); let accounts = match account_options { 0 => WalletAccountCreationOptions::None, diff --git a/packages/rs-platform-wallet-ffi/src/persistence.rs b/packages/rs-platform-wallet-ffi/src/persistence.rs index fecdd88cb1..0e1b98ecf0 100644 --- a/packages/rs-platform-wallet-ffi/src/persistence.rs +++ b/packages/rs-platform-wallet-ffi/src/persistence.rs @@ -12,8 +12,10 @@ use key_wallet::bip32::ExtendedPubKey; use key_wallet::managed_account::address_pool::{AddressPoolType, PublicKeyType}; use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo; use key_wallet::wallet::Wallet; -use key_wallet::{AddressInfo, Network}; +use key_wallet::AddressInfo; use parking_lot::RwLock; + +use crate::types::{FFINetwork, Network}; use platform_wallet::changeset::{ AccountAddressPoolEntry, AccountRegistrationEntry, ClientStartState, ClientWalletStartState, Merge, PersistenceError, PlatformWalletChangeSet, PlatformWalletPersistence, @@ -177,7 +179,7 @@ pub struct PersistenceCallbacks { unsafe extern "C" fn( context: *mut c_void, wallet_id: *const u8, - network: u8, + network: FFINetwork, birth_height: u32, ) -> i32, >, @@ -329,12 +331,11 @@ impl PlatformWalletPersistence for FFIPersister { // `wallet_metadata: None` so no callback fires). if let Some(meta) = changeset.wallet_metadata.as_ref() { if let Some(cb) = self.callbacks.on_persist_wallet_metadata_fn { - let network_tag = network_tag_for(meta.network); let result = unsafe { cb( self.callbacks.context, wallet_id.as_ptr(), - network_tag, + meta.network.into(), meta.birth_height, ) }; @@ -855,18 +856,6 @@ impl PlatformWalletPersistence for FFIPersister { } } -/// Reverse of [`network_from_tag`] — keeps the discriminant in sync -/// with `platform_wallet_manager_create_wallet_from_seed` (0 = Mainnet, -/// 1 = Testnet, 2 = Devnet, 3 = Regtest). -fn network_tag_for(network: Network) -> u8 { - match network { - Network::Mainnet => 0, - Network::Testnet => 1, - Network::Devnet => 2, - Network::Regtest => 3, - } -} - /// Flatten an `AccountType` + encoded xpub into the C-flat /// [`AccountSpecFFI`] layout. /// @@ -1165,7 +1154,7 @@ fn build_wallet_start_state( ), PersistenceError, > { - let network = network_from_tag(entry.network)?; + let network: Network = entry.network.into(); // Build the per-account collection from the typed spec array. let mut accounts = AccountCollection::new(); @@ -1457,16 +1446,6 @@ fn identity_status_from_tag(tag: u8) -> IdentityStatus { } } -fn network_from_tag(tag: u8) -> Result { - match tag { - 0 => Ok(Network::Mainnet), - 1 => Ok(Network::Testnet), - 2 => Ok(Network::Devnet), - 3 => Ok(Network::Regtest), - other => Err(format!("unknown network tag {}", other).into()), - } -} - fn account_type_from_spec(spec: &AccountSpecFFI) -> Result { Ok(match spec.type_tag { AccountTypeTagFFI::Standard => { diff --git a/packages/rs-platform-wallet-ffi/src/platform_addresses/fund_from_asset_lock.rs b/packages/rs-platform-wallet-ffi/src/platform_addresses/fund_from_asset_lock.rs index 361a0ac18b..f29d7cad7f 100644 --- a/packages/rs-platform-wallet-ffi/src/platform_addresses/fund_from_asset_lock.rs +++ b/packages/rs-platform-wallet-ffi/src/platform_addresses/fund_from_asset_lock.rs @@ -117,7 +117,7 @@ pub unsafe extern "C" fn platform_address_wallet_fund_from_asset_lock( } }; let private_key = - match dashcore::PrivateKey::from_byte_array(key_array, dashcore::Network::Mainnet) { + match dashcore::PrivateKey::from_byte_array(key_array, crate::types::Network::Mainnet) { Ok(k) => k, Err(e) => { if !out_error.is_null() { diff --git a/packages/rs-platform-wallet-ffi/src/platform_wallet_info.rs b/packages/rs-platform-wallet-ffi/src/platform_wallet_info.rs index 542b5ab4d0..beffad82c5 100644 --- a/packages/rs-platform-wallet-ffi/src/platform_wallet_info.rs +++ b/packages/rs-platform-wallet-ffi/src/platform_wallet_info.rs @@ -1,18 +1,15 @@ use crate::error::*; use crate::handle::*; -use crate::types::Network; +use crate::types::{FFINetwork, Network}; use key_wallet::wallet::initialization::WalletAccountCreationOptions; use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface; use platform_wallet::PlatformWalletInfo; use std::os::raw::{c_char, c_uchar}; /// Create a new PlatformWalletInfo from seed bytes. -/// -/// `network` encoding matches other entry points in this crate: -/// 0 = Mainnet, 1 = Testnet, 2 = Devnet, 3 = Regtest. #[no_mangle] pub unsafe extern "C" fn platform_wallet_info_create_from_seed( - network: u32, + network: FFINetwork, seed_bytes: *const c_uchar, seed_len: usize, out_handle: *mut Handle, @@ -30,23 +27,7 @@ pub unsafe extern "C" fn platform_wallet_info_create_from_seed( return PlatformWalletFFIResult::ErrorNullPointer; } - let network = match network { - 0 => Network::Mainnet, - 1 => Network::Testnet, - 2 => Network::Devnet, - 3 => Network::Regtest, - _ => { - if !out_error.is_null() { - unsafe { - *out_error = PlatformWalletFFIError::new( - PlatformWalletFFIResult::ErrorInvalidNetwork, - format!("Unknown network: {}", network), - ); - } - } - return PlatformWalletFFIResult::ErrorInvalidNetwork; - } - }; + let network: Network = network.into(); // Validate seed length (should be 64 bytes for BIP39) if seed_len != 64 { @@ -98,12 +79,9 @@ pub unsafe extern "C" fn platform_wallet_info_create_from_seed( } /// Create a new PlatformWalletInfo from mnemonic. -/// -/// `network` encoding matches other entry points in this crate: -/// 0 = Mainnet, 1 = Testnet, 2 = Devnet, 3 = Regtest. #[no_mangle] pub unsafe extern "C" fn platform_wallet_info_create_from_mnemonic( - network: u32, + network: FFINetwork, mnemonic: *const c_char, passphrase: *const c_char, out_handle: *mut Handle, @@ -121,23 +99,7 @@ pub unsafe extern "C" fn platform_wallet_info_create_from_mnemonic( return PlatformWalletFFIResult::ErrorNullPointer; } - let network = match network { - 0 => Network::Mainnet, - 1 => Network::Testnet, - 2 => Network::Devnet, - 3 => Network::Regtest, - _ => { - if !out_error.is_null() { - unsafe { - *out_error = PlatformWalletFFIError::new( - PlatformWalletFFIResult::ErrorInvalidNetwork, - format!("Unknown network: {}", network), - ); - } - } - return PlatformWalletFFIResult::ErrorInvalidNetwork; - } - }; + let network: Network = network.into(); let mnemonic_str = unsafe { match std::ffi::CStr::from_ptr(mnemonic).to_str() { @@ -382,7 +344,7 @@ mod tests { let mut error = PlatformWalletFFIError::success(); let result = platform_wallet_info_create_from_seed( - 1, // Testnet + FFINetwork::Testnet, seed.as_ptr(), seed.len(), &mut handle, @@ -408,7 +370,7 @@ mod tests { let mut error = PlatformWalletFFIError::success(); let result = platform_wallet_info_create_from_mnemonic( - 1, // Testnet + FFINetwork::Testnet, mnemonic.as_ptr(), std::ptr::null(), &mut handle, @@ -432,7 +394,7 @@ mod tests { let mut error = PlatformWalletFFIError::success(); platform_wallet_info_create_from_seed( - 1, // Testnet + FFINetwork::Testnet, seed.as_ptr(), seed.len(), &mut handle, diff --git a/packages/rs-platform-wallet-ffi/src/sign_with_mnemonic_resolver.rs b/packages/rs-platform-wallet-ffi/src/sign_with_mnemonic_resolver.rs index 168e82f3f4..7010390191 100644 --- a/packages/rs-platform-wallet-ffi/src/sign_with_mnemonic_resolver.rs +++ b/packages/rs-platform-wallet-ffi/src/sign_with_mnemonic_resolver.rs @@ -40,15 +40,15 @@ use std::ffi::{c_void, CStr}; use std::os::raw::c_char; use std::str::FromStr; +use crate::types::{FFINetwork, Network}; use dashcore::secp256k1::Secp256k1; use key_wallet::bip32::{DerivationPath, ExtendedPrivKey}; -use rs_sdk_ffi::DashSDKNetwork; use zeroize::Zeroizing; use crate::derive_and_persist_callbacks::{ mnemonic_resolver_result, MnemonicResolverHandle, MNEMONIC_RESOLVER_BUFFER_CAPACITY, }; -use crate::identity_keys_from_mnemonic::{map_network, parse_mnemonic_any_language}; +use crate::identity_keys_from_mnemonic::parse_mnemonic_any_language; // One-byte error tags. Mirror the shape of // `signer_simple::SIGN_WITH_MNEMONIC_ERR_*` so call sites already @@ -108,7 +108,7 @@ pub unsafe extern "C" fn dash_sdk_sign_with_mnemonic_resolver_and_path( data: *const u8, data_len: usize, key_type: u8, - network: DashSDKNetwork, + network: FFINetwork, out_signature: *mut u8, out_signature_capacity: usize, out_signature_len: *mut usize, @@ -199,7 +199,7 @@ pub unsafe extern "C" fn dash_sdk_sign_with_mnemonic_resolver_and_path( Err(_) => return fail(SIGN_WITH_RESOLVER_ERR_INVALID_PATH), }; - let kw_network = map_network(network); + let kw_network: Network = network.into(); let master = match ExtendedPrivKey::new_master(kw_network, seed.as_ref()) { Ok(m) => m, Err(_) => return fail(SIGN_WITH_RESOLVER_ERR_DERIVATION), @@ -298,7 +298,7 @@ mod tests { data.as_ptr(), data.len(), 0, // ECDSA_SECP256K1 - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, sig_buf.as_mut_ptr(), sig_buf.len(), &mut sig_len, @@ -329,7 +329,7 @@ mod tests { data.as_ptr(), data.len(), 0, - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, sig_buf.as_mut_ptr(), sig_buf.len(), &mut sig_len, @@ -359,7 +359,7 @@ mod tests { data.as_ptr(), data.len(), 1, // BLS12_381 — not supported - DashSDKNetwork::SDKTestnet, + FFINetwork::Testnet, sig_buf.as_mut_ptr(), sig_buf.len(), &mut sig_len, diff --git a/packages/rs-platform-wallet-ffi/src/spv.rs b/packages/rs-platform-wallet-ffi/src/spv.rs index 4faf84f4c6..37e32c4459 100644 --- a/packages/rs-platform-wallet-ffi/src/spv.rs +++ b/packages/rs-platform-wallet-ffi/src/spv.rs @@ -15,6 +15,7 @@ use platform_wallet::spv::{ClientConfig, ProgressPercentage, SyncProgress, SyncS use crate::error::*; use crate::handle::*; use crate::runtime::runtime; +use crate::types::FFINetwork; // --------------------------------------------------------------------------- // Sync progress @@ -222,7 +223,7 @@ pub unsafe extern "C" fn platform_wallet_manager_spv_is_running( pub unsafe extern "C" fn platform_wallet_manager_spv_start( handle: Handle, data_dir: *const c_char, - network: u32, + network: FFINetwork, user_agent: *const c_char, peers: *const *const c_char, peer_count: usize, @@ -247,13 +248,7 @@ pub unsafe extern "C" fn platform_wallet_manager_spv_start( } }; - let net = match network { - 0 => dashcore::Network::Mainnet, - 1 => dashcore::Network::Testnet, - 2 => dashcore::Network::Devnet, - 3 => dashcore::Network::Regtest, - _ => return PlatformWalletFFIResult::ErrorInvalidNetwork, - }; + let net: crate::types::Network = network.into(); let mut peer_list: Vec = Vec::new(); if !peers.is_null() && peer_count > 0 { diff --git a/packages/rs-platform-wallet-ffi/src/types.rs b/packages/rs-platform-wallet-ffi/src/types.rs index 078be6be69..4d051ac79f 100644 --- a/packages/rs-platform-wallet-ffi/src/types.rs +++ b/packages/rs-platform-wallet-ffi/src/types.rs @@ -1,6 +1,12 @@ use std::os::raw::c_char; -pub use dashcore::Network; +// Single source of truth for the network type across the Rust-side +// wallet stack and the FFI boundary. `Network` is the typed enum; +// `FFINetwork` is the `#[repr(C)]` mirror cbindgen emits for callers. +// Every FFI entry point in this crate takes / returns `FFINetwork`; +// internal Rust code converts via `Network::from(ffi)` / `ffi.into()`. +pub use dash_network::ffi::FFINetwork; +pub use dash_network::Network; /// Block time structure #[repr(C)] diff --git a/packages/rs-platform-wallet-ffi/src/wallet.rs b/packages/rs-platform-wallet-ffi/src/wallet.rs index 086f18ac66..9d03980c17 100644 --- a/packages/rs-platform-wallet-ffi/src/wallet.rs +++ b/packages/rs-platform-wallet-ffi/src/wallet.rs @@ -242,7 +242,7 @@ pub unsafe extern "C" fn platform_wallet_manager_free_account_balances( count: usize, ) { if !entries.is_null() && count > 0 { - let _ = Box::from_raw(std::slice::from_raw_parts_mut(entries, count)); + let _ = Box::from_raw(std::ptr::slice_from_raw_parts_mut(entries, count)); } } diff --git a/packages/rs-platform-wallet-ffi/src/wallet_restore_types.rs b/packages/rs-platform-wallet-ffi/src/wallet_restore_types.rs index 29c59049a5..1ff953aab3 100644 --- a/packages/rs-platform-wallet-ffi/src/wallet_restore_types.rs +++ b/packages/rs-platform-wallet-ffi/src/wallet_restore_types.rs @@ -22,6 +22,7 @@ use std::os::raw::{c_char, c_void}; use crate::platform_address_types::AddressBalanceEntryFFI; +use crate::types::FFINetwork; /// Discriminant for [`key_wallet::account::AccountType`]. /// @@ -222,10 +223,9 @@ pub struct IdentityRestoreEntryFFI { #[repr(C)] pub struct WalletRestoreEntryFFI { pub wallet_id: [u8; 32], - /// [`key_wallet::Network`] discriminant, matching - /// `platform_wallet_manager_create_wallet_from_seed`: - /// 0 = Mainnet, 1 = Testnet, 2 = Devnet, 3 = Regtest. - pub network: u8, + /// Network this wallet was created on. Mirrors what was supplied to + /// `platform_wallet_manager_create_wallet_from_seed`. + pub network: FFINetwork, pub accounts: *const AccountSpecFFI, pub accounts_count: usize, /// Cached platform-address balances for this wallet. The pointer is diff --git a/packages/rs-platform-wallet-ffi/tests/integration_tests.rs b/packages/rs-platform-wallet-ffi/tests/integration_tests.rs index 72f4f645a9..0eb6c3dda5 100644 --- a/packages/rs-platform-wallet-ffi/tests/integration_tests.rs +++ b/packages/rs-platform-wallet-ffi/tests/integration_tests.rs @@ -21,7 +21,7 @@ fn test_wallet_creation_and_destruction() { let mut error = PlatformWalletFFIError::success(); let result = platform_wallet_info_create_from_seed( - 1, // Testnet + Network::Testnet.into(), seed.as_ptr(), seed.len(), &mut handle, @@ -51,7 +51,7 @@ fn test_wallet_from_mnemonic() { let mut error = PlatformWalletFFIError::success(); let result = platform_wallet_info_create_from_mnemonic( - 1, // Testnet + Network::Testnet.into(), mnemonic.as_ptr(), std::ptr::null(), &mut handle, @@ -191,7 +191,7 @@ fn test_serialization() { let mut error = PlatformWalletFFIError::success(); platform_wallet_info_create_from_seed( - 1, // Testnet + Network::Testnet.into(), seed.as_ptr(), seed.len(), &mut handle, @@ -258,7 +258,7 @@ fn test_error_handling() { // Try to create wallet with null pointer let result = platform_wallet_info_create_from_seed( - 1, // Testnet + Network::Testnet.into(), std::ptr::null(), 0, std::ptr::null_mut(), @@ -284,7 +284,7 @@ fn test_full_workflow() { let mut wallet_handle: Handle = NULL_HANDLE; let result = platform_wallet_info_create_from_mnemonic( - 1, // Testnet + Network::Testnet.into(), mnemonic.as_ptr(), std::ptr::null(), &mut wallet_handle, diff --git a/packages/rs-platform-wallet/src/wallet/apply.rs b/packages/rs-platform-wallet/src/wallet/apply.rs index 6fb35bc546..1c0ea40654 100644 --- a/packages/rs-platform-wallet/src/wallet/apply.rs +++ b/packages/rs-platform-wallet/src/wallet/apply.rs @@ -364,7 +364,7 @@ mod tests { fn empty_info(wallet: &Wallet) -> PlatformWalletInfo { PlatformWalletInfo { - core_wallet: ManagedWalletInfo::from_wallet(wallet), + core_wallet: ManagedWalletInfo::from_wallet(wallet, 0), balance: std::sync::Arc::new(WalletBalance::new()), identity_manager: IdentityManager::new(), tracked_asset_locks: BTreeMap::new(), diff --git a/packages/rs-sdk-ffi/Cargo.toml b/packages/rs-sdk-ffi/Cargo.toml index 5f2ee2fe1d..ca0b199828 100644 --- a/packages/rs-sdk-ffi/Cargo.toml +++ b/packages/rs-sdk-ffi/Cargo.toml @@ -35,6 +35,10 @@ dash-async = { path = "../rs-dash-async" } # this crate. key-wallet = { workspace = true } +# Single source of truth for the Network enum and its `#[repr(C)]` +# FFI variant, both used directly across this crate's FFI surface. +dash-network = { workspace = true, features = ["ffi"] } + # FFI and serialization serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/packages/rs-sdk-ffi/src/address/mod.rs b/packages/rs-sdk-ffi/src/address/mod.rs index 140d6dc313..ed96a5fed2 100644 --- a/packages/rs-sdk-ffi/src/address/mod.rs +++ b/packages/rs-sdk-ffi/src/address/mod.rs @@ -9,6 +9,7 @@ pub use queries::*; // Re-export transition functions pub use transitions::*; +use crate::types::{FFINetwork, Network}; use crate::{DashSDKError, DashSDKErrorCode, DashSDKResult}; use dash_sdk::dpp::address_funds::PlatformAddress; use dash_sdk::dpp::dashcore::blockdata::script::Script; @@ -23,14 +24,13 @@ use std::panic::{self, AssertUnwindSafe}; /// /// # Safety /// - `script_pubkey` must point to `script_len` bytes -/// - `network`: 0 = mainnet, 1 = testnet, 2 = regtest, 3 = devnet /// - Returns a DashSDKResult whose `data` field is a heap-allocated C string. /// Free it with `dash_sdk_string_free`. #[no_mangle] pub unsafe extern "C" fn dash_sdk_encode_platform_address( script_pubkey: *const u8, script_len: u32, - network: u32, + network: FFINetwork, ) -> DashSDKResult { let result = panic::catch_unwind(AssertUnwindSafe(|| { if script_pubkey.is_null() { @@ -64,20 +64,8 @@ pub unsafe extern "C" fn dash_sdk_encode_platform_address( .expect("slice is exactly 20 bytes after length check"); let platform_addr = PlatformAddress::P2pkh(hash); - let dash_network = match network { - 0 => dash_sdk::dpp::dashcore::Network::Mainnet, - 1 => dash_sdk::dpp::dashcore::Network::Testnet, - 2 => dash_sdk::dpp::dashcore::Network::Regtest, - 3 => dash_sdk::dpp::dashcore::Network::Devnet, - _ => { - return DashSDKResult::error(DashSDKError::new( - DashSDKErrorCode::InvalidParameter, - format!("Unknown network code: {}. Expected 0 (mainnet), 1 (testnet), 2 (regtest), or 3 (devnet)", network), - )); - } - }; - - let encoded = platform_addr.to_bech32m_string(dash_network); + let network: Network = network.into(); + let encoded = platform_addr.to_bech32m_string(network); match CString::new(encoded) { Ok(c_str) => DashSDKResult::success_string(c_str.into_raw()), diff --git a/packages/rs-sdk-ffi/src/crypto/mod.rs b/packages/rs-sdk-ffi/src/crypto/mod.rs index 4ab971d819..afb617a886 100644 --- a/packages/rs-sdk-ffi/src/crypto/mod.rs +++ b/packages/rs-sdk-ffi/src/crypto/mod.rs @@ -1,7 +1,7 @@ //! Cryptographic utilities for key validation +use crate::types::{FFINetwork, Network}; use crate::{DashSDKError, DashSDKErrorCode, DashSDKResult}; -use dash_sdk::dpp::dashcore::Network; use dash_sdk::dpp::identity::KeyType; use std::ffi::{c_char, CStr}; use zeroize::Zeroizing; @@ -11,7 +11,7 @@ use zeroize::Zeroizing; /// # Safety /// - `private_key_hex` and `public_key_hex` must be valid, non-null pointers to NUL-terminated C strings that /// remain valid for the duration of the call. -/// - `key_type` and `is_testnet` are passed by value; no references are retained. +/// - `key_type` and `network` are passed by value; no references are retained. /// - On success, the returned `DashSDKResult` contains a heap-allocated C string pointer which must be freed using /// the SDK's free routine. It may also return no data (null pointer) to indicate success without payload. /// - Passing invalid or dangling pointers results in undefined behavior. @@ -20,7 +20,7 @@ pub unsafe extern "C" fn dash_sdk_validate_private_key_for_public_key( private_key_hex: *const c_char, public_key_hex: *const c_char, key_type: u8, - is_testnet: bool, + network: FFINetwork, ) -> DashSDKResult { if private_key_hex.is_null() || public_key_hex.is_null() { return DashSDKResult::error(DashSDKError::new( @@ -80,11 +80,7 @@ pub unsafe extern "C" fn dash_sdk_validate_private_key_for_public_key( } }; - let network = if is_testnet { - Network::Testnet - } else { - Network::Mainnet - }; + let network: Network = network.into(); // Use DPP's public_key_data_from_private_key_data to derive the public key let derived_public_key_data = @@ -134,7 +130,7 @@ pub unsafe extern "C" fn dash_sdk_validate_private_key_for_public_key( #[no_mangle] pub unsafe extern "C" fn dash_sdk_private_key_to_wif( private_key_hex: *const c_char, - is_testnet: bool, + network: FFINetwork, ) -> DashSDKResult { if private_key_hex.is_null() { return DashSDKResult::error(DashSDKError::new( @@ -170,12 +166,7 @@ pub unsafe extern "C" fn dash_sdk_private_key_to_wif( } }; - // Create PrivateKey from bytes - let network = if is_testnet { - Network::Testnet - } else { - Network::Mainnet - }; + let network: Network = network.into(); let mut key_array = Zeroizing::new([0u8; 32]); key_array.copy_from_slice(&private_key_bytes); @@ -202,14 +193,14 @@ pub unsafe extern "C" fn dash_sdk_private_key_to_wif( /// # Safety /// - `private_key_hex` must be a valid, non-null pointer to a NUL-terminated C string representing a 32-byte hex key /// and remain valid for the duration of the call. -/// - `key_type` and `is_testnet` are passed by value; no references are retained. +/// - `key_type` and `network` are passed by value; no references are retained. /// - On success, the returned `DashSDKResult` contains a heap-allocated C string pointer which must be freed using /// the SDK's free routine. #[no_mangle] pub unsafe extern "C" fn dash_sdk_public_key_data_from_private_key_data( private_key_hex: *const c_char, key_type: u8, - is_testnet: bool, + network: FFINetwork, ) -> DashSDKResult { if private_key_hex.is_null() { return DashSDKResult::error(DashSDKError::new( @@ -259,11 +250,7 @@ pub unsafe extern "C" fn dash_sdk_public_key_data_from_private_key_data( } }; - let network = if is_testnet { - Network::Testnet - } else { - Network::Mainnet - }; + let network: Network = network.into(); // Use DPP's public_key_data_from_private_key_data to derive the public key match key_type.public_key_data_from_private_key_data(&key_array, network) { diff --git a/packages/rs-sdk-ffi/src/identity/top_up_from_addresses.rs b/packages/rs-sdk-ffi/src/identity/top_up_from_addresses.rs index e25bdbeed9..fa60623851 100644 --- a/packages/rs-sdk-ffi/src/identity/top_up_from_addresses.rs +++ b/packages/rs-sdk-ffi/src/identity/top_up_from_addresses.rs @@ -2,7 +2,6 @@ use dash_sdk::dpp::address_funds::PlatformAddress; use dash_sdk::dpp::dashcore::secp256k1::SecretKey; -use dash_sdk::dpp::dashcore::Network; use dash_sdk::dpp::dashcore::PrivateKey; use dash_sdk::dpp::fee::Credits; use dash_sdk::dpp::prelude::Identity; @@ -162,8 +161,9 @@ unsafe fn dash_sdk_identity_top_up_from_addresses_inner( } }; - // Create PrivateKey (network doesn't matter for signing) - let private_key = PrivateKey::new(secret_key, Network::Testnet); + // Create PrivateKey (network doesn't matter for signing — `PrivateKey` + // only carries it through to WIF encoding, which we never invoke here). + let private_key = PrivateKey::new(secret_key, wrapper.sdk.network); signer.add_key(&address, private_key); input_map.insert(address, input.amount); diff --git a/packages/rs-sdk-ffi/src/sdk.rs b/packages/rs-sdk-ffi/src/sdk.rs index ae445c530a..aa53fa8fcc 100644 --- a/packages/rs-sdk-ffi/src/sdk.rs +++ b/packages/rs-sdk-ffi/src/sdk.rs @@ -4,7 +4,6 @@ use std::sync::{Arc, OnceLock}; use tokio::runtime::Runtime; use tracing::{debug, error, info, warn}; -use dash_sdk::dpp::dashcore::Network; use dash_sdk::dpp::serialization::PlatformDeserializableWithPotentialValidationFromVersionedStructure; use dash_sdk::sdk::AddressList; use dash_sdk::{Sdk, SdkBuilder}; @@ -12,7 +11,7 @@ use std::ffi::CStr; use std::str::FromStr; use crate::context_provider::{ContextProviderHandle, ContextProviderWrapper, CoreSDKHandle}; -use crate::types::{DashSDKConfig, DashSDKNetwork, SDKHandle}; +use crate::types::{DashSDKConfig, FFINetwork, Network, SDKHandle}; use crate::{DashSDKError, DashSDKErrorCode, DashSDKResult, FFIError}; /// Extended SDK configuration with context provider support @@ -106,13 +105,7 @@ pub unsafe extern "C" fn dash_sdk_create(config: *const DashSDKConfig) -> DashSD let config = &*config; // Parse configuration - let network = match config.network { - DashSDKNetwork::SDKMainnet => Network::Mainnet, - DashSDKNetwork::SDKTestnet => Network::Testnet, - DashSDKNetwork::SDKRegtest => Network::Regtest, - DashSDKNetwork::SDKDevnet => Network::Devnet, - DashSDKNetwork::SDKLocal => Network::Regtest, - }; + let network: Network = config.network.into(); // Use shared runtime let runtime = match init_or_get_runtime() { @@ -195,13 +188,7 @@ pub unsafe extern "C" fn dash_sdk_create_extended( let base_config = &config.base_config; // Parse configuration - let network = match base_config.network { - DashSDKNetwork::SDKMainnet => Network::Mainnet, - DashSDKNetwork::SDKTestnet => Network::Testnet, - DashSDKNetwork::SDKRegtest => Network::Regtest, - DashSDKNetwork::SDKDevnet => Network::Devnet, - DashSDKNetwork::SDKLocal => Network::Regtest, - }; + let network: Network = base_config.network.into(); // Use shared runtime let runtime = match init_or_get_runtime() { @@ -309,13 +296,7 @@ pub unsafe extern "C" fn dash_sdk_create_trusted(config: *const DashSDKConfig) - let config = &*config; // Parse configuration - let network = match config.network { - DashSDKNetwork::SDKMainnet => Network::Mainnet, - DashSDKNetwork::SDKTestnet => Network::Testnet, - DashSDKNetwork::SDKRegtest => Network::Regtest, - DashSDKNetwork::SDKDevnet => Network::Devnet, - DashSDKNetwork::SDKLocal => Network::Regtest, - }; + let network: Network = config.network.into(); // Use shared runtime let runtime = match init_or_get_runtime() { @@ -331,11 +312,8 @@ pub unsafe extern "C" fn dash_sdk_create_trusted(config: *const DashSDKConfig) - ); // Create trusted context provider - // For local/regtest, use the quorum sidecar at localhost:22444 (dashmate Docker default) - let is_local = matches!( - config.network, - DashSDKNetwork::SDKLocal | DashSDKNetwork::SDKRegtest - ); + // For regtest, use the quorum sidecar at localhost:22444 (dashmate Docker default) + let is_local = matches!(network, Network::Regtest); let trusted_provider = if is_local { info!("dash_sdk_create_trusted: using local quorum sidecar for regtest"); match rs_sdk_trusted_context_provider::TrustedHttpContextProvider::new_with_url( @@ -614,18 +592,13 @@ pub unsafe extern "C" fn dash_sdk_create_with_callbacks( /// # Safety /// - `handle` must be a valid pointer to an SDKHandle (or null, in which case a default is returned). #[no_mangle] -pub unsafe extern "C" fn dash_sdk_get_network(handle: *const SDKHandle) -> DashSDKNetwork { +pub unsafe extern "C" fn dash_sdk_get_network(handle: *const SDKHandle) -> FFINetwork { if handle.is_null() { - return DashSDKNetwork::SDKMainnet; + return FFINetwork::Mainnet; } let wrapper = &*(handle as *const SDKWrapper); - match wrapper.sdk.network { - Network::Mainnet => DashSDKNetwork::SDKMainnet, - Network::Testnet => DashSDKNetwork::SDKTestnet, - Network::Regtest => DashSDKNetwork::SDKRegtest, - Network::Devnet => DashSDKNetwork::SDKDevnet, - } + wrapper.sdk.network.into() } /// Add known contracts to the SDK's trusted context provider diff --git a/packages/rs-sdk-ffi/src/signer_simple.rs b/packages/rs-sdk-ffi/src/signer_simple.rs index 4592da879e..71a61ffacd 100644 --- a/packages/rs-sdk-ffi/src/signer_simple.rs +++ b/packages/rs-sdk-ffi/src/signer_simple.rs @@ -1,9 +1,8 @@ //! Simple private key signer for iOS FFI use crate::signer::{signer_handle_from_single_key, VTableSigner}; -use crate::types::{DashSDKNetwork, SignerHandle}; +use crate::types::{FFINetwork, Network, SignerHandle}; use crate::{DashSDKError, DashSDKErrorCode, DashSDKResult}; -use dash_sdk::dpp::dashcore::Network; use dash_sdk::dpp::identity::signer::Signer; use dash_sdk::dpp::identity::{IdentityPublicKey, KeyType, Purpose, SecurityLevel}; use simple_signer::SingleKeySigner; @@ -70,7 +69,7 @@ pub(crate) fn parse_mnemonic_any_language( pub unsafe extern "C" fn dash_sdk_signer_create_from_private_key( private_key: *const u8, private_key_len: usize, - network: DashSDKNetwork, + network: FFINetwork, ) -> DashSDKResult { if private_key.is_null() { return DashSDKResult::error(DashSDKError::new( @@ -86,14 +85,7 @@ pub unsafe extern "C" fn dash_sdk_signer_create_from_private_key( )); } - // Map the C-ABI network enum to dashcore::Network (mirrors sdk.rs). - let network = match network { - DashSDKNetwork::SDKMainnet => Network::Mainnet, - DashSDKNetwork::SDKTestnet => Network::Testnet, - DashSDKNetwork::SDKRegtest => Network::Regtest, - DashSDKNetwork::SDKDevnet => Network::Devnet, - DashSDKNetwork::SDKLocal => Network::Regtest, - }; + let network: Network = network.into(); // Copy into a zeroizing buffer so the key material doesn't linger on // the stack after we hand it off to SingleKeySigner. @@ -273,7 +265,6 @@ pub const SIGN_WITH_MNEMONIC_ERR_UNSUPPORTED_KEY_TYPE: u8 = 8; /// network-independent (BIP-32 derivation only uses `network` as a /// tag on the `ExtendedPrivKey`), but we thread it through so the /// type matches every other key-derivation entry point in this crate. -/// Mirrors [`DashSDKNetwork`] used elsewhere in `signer_simple.rs`. /// /// On any failure the function writes a non-zero tag into `*out_error`, /// zeroes the first `out_signature_capacity` bytes of `out_signature`, @@ -300,7 +291,7 @@ pub unsafe extern "C" fn dash_sdk_sign_with_mnemonic_and_path( data: *const u8, data_len: usize, key_type: u8, - network: DashSDKNetwork, + network: FFINetwork, out_signature: *mut u8, out_signature_capacity: usize, out_signature_len: *mut usize, @@ -384,18 +375,10 @@ pub unsafe extern "C" fn dash_sdk_sign_with_mnemonic_and_path( Err(_) => return fail(SIGN_WITH_MNEMONIC_ERR_INVALID_PATH), }; - // Map the C-ABI network enum to dashcore::Network. Mirrors the - // mapping used in `dash_sdk_signer_create_from_private_key` above. - let dashcore_network = match network { - DashSDKNetwork::SDKMainnet => dash_sdk::dpp::dashcore::Network::Mainnet, - DashSDKNetwork::SDKTestnet => dash_sdk::dpp::dashcore::Network::Testnet, - DashSDKNetwork::SDKRegtest => dash_sdk::dpp::dashcore::Network::Regtest, - DashSDKNetwork::SDKDevnet => dash_sdk::dpp::dashcore::Network::Devnet, - DashSDKNetwork::SDKLocal => dash_sdk::dpp::dashcore::Network::Regtest, - }; + let network: Network = network.into(); // ---- Derive ECDSA private key at path ----------------------------------- - let master = match ExtendedPrivKey::new_master(dashcore_network, seed.as_ref()) { + let master = match ExtendedPrivKey::new_master(network, seed.as_ref()) { Ok(m) => m, Err(_) => return fail(SIGN_WITH_MNEMONIC_ERR_DERIVATION), }; diff --git a/packages/rs-sdk-ffi/src/system/queries/platform_status.rs b/packages/rs-sdk-ffi/src/system/queries/platform_status.rs index 220c1536ef..1e2da19140 100644 --- a/packages/rs-sdk-ffi/src/system/queries/platform_status.rs +++ b/packages/rs-sdk-ffi/src/system/queries/platform_status.rs @@ -60,13 +60,7 @@ fn get_platform_status(sdk_handle: *const SDKHandle) -> Result { let wrapper = unsafe { &*(sdk_handle as *const crate::sdk::SDKWrapper) }; let sdk = wrapper.sdk.clone(); - // Get network - let network_str = match sdk.network { - dash_sdk::dpp::dashcore::Network::Mainnet => "mainnet", - dash_sdk::dpp::dashcore::Network::Testnet => "testnet", - dash_sdk::dpp::dashcore::Network::Devnet => "devnet", - dash_sdk::dpp::dashcore::Network::Regtest => "regtest", - }; + let network_str = sdk.network.to_string(); rt.block_on(async move { // Query for the most recent epoch diff --git a/packages/rs-sdk-ffi/src/system/status.rs b/packages/rs-sdk-ffi/src/system/status.rs index 7df92134fd..6d52e042e1 100644 --- a/packages/rs-sdk-ffi/src/system/status.rs +++ b/packages/rs-sdk-ffi/src/system/status.rs @@ -28,13 +28,7 @@ pub unsafe extern "C" fn dash_sdk_get_status(sdk_handle: *const SDKHandle) -> Da let wrapper = &*(sdk_handle as *const SDKWrapper); tracing::debug!("dash_sdk_get_status: got SDK wrapper"); - // Get network - let network_str = match wrapper.sdk.network { - dash_sdk::dpp::dashcore::Network::Mainnet => "mainnet", - dash_sdk::dpp::dashcore::Network::Testnet => "testnet", - dash_sdk::dpp::dashcore::Network::Devnet => "devnet", - dash_sdk::dpp::dashcore::Network::Regtest => "regtest", - }; + let network_str = wrapper.sdk.network.to_string(); // Determine mode based on whether we have a trusted provider let (mode, quorum_count) = if let Some(ref provider) = wrapper.trusted_provider { diff --git a/packages/rs-sdk-ffi/src/token/claim.rs b/packages/rs-sdk-ffi/src/token/claim.rs index 627d339e05..a6c6ab80eb 100644 --- a/packages/rs-sdk-ffi/src/token/claim.rs +++ b/packages/rs-sdk-ffi/src/token/claim.rs @@ -198,7 +198,7 @@ mod tests { // Helper function to create a mock SDK handle fn create_mock_sdk_handle() -> *mut SDKHandle { let config = DashSDKConfig { - network: crate::types::DashSDKNetwork::SDKLocal, + network: crate::types::FFINetwork::Regtest, dapi_addresses: ptr::null(), // Use mock SDK skip_asset_lock_proof_verification: false, request_retry_count: 3, diff --git a/packages/rs-sdk-ffi/src/token/emergency_action.rs b/packages/rs-sdk-ffi/src/token/emergency_action.rs index 52dd6e308b..391bc090f4 100644 --- a/packages/rs-sdk-ffi/src/token/emergency_action.rs +++ b/packages/rs-sdk-ffi/src/token/emergency_action.rs @@ -205,7 +205,7 @@ mod tests { // Helper function to create a mock SDK handle fn create_mock_sdk_handle() -> *mut SDKHandle { let config = DashSDKConfig { - network: crate::types::DashSDKNetwork::SDKLocal, + network: crate::types::FFINetwork::Regtest, dapi_addresses: ptr::null(), // Use mock SDK skip_asset_lock_proof_verification: false, request_retry_count: 3, diff --git a/packages/rs-sdk-ffi/src/token/freeze.rs b/packages/rs-sdk-ffi/src/token/freeze.rs index d13bccf771..b7a1fcd5cd 100644 --- a/packages/rs-sdk-ffi/src/token/freeze.rs +++ b/packages/rs-sdk-ffi/src/token/freeze.rs @@ -207,7 +207,7 @@ mod tests { // Helper function to create a mock SDK handle fn create_mock_sdk_handle() -> *mut SDKHandle { let config = DashSDKConfig { - network: crate::types::DashSDKNetwork::SDKLocal, + network: crate::types::FFINetwork::Regtest, dapi_addresses: ptr::null(), // Use mock SDK skip_asset_lock_proof_verification: false, request_retry_count: 3, diff --git a/packages/rs-sdk-ffi/src/types.rs b/packages/rs-sdk-ffi/src/types.rs index b55a0a6157..0f57d4bda6 100644 --- a/packages/rs-sdk-ffi/src/types.rs +++ b/packages/rs-sdk-ffi/src/types.rs @@ -35,21 +35,13 @@ pub struct IdentityPublicKeyHandle { /// Alias for compatibility pub type DashSDKPublicKeyHandle = IdentityPublicKeyHandle; -/// Network type for SDK configuration -#[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum DashSDKNetwork { - /// Mainnet - SDKMainnet = 0, - /// Testnet - SDKTestnet = 1, - /// Regtest - SDKRegtest = 2, - /// Devnet - SDKDevnet = 3, - /// Local development network - SDKLocal = 4, -} +// Single source of truth for the network type across the Rust-side +// SDK and the FFI boundary. `Network` is the typed enum; `FFINetwork` +// is the `#[repr(C)]` mirror cbindgen emits for callers. Every FFI +// entry point in this crate takes / returns `FFINetwork`; internal +// Rust code converts via `Network::from(ffi)` / `ffi.into()`. +pub use dash_network::ffi::FFINetwork; +pub use dash_network::Network; /// SDK configuration passed from C callers. /// @@ -67,7 +59,7 @@ pub enum DashSDKNetwork { #[repr(C)] pub struct DashSDKConfig { /// Network to connect to - pub network: DashSDKNetwork, + pub network: FFINetwork, /// Comma-separated list of DAPI addresses (e.g., "http://127.0.0.1:3000,http://127.0.0.1:3001") /// If null or empty, will use mock SDK. /// diff --git a/packages/rs-sdk-ffi/test_header.h b/packages/rs-sdk-ffi/test_header.h deleted file mode 100644 index 928c7bbb6c..0000000000 --- a/packages/rs-sdk-ffi/test_header.h +++ /dev/null @@ -1,1703 +0,0 @@ -#ifndef DASH_SDK_FFI_H -#define DASH_SDK_FFI_H - -#pragma once - -/* Generated with cbindgen:0.29.0 */ - -/* This file is auto-generated. Do not modify manually. */ - -#include -#include -#include -#include -#include -#include - -// Authorized action takers for token operations -typedef enum DashSDKAuthorizedActionTakers { - // No one can perform the action - DashSDKAuthorizedActionTakers_NoOne = 0, - // Only the contract owner can perform the action - DashSDKAuthorizedActionTakers_AuthorizedContractOwner = 1, - // Main group can perform the action - DashSDKAuthorizedActionTakers_MainGroup = 2, - // A specific identity (requires identity_id to be set) - DashSDKAuthorizedActionTakers_Identity = 3, - // A specific group (requires group_position to be set) - DashSDKAuthorizedActionTakers_Group = 4, -} DashSDKAuthorizedActionTakers; - -// Error codes returned by FFI functions -typedef enum DashSDKErrorCode { - // Operation completed successfully - DashSDKErrorCode_Success = 0, - // Invalid parameter passed to function - DashSDKErrorCode_InvalidParameter = 1, - // SDK not initialized or in invalid state - DashSDKErrorCode_InvalidState = 2, - // Network error occurred - DashSDKErrorCode_NetworkError = 3, - // Serialization/deserialization error - DashSDKErrorCode_SerializationError = 4, - // Platform protocol error - DashSDKErrorCode_ProtocolError = 5, - // Cryptographic operation failed - DashSDKErrorCode_CryptoError = 6, - // Resource not found - DashSDKErrorCode_NotFound = 7, - // Operation timed out - DashSDKErrorCode_Timeout = 8, - // Feature not implemented - DashSDKErrorCode_NotImplemented = 9, - // Internal error - DashSDKErrorCode_InternalError = 99, -} DashSDKErrorCode; - -// Gas fees payer option -typedef enum DashSDKGasFeesPaidBy { - // The document owner pays the gas fees - DashSDKGasFeesPaidBy_DocumentOwner = 0, - // The contract owner pays the gas fees - DashSDKGasFeesPaidBy_GasFeesContractOwner = 1, - // Prefer contract owner but fallback to document owner if insufficient balance - DashSDKGasFeesPaidBy_GasFeesPreferContractOwner = 2, -} DashSDKGasFeesPaidBy; - -// Network type for SDK configuration -typedef enum DashSDKNetwork { - // Mainnet - DashSDKNetwork_Mainnet = 0, - // Testnet - DashSDKNetwork_Testnet = 1, - // Devnet - DashSDKNetwork_Devnet = 2, - // Local development network - DashSDKNetwork_Local = 3, -} DashSDKNetwork; - -// Result data type indicator for iOS -typedef enum DashSDKResultDataType { - // No data (void/null) - DashSDKResultDataType_None = 0, - // C string (char*) - DashSDKResultDataType_String = 1, - // Binary data with length - DashSDKResultDataType_BinaryData = 2, - // Identity handle - DashSDKResultDataType_ResultIdentityHandle = 3, - // Document handle - DashSDKResultDataType_ResultDocumentHandle = 4, - // Data contract handle - DashSDKResultDataType_ResultDataContractHandle = 5, - // Map of identity IDs to balances - DashSDKResultDataType_IdentityBalanceMap = 6, -} DashSDKResultDataType; - -// Token configuration update type -typedef enum DashSDKTokenConfigUpdateType { - // No change - DashSDKTokenConfigUpdateType_NoChange = 0, - // Update max supply (requires amount field) - DashSDKTokenConfigUpdateType_MaxSupply = 1, - // Update minting allow choosing destination (requires bool_value field) - DashSDKTokenConfigUpdateType_MintingAllowChoosingDestination = 2, - // Update new tokens destination identity (requires identity_id field) - DashSDKTokenConfigUpdateType_NewTokensDestinationIdentity = 3, - // Update manual minting permissions (requires action_takers field) - DashSDKTokenConfigUpdateType_ManualMinting = 4, - // Update manual burning permissions (requires action_takers field) - DashSDKTokenConfigUpdateType_ManualBurning = 5, - // Update freeze permissions (requires action_takers field) - DashSDKTokenConfigUpdateType_Freeze = 6, - // Update unfreeze permissions (requires action_takers field) - DashSDKTokenConfigUpdateType_Unfreeze = 7, - // Update main control group (requires group_position field) - DashSDKTokenConfigUpdateType_MainControlGroup = 8, -} DashSDKTokenConfigUpdateType; - -// Token distribution type for claim operations -typedef enum DashSDKTokenDistributionType { - // Pre-programmed distribution - DashSDKTokenDistributionType_PreProgrammed = 0, - // Perpetual distribution - DashSDKTokenDistributionType_Perpetual = 1, -} DashSDKTokenDistributionType; - -// Token emergency action type -typedef enum DashSDKTokenEmergencyAction { - // Pause token operations - DashSDKTokenEmergencyAction_Pause = 0, - // Resume token operations - DashSDKTokenEmergencyAction_Resume = 1, -} DashSDKTokenEmergencyAction; - -// Token pricing type -typedef enum DashSDKTokenPricingType { - // Single flat price for all amounts - DashSDKTokenPricingType_SinglePrice = 0, - // Tiered pricing based on amounts - DashSDKTokenPricingType_SetPrices = 1, -} DashSDKTokenPricingType; - -// Opaque handle to a DataContract -typedef struct DataContractHandle DataContractHandle; - -// Opaque handle to a Document -typedef struct DocumentHandle DocumentHandle; - -// Opaque handle to an Identity -typedef struct IdentityHandle IdentityHandle; - -// Opaque handle to an IdentityPublicKey -typedef struct IdentityPublicKeyHandle IdentityPublicKeyHandle; - -// Opaque handle to an SDK instance -typedef struct dash_sdk_handle_t dash_sdk_handle_t; - -// Opaque handle to a Signer -typedef struct SignerHandle SignerHandle; - -// Error structure returned by FFI functions -typedef struct DashSDKError { - // Error code - enum DashSDKErrorCode code; - // Human-readable error message (null-terminated C string) - // Caller must free this with dash_sdk_error_free - char *message; -} DashSDKError; - -// Result type for FFI functions that return data -typedef struct DashSDKResult { - // Type of data being returned - enum DashSDKResultDataType data_type; - // Pointer to the result data (null on error) - void *data; - // Error information (null on success) - struct DashSDKError *error; -} DashSDKResult; - -// Opaque handle to a context provider -typedef struct ContextProviderHandle { - uint8_t private_[0]; -} ContextProviderHandle; - -typedef struct FFIDashSpvClient { - uint8_t opaque[0]; -} FFIDashSpvClient; - -// Handle for Core SDK that can be passed to Platform SDK -// This matches the definition from dash_spv_ffi.h -typedef struct CoreSDKHandle { - struct FFIDashSpvClient *client; -} CoreSDKHandle; - -// Result type for FFI callbacks -typedef struct CallbackResult { - bool success; - int32_t error_code; - const char *error_message; -} CallbackResult; - -// Function pointer type for getting platform activation height -typedef struct CallbackResult (*GetPlatformActivationHeightFn)(void *handle, uint32_t *out_height); - -// Function pointer type for getting quorum public key -typedef struct CallbackResult (*GetQuorumPublicKeyFn)(void *handle, uint32_t quorum_type, const uint8_t *quorum_hash, uint32_t core_chain_locked_height, uint8_t *out_pubkey); - -// Container for context provider callbacks -typedef struct ContextProviderCallbacks { - // Handle to the Core SDK instance - void *core_handle; - // Function to get platform activation height - GetPlatformActivationHeightFn get_platform_activation_height; - // Function to get quorum public key - GetQuorumPublicKeyFn get_quorum_public_key; -} ContextProviderCallbacks; - -// Document creation parameters -typedef struct DashSDKDocumentCreateParams { - // Data contract handle - const struct DataContractHandle *data_contract_handle; - // Document type name - const char *document_type; - // Owner identity handle - const struct IdentityHandle *owner_identity_handle; - // JSON string of document properties - const char *properties_json; -} DashSDKDocumentCreateParams; - -// Token payment information for transactions -typedef struct DashSDKTokenPaymentInfo { - // Payment token contract ID (32 bytes), null for same contract - const uint8_t (*payment_token_contract_id)[32]; - // Token position within the contract (0-based index) - uint16_t token_contract_position; - // Minimum token cost (0 means no minimum) - uint64_t minimum_token_cost; - // Maximum token cost (0 means no maximum) - uint64_t maximum_token_cost; - // Who pays the gas fees - enum DashSDKGasFeesPaidBy gas_fees_paid_by; -} DashSDKTokenPaymentInfo; - -// Put settings for platform operations -typedef struct DashSDKPutSettings { - // Timeout for establishing a connection (milliseconds), 0 means use default - uint64_t connect_timeout_ms; - // Timeout for single request (milliseconds), 0 means use default - uint64_t timeout_ms; - // Number of retries in case of failed requests, 0 means use default - uint32_t retries; - // Ban DAPI address if node not responded or responded with error - bool ban_failed_address; - // Identity nonce stale time in seconds, 0 means use default - uint64_t identity_nonce_stale_time_s; - // User fee increase (additional percentage of processing fee), 0 means no increase - uint16_t user_fee_increase; - // Enable signing with any security level (for debugging) - bool allow_signing_with_any_security_level; - // Enable signing with any purpose (for debugging) - bool allow_signing_with_any_purpose; - // Wait timeout in milliseconds, 0 means use default - uint64_t wait_timeout_ms; -} DashSDKPutSettings; - -// State transition creation options for advanced use cases -typedef struct DashSDKStateTransitionCreationOptions { - // Allow signing with any security level (for debugging) - bool allow_signing_with_any_security_level; - // Allow signing with any purpose (for debugging) - bool allow_signing_with_any_purpose; - // Batch feature version (0 means use default) - uint16_t batch_feature_version; - // Method feature version (0 means use default) - uint16_t method_feature_version; - // Base feature version (0 means use default) - uint16_t base_feature_version; -} DashSDKStateTransitionCreationOptions; - -// Document information -typedef struct DashSDKDocumentInfo { - // Document ID as hex string (null-terminated) - char *id; - // Owner ID as hex string (null-terminated) - char *owner_id; - // Data contract ID as hex string (null-terminated) - char *data_contract_id; - // Document type (null-terminated) - char *document_type; - // Revision number - uint64_t revision; - // Created at timestamp (milliseconds since epoch) - int64_t created_at; - // Updated at timestamp (milliseconds since epoch) - int64_t updated_at; -} DashSDKDocumentInfo; - -// Document search parameters -typedef struct DashSDKDocumentSearchParams { - // Data contract handle - const struct DataContractHandle *data_contract_handle; - // Document type name - const char *document_type; - // JSON string of where clauses (optional) - const char *where_json; - // JSON string of order by clauses (optional) - const char *order_by_json; - // Limit number of results (0 = default) - uint32_t limit; - // Start from index (for pagination) - uint32_t start_at; -} DashSDKDocumentSearchParams; - -// Identity information -typedef struct DashSDKIdentityInfo { - // Identity ID as hex string (null-terminated) - char *id; - // Balance in credits - uint64_t balance; - // Revision number - uint64_t revision; - // Public keys count - uint32_t public_keys_count; -} DashSDKIdentityInfo; - -// Result structure for credit transfer operations -typedef struct DashSDKTransferCreditsResult { - // Sender's final balance after transfer - uint64_t sender_balance; - // Receiver's final balance after transfer - uint64_t receiver_balance; -} DashSDKTransferCreditsResult; - -// SDK configuration -typedef struct DashSDKConfig { - // Network to connect to - enum DashSDKNetwork network; - // Comma-separated list of DAPI addresses (e.g., "http://127.0.0.1:3000,http://127.0.0.1:3001") - // If null or empty, will use mock SDK - const char *dapi_addresses; - // Skip asset lock proof verification (for testing) - bool skip_asset_lock_proof_verification; - // Number of retries for failed requests - uint32_t request_retry_count; - // Timeout for requests in milliseconds - uint64_t request_timeout_ms; -} DashSDKConfig; - -// Extended SDK configuration with context provider support -typedef struct DashSDKConfigExtended { - // Base SDK configuration - struct DashSDKConfig base_config; - // Optional context provider handle - struct ContextProviderHandle *context_provider; - // Optional Core SDK handle for automatic context provider creation - struct CoreSDKHandle *core_sdk_handle; -} DashSDKConfigExtended; - -// Function pointer type for iOS signing callback -// Returns pointer to allocated byte array (caller must free with dash_sdk_bytes_free) -// Returns null on error -typedef uint8_t *(*IOSSignCallback)(const uint8_t *identity_public_key_bytes, uintptr_t identity_public_key_len, const uint8_t *data, uintptr_t data_len, uintptr_t *result_len); - -// Function pointer type for iOS can_sign_with callback -typedef bool (*IOSCanSignCallback)(const uint8_t *identity_public_key_bytes, uintptr_t identity_public_key_len); - -// Optional custom deallocator for sign result buffers. -// When provided, this function is called to free the buffer returned by the -// sign callback instead of the default libc free. Pass NULL to use libc free. -typedef void (*FreeResultCallback)(uint8_t *data, uintptr_t len); - -// Token burn parameters -typedef struct DashSDKTokenBurnParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // Amount to burn - uint64_t amount; - // Optional public note - const char *public_note; -} DashSDKTokenBurnParams; - -// Token claim parameters -typedef struct DashSDKTokenClaimParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // Distribution type (PreProgrammed or Perpetual) - enum DashSDKTokenDistributionType distribution_type; - // Optional public note - const char *public_note; -} DashSDKTokenClaimParams; - -// Token mint parameters -typedef struct DashSDKTokenMintParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // Recipient identity ID (32 bytes) - optional - const uint8_t *recipient_id; - // Amount to mint - uint64_t amount; - // Optional public note - const char *public_note; -} DashSDKTokenMintParams; - -// Token transfer parameters -typedef struct DashSDKTokenTransferParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // Recipient identity ID (32 bytes) - const uint8_t *recipient_id; - // Amount to transfer - uint64_t amount; - // Optional public note - const char *public_note; - // Optional private encrypted note - const char *private_encrypted_note; - // Optional shared encrypted note - const char *shared_encrypted_note; -} DashSDKTokenTransferParams; - -// Token configuration update parameters -typedef struct DashSDKTokenConfigUpdateParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // The type of configuration update - enum DashSDKTokenConfigUpdateType update_type; - // For MaxSupply updates - the new max supply (0 for no limit) - uint64_t amount; - // For boolean updates like MintingAllowChoosingDestination - bool bool_value; - // For identity-based updates - identity ID (32 bytes) - const uint8_t *identity_id; - // For group-based updates - the group position - uint16_t group_position; - // For permission updates - the authorized action takers - enum DashSDKAuthorizedActionTakers action_takers; - // Optional public note - const char *public_note; -} DashSDKTokenConfigUpdateParams; - -// Token destroy frozen funds parameters -typedef struct DashSDKTokenDestroyFrozenFundsParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // The frozen identity whose funds to destroy (32 bytes) - const uint8_t *frozen_identity_id; - // Optional public note - const char *public_note; -} DashSDKTokenDestroyFrozenFundsParams; - -// Token emergency action parameters -typedef struct DashSDKTokenEmergencyActionParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // The emergency action to perform - enum DashSDKTokenEmergencyAction action; - // Optional public note - const char *public_note; -} DashSDKTokenEmergencyActionParams; - -// Token freeze/unfreeze parameters -typedef struct DashSDKTokenFreezeParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // The identity to freeze/unfreeze (32 bytes) - const uint8_t *target_identity_id; - // Optional public note - const char *public_note; -} DashSDKTokenFreezeParams; - -// Token purchase parameters -typedef struct DashSDKTokenPurchaseParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // Amount of tokens to purchase - uint64_t amount; - // Total agreed price in credits - uint64_t total_agreed_price; -} DashSDKTokenPurchaseParams; - -// Token price entry for tiered pricing -typedef struct DashSDKTokenPriceEntry { - // Token amount threshold - uint64_t amount; - // Price in credits for this amount - uint64_t price; -} DashSDKTokenPriceEntry; - -// Token set price parameters -typedef struct DashSDKTokenSetPriceParams { - // Token contract ID (Base58 encoded) - mutually exclusive with serialized_contract - const char *token_contract_id; - // Serialized data contract (bincode) - mutually exclusive with token_contract_id - const uint8_t *serialized_contract; - // Length of serialized contract data - uintptr_t serialized_contract_len; - // Token position in the contract (defaults to 0 if not specified) - uint16_t token_position; - // Pricing type - enum DashSDKTokenPricingType pricing_type; - // For SinglePrice - the price in credits (ignored for SetPrices) - uint64_t single_price; - // For SetPrices - array of price entries (ignored for SinglePrice) - const struct DashSDKTokenPriceEntry *price_entries; - // Number of price entries - uint32_t price_entries_count; - // Optional public note - const char *public_note; -} DashSDKTokenSetPriceParams; - -// Binary data container for results -typedef struct DashSDKBinaryData { - // Pointer to the data - uint8_t *data; - // Length of the data - uintptr_t len; -} DashSDKBinaryData; - -// Single entry in an identity balance map -typedef struct DashSDKIdentityBalanceEntry { - // Identity ID (32 bytes) - uint8_t identity_id[32]; - // Balance in credits (u64::MAX means identity not found) - uint64_t balance; -} DashSDKIdentityBalanceEntry; - -// Map of identity IDs to balances -typedef struct DashSDKIdentityBalanceMap { - // Array of entries - struct DashSDKIdentityBalanceEntry *entries; - // Number of entries - uintptr_t count; -} DashSDKIdentityBalanceMap; - -// Unified SDK handle containing both Core and Platform SDKs -typedef struct UnifiedSDKHandle { - CoreSDKClient *core_client; - struct dash_sdk_handle_t *platform_sdk; - bool integration_enabled; -} UnifiedSDKHandle; - -// Unified SDK configuration combining both Core and Platform settings -typedef struct UnifiedSDKConfig { - // Core SDK configuration (ignored if core feature disabled) - CoreSDKConfig core_config; - // Platform SDK configuration - struct DashSDKConfig platform_config; - // Whether to enable cross-layer integration - bool enable_integration; -} UnifiedSDKConfig; - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -// Initialize the FFI library. -// This should be called once at app startup before using any other functions. - void dash_sdk_init(void) ; - -// Get the version of the Dash SDK FFI library - const char *dash_sdk_version(void) ; - -// Register Core SDK handle and setup callback bridge with Platform SDK -// -// This function implements the core pattern from dash-unified-ffi-old: -// 1. Takes a Core SDK handle -// 2. Creates callback wrappers for the functions Platform SDK needs -// 3. Registers these callbacks with Platform SDK's context provider system -// -// # Safety -// - `core_handle` must be a valid Core SDK handle that remains valid for the SDK lifetime -// - This function should be called once after creating both Core and Platform SDK instances - int32_t dash_unified_register_core_sdk_handle(void *core_handle) ; - -// Initialize the unified SDK system with callback bridge support -// -// This function initializes both Core SDK and Platform SDK and sets up -// the callback bridge pattern for inter-SDK communication. - int32_t dash_unified_init(void) ; - -// Get unified SDK version information including both Core and Platform components - const char *dash_unified_version(void) ; - -// Check if unified SDK has both Core and Platform support - bool dash_unified_has_full_support(void) ; - -// Fetches contested resource identity votes -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `identity_id` - Base58-encoded identity identifier -// * `limit` - Maximum number of votes to return (optional, 0 for no limit) -// * `offset` - Number of votes to skip (optional, 0 for no offset) -// * `order_ascending` - Whether to order results in ascending order -// -// # Returns -// * JSON array of votes or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_contested_resource_get_identity_votes(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id, uint32_t limit, uint32_t offset, bool order_ascending) ; - -// Fetches contested resources -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `contract_id` - Base58-encoded contract identifier -// * `document_type_name` - Name of the document type -// * `index_name` - Name of the index -// * `start_index_values_json` - JSON array of hex-encoded start index values -// * `end_index_values_json` - JSON array of hex-encoded end index values -// * `count` - Maximum number of resources to return -// * `order_ascending` - Whether to order results in ascending order -// -// # Returns -// * JSON array of contested resources or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_contested_resource_get_resources(const struct dash_sdk_handle_t *sdk_handle, const char *contract_id, const char *document_type_name, const char *index_name, const char *start_index_values_json, const char *end_index_values_json, uint32_t count, bool order_ascending) ; - -// Fetches contested resource vote state -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `contract_id` - Base58-encoded contract identifier -// * `document_type_name` - Name of the document type -// * `index_name` - Name of the index -// * `index_values_json` - JSON array of hex-encoded index values -// * `result_type` - Result type (0=DOCUMENTS, 1=VOTE_TALLY, 2=DOCUMENTS_AND_VOTE_TALLY) -// * `allow_include_locked_and_abstaining_vote_tally` - Whether to include locked and abstaining votes -// * `count` - Maximum number of results to return -// -// # Returns -// * JSON array of contenders or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_contested_resource_get_vote_state(const struct dash_sdk_handle_t *sdk_handle, const char *contract_id, const char *document_type_name, const char *index_name, const char *index_values_json, uint8_t result_type, bool allow_include_locked_and_abstaining_vote_tally, uint32_t count) ; - -// Fetches voters for a contested resource identity -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `contract_id` - Base58-encoded contract identifier -// * `document_type_name` - Name of the document type -// * `index_name` - Name of the index -// * `index_values_json` - JSON array of hex-encoded index values -// * `contestant_id` - Base58-encoded contestant identifier -// * `count` - Maximum number of voters to return -// * `order_ascending` - Whether to order results in ascending order -// -// # Returns -// * JSON array of voters or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_contested_resource_get_voters_for_identity(const struct dash_sdk_handle_t *sdk_handle, const char *contract_id, const char *document_type_name, const char *index_name, const char *index_values_json, const char *contestant_id, uint32_t count, bool order_ascending) ; - -// Create a context provider from a Core SDK handle (DEPRECATED) -// -// This function is deprecated. Use dash_sdk_context_provider_from_callbacks instead. -// -// # Safety -// - `core_handle` must be a valid Core SDK handle -// - String parameters must be valid UTF-8 C strings or null - struct ContextProviderHandle *dash_sdk_context_provider_from_core(struct CoreSDKHandle *core_handle, const char *core_rpc_url, const char *core_rpc_user, const char *core_rpc_password) ; - -// Create a context provider from callbacks -// -// # Safety -// - `callbacks` must contain valid function pointers - struct ContextProviderHandle *dash_sdk_context_provider_from_callbacks(const struct ContextProviderCallbacks *callbacks) ; - -// Destroy a context provider handle -// -// # Safety -// - `handle` must be a valid context provider handle or null - void dash_sdk_context_provider_destroy(struct ContextProviderHandle *handle) ; - -// Initialize the Core SDK -// Returns 0 on success, error code on failure - int32_t dash_core_sdk_init(void) ; - -// Create a Core SDK client with testnet config -// -// # Safety -// - Returns null on failure - CoreSDKClient *dash_core_sdk_create_client_testnet(void) ; - -// Create a Core SDK client with mainnet config -// -// # Safety -// - Returns null on failure - CoreSDKClient *dash_core_sdk_create_client_mainnet(void) ; - -// Create a Core SDK client with custom config -// -// # Safety -// - `config` must be a valid CoreSDKConfig pointer -// - Returns null on failure - CoreSDKClient *dash_core_sdk_create_client(const CoreSDKConfig *config) ; - -// Destroy a Core SDK client -// -// # Safety -// - `client` must be a valid Core SDK client handle or null - void dash_core_sdk_destroy_client(CoreSDKClient *client) ; - -// Start the Core SDK client (begin sync) -// -// # Safety -// - `client` must be a valid Core SDK client handle - int32_t dash_core_sdk_start(CoreSDKClient *client) ; - -// Stop the Core SDK client -// -// # Safety -// - `client` must be a valid Core SDK client handle - int32_t dash_core_sdk_stop(CoreSDKClient *client) ; - -// Sync Core SDK client to tip -// -// # Safety -// - `client` must be a valid Core SDK client handle - int32_t dash_core_sdk_sync_to_tip(CoreSDKClient *client) ; - -// Get the current sync progress -// -// # Safety -// - `client` must be a valid Core SDK client handle -// - Returns pointer to FFISyncProgress structure (caller must free it) - FFISyncProgress *dash_core_sdk_get_sync_progress(CoreSDKClient *client) ; - -// Get Core SDK statistics -// -// # Safety -// - `client` must be a valid Core SDK client handle -// - Returns pointer to FFISpvStats structure (caller must free it) - FFISpvStats *dash_core_sdk_get_stats(CoreSDKClient *client) ; - -// Get the current block height -// -// # Safety -// - `client` must be a valid Core SDK client handle -// - `height` must point to a valid u32 - int32_t dash_core_sdk_get_block_height(CoreSDKClient *client, uint32_t *height) ; - -// Add an address to watch -// -// # Safety -// - `client` must be a valid Core SDK client handle -// - `address` must be a valid null-terminated C string - int32_t dash_core_sdk_watch_address(CoreSDKClient *client, const char *address) ; - -// Remove an address from watching -// -// # Safety -// - `client` must be a valid Core SDK client handle -// - `address` must be a valid null-terminated C string - int32_t dash_core_sdk_unwatch_address(CoreSDKClient *client, const char *address) ; - -// Get balance for all watched addresses -// -// # Safety -// - `client` must be a valid Core SDK client handle -// - Returns pointer to FFIBalance structure (caller must free it) - FFIBalance *dash_core_sdk_get_total_balance(CoreSDKClient *client) ; - -// Get platform activation height -// -// # Safety -// - `client` must be a valid Core SDK client handle -// - `height` must point to a valid u32 - int32_t dash_core_sdk_get_platform_activation_height(CoreSDKClient *client, uint32_t *height) ; - -// Get quorum public key -// -// # Safety -// - `client` must be a valid Core SDK client handle -// - `quorum_hash` must point to a valid 32-byte buffer -// - `public_key` must point to a valid 48-byte buffer - int32_t dash_core_sdk_get_quorum_public_key(CoreSDKClient *client, uint32_t quorum_type, const uint8_t *quorum_hash, uint32_t core_chain_locked_height, uint8_t *public_key, uintptr_t public_key_size) ; - -// Get Core SDK handle for platform integration -// -// # Safety -// - `client` must be a valid Core SDK client handle - struct CoreSDKHandle *dash_core_sdk_get_core_handle(CoreSDKClient *client) ; - -// Broadcast a transaction -// -// # Safety -// - `client` must be a valid Core SDK client handle -// - `transaction_hex` must be a valid null-terminated C string - int32_t dash_core_sdk_broadcast_transaction(CoreSDKClient *client, const char *transaction_hex) ; - -// Check if Core SDK feature is enabled at runtime - bool dash_core_sdk_is_enabled(void) ; - -// Get Core SDK version - const char *dash_core_sdk_version(void) ; - -// Create a new data contract - struct DashSDKResult dash_sdk_data_contract_create(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *owner_identity_handle, const char *documents_schema_json) ; - -// Destroy a data contract handle - void dash_sdk_data_contract_destroy(struct DataContractHandle *handle) ; - -// Put data contract to platform (broadcast state transition) - struct DashSDKResult dash_sdk_data_contract_put_to_platform(struct dash_sdk_handle_t *sdk_handle, const struct DataContractHandle *data_contract_handle, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle) ; - -// Put data contract to platform and wait for confirmation (broadcast state transition and wait for response) - struct DashSDKResult dash_sdk_data_contract_put_to_platform_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct DataContractHandle *data_contract_handle, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle) ; - -// Fetch a data contract by ID - struct DashSDKResult dash_sdk_data_contract_fetch(const struct dash_sdk_handle_t *sdk_handle, const char *contract_id) ; - -// Fetch multiple data contracts by their IDs -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `contract_ids`: Comma-separated list of Base58-encoded contract IDs -// -// # Returns -// JSON string containing contract IDs mapped to their data contracts - struct DashSDKResult dash_sdk_data_contracts_fetch_many(const struct dash_sdk_handle_t *sdk_handle, const char *contract_ids) ; - -// Fetch data contract history -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `contract_id`: Base58-encoded contract ID -// - `limit`: Maximum number of history entries to return (0 for default) -// - `offset`: Number of entries to skip (for pagination) -// - `start_at_ms`: Start timestamp in milliseconds (0 for beginning) -// -// # Returns -// JSON string containing the data contract history - struct DashSDKResult dash_sdk_data_contract_fetch_history(const struct dash_sdk_handle_t *sdk_handle, const char *contract_id, unsigned int limit, unsigned int offset, uint64_t start_at_ms) ; - -// Get schema for a specific document type - char *dash_sdk_data_contract_get_schema(const struct DataContractHandle *contract_handle, const char *document_type) ; - -// Create a new document - struct DashSDKResult dash_sdk_document_create(struct dash_sdk_handle_t *sdk_handle, const struct DashSDKDocumentCreateParams *params) ; - -// Delete a document from the platform - struct DashSDKResult dash_sdk_document_delete(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Delete a document from the platform and wait for confirmation - struct DashSDKResult dash_sdk_document_delete_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Update document price (broadcast state transition) - struct DashSDKResult dash_sdk_document_update_price_of_document(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, uint64_t price, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Update document price and wait for confirmation (broadcast state transition and wait for response) - struct DashSDKResult dash_sdk_document_update_price_of_document_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, uint64_t price, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Purchase document (broadcast state transition) - struct DashSDKResult dash_sdk_document_purchase(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, uint64_t price, const char *purchaser_id, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Purchase document and wait for confirmation (broadcast state transition and wait for response) - struct DashSDKResult dash_sdk_document_purchase_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, uint64_t price, const char *purchaser_id, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Put document to platform (broadcast state transition) - struct DashSDKResult dash_sdk_document_put_to_platform(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, const uint8_t (*entropy)[32], const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Put document to platform and wait for confirmation (broadcast state transition and wait for response) - struct DashSDKResult dash_sdk_document_put_to_platform_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, const uint8_t (*entropy)[32], const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Fetch a document by ID - struct DashSDKResult dash_sdk_document_fetch(const struct dash_sdk_handle_t *sdk_handle, const struct DataContractHandle *data_contract_handle, const char *document_type, const char *document_id) ; - -// Get document information - struct DashSDKDocumentInfo *dash_sdk_document_get_info(const struct DocumentHandle *document_handle) ; - -// Search for documents - struct DashSDKResult dash_sdk_document_search(const struct dash_sdk_handle_t *sdk_handle, const struct DashSDKDocumentSearchParams *params) ; - -// Replace document on platform (broadcast state transition) - struct DashSDKResult dash_sdk_document_replace_on_platform(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Replace document on platform and wait for confirmation (broadcast state transition and wait for response) - struct DashSDKResult dash_sdk_document_replace_on_platform_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const struct DataContractHandle *data_contract_handle, const char *document_type_name, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Transfer document to another identity -// -// # Parameters -// - `document_handle`: Handle to the document to transfer -// - `recipient_id`: Base58-encoded ID of the recipient identity -// - `data_contract_handle`: Handle to the data contract -// - `document_type_name`: Name of the document type -// - `identity_public_key_handle`: Public key for signing -// - `signer_handle`: Cryptographic signer -// - `token_payment_info`: Optional token payment information (can be null for defaults) -// - `put_settings`: Optional settings for the operation (can be null for defaults) -// -// # Returns -// Serialized state transition on success - struct DashSDKResult dash_sdk_document_transfer_to_identity(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const char *recipient_id, const struct DataContractHandle *data_contract_handle, const char *document_type_name, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Transfer document to another identity and wait for confirmation -// -// # Parameters -// - `document_handle`: Handle to the document to transfer -// - `recipient_id`: Base58-encoded ID of the recipient identity -// - `data_contract_handle`: Handle to the data contract -// - `document_type_name`: Name of the document type -// - `identity_public_key_handle`: Public key for signing -// - `signer_handle`: Cryptographic signer -// - `token_payment_info`: Optional token payment information (can be null for defaults) -// - `put_settings`: Optional settings for the operation (can be null for defaults) -// -// # Returns -// Handle to the transferred document on success - struct DashSDKResult dash_sdk_document_transfer_to_identity_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct DocumentHandle *document_handle, const char *recipient_id, const struct DataContractHandle *data_contract_handle, const char *document_type_name, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKTokenPaymentInfo *token_payment_info, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Destroy a document - struct DashSDKError *dash_sdk_document_destroy(struct dash_sdk_handle_t *sdk_handle, struct DocumentHandle *document_handle) ; - -// Destroy a document handle - void dash_sdk_document_handle_destroy(struct DocumentHandle *handle) ; - -// Free an error message - void dash_sdk_error_free(struct DashSDKError *error) ; - -// Fetches proposed epoch blocks by evonode IDs -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `epoch` - Epoch number (optional, 0 for current epoch) -// * `ids_json` - JSON array of hex-encoded evonode pro_tx_hash IDs -// -// # Returns -// * JSON array of evonode proposed block counts or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_evonode_get_proposed_epoch_blocks_by_ids(const struct dash_sdk_handle_t *sdk_handle, uint32_t epoch, const char *ids_json) ; - -// Fetches proposed epoch blocks by range -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `epoch` - Epoch number (optional, 0 for current epoch) -// * `limit` - Maximum number of results to return (optional, 0 for no limit) -// * `start_after` - Start after this pro_tx_hash (hex-encoded, optional) -// * `start_at` - Start at this pro_tx_hash (hex-encoded, optional) -// -// # Returns -// * JSON array of evonode proposed block counts or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_evonode_get_proposed_epoch_blocks_by_range(const struct dash_sdk_handle_t *sdk_handle, uint32_t epoch, uint32_t limit, const char *start_after, const char *start_at) ; - -// Fetches group action signers -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `contract_id` - Base58-encoded contract identifier -// * `group_contract_position` - Position of the group in the contract -// * `status` - Action status (0=Pending, 1=Completed, 2=Expired) -// * `action_id` - Base58-encoded action identifier -// -// # Returns -// * JSON array of signers or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_group_get_action_signers(const struct dash_sdk_handle_t *sdk_handle, const char *contract_id, uint16_t group_contract_position, uint8_t status, const char *action_id) ; - -// Fetches group actions -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `contract_id` - Base58-encoded contract identifier -// * `group_contract_position` - Position of the group in the contract -// * `status` - Action status (0=Pending, 1=Completed, 2=Expired) -// * `start_at_action_id` - Optional starting action ID (Base58-encoded) -// * `limit` - Maximum number of actions to return -// -// # Returns -// * JSON array of group actions or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_group_get_actions(const struct dash_sdk_handle_t *sdk_handle, const char *contract_id, uint16_t group_contract_position, uint8_t status, const char *start_at_action_id, uint16_t limit) ; - -// Fetches information about a group -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `contract_id` - Base58-encoded contract identifier -// * `group_contract_position` - Position of the group in the contract -// -// # Returns -// * JSON string with group information or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_group_get_info(const struct dash_sdk_handle_t *sdk_handle, const char *contract_id, uint16_t group_contract_position) ; - -// Fetches information about multiple groups -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `start_at_position` - Starting position (optional, null for beginning) -// * `limit` - Maximum number of groups to return -// -// # Returns -// * JSON array of group information or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_group_get_infos(const struct dash_sdk_handle_t *sdk_handle, const char *start_at_position, uint32_t limit) ; - -// Create a new identity - struct DashSDKResult dash_sdk_identity_create(struct dash_sdk_handle_t *sdk_handle) ; - -// Get identity information - struct DashSDKIdentityInfo *dash_sdk_identity_get_info(const struct IdentityHandle *identity_handle) ; - -// Destroy an identity handle - void dash_sdk_identity_destroy(struct IdentityHandle *handle) ; - -// Register a name for an identity - struct DashSDKError *dash_sdk_identity_register_name(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *identity_handle, const char *name) ; - -// Put identity to platform with instant lock proof -// -// # Parameters -// - `instant_lock_bytes`: Serialized InstantLock data -// - `transaction_bytes`: Serialized Transaction data -// - `output_index`: Index of the output in the transaction payload -// - `private_key`: 32-byte private key associated with the asset lock -// - `put_settings`: Optional settings for the operation (can be null for defaults) - struct DashSDKResult dash_sdk_identity_put_to_platform_with_instant_lock(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *identity_handle, const uint8_t *instant_lock_bytes, uintptr_t instant_lock_len, const uint8_t *transaction_bytes, uintptr_t transaction_len, uint32_t output_index, const uint8_t (*private_key)[32], const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings) ; - -// Put identity to platform with instant lock proof and wait for confirmation -// -// # Parameters -// - `instant_lock_bytes`: Serialized InstantLock data -// - `transaction_bytes`: Serialized Transaction data -// - `output_index`: Index of the output in the transaction payload -// - `private_key`: 32-byte private key associated with the asset lock -// - `put_settings`: Optional settings for the operation (can be null for defaults) -// -// # Returns -// Handle to the confirmed identity on success - struct DashSDKResult dash_sdk_identity_put_to_platform_with_instant_lock_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *identity_handle, const uint8_t *instant_lock_bytes, uintptr_t instant_lock_len, const uint8_t *transaction_bytes, uintptr_t transaction_len, uint32_t output_index, const uint8_t (*private_key)[32], const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings) ; - -// Put identity to platform with chain lock proof -// -// # Parameters -// - `core_chain_locked_height`: Core height at which the transaction was chain locked -// - `out_point`: 36-byte OutPoint (32-byte txid + 4-byte vout) -// - `private_key`: 32-byte private key associated with the asset lock -// - `put_settings`: Optional settings for the operation (can be null for defaults) - struct DashSDKResult dash_sdk_identity_put_to_platform_with_chain_lock(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *identity_handle, uint32_t core_chain_locked_height, const uint8_t (*out_point)[36], const uint8_t (*private_key)[32], const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings) ; - -// Put identity to platform with chain lock proof and wait for confirmation -// -// # Parameters -// - `core_chain_locked_height`: Core height at which the transaction was chain locked -// - `out_point`: 36-byte OutPoint (32-byte txid + 4-byte vout) -// - `private_key`: 32-byte private key associated with the asset lock -// - `put_settings`: Optional settings for the operation (can be null for defaults) -// -// # Returns -// Handle to the confirmed identity on success - struct DashSDKResult dash_sdk_identity_put_to_platform_with_chain_lock_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *identity_handle, uint32_t core_chain_locked_height, const uint8_t (*out_point)[36], const uint8_t (*private_key)[32], const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings) ; - -// Fetch identity balance -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_id`: Base58-encoded identity ID -// -// # Returns -// The balance of the identity as a string - struct DashSDKResult dash_sdk_identity_fetch_balance(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id) ; - -// Fetch identity balance and revision -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_id`: Base58-encoded identity ID -// -// # Returns -// JSON string containing the balance and revision information - struct DashSDKResult dash_sdk_identity_fetch_balance_and_revision(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id) ; - -// Fetch identity by non-unique public key hash with optional pagination -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `public_key_hash`: Hex-encoded 20-byte public key hash -// - `start_after`: Optional Base58-encoded identity ID to start after (for pagination) -// -// # Returns -// JSON string containing the identity information, or null if not found - struct DashSDKResult dash_sdk_identity_fetch_by_non_unique_public_key_hash(const struct dash_sdk_handle_t *sdk_handle, const char *public_key_hash, const char *start_after) ; - -// Fetch identity by public key hash -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `public_key_hash`: Hex-encoded 20-byte public key hash -// -// # Returns -// JSON string containing the identity information, or null if not found - struct DashSDKResult dash_sdk_identity_fetch_by_public_key_hash(const struct dash_sdk_handle_t *sdk_handle, const char *public_key_hash) ; - -// Fetch identity contract nonce -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_id`: Base58-encoded identity ID -// - `contract_id`: Base58-encoded contract ID -// -// # Returns -// The contract nonce of the identity as a string - struct DashSDKResult dash_sdk_identity_fetch_contract_nonce(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id, const char *contract_id) ; - -// Fetch an identity by ID - struct DashSDKResult dash_sdk_identity_fetch(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id) ; - -// Fetch balances for multiple identities -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_ids`: Array of identity IDs (32-byte arrays) -// - `identity_ids_len`: Number of identity IDs in the array -// -// # Returns -// DashSDKResult with data_type = IdentityBalanceMap containing identity IDs mapped to their balances - struct DashSDKResult dash_sdk_identities_fetch_balances(const struct dash_sdk_handle_t *sdk_handle, const uint8_t (*identity_ids)[32], uintptr_t identity_ids_len) ; - -// Fetch contract keys for multiple identities -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_ids`: Comma-separated list of Base58-encoded identity IDs -// - `contract_id`: Base58-encoded contract ID -// - `document_type_name`: Optional document type name (pass NULL if not needed) -// - `purposes`: Comma-separated list of key purposes (0=Authentication, 1=Encryption, 2=Decryption, 3=Withdraw) -// -// # Returns -// JSON string containing identity IDs mapped to their contract keys by purpose - struct DashSDKResult dash_sdk_identities_fetch_contract_keys(const struct dash_sdk_handle_t *sdk_handle, const char *identity_ids, const char *contract_id, const char *document_type_name, const char *purposes) ; - -// Fetch identity nonce -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_id`: Base58-encoded identity ID -// -// # Returns -// The nonce of the identity as a string - struct DashSDKResult dash_sdk_identity_fetch_nonce(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id) ; - -// Fetch identity public keys -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_id`: Base58-encoded identity ID -// -// # Returns -// A JSON string containing the identity's public keys - struct DashSDKResult dash_sdk_identity_fetch_public_keys(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id) ; - -// Resolve a name to an identity -// -// This function takes a name in the format "label.parentdomain" (e.g., "alice.dash") -// or just "label" for top-level domains, and returns the associated identity ID. -// -// # Arguments -// * `sdk_handle` - Handle to the SDK instance -// * `name` - C string containing the name to resolve -// -// # Returns -// * On success: A result containing the resolved identity ID -// * On error: An error result - struct DashSDKResult dash_sdk_identity_resolve_name(const struct dash_sdk_handle_t *sdk_handle, const char *name) ; - -// Top up an identity with credits using instant lock proof - struct DashSDKResult dash_sdk_identity_topup_with_instant_lock(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *identity_handle, const uint8_t *instant_lock_bytes, uintptr_t instant_lock_len, const uint8_t *transaction_bytes, uintptr_t transaction_len, uint32_t output_index, const uint8_t (*private_key)[32], const struct DashSDKPutSettings *put_settings) ; - -// Top up an identity with credits using instant lock proof and wait for confirmation - struct DashSDKResult dash_sdk_identity_topup_with_instant_lock_and_wait(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *identity_handle, const uint8_t *instant_lock_bytes, uintptr_t instant_lock_len, const uint8_t *transaction_bytes, uintptr_t transaction_len, uint32_t output_index, const uint8_t (*private_key)[32], const struct DashSDKPutSettings *put_settings) ; - -// Transfer credits from one identity to another -// -// # Parameters -// - `from_identity_handle`: Identity to transfer credits from -// - `to_identity_id`: Base58-encoded ID of the identity to transfer credits to -// - `amount`: Amount of credits to transfer -// - `identity_public_key_handle`: Public key for signing (optional, pass null to auto-select) -// - `signer_handle`: Cryptographic signer -// - `put_settings`: Optional settings for the operation (can be null for defaults) -// -// # Returns -// DashSDKTransferCreditsResult with sender and receiver final balances on success - struct DashSDKResult dash_sdk_identity_transfer_credits(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *from_identity_handle, const char *to_identity_id, uint64_t amount, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings) ; - -// Free a transfer credits result structure - void dash_sdk_transfer_credits_result_free(struct DashSDKTransferCreditsResult *result) ; - -// Withdraw credits from identity to a Dash address -// -// # Parameters -// - `identity_handle`: Identity to withdraw credits from -// - `address`: Base58-encoded Dash address to withdraw to -// - `amount`: Amount of credits to withdraw -// - `core_fee_per_byte`: Core fee per byte (optional, pass 0 for default) -// - `identity_public_key_handle`: Public key for signing (optional, pass null to auto-select) -// - `signer_handle`: Cryptographic signer -// - `put_settings`: Optional settings for the operation (can be null for defaults) -// -// # Returns -// The new balance of the identity after withdrawal - struct DashSDKResult dash_sdk_identity_withdraw(struct dash_sdk_handle_t *sdk_handle, const struct IdentityHandle *identity_handle, const char *address, uint64_t amount, uint32_t core_fee_per_byte, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings) ; - -// Fetches protocol version upgrade state -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// -// # Returns -// * JSON array of protocol version upgrade information -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_protocol_version_get_upgrade_state(const struct dash_sdk_handle_t *sdk_handle) ; - -// Fetches protocol version upgrade vote status -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `start_pro_tx_hash` - Starting masternode pro_tx_hash (hex-encoded, optional) -// * `count` - Number of vote entries to retrieve -// -// # Returns -// * JSON array of masternode protocol version votes or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_protocol_version_get_upgrade_vote_status(const struct dash_sdk_handle_t *sdk_handle, const char *start_pro_tx_hash, uint32_t count) ; - -// Create a new SDK instance - struct DashSDKResult dash_sdk_create(const struct DashSDKConfig *config) ; - -// Create a new SDK instance with extended configuration including context provider - struct DashSDKResult dash_sdk_create_extended(const struct DashSDKConfigExtended *config) ; - -// Destroy an SDK instance - void dash_sdk_destroy(struct dash_sdk_handle_t *handle) ; - -// Register global context provider callbacks -// -// This must be called before creating an SDK instance that needs Core SDK functionality. -// The callbacks will be used by all SDK instances created after registration. -// -// # Safety -// - `callbacks` must contain valid function pointers that remain valid for the lifetime of the SDK - int32_t dash_sdk_register_context_callbacks(const struct ContextProviderCallbacks *callbacks) ; - -// Create a new SDK instance with explicit context callbacks -// -// This is an alternative to registering global callbacks. The callbacks are used only for this SDK instance. -// -// # Safety -// - `config` must be a valid pointer to a DashSDKConfig structure -// - `callbacks` must contain valid function pointers that remain valid for the lifetime of the SDK - struct DashSDKResult dash_sdk_create_with_callbacks(const struct DashSDKConfig *config, const struct ContextProviderCallbacks *callbacks) ; - -// Get the current network the SDK is connected to - enum DashSDKNetwork dash_sdk_get_network(const struct dash_sdk_handle_t *handle) ; - -// Create a mock SDK instance with a dump directory (for offline testing) - struct dash_sdk_handle_t *dash_sdk_create_handle_with_mock(const char *dump_dir) ; - -// Create a new iOS signer -// free_result_callback: Optional custom deallocator for sign result buffers (NULL = use libc free). - struct SignerHandle *dash_sdk_signer_create(IOSSignCallback sign_callback, IOSCanSignCallback can_sign_callback, void (*destroy_callback)(void *signer), FreeResultCallback free_result_callback) ; - -// Destroy an iOS signer - void dash_sdk_signer_destroy(struct SignerHandle *handle) ; - -// Free bytes allocated with malloc/calloc. This is the default deallocator used -// when SignerVTable::free_result is NULL. If your callback uses a different -// allocator, supply a custom free_result in the vtable instead. - void dash_sdk_bytes_free(uint8_t *bytes) ; - -// Fetches information about current quorums -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// -// # Returns -// * JSON string with current quorums information -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_system_get_current_quorums_info(const struct dash_sdk_handle_t *sdk_handle) ; - -// Fetches information about multiple epochs -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `start_epoch` - Starting epoch index (optional, null for default) -// * `count` - Number of epochs to retrieve -// * `ascending` - Whether to return epochs in ascending order -// -// # Returns -// * JSON array of epoch information or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_system_get_epochs_info(const struct dash_sdk_handle_t *sdk_handle, const char *start_epoch, uint32_t count, bool ascending) ; - -// Fetches path elements -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `path_json` - JSON array of path elements (hex-encoded byte arrays) -// * `keys_json` - JSON array of keys (hex-encoded byte arrays) -// -// # Returns -// * JSON array of elements or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_system_get_path_elements(const struct dash_sdk_handle_t *sdk_handle, const char *path_json, const char *keys_json) ; - -// Fetches a prefunded specialized balance -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `id` - Base58-encoded identifier -// -// # Returns -// * JSON string with balance or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_system_get_prefunded_specialized_balance(const struct dash_sdk_handle_t *sdk_handle, const char *id) ; - -// Fetches the total credits in the platform -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// -// # Returns -// * JSON string with total credits -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_system_get_total_credits_in_platform(const struct dash_sdk_handle_t *sdk_handle) ; - -// Burn tokens from an identity and wait for confirmation - struct DashSDKResult dash_sdk_token_burn(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenBurnParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Claim tokens from a distribution and wait for confirmation - struct DashSDKResult dash_sdk_token_claim(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenClaimParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Mint tokens to an identity and wait for confirmation - struct DashSDKResult dash_sdk_token_mint(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenMintParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Token transfer to another identity and wait for confirmation - struct DashSDKResult dash_sdk_token_transfer(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenTransferParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Update token configuration and wait for confirmation - struct DashSDKResult dash_sdk_token_update_contract_token_configuration(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenConfigUpdateParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Destroy frozen token funds and wait for confirmation - struct DashSDKResult dash_sdk_token_destroy_frozen_funds(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenDestroyFrozenFundsParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Perform emergency action on token and wait for confirmation - struct DashSDKResult dash_sdk_token_emergency_action(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenEmergencyActionParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Freeze a token for an identity and wait for confirmation - struct DashSDKResult dash_sdk_token_freeze(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenFreezeParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Unfreeze a token for an identity and wait for confirmation - struct DashSDKResult dash_sdk_token_unfreeze(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenFreezeParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Purchase tokens directly and wait for confirmation - struct DashSDKResult dash_sdk_token_purchase(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenPurchaseParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Set token price for direct purchase and wait for confirmation - struct DashSDKResult dash_sdk_token_set_price(struct dash_sdk_handle_t *sdk_handle, const uint8_t *transition_owner_id, const struct DashSDKTokenSetPriceParams *params, const struct IdentityPublicKeyHandle *identity_public_key_handle, const struct SignerHandle *signer_handle, const struct DashSDKPutSettings *put_settings, const struct DashSDKStateTransitionCreationOptions *state_transition_creation_options) ; - -// Get identity token balances -// -// This is an alias for dash_sdk_identity_fetch_token_balances for backward compatibility -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_id`: Base58-encoded identity ID -// - `token_ids`: Comma-separated list of Base58-encoded token IDs -// -// # Returns -// JSON string containing token IDs mapped to their balances - struct DashSDKResult dash_sdk_token_get_identity_balances(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id, const char *token_ids) ; - -// Get token contract info -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `token_id`: Base58-encoded token ID -// -// # Returns -// JSON string containing the contract ID and token position, or null if not found - struct DashSDKResult dash_sdk_token_get_contract_info(const struct dash_sdk_handle_t *sdk_handle, const char *token_id) ; - -// Get token direct purchase prices -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `token_ids`: Comma-separated list of Base58-encoded token IDs -// -// # Returns -// JSON string containing token IDs mapped to their pricing information - struct DashSDKResult dash_sdk_token_get_direct_purchase_prices(const struct dash_sdk_handle_t *sdk_handle, const char *token_ids) ; - -// Fetch token balances for multiple identities for a specific token -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_ids`: Comma-separated list of Base58-encoded identity IDs -// - `token_id`: Base58-encoded token ID -// -// # Returns -// JSON string containing identity IDs mapped to their token balances - struct DashSDKResult dash_sdk_identities_fetch_token_balances(const struct dash_sdk_handle_t *sdk_handle, const char *identity_ids, const char *token_id) ; - -// Fetch token information for multiple identities for a specific token -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_ids`: Comma-separated list of Base58-encoded identity IDs -// - `token_id`: Base58-encoded token ID -// -// # Returns -// JSON string containing identity IDs mapped to their token information - struct DashSDKResult dash_sdk_identities_fetch_token_infos(const struct dash_sdk_handle_t *sdk_handle, const char *identity_ids, const char *token_id) ; - -// Fetch token balances for a specific identity -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_id`: Base58-encoded identity ID -// - `token_ids`: Comma-separated list of Base58-encoded token IDs -// -// # Returns -// JSON string containing token IDs mapped to their balances - struct DashSDKResult dash_sdk_identity_fetch_token_balances(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id, const char *token_ids) ; - -// Fetch token information for a specific identity -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_id`: Base58-encoded identity ID -// - `token_ids`: Comma-separated list of Base58-encoded token IDs -// -// # Returns -// JSON string containing token IDs mapped to their information - struct DashSDKResult dash_sdk_identity_fetch_token_infos(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id, const char *token_ids) ; - -// Get identity token information -// -// This is an alias for dash_sdk_identity_fetch_token_infos for backward compatibility -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `identity_id`: Base58-encoded identity ID -// - `token_ids`: Comma-separated list of Base58-encoded token IDs -// -// # Returns -// JSON string containing token IDs mapped to their information - struct DashSDKResult dash_sdk_token_get_identity_infos(const struct dash_sdk_handle_t *sdk_handle, const char *identity_id, const char *token_ids) ; - -// Get token perpetual distribution last claim -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `token_id`: Base58-encoded token ID -// - `identity_id`: Base58-encoded identity ID -// -// # Returns -// JSON string containing the last claim information - struct DashSDKResult dash_sdk_token_get_perpetual_distribution_last_claim(const struct dash_sdk_handle_t *sdk_handle, const char *token_id, const char *identity_id) ; - -// Get token statuses -// -// # Parameters -// - `sdk_handle`: SDK handle -// - `token_ids`: Comma-separated list of Base58-encoded token IDs -// -// # Returns -// JSON string containing token IDs mapped to their status information - struct DashSDKResult dash_sdk_token_get_statuses(const struct dash_sdk_handle_t *sdk_handle, const char *token_ids) ; - -// Fetches the total supply of a token -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `token_id` - Base58-encoded token identifier -// -// # Returns -// * JSON string with token supply info or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_token_get_total_supply(const struct dash_sdk_handle_t *sdk_handle, const char *token_id) ; - -// Free a string allocated by the FFI - void dash_sdk_string_free(char *s) ; - -// Free binary data allocated by the FFI - void dash_sdk_binary_data_free(struct DashSDKBinaryData *binary_data) ; - -// Free an identity info structure - void dash_sdk_identity_info_free(struct DashSDKIdentityInfo *info) ; - -// Free a document info structure - void dash_sdk_document_info_free(struct DashSDKDocumentInfo *info) ; - -// Free an identity balance map - void dash_sdk_identity_balance_map_free(struct DashSDKIdentityBalanceMap *map) ; - -// Initialize the unified SDK system -// This initializes both Core SDK (if enabled) and Platform SDK - int32_t dash_unified_sdk_init(void) ; - -// Create a unified SDK handle with both Core and Platform SDKs -// -// # Safety -// - `config` must point to a valid UnifiedSDKConfig structure - struct UnifiedSDKHandle *dash_unified_sdk_create(const struct UnifiedSDKConfig *config) ; - -// Destroy a unified SDK handle -// -// # Safety -// - `handle` must be a valid unified SDK handle or null - void dash_unified_sdk_destroy(struct UnifiedSDKHandle *handle) ; - -// Start both Core and Platform SDKs -// -// # Safety -// - `handle` must be a valid unified SDK handle - int32_t dash_unified_sdk_start(struct UnifiedSDKHandle *handle) ; - -// Stop both Core and Platform SDKs -// -// # Safety -// - `handle` must be a valid unified SDK handle - int32_t dash_unified_sdk_stop(struct UnifiedSDKHandle *handle) ; - -// Get the Core SDK client from a unified handle -// -// # Safety -// - `handle` must be a valid unified SDK handle - CoreSDKClient *dash_unified_sdk_get_core_client(struct UnifiedSDKHandle *handle) ; - -// Get the Platform SDK from a unified handle -// -// # Safety -// - `handle` must be a valid unified SDK handle - struct dash_sdk_handle_t *dash_unified_sdk_get_platform_sdk(struct UnifiedSDKHandle *handle) ; - -// Check if integration is enabled for this unified SDK -// -// # Safety -// - `handle` must be a valid unified SDK handle - bool dash_unified_sdk_is_integration_enabled(struct UnifiedSDKHandle *handle) ; - -// Check if Core SDK is available in this unified SDK -// -// # Safety -// - `handle` must be a valid unified SDK handle - bool dash_unified_sdk_has_core_sdk(struct UnifiedSDKHandle *handle) ; - -// Register Core SDK with Platform SDK for context provider callbacks -// This enables Platform SDK to query Core SDK for blockchain state -// -// # Safety -// - `handle` must be a valid unified SDK handle - int32_t dash_unified_sdk_register_core_context(struct UnifiedSDKHandle *handle) ; - -// Get combined status of both SDKs -// -// # Safety -// - `handle` must be a valid unified SDK handle -// - `core_height` must point to a valid u32 (set to 0 if core disabled) -// - `platform_ready` must point to a valid bool - int32_t dash_unified_sdk_get_status(struct UnifiedSDKHandle *handle, uint32_t *core_height, bool *platform_ready) ; - -// Get unified SDK version information - const char *dash_unified_sdk_version(void) ; - -// Check if unified SDK was compiled with core support - bool dash_unified_sdk_has_core_support(void) ; - -// Fetches vote polls by end date -// -// # Parameters -// * `sdk_handle` - Handle to the SDK instance -// * `start_time_ms` - Start time in milliseconds (optional, 0 for no start time) -// * `start_time_included` - Whether to include the start time -// * `end_time_ms` - End time in milliseconds (optional, 0 for no end time) -// * `end_time_included` - Whether to include the end time -// * `limit` - Maximum number of results to return (optional, 0 for no limit) -// * `offset` - Number of results to skip (optional, 0 for no offset) -// * `ascending` - Whether to order results in ascending order -// -// # Returns -// * JSON array of vote polls grouped by timestamp or null if not found -// * Error message if operation fails -// -// # Safety -// This function is unsafe because it handles raw pointers from C - struct DashSDKResult dash_sdk_voting_get_vote_polls_by_end_date(const struct dash_sdk_handle_t *sdk_handle, uint64_t start_time_ms, bool start_time_included, uint64_t end_time_ms, bool end_time_included, uint32_t limit, uint32_t offset, bool ascending) ; - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif /* DASH_SDK_FFI_H */ diff --git a/packages/rs-sdk-ffi/tests/context_provider_test.rs b/packages/rs-sdk-ffi/tests/context_provider_test.rs index f4fba6d3a6..6cbdc2050c 100644 --- a/packages/rs-sdk-ffi/tests/context_provider_test.rs +++ b/packages/rs-sdk-ffi/tests/context_provider_test.rs @@ -4,7 +4,7 @@ mod tests { context_provider::CoreSDKHandle, dash_sdk_context_provider_destroy, dash_sdk_context_provider_from_callbacks, dash_sdk_create_extended, dash_sdk_register_context_callbacks, CallbackResult, ContextProviderCallbacks, - DashSDKConfig, DashSDKConfigExtended, DashSDKNetwork, + DashSDKConfig, DashSDKConfigExtended, FFINetwork, }; use std::ffi::CString; use std::ptr; @@ -80,7 +80,7 @@ mod tests { // Create base config let dapi_addresses = CString::new("https://testnet.dash.org:3000").unwrap(); let base_config = DashSDKConfig { - network: DashSDKNetwork::SDKTestnet, + network: FFINetwork::Testnet, dapi_addresses: dapi_addresses.as_ptr(), skip_asset_lock_proof_verification: false, request_retry_count: 3, diff --git a/packages/rs-unified-sdk-ffi/Cargo.toml b/packages/rs-unified-sdk-ffi/Cargo.toml index ca49b101a9..14a1af512f 100644 --- a/packages/rs-unified-sdk-ffi/Cargo.toml +++ b/packages/rs-unified-sdk-ffi/Cargo.toml @@ -11,4 +11,5 @@ crate-type = ["staticlib", "cdylib"] dash-spv-ffi = { workspace = true } key-wallet-ffi = { workspace = true } platform-wallet-ffi = { path = "../rs-platform-wallet-ffi" } -rs-sdk-ffi = { path = "../rs-sdk-ffi" } \ No newline at end of file +rs-sdk-ffi = { path = "../rs-sdk-ffi" } +dash-network = { workspace = true, features = ["ffi"] } \ No newline at end of file diff --git a/packages/rs-unified-sdk-ffi/src/lib.rs b/packages/rs-unified-sdk-ffi/src/lib.rs index b9e1d56797..833ae1c557 100644 --- a/packages/rs-unified-sdk-ffi/src/lib.rs +++ b/packages/rs-unified-sdk-ffi/src/lib.rs @@ -1,3 +1,4 @@ +pub use dash_network; pub use dash_spv_ffi; pub use key_wallet_ffi; pub use platform_wallet_ffi; diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Address/Addresses.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Address/Addresses.swift index c88ec266f9..c804d24fec 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Address/Addresses.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Address/Addresses.swift @@ -1441,7 +1441,7 @@ public class Addresses: @unchecked Sendable { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(identityPrivateKey.count), - sdk.network + sdk.network.ffiValue ) } @@ -1595,7 +1595,7 @@ public class Addresses: @unchecked Sendable { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(identityPrivateKey.count), - sdk.network + sdk.network.ffiValue ) } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Address/PlatformAddressInfo.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Address/PlatformAddressInfo.swift index 5fbfe457bb..408df3ba9e 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Address/PlatformAddressInfo.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Address/PlatformAddressInfo.swift @@ -43,19 +43,9 @@ public struct PlatformAddressInfo: Sendable, Equatable, Codable { /// Convert address bytes to bech32m string (requires network parameter) /// Format: [type_byte][20_byte_hash] - public func toBech32m(network: DashSDKNetwork) -> String? { + public func toBech32m(network: Network) -> String? { guard addressBytes.count == 21 else { return nil } - - // Get HRP based on network - // DashSDKNetwork raw values: 0 = mainnet, 1 = testnet, 2 = regtest, 3 = devnet, 4 = local - let hrp: String - if network.rawValue == 0 { - hrp = "dashevo" // mainnet - } else { - hrp = "tdashevo" // testnet, devnet, regtest, local - } - - // Use bech32m encoding + let hrp = network == .mainnet ? "dashevo" : "tdashevo" return Bech32m.encode(hrp: hrp, data: addressBytes) } } @@ -189,14 +179,9 @@ public struct AddressBalanceChange: Sendable, Equatable { } /// Convert address bytes to bech32m string - public func toBech32m(network: DashSDKNetwork) -> String? { + public func toBech32m(network: Network) -> String? { guard addressBytes.count == 21 else { return nil } - let hrp: String - if network.rawValue == 0 { - hrp = "dashevo" - } else { - hrp = "tdashevo" - } + let hrp = network == .mainnet ? "dashevo" : "tdashevo" return Bech32m.encode(hrp: hrp, data: addressBytes) } } @@ -278,14 +263,9 @@ public struct CompactedAddressChange: Sendable, Equatable { } /// Convert address bytes to bech32m string - public func toBech32m(network: DashSDKNetwork) -> String? { + public func toBech32m(network: Network) -> String? { guard addressBytes.count == 21 else { return nil } - let hrp: String - if network.rawValue == 0 { - hrp = "dashevo" - } else { - hrp = "tdashevo" - } + let hrp = network == .mainnet ? "dashevo" : "tdashevo" return Bech32m.encode(hrp: hrp, data: addressBytes) } } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/DashNetwork.swift b/packages/swift-sdk/Sources/SwiftDashSDK/DashNetwork.swift new file mode 100644 index 0000000000..32cd4e6f92 --- /dev/null +++ b/packages/swift-sdk/Sources/SwiftDashSDK/DashNetwork.swift @@ -0,0 +1,62 @@ +import Foundation +import DashSDKFFI + +/// The Dash network the SDK is operating on. +/// +/// Single Swift wrapper for `dash-network`'s `FFINetwork` C-ABI mirror +/// (the `#[repr(C)]` enum exposed by the `dash-network` Rust crate's +/// `ffi` module). Every Rust-side FFI surface — `rs-platform-wallet-ffi`, +/// `rs-sdk-ffi`, `rs-key-wallet-ffi`, `dash-spv-ffi` — takes / returns +/// `FFINetwork`; this Swift enum is the matching surface on the iOS +/// side so callers never reach for `UInt32` or per-module mirror enums. +public enum Network: UInt32, Sendable, Hashable, CaseIterable, Codable { + case mainnet = 0 + case testnet = 1 + case devnet = 2 + case regtest = 3 + + /// Build from the C-ABI `FFINetwork` mirror exposed by `dash-network`. + public init(ffiNetwork: FFINetwork) { + switch ffiNetwork { + case FFINetwork_Mainnet: self = .mainnet + case FFINetwork_Testnet: self = .testnet + case FFINetwork_Devnet: self = .devnet + case FFINetwork_Regtest: self = .regtest + default: fatalError("Invalid FFINetwork value: \(ffiNetwork)") + } + } + + /// The matching `FFINetwork` value; pass to any function whose + /// signature in the cbindgen-generated header takes + /// `enum FFINetwork`. Named `ffiValue` to match the convention + /// sibling enums in this module already use (`AccountType`, + /// `KeyPurpose`, …). + public var ffiValue: FFINetwork { + switch self { + case .mainnet: return FFINetwork_Mainnet + case .testnet: return FFINetwork_Testnet + case .devnet: return FFINetwork_Devnet + case .regtest: return FFINetwork_Regtest + } + } + + public var displayName: String { + switch self { + case .mainnet: return "Mainnet" + case .testnet: return "Testnet" + case .regtest: return "Local" + case .devnet: return "Devnet" + } + } + + public var networkName: String { + switch self { + case .mainnet: return "mainnet" + case .testnet: return "testnet" + case .regtest: return "regtest" + case .devnet: return "devnet" + } + } + + public static var defaultNetwork: Network { .testnet } +} diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/FFI/KeychainSigner.swift b/packages/swift-sdk/Sources/SwiftDashSDK/FFI/KeychainSigner.swift index 5d596e1f67..a7a6d34ed4 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/FFI/KeychainSigner.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/FFI/KeychainSigner.swift @@ -164,7 +164,7 @@ public final class KeychainSigner: Signer, @unchecked Sendable { /// Network is only used for `dash_sdk_signer_create_from_private_key`, /// which uses it for WIF / address derivation but not for signing /// itself. Stored here so the trampoline doesn't have to plumb it. - private let network: DashSDKNetwork + private let network: Network /// Background `ModelContext` pinned to this signer. Created lazily /// per-trampoline-call (see `lookupPrivateKey`) — SwiftData /// `ModelContext` instances are cheap and let us stay off the @@ -196,7 +196,7 @@ public final class KeychainSigner: Signer, @unchecked Sendable { /// - keychain: defaults to `KeychainManager.shared`. public init( modelContainer: ModelContainer, - network: DashSDKNetwork = DashSDKNetwork(rawValue: 1), + network: Network = .testnet, keychain: KeychainManager = .shared ) { self.modelContainer = modelContainer @@ -533,7 +533,7 @@ public final class KeychainSigner: Signer, @unchecked Sendable { dataBase, UInt(dataRaw.count), ecdsaSecp256k1KeyType, - self.network, + self.network.ffiValue, bufPtr.baseAddress, UInt(bufPtr.count), &sigLen, @@ -591,7 +591,7 @@ public final class KeychainSigner: Signer, @unchecked Sendable { dash_sdk_signer_create_from_private_key( keyBuf.baseAddress!, UInt(keyBuf.count), - self.network + self.network.ffiValue ) } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Helpers/WIFParser.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Helpers/WIFParser.swift index 2c775c2d7b..883310c2f5 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Helpers/WIFParser.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Helpers/WIFParser.swift @@ -67,16 +67,17 @@ public enum WIFParser { /// /// - Parameters: /// - privateKey: The raw 32-byte secp256k1 secret scalar. - /// - isTestnet: `true` → testnet (`0xEF`); `false` → mainnet - /// (`0xCC`). - public static func encodeToWIF(_ privateKey: Data, isTestnet: Bool = true) -> String? { + /// - network: Which network the key belongs to (default: testnet). + /// Mainnet uses version byte `0xCC`; every other network uses + /// the testnet `0xEF` byte. + public static func encodeToWIF(_ privateKey: Data, network: Network = .testnet) -> String? { guard privateKey.count == 32 else { return nil } // The FFI takes a NUL-terminated hex string for the private // key. Encode → call → free → parse the returned C string. let privateKeyHex = privateKey.toHexString() let result = privateKeyHex.withCString { hexPtr in - dash_sdk_private_key_to_wif(hexPtr, isTestnet) + dash_sdk_private_key_to_wif(hexPtr, network.ffiValue) } if let error = result.error { diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Address.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Address.swift index 73a4101850..0984b37b70 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Address.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Address.swift @@ -17,7 +17,7 @@ public class Address { /// - address: The address to validate /// - network: The network type /// - Returns: True if the address is valid - public static func validate(_ address: String, network: KeyWalletNetwork = .mainnet) -> Bool { + public static func validate(_ address: String, network: Network = .mainnet) -> Bool { var error = FFIError() let isValid = address.withCString { addressCStr in @@ -38,7 +38,7 @@ public class Address { /// - address: The address to check /// - network: The network type /// - Returns: The address type - public static func getType(of address: String, network: KeyWalletNetwork = .mainnet) -> AddressType { + public static func getType(of address: String, network: Network = .mainnet) -> AddressType { var error = FFIError() let typeRaw = address.withCString { addressCStr in diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyDerivation.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyDerivation.swift index f39f2e5518..0060d20b5c 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyDerivation.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyDerivation.swift @@ -9,7 +9,7 @@ public class KeyDerivation { /// - seed: The seed bytes /// - network: The network type /// - Returns: Extended private key handle - public static func createMasterKey(seed: Data, network: KeyWalletNetwork = .mainnet) throws -> ExtendedPrivateKey { + public static func createMasterKey(seed: Data, network: Network = .mainnet) throws -> ExtendedPrivateKey { var error = FFIError() let xprivPtr = seed.withUnsafeBytes { seedBytes in @@ -35,7 +35,7 @@ public class KeyDerivation { /// - network: The network type /// - accountIndex: The account index /// - Returns: The derivation path string - public static func getBIP44AccountPath(network: KeyWalletNetwork = .mainnet, + public static func getBIP44AccountPath(network: Network = .mainnet, accountIndex: UInt32) throws -> String { var error = FFIError() let maxPathLen = 256 @@ -67,7 +67,7 @@ public class KeyDerivation { /// - isChange: Whether this is a change address /// - addressIndex: The address index /// - Returns: The derivation path string - public static func getBIP44PaymentPath(network: KeyWalletNetwork = .mainnet, + public static func getBIP44PaymentPath(network: Network = .mainnet, accountIndex: UInt32, isChange: Bool, addressIndex: UInt32) throws -> String { @@ -100,7 +100,7 @@ public class KeyDerivation { /// - network: The network type /// - accountIndex: The account index /// - Returns: The derivation path string - public static func getCoinJoinPath(network: KeyWalletNetwork = .mainnet, + public static func getCoinJoinPath(network: Network = .mainnet, accountIndex: UInt32) throws -> String { var error = FFIError() let maxPathLen = 256 @@ -130,7 +130,7 @@ public class KeyDerivation { /// - network: The network type /// - identityIndex: The identity index /// - Returns: The derivation path string - public static func getIdentityRegistrationPath(network: KeyWalletNetwork = .mainnet, + public static func getIdentityRegistrationPath(network: Network = .mainnet, identityIndex: UInt32) throws -> String { var error = FFIError() let maxPathLen = 256 @@ -161,7 +161,7 @@ public class KeyDerivation { /// - identityIndex: The identity index /// - topupIndex: The top-up index /// - Returns: The derivation path string - public static func getIdentityTopUpPath(network: KeyWalletNetwork = .mainnet, + public static func getIdentityTopUpPath(network: Network = .mainnet, identityIndex: UInt32, topupIndex: UInt32) throws -> String { var error = FFIError() @@ -194,7 +194,7 @@ public class KeyDerivation { /// - identityIndex: The identity index /// - keyIndex: The key index /// - Returns: The derivation path string - public static func getIdentityAuthenticationPath(network: KeyWalletNetwork = .mainnet, + public static func getIdentityAuthenticationPath(network: Network = .mainnet, identityIndex: UInt32, keyIndex: UInt32) throws -> String { var error = FFIError() diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyManager.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyManager.swift index 8dc6fe9410..2ee761ad1f 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyManager.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyManager.swift @@ -292,7 +292,7 @@ public final class KeyManager: Sendable { /// - Note: The returned signer must be destroyed with `destroySigner(_:)` when done public func createSigner( from privateKeyData: Data, - network: Network = DashSDKNetwork(rawValue: 1) + network: Network = .testnet ) throws -> OpaquePointer { // Validate private key length guard privateKeyData.count == 32 else { @@ -303,7 +303,7 @@ public final class KeyManager: Sendable { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(privateKeyData.count), - network + network.ffiValue ) } @@ -337,12 +337,12 @@ public final class KeyManager: Sendable { /// - Parameters: /// - privateKeyData: The private key data /// - publicKey: The public key to validate against - /// - isTestnet: Whether this is for testnet (default: true) + /// - network: Which network the keys belong to (default: testnet) /// - Returns: True if the private key matches the public key public func validatePrivateKey( _ privateKeyData: Data, matches publicKey: IdentityPublicKey, - isTestnet: Bool = true + network: Network = .testnet ) -> Bool { let privateKeyHex = privateKeyData.toHexString() let publicKeyHex = publicKey.data.toHexString() @@ -351,7 +351,7 @@ public final class KeyManager: Sendable { privateKeyHex: privateKeyHex, publicKeyHex: publicKeyHex, keyType: publicKey.keyType, - isTestnet: isTestnet + network: network ) } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyWalletTypes.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyWalletTypes.swift index 6813934fd5..d4f4c63254 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyWalletTypes.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/KeyWalletTypes.swift @@ -1,35 +1,6 @@ import Foundation import DashSDKFFI -// MARK: - Network Types - -/// Network type for Dash networks -public enum KeyWalletNetwork: UInt32 { - case mainnet = 0 // DASH - case testnet = 1 // TESTNET - case regtest = 2 // REGTEST - case devnet = 3 // DEVNET - - var ffiValue: FFINetwork { - switch self { - case .mainnet: return FFINetwork(rawValue: 0) // Dash = 0 - case .testnet: return FFINetwork(rawValue: 1) // Testnet = 1 - case .regtest: return FFINetwork(rawValue: 2) // Regtest = 2 - case .devnet: return FFINetwork(rawValue: 3) // Devnet = 3 - } - } - - init(ffiNetwork: FFINetwork) { - switch ffiNetwork.rawValue { - case 0: self = .mainnet // Dash = 0 - case 1: self = .testnet // Testnet = 1 - case 2: self = .regtest // Regtest = 2 - case 3: self = .devnet // Devnet = 3 - default: self = .mainnet - } - } -} - // MARK: - Account Types /// Account type for wallet accounts diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift index 62b6e5b6e9..728616096b 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedAccount.swift @@ -18,9 +18,9 @@ public class ManagedAccount { // MARK: - Properties /// Get the network this account is on - public var network: KeyWalletNetwork { + public var network: Network { let ffiNetwork = managed_core_account_get_network(handle) - return KeyWalletNetwork(ffiNetwork: ffiNetwork) + return Network(ffiNetwork: ffiNetwork) } /// Get the account type diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedPlatformAccount.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedPlatformAccount.swift index cd30e9dbed..171ca72b6d 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedPlatformAccount.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/ManagedPlatformAccount.swift @@ -46,9 +46,9 @@ public class ManagedPlatformAccount { // MARK: - Properties /// The network this account belongs to. - public var network: KeyWalletNetwork { + public var network: Network { let ffiNetwork = managed_platform_account_get_network(handle) - return KeyWalletNetwork(ffiNetwork: ffiNetwork) + return Network(ffiNetwork: ffiNetwork) } /// The account index (hardened). diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Wallet.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Wallet.swift index c8a9e79c78..a37a0af8f0 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Wallet.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Wallet.swift @@ -30,7 +30,7 @@ public class Wallet { /// - network: The network type /// - accountOptions: Account creation options public init(mnemonic: String, passphrase: String? = nil, - network: KeyWalletNetwork = .mainnet, + network: Network = .mainnet, accountOptions: AccountCreationOption = .default) throws { var error = FFIError() @@ -105,7 +105,7 @@ public class Wallet { /// - seed: The seed bytes (typically 64 bytes) /// - network: The network type /// - accountOptions: Account creation options - public init(seed: Data, network: KeyWalletNetwork = .mainnet, + public init(seed: Data, network: Network = .mainnet, accountOptions: AccountCreationOption = .default) throws { self.ownsHandle = true @@ -149,7 +149,7 @@ public class Wallet { /// - Parameters: /// - xpub: The extended public key string /// - network: The network type - public init(xpub: String, network: KeyWalletNetwork = .mainnet) throws { + public init(xpub: String, network: Network = .mainnet) throws { // Create an empty wallet first (no accounts) var error = FFIError() var options = AccountCreationOption.noAccounts.toFFIOptions() @@ -184,7 +184,7 @@ public class Wallet { /// - Parameters: /// - network: The network type /// - accountOptions: Account creation options - public static func createRandom(network: KeyWalletNetwork = .mainnet, + public static func createRandom(network: Network = .mainnet, accountOptions: AccountCreationOption = .default) throws -> Wallet { var error = FFIError() let walletPtr: UnsafeMutablePointer? @@ -212,7 +212,7 @@ public class Wallet { } /// Private initializer for internal use (takes ownership) - private init(handle: UnsafeMutablePointer, network: KeyWalletNetwork) { + private init(handle: UnsafeMutablePointer, network: Network) { self.handle = handle self.ownsHandle = true } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/WalletManager.swift b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/WalletManager.swift index 4da4b7f48c..37b6b22676 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/WalletManager.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/WalletManager.swift @@ -4,12 +4,12 @@ import DashSDKFFI /// Swift wrapper for wallet manager that manages multiple wallets public class WalletManager { private let handle: UnsafeMutablePointer - internal let network: KeyWalletNetwork + internal let network: Network private let ownsHandle: Bool /// Create a new standalone wallet manager /// Note: Consider using SPVClient.getWalletManager() instead if you have an SPV client - public init(network: KeyWalletNetwork = .mainnet,) throws { + public init(network: Network = .mainnet,) throws { var error = FFIError() guard let managerHandle = wallet_manager_create(network.ffiValue, &error) else { defer { @@ -43,7 +43,7 @@ public class WalletManager { } self.handle = handle - self.network = KeyWalletNetwork(ffiNetwork: network) + self.network = Network(ffiNetwork: network) self.ownsHandle = false } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Models/Network.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Models/Network.swift deleted file mode 100644 index ce5f517600..0000000000 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Models/Network.swift +++ /dev/null @@ -1,62 +0,0 @@ -import Foundation - -/// App-level network enum (distinct from the SDK's DashSDKNetwork typealias). -/// -/// Raw values intentionally match `KeyWalletNetwork.rawValue` so conversions -/// between the two are a direct raw-value passthrough. -public enum AppNetwork: Int, CaseIterable, Codable, Sendable { - case mainnet = 0 - case testnet = 1 - case regtest = 2 - case devnet = 3 - - init(network: KeyWalletNetwork) { - // Raw values are aligned with `KeyWalletNetwork` by construction, - // so every case maps; the force-unwrap can never fire. - self = AppNetwork(rawValue: Int(network.rawValue))! - } - - public var displayName: String { - switch self { - case .mainnet: - return "Mainnet" - case .testnet: - return "Testnet" - case .regtest: - return "Local" - case .devnet: - return "Devnet" - } - } - - /// Lowercase canonical name ("mainnet", "testnet", "regtest", - /// "devnet"). Used as the persisted string key for sibling - /// `PersistentX` rows (identities, documents, contracts, sync - /// state) that still store network as `String`. - public var networkName: String { - switch self { - case .mainnet: - return "mainnet" - case .testnet: - return "testnet" - case .regtest: - return "regtest" - case .devnet: - return "devnet" - } - } - - public var sdkNetwork: DashSDKNetwork { - DashSDKNetwork(rawValue: UInt32(rawValue)) - } - - public static var defaultNetwork: AppNetwork { - return .testnet - } - - // Convert to KeyWalletNetwork for wallet operations - public func toKeyWalletNetwork() -> KeyWalletNetwork { - // Raw values are aligned by construction; unwrap is safe. - return KeyWalletNetwork(rawValue: UInt32(rawValue))! - } -} diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDPNSName.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDPNSName.swift index aa3b72872b..67861cb9c4 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDPNSName.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDPNSName.swift @@ -26,17 +26,17 @@ public final class PersistentDPNSName { /// on a given chain. #Unique([\.networkRaw, \.normalizedParentDomainName, \.normalizedLabel]) - /// Network discriminant. `Int` mirror of `AppNetwork.rawValue` — + /// Network discriminant. `UInt32` mirror of `Network.rawValue` — /// Foundation's predicate engine compares it directly without a /// custom converter. Stays in sync with `identity.networkRaw` /// via the init; identities don't migrate between networks. - public var networkRaw: Int + public var networkRaw: UInt32 /// Type-safe accessor over `networkRaw`. Falls back to `.testnet` /// if the stored raw value drifts — matches /// `PersistentIdentity.network`. - public var network: AppNetwork { - get { AppNetwork(rawValue: networkRaw) ?? .testnet } + public var network: Network { + get { Network(rawValue: networkRaw) ?? .testnet } set { networkRaw = newValue.rawValue } } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDashpayContactRequest.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDashpayContactRequest.swift index 7e8679f137..11196c7d02 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDashpayContactRequest.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDashpayContactRequest.swift @@ -29,16 +29,16 @@ public final class PersistentDashpayContactRequest { \.networkRaw, \.ownerIdentityId, \.contactIdentityId, \.isOutgoing ]) - /// Network discriminant. `Int` mirror of `AppNetwork.rawValue` — + /// Network discriminant. `UInt32` mirror of `Network.rawValue` — /// Foundation's predicate engine compares it directly without a /// custom converter. Kept in sync with `owner.networkRaw` by the /// init. - public var networkRaw: Int + public var networkRaw: UInt32 /// Type-safe accessor over `networkRaw`. Falls back to `.testnet` /// if the stored raw value drifts. - public var network: AppNetwork { - get { AppNetwork(rawValue: networkRaw) ?? .testnet } + public var network: Network { + get { Network(rawValue: networkRaw) ?? .testnet } set { networkRaw = newValue.rawValue } } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDashpayProfile.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDashpayProfile.swift index 1d228be18f..3e6eb2dd12 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDashpayProfile.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDashpayProfile.swift @@ -24,17 +24,17 @@ public final class PersistentDashpayProfile { /// shared local store. #Unique([\.networkRaw, \.identity]) - /// Network discriminant. `Int` mirror of `AppNetwork.rawValue` — + /// Network discriminant. `UInt32` mirror of `Network.rawValue` — /// Foundation's predicate engine compares it directly without a /// custom converter. Stays in sync with `identity.networkRaw` /// (set by the init); identities don't migrate between networks. - public var networkRaw: Int + public var networkRaw: UInt32 /// Type-safe accessor over `networkRaw`. Falls back to `.testnet` /// if the stored raw value drifts — matches /// `PersistentIdentity.network`. - public var network: AppNetwork { - get { AppNetwork(rawValue: networkRaw) ?? .testnet } + public var network: Network { + get { Network(rawValue: networkRaw) ?? .testnet } set { networkRaw = newValue.rawValue } } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDataContract.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDataContract.swift index 36e1c38397..c577957488 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDataContract.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDataContract.swift @@ -30,14 +30,14 @@ public final class PersistentDataContract { public var groupsData: Data? // Network - /// Stored as the `AppNetwork.rawValue` `Int` so SwiftData + /// Stored as the `Network.rawValue` `UInt32` so SwiftData /// `#Predicate` expressions can evaluate it directly. See /// `PersistentIdentity.networkRaw` for the full rationale. - public var networkRaw: Int + public var networkRaw: UInt32 /// Type-safe accessor over `networkRaw`. Setter writes through. - public var network: AppNetwork { - get { AppNetwork(rawValue: networkRaw) ?? .testnet } + public var network: Network { + get { Network(rawValue: networkRaw) ?? .testnet } set { networkRaw = newValue.rawValue } } @@ -179,7 +179,7 @@ public final class PersistentDataContract { keywords: [String] = [], description: String? = nil, hasTokens: Bool = false, - network: AppNetwork + network: Network ) { self.id = id self.name = name @@ -295,17 +295,17 @@ extension PersistentDataContract { } } - public static func predicate(network: AppNetwork) -> Predicate { + public static func predicate(network: Network) -> Predicate { // See `PersistentIdentity.predicate(network:)` — Foundation's - // predicate engine can't capture `AppNetwork`, so we filter on - // the Int-backed `networkRaw` shadow field. + // predicate engine can't capture `Network`, so we filter on + // the UInt32-backed `networkRaw` shadow field. let target = network.rawValue return #Predicate { contract in contract.networkRaw == target } } - public static func contractsWithTokensPredicate(network: AppNetwork) -> Predicate { + public static func contractsWithTokensPredicate(network: Network) -> Predicate { let target = network.rawValue return #Predicate { contract in contract.hasTokens == true && contract.networkRaw == target diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDocument.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDocument.swift index 7f03e417be..cc1812c5f7 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDocument.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentDocument.swift @@ -36,14 +36,14 @@ public final class PersistentDocument { public var transferredAtCoreBlockHeight: Int64? // Network - /// Stored as the `AppNetwork.rawValue` `Int` so SwiftData + /// Stored as the `Network.rawValue` `UInt32` so SwiftData /// `#Predicate` expressions can evaluate it directly. See /// `PersistentIdentity.networkRaw` for the full rationale. - public var networkRaw: Int + public var networkRaw: UInt32 /// Type-safe accessor over `networkRaw`. Setter writes through. - public var network: AppNetwork { - get { AppNetwork(rawValue: networkRaw) ?? .testnet } + public var network: Network { + get { Network(rawValue: networkRaw) ?? .testnet } set { networkRaw = newValue.rawValue } } @@ -119,7 +119,7 @@ public final class PersistentDocument { data: Data, contractId: String, ownerId: String, - network: AppNetwork + network: Network ) { self.documentId = documentId self.documentType = documentType @@ -159,10 +159,10 @@ public final class PersistentDocument { } } - public static func predicate(contractId: String, network: AppNetwork) -> Predicate { + public static func predicate(contractId: String, network: Network) -> Predicate { // See `PersistentIdentity.predicate(network:)` — Foundation's - // predicate engine can't capture `AppNetwork`, so we filter on - // the Int-backed `networkRaw` shadow field. + // predicate engine can't capture `Network`, so we filter on + // the UInt32-backed `networkRaw` shadow field. let target = network.rawValue return #Predicate { doc in doc.contractId == contractId && doc.networkRaw == target && doc.isDeleted == false diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentIdentity.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentIdentity.swift index 9f8da43d30..fb7a00cbfa 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentIdentity.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentIdentity.swift @@ -34,22 +34,22 @@ public final class PersistentIdentity { public var lastSyncedAt: Date? // MARK: - Network - /// Stored as the `AppNetwork.rawValue` `Int` so SwiftData + /// Stored as the `Network.rawValue` `UInt32` so SwiftData /// `#Predicate` expressions can evaluate it directly. Foundation's /// predicate engine rejects captured non-primitive types — even /// Codable raw-value enums crash at evaluation with /// "Unsupported Predicate: Captured/constant values of type - /// 'AppNetwork' are not supported". The `network` computed + /// 'Network' are not supported". The `network` computed /// accessor below keeps the public API type-safe; only predicates /// that need to filter by network reach for `networkRaw`. - public var networkRaw: Int + public var networkRaw: UInt32 /// Type-safe accessor over `networkRaw`. Reads fall back to /// `.testnet` if the stored raw value ever drifts out of the - /// `AppNetwork` range (shouldn't happen — writers only go through - /// this setter which uses `AppNetwork.rawValue`). - public var network: AppNetwork { - get { AppNetwork(rawValue: networkRaw) ?? .testnet } + /// `Network` range (shouldn't happen — writers only go through + /// this setter which uses `Network.rawValue`). + public var network: Network { + get { Network(rawValue: networkRaw) ?? .testnet } set { networkRaw = newValue.rawValue } } @@ -136,7 +136,7 @@ public final class PersistentIdentity { votingPrivateKeyIdentifier: String? = nil, ownerPrivateKeyIdentifier: String? = nil, payoutPrivateKeyIdentifier: String? = nil, - network: AppNetwork, + network: Network, identityIndex: UInt32 = 0 ) { self.identityId = identityId @@ -279,10 +279,10 @@ extension PersistentIdentity { } } - public static func predicate(network: AppNetwork) -> Predicate { - // Compare against the Int-backed `networkRaw` because Foundation's + public static func predicate(network: Network) -> Predicate { + // Compare against the UInt32-backed `networkRaw` because Foundation's // predicate evaluator can't capture non-primitive types like - // `AppNetwork` (the computed `network` accessor is invisible to + // `Network` (the computed `network` accessor is invisible to // SwiftData — it can't see through `\.network.rawValue` either). let target = network.rawValue return #Predicate { identity in @@ -294,7 +294,7 @@ extension PersistentIdentity { /// Used by the recipient pickers, the "Acting as" picker, and any /// view that needs to restrict to identities the user controls on /// a specific network. - public static func walletOwnedIdentitiesPredicate(network: AppNetwork) -> Predicate { + public static func walletOwnedIdentitiesPredicate(network: Network) -> Predicate { let target = network.rawValue return #Predicate { identity in identity.wallet != nil && identity.networkRaw == target diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentPlatformAddressesSyncState.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentPlatformAddressesSyncState.swift index 31419370b9..06f7d469ae 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentPlatformAddressesSyncState.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentPlatformAddressesSyncState.swift @@ -16,14 +16,14 @@ public final class PersistentPlatformAddressesSyncState { @Attribute(.unique) public var walletId: Data /// Network this sync checkpoint belongs to. /// - /// Stored as the `AppNetwork.rawValue` `Int` so SwiftData + /// Stored as the `Network.rawValue` `UInt32` so SwiftData /// `#Predicate` expressions can evaluate it directly. See /// `PersistentIdentity.networkRaw` for the full rationale. - public var networkRaw: Int + public var networkRaw: UInt32 /// Type-safe accessor over `networkRaw`. Setter writes through. - public var network: AppNetwork { - get { AppNetwork(rawValue: networkRaw) ?? .testnet } + public var network: Network { + get { Network(rawValue: networkRaw) ?? .testnet } set { networkRaw = newValue.rawValue } } /// Highest block height covered by the last sync. @@ -37,7 +37,7 @@ public final class PersistentPlatformAddressesSyncState { public init( walletId: Data, - network: AppNetwork, + network: Network, syncHeight: UInt64, syncTimestamp: UInt64, lastKnownRecentBlock: UInt64 diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentTokenBalance.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentTokenBalance.swift index 499f0a6239..5651c0f224 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentTokenBalance.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentTokenBalance.swift @@ -21,14 +21,14 @@ public final class PersistentTokenBalance { public var tokenDecimals: Int32? // MARK: - Network - /// Stored as the `AppNetwork.rawValue` `Int` so SwiftData + /// Stored as the `Network.rawValue` `UInt32` so SwiftData /// `#Predicate` expressions can evaluate it directly. See /// `PersistentIdentity.networkRaw` for the full rationale. - public var networkRaw: Int + public var networkRaw: UInt32 /// Type-safe accessor over `networkRaw`. Setter writes through. - public var network: AppNetwork { - get { AppNetwork(rawValue: networkRaw) ?? .testnet } + public var network: Network { + get { Network(rawValue: networkRaw) ?? .testnet } set { networkRaw = newValue.rawValue } } @@ -45,7 +45,7 @@ public final class PersistentTokenBalance { tokenName: String? = nil, tokenSymbol: String? = nil, tokenDecimals: Int32? = nil, - network: AppNetwork + network: Network ) { self.tokenId = tokenId self.identityId = identityId diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentWallet.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentWallet.swift index 948fe7a508..48d81eb39c 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentWallet.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentWallet.swift @@ -14,18 +14,18 @@ public final class PersistentWallet { /// the row was created by a changeset before `persistWalletMetadata` /// filled the network in. Views treat `nil` as unknown. /// - /// Stored as the `AppNetwork.rawValue` `Int?` so SwiftData + /// Stored as the `Network.rawValue` `UInt32?` so SwiftData /// `#Predicate` expressions can evaluate it directly. See /// `PersistentIdentity.networkRaw` for the full rationale. - public var networkRaw: Int? + public var networkRaw: UInt32? /// Type-safe accessor over `networkRaw`. `nil` round-trips as /// `nil`; non-nil reads fall back to `.testnet` if the stored - /// raw value ever drifts out of the `AppNetwork` range. - public var network: AppNetwork? { + /// raw value ever drifts out of the `Network` range. + public var network: Network? { get { guard let raw = networkRaw else { return nil } - return AppNetwork(rawValue: raw) ?? .testnet + return Network(rawValue: raw) ?? .testnet } set { networkRaw = newValue?.rawValue } } @@ -72,7 +72,7 @@ public final class PersistentWallet { public init( walletId: Data, - network: AppNetwork? = nil, + network: Network? = nil, name: String? = nil, birthHeight: UInt32 = 0, syncedHeight: UInt32 = 0, diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentWalletManagerMetadata.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentWalletManagerMetadata.swift index d5a96516f7..797a3fbe24 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentWalletManagerMetadata.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Persistence/Models/PersistentWalletManagerMetadata.swift @@ -9,7 +9,7 @@ import SwiftData public final class PersistentWalletManagerMetadata { /// Network this metadata row belongs to (unique per network). /// - /// Stored as the `AppNetwork.rawValue` `Int` rather than the + /// Stored as the `Network.rawValue` `UInt32` rather than the /// enum itself because SwiftData refuses `@Attribute(.unique)` /// on non-primitive types (Codable-wrapped raw-value enums are /// not "valid for unique constraints" per Core Data's rule) — @@ -17,7 +17,7 @@ public final class PersistentWalletManagerMetadata { /// computed accessor below keeps the public API type-safe; only /// predicates that need to filter by network have to reach for /// `networkRaw`. - @Attribute(.unique) public var networkRaw: Int + @Attribute(.unique) public var networkRaw: UInt32 /// Combined sync height across all wallets. public var combinedSyncHeight: UInt32 /// Combined sync block hash (32 bytes). @@ -30,14 +30,14 @@ public final class PersistentWalletManagerMetadata { /// Type-safe accessor over `networkRaw`. Reads fall back to /// `.testnet` if the stored raw value ever drifts out of the - /// `AppNetwork` range (shouldn't happen — writers only go - /// through this setter which uses `AppNetwork.rawValue`). - public var network: AppNetwork { - get { AppNetwork(rawValue: networkRaw) ?? .testnet } + /// `Network` range (shouldn't happen — writers only go + /// through this setter which uses `Network.rawValue`). + public var network: Network { + get { Network(rawValue: networkRaw) ?? .testnet } set { networkRaw = newValue.rawValue } } - public init(network: AppNetwork) { + public init(network: Network) { self.networkRaw = network.rawValue self.combinedSyncHeight = 0 self.walletCount = 0 diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift index 010014e85e..3fa4f8a5da 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift @@ -57,16 +57,16 @@ public class ManagedCoreWallet { } /// Get the network this wallet operates on. - public func network() throws -> PlatformNetwork { - var networkValue: UInt32 = 0 + public func network() throws -> Network { + var ffiNetwork = FFINetwork(0) var error = PlatformWalletFFIError() - let result = core_wallet_get_network(handle, &networkValue, &error) + let result = core_wallet_get_network(handle, &ffiNetwork, &error) guard result == PLATFORM_WALLET_FFI_RESULT_SUCCESS else { throw PlatformWalletError(result: result, error: error) } - return PlatformNetwork(rawValue: networkValue) ?? .testnet + return Network(ffiNetwork: ffiNetwork) } // MARK: - Addresses diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/DashPayService.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/DashPayService.swift index 6be547d142..67977a27c2 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/DashPayService.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/DashPayService.swift @@ -11,7 +11,7 @@ public final class DashPayService: Sendable { private let platformWallet: SendableBox private let identityManager: SendableBox private let currentIdentity: SendableBox - private let network: SendableBox + private let network: SendableBox public init() { self.platformWallet = SendableBox(nil) @@ -50,7 +50,7 @@ public final class DashPayService: Sendable { /// - mnemonic: BIP39 mnemonic phrase /// - network: Platform network (mainnet, testnet, devnet) /// - Throws: Error if wallet creation fails - public func initializeWallet(mnemonic: String, network: PlatformNetwork = .testnet) throws { + public func initializeWallet(mnemonic: String, network: Network = .testnet) throws { // Create platform wallet from mnemonic let wallet = try PlatformWallet.fromMnemonic(mnemonic) diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift index cac091d0a6..30c494e9c0 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/ManagedPlatformWallet.swift @@ -886,7 +886,7 @@ extension ManagedPlatformWallet { public func deriveIdentityAuthKeyAtSlot( identityIndex: UInt32, keyId: UInt32, - network: DashSDKNetwork, + network: Network, storage: WalletStorage = WalletStorage() ) throws -> IdentityRegistrationKeyPreview { // The FFI takes a 32-byte wallet id which the resolver uses @@ -909,7 +909,7 @@ extension ManagedPlatformWallet { let result = self.walletId.withUnsafeBytes { walletBytes -> PlatformWalletFFIResult in let walletPtr = walletBytes.bindMemory(to: UInt8.self).baseAddress! return dash_sdk_derive_identity_key_at_slot_with_resolver( - network, + network.ffiValue, walletPtr, resolver.handle, identityIndex, @@ -1016,7 +1016,7 @@ extension ManagedPlatformWallet { public func prePersistIdentityKeysForRegistration( identityIndex: UInt32, keyCount: UInt32, - network: DashSDKNetwork, + network: Network, keychain: KeychainManager = .shared, storage: WalletStorage = WalletStorage() ) throws -> [IdentityPubkey] { @@ -1043,7 +1043,7 @@ extension ManagedPlatformWallet { let result = self.walletId.withUnsafeBytes { walletBytes -> PlatformWalletFFIResult in let walletPtr = walletBytes.bindMemory(to: UInt8.self).baseAddress return dash_sdk_derive_and_persist_identity_keys( - network, + network.ffiValue, walletPtr, identityIndex, keyCount, diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWallet.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWallet.swift index 0623e5419e..cb7e232070 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWallet.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWallet.swift @@ -4,7 +4,7 @@ import DashSDKFFI /// Platform Wallet for managing identities and DashPay contacts public class PlatformWallet { private let handle: Handle - private var identityManagers: [PlatformNetwork: IdentityManager] = [:] + private var identityManagers: [Network: IdentityManager] = [:] private init(handle: Handle) { self.handle = handle @@ -15,7 +15,7 @@ public class PlatformWallet { } /// Create a new Platform Wallet from a 64-byte seed - public static func fromSeed(_ seed: Data, network: PlatformNetwork = .testnet) throws -> PlatformWallet { + public static func fromSeed(_ seed: Data, network: Network = .testnet) throws -> PlatformWallet { guard seed.count == 64 else { throw PlatformWalletError.invalidParameter } @@ -44,7 +44,7 @@ public class PlatformWallet { public static func fromMnemonic( _ mnemonic: String, passphrase: String? = nil, - network: PlatformNetwork = .testnet + network: Network = .testnet ) throws -> PlatformWallet { var handle: Handle = NULL_HANDLE var error = PlatformWalletFFIError() @@ -68,7 +68,7 @@ public class PlatformWallet { } /// Get the identity manager for a specific network - public func getIdentityManager(for network: PlatformNetwork) throws -> IdentityManager { + public func getIdentityManager(for network: Network) throws -> IdentityManager { // Check if we already have it cached if let manager = identityManagers[network] { return manager @@ -93,7 +93,7 @@ public class PlatformWallet { } /// Set the identity manager for a specific network - public func setIdentityManager(_ manager: IdentityManager, for network: PlatformNetwork) throws { + public func setIdentityManager(_ manager: IdentityManager, for network: Network) throws { var error = PlatformWalletFFIError() let result = platform_wallet_info_set_identity_manager( diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManager.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManager.swift index 84d01eb5e8..23c7e2d73b 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManager.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManager.swift @@ -154,7 +154,7 @@ public class PlatformWalletManager: ObservableObject { @discardableResult public func createWallet( mnemonic: String, - network: PlatformNetwork, + network: Network, name: String? = nil, createDefaultAccounts: Bool = true ) throws -> ManagedPlatformWallet { @@ -173,7 +173,7 @@ public class PlatformWalletManager: ObservableObject { platform_wallet_manager_create_wallet_from_mnemonic( handle, mnemonicPtr, - network.rawValue, + network.ffiValue, accountOptions, &walletHandle, &walletId, @@ -198,7 +198,7 @@ public class PlatformWalletManager: ObservableObject { @discardableResult public func createWallet( seed: Data, - network: PlatformNetwork, + network: Network, name: String? = nil, createDefaultAccounts: Bool = true ) throws -> ManagedPlatformWallet { @@ -220,7 +220,7 @@ public class PlatformWalletManager: ObservableObject { let result = seed.withUnsafeBytes { seedPtr in platform_wallet_manager_create_wallet_from_seed( handle, - network.rawValue, + network.ffiValue, seedPtr.baseAddress?.assumingMemoryBound(to: UInt8.self), UInt(seed.count), accountOptions, diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerSPV.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerSPV.swift index 69fee0109d..9f0bb4ac78 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerSPV.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletManagerSPV.swift @@ -100,7 +100,7 @@ public struct PlatformSpvSyncProgress: Sendable, Equatable { /// Config for starting the SPV sync. public struct PlatformSpvStartConfig { public var dataDir: String - public var network: PlatformNetwork + public var network: Network public var userAgent: String? public var peers: [String] public var restrictToConfiguredPeers: Bool @@ -109,7 +109,7 @@ public struct PlatformSpvStartConfig { public init( dataDir: String, - network: PlatformNetwork, + network: Network, userAgent: String? = nil, peers: [String] = [], restrictToConfiguredPeers: Bool = false, @@ -188,7 +188,7 @@ extension PlatformWalletManager { return platform_wallet_manager_spv_start( handle, dataDirPtr, - config.network.rawValue, + config.network.ffiValue, userAgentPtr, peersPtr, UInt(peerCStrings.count), diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletPersistenceHandler.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletPersistenceHandler.swift index 34312ba877..81da84f9d1 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletPersistenceHandler.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletPersistenceHandler.swift @@ -189,7 +189,7 @@ public class PlatformWalletPersistenceHandler { } /// Load cached sync state for a specific network. - public func loadCachedSyncState(network: AppNetwork) -> (syncHeight: UInt64, syncTimestamp: UInt64, lastKnownRecentBlock: UInt64)? { + public func loadCachedSyncState(network: Network) -> (syncHeight: UInt64, syncTimestamp: UInt64, lastKnownRecentBlock: UInt64)? { onQueue { loadCachedSyncStateOnQueue(network: network) } } @@ -198,7 +198,7 @@ public class PlatformWalletPersistenceHandler { /// route through this so the `(walletId:)` variant can resolve /// the network and read the row in a single queue hop without /// recursing into `onQueue`, which would deadlock. - private func loadCachedSyncStateOnQueue(network: AppNetwork) -> (syncHeight: UInt64, syncTimestamp: UInt64, lastKnownRecentBlock: UInt64)? { + private func loadCachedSyncStateOnQueue(network: Network) -> (syncHeight: UInt64, syncTimestamp: UInt64, lastKnownRecentBlock: UInt64)? { let scopeId = syncStateScopeId(for: network) let descriptor = FetchDescriptor( predicate: #Predicate { $0.walletId == scopeId } @@ -1418,7 +1418,7 @@ public class PlatformWalletPersistenceHandler { print("⚠️ deriveAndStoreIdentityKey: wallet row not found for \(walletId.prefix(4).toHexString())…") return nil } - let network: KeyWalletNetwork = persistentWallet.network?.toKeyWalletNetwork() ?? .testnet + let network: Network = persistentWallet.network ?? .testnet // 2. Fetch the mnemonic UTF-8 bytes for this wallet from the // keychain. Keep the call site off Swift `String` so the @@ -1825,10 +1825,10 @@ public class PlatformWalletPersistenceHandler { /// once at wallet registration with values the Rust side can /// contribute but Swift can't easily recompute (network is on the /// manager's SDK; birth height is SPV's confirmed tip at creation). - func persistWalletMetadata(walletId: Data, networkTag: UInt8, birthHeight: UInt32) { + func persistWalletMetadata(walletId: Data, network: Network, birthHeight: UInt32) { onQueue { let wallet = ensureWalletRecord(walletId: walletId) - wallet.network = appNetwork(for: networkTag) + wallet.network = network wallet.birthHeight = birthHeight wallet.lastUpdated = Date() if !self.inChangeset { try? backgroundContext.save() } @@ -1848,22 +1848,6 @@ public class PlatformWalletPersistenceHandler { } } - /// Reverse of the tag convention used by - /// `platform_wallet_manager_create_wallet_from_seed`. Note the - /// tag ordering (0=mainnet, 1=testnet, 2=devnet, 3=regtest) - /// intentionally does not match `AppNetwork.rawValue` - /// (which swaps devnet/regtest to align with `KeyWalletNetwork`), - /// so this has to stay an explicit switch. - private func appNetwork(for tag: UInt8) -> AppNetwork? { - switch tag { - case 0: return .mainnet - case 1: return .testnet - case 2: return .devnet - case 3: return .regtest - default: return nil - } - } - // MARK: - Watch-only Restore: Account xpub /// Upsert a `PersistentAccount` row with the full `AccountSpecFFI` @@ -2074,7 +2058,7 @@ public class PlatformWalletPersistenceHandler { var entry = WalletRestoreEntryFFI() copyBytes(w.walletId, into: &entry.wallet_id) - entry.network = networkTag(for: w.network) + entry.network = (w.network ?? .testnet).ffiValue entry.accounts = accountsBuffer.map { UnsafePointer($0) } entry.accounts_count = UInt(sortedAccounts.count) entry.platform_address_balances = addressBalancesBuffer.map { UnsafePointer($0) } @@ -2297,25 +2281,10 @@ public class PlatformWalletPersistenceHandler { } } - /// Inverse of `appNetwork(for:)`. The Rust-side tag convention - /// (0=mainnet, 1=testnet, 2=devnet, 3=regtest) differs from - /// `AppNetwork.rawValue` ordering, so this has to stay an - /// explicit switch. `nil` defaults to testnet (tag=1) — - /// matches the old "unknown" fallback during dev. - private func networkTag(for network: AppNetwork?) -> UInt8 { - switch network { - case .mainnet: return 0 - case .testnet: return 1 - case .devnet: return 2 - case .regtest: return 3 - case .none: return 1 - } - } - /// Build the 32-byte synthetic walletId used as the uniqueness /// key for the per-network `PersistentPlatformAddressesSyncState` row. The content /// is "platform-sync:" zero-padded to 32 bytes. - private func syncStateScopeId(for network: AppNetwork) -> Data { + private func syncStateScopeId(for network: Network) -> Data { let scopeString = "platform-sync:\(network.networkName)" var data = Data(scopeString.utf8.prefix(32)) if data.count < 32 { @@ -2327,7 +2296,7 @@ public class PlatformWalletPersistenceHandler { /// Look up the network for a wallet id by reading the owning /// `PersistentWallet` row. Returns `nil` if the wallet row /// doesn't exist or its network hasn't been resolved yet. - private func walletNetwork(walletId: Data) -> AppNetwork? { + private func walletNetwork(walletId: Data) -> Network? { let descriptor = FetchDescriptor( predicate: #Predicate { $0.walletId == walletId } ) @@ -3055,7 +3024,7 @@ private func dataFromTuple20(_ tuple: FFIByteTuple20) -> Data { private func persistWalletMetadataCallback( context: UnsafeMutableRawPointer?, walletIdPtr: UnsafePointer?, - networkTag: UInt8, + network: FFINetwork, birthHeight: UInt32 ) -> Int32 { guard let context = context, @@ -3068,7 +3037,7 @@ private func persistWalletMetadataCallback( let walletId = Data(bytes: walletIdPtr, count: 32) handler.persistWalletMetadata( walletId: walletId, - networkTag: networkTag, + network: Network(ffiNetwork: network), birthHeight: birthHeight ) return 0 diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift index a2751691df..7b951339e9 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletTypes.swift @@ -20,8 +20,6 @@ extension Identifier { } } -typealias NetworkType = UInt32 - /// Platform Wallet error types public enum PlatformWalletError: LocalizedError { case nullPointer @@ -103,18 +101,6 @@ public enum PlatformWalletError: LocalizedError { } } -/// Network type for Platform wallet -public enum PlatformNetwork: UInt32 { - case mainnet = 0 - case testnet = 1 - case devnet = 2 - case local = 3 - - var ffiValue: NetworkType { - NetworkType(self.rawValue) - } -} - /// Identity lifecycle status as carried on the Rust-side /// `ManagedIdentity.status`. Mirrors `IdentityStatusFFI` / /// `platform_wallet::wallet::identity::state::managed_identity::IdentityStatus`. diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/SDK.swift b/packages/swift-sdk/Sources/SwiftDashSDK/SDK.swift index 9639efb1be..5f9ef81596 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/SDK.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/SDK.swift @@ -52,7 +52,7 @@ public final class SDK: @unchecked Sendable { public private(set) var handle: UnsafeMutablePointer? /// The network this SDK instance is connected to - public private(set) var network: Network = DashSDKNetwork(rawValue: 1) // Default to testnet + public private(set) var network: Network = .testnet /// Identities operations public lazy var identities = Identities(sdk: self) @@ -152,7 +152,7 @@ public final class SDK: @unchecked Sendable { /// This is suitable for mobile applications where proof verification would be resource-intensive. public init(network: Network) throws { var config = DashSDKConfig() - config.network = network + config.network = network.ffiValue config.dapi_addresses = nil config.skip_asset_lock_proof_verification = false config.request_retry_count = 1 diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Services/DataManager.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Services/DataManager.swift index d97be57423..b46b40554f 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Services/DataManager.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Services/DataManager.swift @@ -18,9 +18,9 @@ import SwiftData @MainActor public final class DataManager: ObservableObject { private let modelContext: ModelContext - public var currentNetwork: AppNetwork + public var currentNetwork: Network - public init(modelContext: ModelContext, currentNetwork: AppNetwork = .testnet) { + public init(modelContext: ModelContext, currentNetwork: Network = .testnet) { self.modelContext = modelContext self.currentNetwork = currentNetwork } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/SwiftDashSDK.swift b/packages/swift-sdk/Sources/SwiftDashSDK/SwiftDashSDK.swift index 4933dfb296..ca3e4b2dbf 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/SwiftDashSDK.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/SwiftDashSDK.swift @@ -1,7 +1,5 @@ // Re-export all C types so they're available to clients @_exported import DashSDKFFI -// Type aliases for easier access -public typealias Network = DashSDKNetwork public typealias ErrorCode = DashSDKErrorCode public typealias SDKConfig = DashSDKConfig diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Utils/KeyValidation.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Utils/KeyValidation.swift index 8b82414910..00d144754e 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Utils/KeyValidation.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Utils/KeyValidation.swift @@ -8,7 +8,7 @@ public enum KeyValidation { privateKeyHex: String, publicKeyHex: String, keyType: KeyType, - isTestnet: Bool = true + network: Network = .testnet ) -> Bool { // Convert key type to FFI representation let ffiKeyType: UInt8 @@ -27,7 +27,7 @@ public enum KeyValidation { let result = privateKeyHex.withCString { privateKeyCStr in publicKeyHex.withCString { publicKeyCStr in - dash_sdk_validate_private_key_for_public_key(privateKeyCStr, publicKeyCStr, ffiKeyType, isTestnet) + dash_sdk_validate_private_key_for_public_key(privateKeyCStr, publicKeyCStr, ffiKeyType, network.ffiValue) } } @@ -59,7 +59,7 @@ public enum KeyValidation { public static func matchPrivateKeyToPublicKeys( privateKeyData: Data, publicKeys: [IdentityPublicKey], - isTestnet: Bool = true + network: Network = .testnet ) -> IdentityPublicKey? { let privateKeyHex = privateKeyData.toHexString() @@ -70,7 +70,7 @@ public enum KeyValidation { privateKeyHex: privateKeyHex, publicKeyHex: publicKeyHex, keyType: publicKey.keyType, - isTestnet: isTestnet + network: network ) { return publicKey } diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/Utils/PrivateKeyUtils.swift b/packages/swift-sdk/Sources/SwiftDashSDK/Utils/PrivateKeyUtils.swift index 76ce3cc8fa..fd83426778 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/Utils/PrivateKeyUtils.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/Utils/PrivateKeyUtils.swift @@ -181,12 +181,12 @@ public enum KeyValidator { /// - Parameters: /// - privateKey: The private key data (32 bytes). /// - publicKeys: List of public keys to match against. - /// - isTestnet: Whether to use testnet parameters. + /// - network: Which network the keys belong to (default: testnet). /// - Returns: ValidationResult with the matched key or error. public static func validatePrivateKey( _ privateKey: Data, against publicKeys: [IdentityPublicKey], - isTestnet: Bool = true + network: Network = .testnet ) -> ValidationResult { guard privateKey.count == 32 else { return .invalid("Private key must be 32 bytes, got \(privateKey.count)") @@ -199,7 +199,7 @@ public enum KeyValidator { if let matchedKey = KeyValidation.matchPrivateKeyToPublicKeys( privateKeyData: privateKey, publicKeys: publicKeys, - isTestnet: isTestnet + network: network ) { return .valid(matchedKey: matchedKey) } @@ -211,12 +211,12 @@ public enum KeyValidator { /// - Parameters: /// - privateKeyInput: The private key string (hex or WIF). /// - publicKeys: List of public keys to match against. - /// - isTestnet: Whether to use testnet parameters. + /// - network: Which network the keys belong to (default: testnet). /// - Returns: ValidationResult with the matched key or error. public static func validatePrivateKeyInput( _ privateKeyInput: String, against publicKeys: [IdentityPublicKey], - isTestnet: Bool = true + network: Network = .testnet ) -> ValidationResult { let parseResult = PrivateKeyParser.parse(privateKeyInput) @@ -224,7 +224,7 @@ public enum KeyValidator { return .invalid(parseResult.error ?? "Failed to parse private key") } - return validatePrivateKey(privateKey, against: publicKeys, isTestnet: isTestnet) + return validatePrivateKey(privateKey, against: publicKeys, network: network) } } @@ -276,10 +276,10 @@ public enum KeyFormatter { /// Format a private key as WIF string. /// - Parameters: /// - privateKey: The private key data. - /// - isTestnet: Whether to encode for testnet. + /// - network: Which network the key belongs to (default: testnet). /// - Returns: WIF string or nil if encoding fails. - public static func toWIF(_ privateKey: Data, isTestnet: Bool = true) -> String? { - WIFParser.encodeToWIF(privateKey, isTestnet: isTestnet) + public static func toWIF(_ privateKey: Data, network: Network = .testnet) -> String? { + WIFParser.encodeToWIF(privateKey, network: network) } /// Format a public key for display. diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/AppState.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/AppState.swift index 8a04aabe4a..b56e46c417 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/AppState.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/AppState.swift @@ -9,9 +9,9 @@ class AppState: ObservableObject { @Published var showError = false @Published var errorMessage = "" - @Published var currentNetwork: AppNetwork { + @Published var currentNetwork: Network { didSet { - UserDefaults.standard.set(currentNetwork.rawValue, forKey: "currentNetwork") + UserDefaults.standard.set(Int(currentNetwork.rawValue), forKey: "currentNetwork") Task { await switchNetwork(to: currentNetwork) } @@ -45,7 +45,7 @@ class AppState: ObservableObject { // `object(forKey:)` and cast — `integer(forKey:)` returns 0 // for missing keys, which would silently pin to mainnet. if let rawInt = UserDefaults.standard.object(forKey: "currentNetwork") as? Int, - let network = AppNetwork(rawValue: rawInt) { + let network = Network(rawValue: UInt32(rawInt)) { self.currentNetwork = network } else { self.currentNetwork = .testnet @@ -78,9 +78,8 @@ class AppState: ObservableObject { SDK.initialize() SDK.enableLogging(level: .debug) - let sdkNetwork: DashSDKNetwork = currentNetwork.sdkNetwork NSLog("🔵 AppState: Creating SDK for network=\(currentNetwork), docker=\(useDockerSetup)") - let newSDK = try SDK(network: sdkNetwork) + let newSDK = try SDK(network: currentNetwork) sdk = newSDK NSLog("✅ AppState: SDK created successfully") @@ -102,7 +101,7 @@ class AppState: ObservableObject { showError = true } - func switchNetwork(to network: AppNetwork) async { + func switchNetwork(to network: Network) async { guard let modelContext = modelContext else { return } // Identities, contracts, documents, and token balances are @@ -118,8 +117,7 @@ class AppState: ObservableObject { isLoading = true // Create new SDK instance for the network - let sdkNetwork: DashSDKNetwork = network.sdkNetwork - let newSDK = try SDK(network: sdkNetwork) + let newSDK = try SDK(network: network) sdk = newSDK // Load known contracts into the SDK's trusted provider diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/ContentView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/ContentView.swift index 18b6459b92..2bb6b5cb9b 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/ContentView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/ContentView.swift @@ -261,7 +261,7 @@ struct ContentView: View { // is created by the persister callback downstream of // `walletManager.createWallet` — we only need to // stamp the `isImported` flag here. - let platformNetwork: PlatformNetwork = .testnet + let platformNetwork: Network = .testnet let label = "Recovered Wallet" let managed = try walletManager.createWallet( mnemonic: mnemonic, diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Models/DashAddress.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Models/DashAddress.swift index 2638357967..388600199d 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Models/DashAddress.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Models/DashAddress.swift @@ -13,7 +13,7 @@ struct DashAddress { let displayString: String /// Parse any address string and detect its type - static func parse(_ input: String, network: AppNetwork) -> DashAddress { + static func parse(_ input: String, network: Network) -> DashAddress { // 1. Try bech32m first if let decoded = Bech32m.decode(input) { let hrp = decoded.hrp @@ -45,7 +45,7 @@ struct DashAddress { } // 2. Try Core address — validate via Rust FFI (Base58Check + network) - let keyWalletNetwork: KeyWalletNetwork = (network == .mainnet) ? .mainnet : .testnet + let keyWalletNetwork: Network = (network == .mainnet) ? .mainnet : .testnet if Address.validate(input, network: keyWalletNetwork), let script = coreAddressToOutputScript(input) { return DashAddress(type: .core(script), displayString: input) @@ -57,7 +57,7 @@ struct DashAddress { /// Encode raw 43-byte Orchard address to bech32m display string. /// Prepends 0x10 type byte then bech32m encodes with dash/tdash HRP. - static func encodeOrchard(rawBytes: Data, network: AppNetwork) -> String? { + static func encodeOrchard(rawBytes: Data, network: Network) -> String? { guard rawBytes.count == 43 else { return nil } let hrp = (network == .mainnet) ? "dash" : "tdash" var payload = Data([0x10]) @@ -66,7 +66,7 @@ struct DashAddress { } /// Encode 21-byte platform address to bech32m display string - static func encodePlatform(rawBytes: Data, network: AppNetwork) -> String? { + static func encodePlatform(rawBytes: Data, network: Network) -> String? { guard rawBytes.count == 21 else { return nil } let hrp = (network == .mainnet) ? "dashevo" : "tdashevo" return Bech32m.encode(hrp: hrp, data: rawBytes) diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/ShieldedService.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/ShieldedService.swift index 914e9e0c6d..f5d114a235 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/ShieldedService.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/ShieldedService.swift @@ -12,7 +12,7 @@ class ShieldedService: ObservableObject { private(set) var poolClient: ShieldedPoolClient? private var spendingKey: Data? - private var currentNetwork: AppNetwork? + private var currentNetwork: Network? /// Initialize (or reinitialize) the shielded pool client. /// @@ -22,7 +22,7 @@ class ShieldedService: ObservableObject { /// - Parameters: /// - seed: Wallet seed (>= 32 bytes). First 32 bytes used as spending key. /// - network: Current network. - func initialize(seed: Data, network: AppNetwork) { + func initialize(seed: Data, network: Network) { guard seed.count >= 32 else { lastError = "Seed must be at least 32 bytes" return @@ -107,7 +107,7 @@ class ShieldedService: ObservableObject { // MARK: - Private - private static func dbPath(for network: AppNetwork) -> String { + private static func dbPath(for network: Network) -> String { let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! return docs.appendingPathComponent("shielded_\(network.networkName).sqlite").path } diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/ZKSyncService.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/ZKSyncService.swift index c19237bafd..9aeabfa903 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/ZKSyncService.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Services/ZKSyncService.swift @@ -71,7 +71,7 @@ class ZKSyncService: ObservableObject { /// Initialize for a network. Restores persisted balance and address. /// The actual periodic loop is managed by UnifiedAppState. - func startPeriodicSync(network: AppNetwork) { + func startPeriodicSync(network: Network) { networkName = network.networkName // Restore persisted state from previous session diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/ViewModels/SendViewModel.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/ViewModels/SendViewModel.swift index af52c65c3d..6a23fbd8c8 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/ViewModels/SendViewModel.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/ViewModels/SendViewModel.swift @@ -83,9 +83,9 @@ class SendViewModel: ObservableObject { @Published var error: String? @Published var successMessage: String? - private let network: AppNetwork + private let network: Network - init(network: AppNetwork) { + init(network: Network) { self.network = network } @@ -204,9 +204,9 @@ class SendViewModel: ObservableObject { // hasn't had its network stamped yet — a wallet in // that state has no identities to find anyway. // - // Filter against `networkRaw` (the Int-backed shadow + // Filter against `networkRaw` (the UInt32-backed shadow // field) because Foundation's predicate engine can't - // capture `AppNetwork`. + // capture `Network`. let walletNetworkRaw = (wallet.network ?? .testnet).rawValue let amountThreshold = Int64(bitPattern: amount) let descriptor = FetchDescriptor( diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/CoreContentView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/CoreContentView.swift index 343d5cc38d..95c5ee0b2d 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/CoreContentView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/CoreContentView.swift @@ -469,7 +469,7 @@ var body: some View { let config = PlatformSpvStartConfig( dataDir: dataDirURL.path, - network: platformNetwork(from: platformState.currentNetwork), + network: platformState.currentNetwork, peers: peers, restrictToConfiguredPeers: useLocalCore, masternodeSyncEnabled: masternodesEnabled @@ -508,14 +508,6 @@ var body: some View { } } - private func platformNetwork(from network: AppNetwork) -> PlatformNetwork { - switch network { - case .mainnet: return .mainnet - case .testnet: return .testnet - case .devnet: return .devnet - case .regtest: return .testnet - } - } } // MARK: - Compact Sync Row diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/CreateWalletView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/CreateWalletView.swift index 80dec9b294..e8a9171605 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/CreateWalletView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/CreateWalletView.swift @@ -35,7 +35,7 @@ struct CreateWalletView: View { case mnemonic } - var currentNetwork: AppNetwork { + var currentNetwork: Network { platformState.currentNetwork } @@ -280,28 +280,19 @@ struct CreateWalletView: View { print("Import option enabled: \(showImportOption)") // Determine primary network to create the wallet in (SDK enforces unique wallet per mnemonic) - let selectedNetworks: [AppNetwork] = [ - createForMainnet ? AppNetwork.mainnet : nil, - createForTestnet ? AppNetwork.testnet : nil, - (createForDevnet && shouldShowDevnet) ? AppNetwork.devnet : nil, + let selectedNetworks: [Network] = [ + createForMainnet ? Network.mainnet : nil, + createForTestnet ? Network.testnet : nil, + (createForDevnet && shouldShowDevnet) ? Network.devnet : nil, ].compactMap { $0 } - guard let primaryNetwork = selectedNetworks.first else { + guard let platformNetwork = selectedNetworks.first else { struct MissingNetwork: LocalizedError { var errorDescription: String? { "No network selected" } } throw MissingNetwork() } - let platformNetwork: PlatformNetwork = { - switch primaryNetwork { - case .mainnet: return .mainnet - case .testnet: return .testnet - case .devnet: return .devnet - case .regtest: return .testnet - } - }() - // Create exactly one wallet via PlatformWalletManager. // The Rust-side wallet creation emits // `persistWalletMetadata` + `setWalletName`, which @@ -354,7 +345,7 @@ struct CreateWalletView: View { dismiss() } - print("=== WALLET CREATION SUCCESS - Created 1 wallet for \(primaryNetwork.displayName) ===") + print("=== WALLET CREATION SUCCESS - Created 1 wallet for \(platformNetwork.displayName) ===") } catch { print("=== WALLET CREATION ERROR ===") print("Error: \(error)") diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/WalletDetailView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/WalletDetailView.swift index cce1735206..d272e54a72 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/WalletDetailView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/Views/WalletDetailView.swift @@ -526,7 +526,7 @@ struct WalletInfoView: View { } } - private func enableNetwork(_ network: AppNetwork) async { + private func enableNetwork(_ network: Network) async { isUpdatingNetworks = true defer { isUpdatingNetworks = false } diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/SwiftExampleAppApp.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/SwiftExampleAppApp.swift index 3f1978646d..00d17f241c 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/SwiftExampleAppApp.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/SwiftExampleAppApp.swift @@ -192,15 +192,6 @@ struct SwiftExampleAppApp: App { // MARK: - Helpers - private func platformNetwork(from network: AppNetwork) -> PlatformNetwork { - switch network { - case .mainnet: return .mainnet - case .testnet: return .testnet - case .devnet: return .devnet - case .regtest: return .testnet - } - } - /// Read local Core peers from UserDefaults (comma-separated addresses). private func readLocalCorePeers() -> [String] { if let csv = UserDefaults.standard.string(forKey: "localCorePeers"), !csv.isEmpty { diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Utils/ContractDownloader.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Utils/ContractDownloader.swift index 6693af2dc6..8ac296cfb9 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Utils/ContractDownloader.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Utils/ContractDownloader.swift @@ -131,7 +131,7 @@ public enum ContractDownloader { suggestedName: String?, sdk: SDK, modelContext: ModelContext, - network: AppNetwork, + network: Network, existingContracts: [PersistentDataContract]? = nil ) async throws -> ContractDownloadResult { let trimmedId = contractId.trimmingCharacters(in: .whitespacesAndNewlines) @@ -360,7 +360,7 @@ public enum ContractDownloader { public static func previewContractInMemory( contractId: String, sdk: SDK, - network: AppNetwork + network: Network ) async throws -> ContractPreviewState { let trimmedId = contractId.trimmingCharacters(in: .whitespacesAndNewlines) guard !trimmedId.isEmpty else { diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/AddIdentityKeyView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/AddIdentityKeyView.swift index 4b5722c939..fe641a9888 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/AddIdentityKeyView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/AddIdentityKeyView.swift @@ -302,7 +302,7 @@ struct AddIdentityKeyView: View { errorMessage = "Wallet not loaded in the wallet manager." return } - let network = appState.sdk?.network ?? DashSDKNetwork(rawValue: 1) + let network = appState.sdk?.network ?? .testnet let chosenKeyId = nextKeyId let chosenSecurityLevel = effectiveSecurityLevel @@ -345,15 +345,12 @@ struct AddIdentityKeyView: View { // Validation goes against the compressed pubkey // (33 bytes) regardless of `keyType`; the HASH160 // variant just stores a different on-chain payload. - // `DashSDKNetwork` is a `(rawValue: UInt32)` struct; - // 0 = mainnet, 1 = testnet (see SDK.swift's default). - let isMainnet = (network.rawValue == 0) guard KeyValidation.validatePrivateKeyForPublicKey( privateKeyHex: preview.privateKeyData.toHexString(), publicKeyHex: preview.publicKeyHex, keyType: .ecdsaSecp256k1, - isTestnet: !isMainnet + network: network ) else { isSubmitting = false diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/AddressQueriesView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/AddressQueriesView.swift index 10d00f4323..5f1b1409c6 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/AddressQueriesView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/AddressQueriesView.swift @@ -215,10 +215,10 @@ struct GetAddressInfoView: View { .cornerRadius(8) } else if let info = viewModel.result { VStack(alignment: .leading, spacing: 8) { - let network = + let network: Network = viewModel.addressInput.lowercased().hasPrefix("tdashevo") - ? DashSDKNetwork(rawValue: 1) - : DashSDKNetwork(rawValue: 0) + ? .testnet + : .mainnet let bech32mAddress = info.toBech32m(network: network) ?? info.addressHex ResultRow(label: "Address", value: bech32mAddress) @@ -355,7 +355,7 @@ struct GetAddressesInfosView: View { .cornerRadius(8) } else if let result = viewModel.result { let isTestnet = viewModel.addressesText.lowercased().contains("tdashevo") - let network = isTestnet ? DashSDKNetwork(rawValue: 1) : DashSDKNetwork(rawValue: 0) + let network: Network = isTestnet ? .testnet : .mainnet VStack(alignment: .leading, spacing: 12) { HStack { @@ -1088,7 +1088,7 @@ struct GetRecentBalanceChangesView: View { .padding(.horizontal) } else if let changes = result { // Get network from SDK (0 = mainnet, 1 = testnet) - let network = appState.sdk?.network ?? DashSDKNetwork(rawValue: 1) + let network = appState.sdk?.network ?? .testnet RecentBalanceChangesResultView(changes: changes, network: network) .padding(.horizontal) } @@ -1142,7 +1142,7 @@ struct GetRecentBalanceChangesView: View { struct RecentBalanceChangesResultView: View { let changes: RecentBalanceChanges - let network: DashSDKNetwork + let network: Network var body: some View { VStack(alignment: .leading, spacing: 16) { @@ -1184,7 +1184,7 @@ struct RecentBalanceChangesResultView: View { struct BlockBalanceChangesView: View { let block: BlockBalanceChanges - let network: DashSDKNetwork + let network: Network @State private var isExpanded = false @@ -1221,7 +1221,7 @@ struct BlockBalanceChangesView: View { struct AddressBalanceChangeView: View { let change: AddressBalanceChange - let network: DashSDKNetwork + let network: Network var body: some View { VStack(alignment: .leading, spacing: 8) { @@ -1378,7 +1378,7 @@ struct GetCompactedBalanceChangesView: View { .padding(.horizontal) } else if let changes = result { // Get network from SDK - let network = appState.sdk?.network ?? DashSDKNetwork(rawValue: 1) + let network = appState.sdk?.network ?? .testnet CompactedBalanceChangesResultView(changes: changes, network: network) .padding(.horizontal) } @@ -1432,7 +1432,7 @@ struct GetCompactedBalanceChangesView: View { struct CompactedBalanceChangesResultView: View { let changes: CompactedBalanceChanges - let network: DashSDKNetwork + let network: Network var body: some View { VStack(alignment: .leading, spacing: 16) { @@ -1474,7 +1474,7 @@ struct CompactedBalanceChangesResultView: View { struct CompactedBlockRangeView: View { let range: CompactedBlockRange - let network: DashSDKNetwork + let network: Network @State private var isExpanded = false @@ -1511,7 +1511,7 @@ struct CompactedBlockRangeView: View { struct CompactedAddressChangeView: View { let change: CompactedAddressChange - let network: DashSDKNetwork + let network: Network var body: some View { VStack(alignment: .leading, spacing: 8) { diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/Components/RecipientPickerView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/Components/RecipientPickerView.swift index 373ffa1da5..e5502df18a 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/Components/RecipientPickerView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/Components/RecipientPickerView.swift @@ -27,7 +27,7 @@ struct RecipientPickerView: View { /// wallet; it only calls `resolveDpnsName`. let wallet: ManagedPlatformWallet /// Limits the local-identity list to identities on this network. - let network: AppNetwork + let network: Network /// Optional identity id to exclude (e.g. the sender — you can't /// transfer to yourself). let exclude: Data? @@ -58,7 +58,7 @@ struct RecipientPickerView: View { init( selection: Binding, wallet: ManagedPlatformWallet, - network: AppNetwork, + network: Network, exclude: Data? = nil ) { self._selection = selection diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/ContractsTabView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/ContractsTabView.swift index cfa4e2a925..0a64ecdfa4 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/ContractsTabView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/ContractsTabView.swift @@ -41,7 +41,7 @@ struct ContractsTabView: View { /// predicates below; the parent re-creates the view when the /// active network changes (SwiftUI sees `network` move and /// re-runs `init`, which rebuilds the `@Query` predicate). - private let network: AppNetwork + private let network: Network @Query private var dataContracts: [PersistentDataContract] @@ -53,7 +53,7 @@ struct ContractsTabView: View { /// name in different contracts stay distinguishable. @Query private var allTokens: [PersistentToken] - init(network: AppNetwork) { + init(network: Network) { self.network = network let target = network.rawValue // `PersistentDataContract.predicate(network:)` already exists diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/CreateIdentityView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/CreateIdentityView.swift index 4f5a558254..fdb1b95595 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/CreateIdentityView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/CreateIdentityView.swift @@ -442,7 +442,7 @@ struct CreateIdentityView: View { identityPubkeys = try managedWallet.prePersistIdentityKeysForRegistration( identityIndex: identityIndex, keyCount: Self.defaultKeyCount, - network: platformState.currentNetwork.sdkNetwork + network: platformState.currentNetwork ) } catch { submitError = .init( @@ -465,7 +465,7 @@ struct CreateIdentityView: View { isCreating = true - let network: AppNetwork = platformState.currentNetwork + let network: Network = platformState.currentNetwork Task { do { @@ -571,7 +571,7 @@ struct CreateIdentityView: View { /// `"derived:"` identifiers — no Keychain write needed. private func persistCreatedIdentity( _ created: ManagedPlatformWallet.CreatedIdentity, - network: AppNetwork + network: Network ) throws { let identityId = created.identityId let descriptor = FetchDescriptor( diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/KeysListView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/KeysListView.swift index 7607abf1a8..104d0e3327 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/KeysListView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/KeysListView.swift @@ -456,18 +456,11 @@ struct PrivateKeyView: View { } private func getWIFForPrivateKey(_ privateKeyData: Data) -> String? { - // Mainnet → `X…` compressed prefix; testnet → `c…`. The SDK - // exposes the active network on its handle; fall back to - // testnet when the SDK isn't loaded so the call still produces - // *some* WIF rather than `nil`. - let isTestnet: Bool = { - guard let sdkNetwork = appState.sdk?.network else { return true } - // `DashSDKNetwork(rawValue: 0)` is mainnet in the FFI; - // anything else is treated as testnet for WIF version-byte - // selection (devnet / regtest share the testnet byte). - return sdkNetwork.rawValue != 0 - }() - return WIFParser.encodeToWIF(privateKeyData, isTestnet: isTestnet) + // Mainnet → `X…` compressed prefix; every other network → `c…`. + // Fall back to testnet when the SDK isn't loaded so the call + // still produces *some* WIF rather than `nil`. + let network = appState.sdk?.network ?? .testnet + return WIFParser.encodeToWIF(privateKeyData, network: network) } } diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/LoadIdentityView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/LoadIdentityView.swift index 3bac1c3d11..fdfaab40f7 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/LoadIdentityView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/LoadIdentityView.swift @@ -45,7 +45,7 @@ struct LoadIdentityView: View { private var formView: some View { Form { - if appState.sdk?.network.rawValue == 1 && testnetNodes != nil { // testnet + if appState.sdk?.network == .testnet && testnetNodes != nil { Section { HStack { Button("Fill Random HPMN") { @@ -469,7 +469,7 @@ struct LoadIdentityView: View { if let matched = KeyValidation.matchPrivateKeyToPublicKeys( privateKeyData: privateKey, publicKeys: capturedPublicKeys, - isTestnet: network == .testnet + network: network ), let persistentKey = row.publicKeys.first( where: { $0.keyId == Int32(matched.id) } ), let keychainId = KeychainManager.shared.storePrivateKey( diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/OptionsView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/OptionsView.swift index 52dbf8b8b1..6227291994 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/OptionsView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/OptionsView.swift @@ -26,7 +26,7 @@ struct OptionsView: View { /// pre-populate the peers text field when the user enables the /// custom-SPV toggle. The FFI drops bare-IP entries (no port), /// so the default must include the network's standard P2P port. - private func defaultSpvPeers(for network: AppNetwork) -> String { + private func defaultSpvPeers(for network: Network) -> String { switch network { case .mainnet: return "127.0.0.1:9999" case .testnet: return "127.0.0.1:19999" @@ -74,7 +74,7 @@ struct OptionsView: View { } } )) { - ForEach(AppNetwork.allCases, id: \.self) { network in + ForEach(Network.allCases, id: \.self) { network in Text(network.displayName).tag(network) } } diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/TokenActionPermissionsView.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/TokenActionPermissionsView.swift index 0da14cf9bd..3d148937e7 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/TokenActionPermissionsView.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/TokenActionPermissionsView.swift @@ -654,8 +654,8 @@ struct TokenActionPermissionsView: View { // crash from `ModelContext.fetch` (the `@Query` getter is the // visible frame). The helper captures the raw Int by a unique // name so the translator stays unambiguous. - let resolvedNetwork: AppNetwork? = token.dataContract - .flatMap { AppNetwork(rawValue: $0.networkRaw) } + let resolvedNetwork: Network? = token.dataContract + .flatMap { Network(rawValue: $0.networkRaw) } if let resolvedNetwork { self._localIdentities = Query( filter: PersistentIdentity.walletOwnedIdentitiesPredicate(network: resolvedNetwork), diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/SDKMethodTests.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/SDKMethodTests.swift index f7d5fcba6b..7378ab6a75 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/SDKMethodTests.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/SDKMethodTests.swift @@ -34,7 +34,7 @@ final class SDKMethodTests: XCTestCase { // Initialize SDK SDK.initialize() - let sdk = try SDK(network: DashSDKNetwork(rawValue: 1)) + let sdk = try SDK(network: .testnet) print("SDK created: \(sdk)") print("SDK handle: \(String(describing: sdk.handle))") @@ -61,7 +61,7 @@ final class SDKMethodTests: XCTestCase { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(key.count), - DashSDKNetwork(rawValue: 1) + Network.testnet.ffiValue ) } @@ -93,7 +93,7 @@ final class SDKMethodTests: XCTestCase { print("=== Testing Simple Identity Fetch ===") SDK.initialize() - let sdk = try SDK(network: DashSDKNetwork(rawValue: 1)) + let sdk = try SDK(network: .testnet) do { // Use a known testnet identity diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/SimpleTransitionTests.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/SimpleTransitionTests.swift index 6c5de2ef24..96da90117c 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/SimpleTransitionTests.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/SimpleTransitionTests.swift @@ -16,7 +16,7 @@ final class SimpleTransitionTests: XCTestCase { print("SDK initialized") // Create SDK instance - let sdk = try SDK(network: DashSDKNetwork(rawValue: 1)) + let sdk = try SDK(network: .testnet) print("SDK instance created") // Load env variables (EnvLoader is @MainActor) @@ -85,7 +85,7 @@ final class SimpleTransitionTests: XCTestCase { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(key3Private.count), - DashSDKNetwork(rawValue: 1) + Network.testnet.ffiValue ) } diff --git a/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/StateTransitionTests.swift b/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/StateTransitionTests.swift index 9b8d885f3b..5edf974359 100644 --- a/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/StateTransitionTests.swift +++ b/packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/StateTransitionTests.swift @@ -126,7 +126,7 @@ final class StateTransitionTests: XCTestCase { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(key3Private.count), - DashSDKNetwork(rawValue: 1) + Network.testnet.ffiValue ) } @@ -275,7 +275,7 @@ final class StateTransitionTests: XCTestCase { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(key3Private.count), - DashSDKNetwork(rawValue: 1) + Network.testnet.ffiValue ) } @@ -369,7 +369,7 @@ final class StateTransitionTests: XCTestCase { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(key3Private.count), - DashSDKNetwork(rawValue: 1) + Network.testnet.ffiValue ) } @@ -458,7 +458,7 @@ final class StateTransitionTests: XCTestCase { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(key3Private.count), - DashSDKNetwork(rawValue: 1) + Network.testnet.ffiValue ) } @@ -536,7 +536,7 @@ final class StateTransitionTests: XCTestCase { dash_sdk_signer_create_from_private_key( keyBytes.bindMemory(to: UInt8.self).baseAddress!, UInt(key3Private.count), - DashSDKNetwork(rawValue: 1) + Network.testnet.ffiValue ) } @@ -656,8 +656,7 @@ final class StateTransitionTests: XCTestCase { SDK.initialize() // Create SDK instance for testnet - let testnetNetwork = DashSDKNetwork(rawValue: 1) - return try SDK(network: testnetNetwork) + return try SDK(network: .testnet) } private func decodePrivateKey(from base58: String) throws -> Data {