From a3551a4924940a8d710bcdbd7fd52e911748f32d Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 7 Aug 2026 03:21:42 +0700 Subject: [PATCH 1/2] refactor(sdk): drop the vestigial v2 suffix from the finalized-transaction surface With the v1 split build/sign path removed (#4323), the v2 markers on the finalized-transaction surface no longer disambiguate anything. Rename, with no behavior change: - C ABI: core_wallet_{broadcast,abandon}_signed_transaction_v2 -> core_wallet_{broadcast,abandon}_signed_transaction; core_wallet_signed_transaction_v2_{free,fee,bytes} -> core_wallet_signed_transaction_{free,fee,bytes} - Rust internals: FFICoreSignedTransactionV2 -> FFICoreSignedTransaction, CORE_SIGNED_TRANSACTION_V2_STORAGE -> CORE_SIGNED_TRANSACTION_STORAGE, publish_v2_handle -> publish_finalized_handle, test names and doc prose - JNI + Kotlin externals: coreWalletBroadcastSignedTransactionV2 -> coreWalletBroadcastSignedTransaction, coreSignedTransactionV2* -> coreSignedTransaction* - parity manifest entries and QA/parity doc references The public Kotlin/Swift API (FinalizedCoreTransaction, finalizeAtomic, broadcastTransactionWithOutcome, abandonTransaction) was already version-free and is untouched. The deferred core_wallet_signed_payment_* family is distinct and unchanged. Prebuilt-host artifacts (xcframework, Android JNI .so) pick up the renamed symbols on their next routine rebuild; both are generated out-of-tree. Co-Authored-By: Claude Fable 5 --- docs/sdk/sdk-parity-manifest.json | 12 ++-- .../kotlin-sdk/KotlinExampleApp/TEST_PLAN.md | 4 +- packages/kotlin-sdk/PARITY.md | 2 +- .../CoreTxBuilderOpReturnBindingTest.kt | 4 +- .../dashsdk/errors/DashSdkError.kt | 4 +- .../dashsdk/ffi/WalletManagerNative.kt | 18 +++--- .../dashsdk/wallet/CoreTransactionBuilder.kt | 8 +-- .../dashsdk/wallet/ManagedCoreWallet.kt | 6 +- .../src/core_wallet/broadcast.rs | 42 +++++++------- .../src/core_wallet/signed_payment.rs | 2 +- .../src/core_wallet/transaction_builder.rs | 27 +++++---- packages/rs-platform-wallet-ffi/src/handle.rs | 6 +- .../rs-platform-wallet-ffi/src/manager.rs | 58 +++++++++---------- .../rs-unified-sdk-jni/src/wallet_manager.rs | 32 +++++----- .../CoreWallet/CoreTransactionBuilder.swift | 8 +-- .../CoreWallet/ManagedCoreWallet.swift | 8 +-- .../PlatformWallet/PlatformWalletResult.swift | 2 +- .../swift-sdk/SwiftExampleApp/TEST_PLAN.md | 2 +- 18 files changed, 121 insertions(+), 124 deletions(-) diff --git a/docs/sdk/sdk-parity-manifest.json b/docs/sdk/sdk-parity-manifest.json index 08ac2ee640..d6de8e6108 100644 --- a/docs/sdk/sdk-parity-manifest.json +++ b/docs/sdk/sdk-parity-manifest.json @@ -13,13 +13,13 @@ "wallet_restore" ], "shared_symbols": { - "core_wallet_abandon_signed_transaction_v2": "packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs", - "core_wallet_broadcast_signed_transaction_v2": "packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs", + "core_wallet_abandon_signed_transaction": "packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs", + "core_wallet_broadcast_signed_transaction": "packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs", "core_wallet_get_balance": "packages/rs-platform-wallet-ffi/src/core_wallet/wallet.rs", "core_wallet_signed_payment_broadcast": "packages/rs-platform-wallet-ffi/src/core_wallet/signed_payment.rs", "core_wallet_signed_payment_finalize": "packages/rs-platform-wallet-ffi/src/core_wallet/transaction_builder.rs", "core_wallet_signed_payment_release": "packages/rs-platform-wallet-ffi/src/core_wallet/signed_payment.rs", - "core_wallet_signed_transaction_v2_bytes": "packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs", + "core_wallet_signed_transaction_bytes": "packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs", "core_wallet_tx_builder_add_op_return": "packages/rs-platform-wallet-ffi/src/core_wallet/transaction_builder.rs", "core_wallet_tx_builder_change_to_first_input": "packages/rs-platform-wallet-ffi/src/core_wallet/transaction_builder.rs", "core_wallet_tx_builder_finalize": "packages/rs-platform-wallet-ffi/src/core_wallet/transaction_builder.rs", @@ -101,8 +101,8 @@ "area": "correctness", "shared_apis": [ "core_wallet_tx_builder_finalize", - "core_wallet_broadcast_signed_transaction_v2", - "core_wallet_abandon_signed_transaction_v2" + "core_wallet_broadcast_signed_transaction", + "core_wallet_abandon_signed_transaction" ], "required_persistence_capabilities": [], "hosts": { @@ -267,7 +267,7 @@ "core_wallet_tx_builder_add_op_return", "core_wallet_tx_builder_preserve_output_order", "core_wallet_tx_builder_change_to_first_input", - "core_wallet_signed_transaction_v2_bytes" + "core_wallet_signed_transaction_bytes" ], "required_persistence_capabilities": [], "hosts": { diff --git a/packages/kotlin-sdk/KotlinExampleApp/TEST_PLAN.md b/packages/kotlin-sdk/KotlinExampleApp/TEST_PLAN.md index 8cd3e7e181..13784fd400 100644 --- a/packages/kotlin-sdk/KotlinExampleApp/TEST_PLAN.md +++ b/packages/kotlin-sdk/KotlinExampleApp/TEST_PLAN.md @@ -96,12 +96,12 @@ Most Platform actions have hard preconditions. Establish these fixtures before s | CORE-02 | Restore wallet (existing mnemonic) | Core | Essential | ✅ | | `CreateWalletScreen` (Import Existing toggle). After sync, derived addresses + balance populate. | | CORE-03 | Backup / view recovery phrase | Core | Essential | ✅ | | `SeedBackupScreen`. Phrase matches creation; biometric-gated reveal on Android. | | CORE-04 | Receive (derive address + QR) | Core | Essential | ✅ | | `ReceiveAddressSheet` → `core_wallet_next_receive_address`. Fresh external address + scannable QR. | -| CORE-05 | Send Core L1 transaction | Core | Essential | ✅ | | Send flow (`SendTransactionScreen`, mode Core→Core) → `ManagedPlatformWallet.sendToAddresses` → `CoreTransactionBuilder.finalizeAtomic` → `core_wallet_broadcast_signed_transaction_v2`. Funding and reservation are atomic; tx broadcasts, balance drops, and it appears in history. | +| CORE-05 | Send Core L1 transaction | Core | Essential | ✅ | | Send flow (`SendTransactionScreen`, mode Core→Core) → `ManagedPlatformWallet.sendToAddresses` → `CoreTransactionBuilder.finalizeAtomic` → `core_wallet_broadcast_signed_transaction`. Funding and reservation are atomic; tx broadcasts, balance drops, and it appears in history. | | CORE-06 | View balance / tx history / UTXOs | Core | Essential | ✅ | | `WalletDetailScreen`, `TransactionListScreen`, `AccountDetailScreen` (Room). | | CORE-07 | SPV sync (start / stop / progress) | Core | Essential | ✅ | | Global sync indicator (`GlobalSyncIndicator`) → `platform_wallet_manager_spv_*`. Headers/filters/masternodes advance to tip. | | CORE-08 | QR scan recipient | Core | Manual | ✅ | | `QrScannerScreen` (CameraX), reachable in the Send flow. Emulators can use a virtual camera scene but reliability varies — treat as `Tier=Manual`. | | CORE-09 | Multiple HD accounts (within one wallet) | Core | Common | ✅ | | Account selection / `AccountDetailScreen`; balances per `account_index`. | -| CORE-10 | Multi-recipient Core send | Core | Common | ✅ | | Send flow (`SendTransactionScreen`, Core→Core) → "Add recipient" appends extra address/amount rows → `CoreTransactionBuilder` (one `addOutput` per recipient) → `finalizeAtomic` + `core_wallet_broadcast_signed_transaction_v2`. One tx with N outputs. | +| CORE-10 | Multi-recipient Core send | Core | Common | ✅ | | Send flow (`SendTransactionScreen`, Core→Core) → "Add recipient" appends extra address/amount rows → `CoreTransactionBuilder` (one `addOutput` per recipient) → `finalizeAtomic` + `core_wallet_broadcast_signed_transaction`. One tx with N outputs. | #### Multiple wallets on one device diff --git a/packages/kotlin-sdk/PARITY.md b/packages/kotlin-sdk/PARITY.md index 8eae44e141..987869e0d0 100644 --- a/packages/kotlin-sdk/PARITY.md +++ b/packages/kotlin-sdk/PARITY.md @@ -158,7 +158,7 @@ verbatim. Documented deviations from iOS are listed after the table. | QRScannerView.swift | ui/scanner/QrScannerScreen.kt · `QrScanner` | ported | | ReceiveAddressView.swift | ui/wallet/ReceiveAddressSheet.kt | ported | | SeedBackupView.swift | ui/wallet/SeedBackupScreen.kt · `SeedBackup` | ported | -| SendTransactionView.swift | ui/wallet/SendTransactionScreen.kt · `SendTransaction` | ported — `ManagedPlatformWallet.sendToAddresses` drives the atomic V2 path (`CoreTransactionBuilder.finalizeAtomic` → `core_wallet_tx_builder_finalize` → `core_wallet_broadcast_signed_transaction_v2`); shared Rust owns selection, reservation, signing, and broadcast classification | +| SendTransactionView.swift | ui/wallet/SendTransactionScreen.kt · `SendTransaction` | ported — `ManagedPlatformWallet.sendToAddresses` drives the atomic V2 path (`CoreTransactionBuilder.finalizeAtomic` → `core_wallet_tx_builder_finalize` → `core_wallet_broadcast_signed_transaction`); shared Rust owns selection, reservation, signing, and broadcast classification | | ShieldedActivityView.swift | ui/shielded/ShieldedActivityScreen.kt · `ShieldedActivity` | ported | | TransactionDetailView.swift | ui/wallet/TransactionDetailScreen.kt · `WalletTransactionDetail` | ported | | TransactionListView.swift | ui/wallet/TransactionListScreen.kt · `WalletTransactions` | ported | diff --git a/packages/kotlin-sdk/sdk/src/androidTest/kotlin/org/dashfoundation/dashsdk/wallet/CoreTxBuilderOpReturnBindingTest.kt b/packages/kotlin-sdk/sdk/src/androidTest/kotlin/org/dashfoundation/dashsdk/wallet/CoreTxBuilderOpReturnBindingTest.kt index 9d32c4e04d..dcb94e7629 100644 --- a/packages/kotlin-sdk/sdk/src/androidTest/kotlin/org/dashfoundation/dashsdk/wallet/CoreTxBuilderOpReturnBindingTest.kt +++ b/packages/kotlin-sdk/sdk/src/androidTest/kotlin/org/dashfoundation/dashsdk/wallet/CoreTxBuilderOpReturnBindingTest.kt @@ -12,7 +12,7 @@ import org.junit.runner.RunWith /** * Binding-level coverage for the MAYACHAIN-deposit builder controls * (`add_op_return`, `preserve_output_order`, `change_to_first_input`, - * `signed_transaction_v2_bytes`) — the Android counterpart of the gated + * `signed_transaction_bytes`) — the Android counterpart of the gated * Swift `MayaDepositVerificationIntegrationTests`, minus everything that * needs a funded wallet. Proves the four new JNI symbols resolve, happy-path * calls succeed against a live builder, and the FFI's error paths surface as @@ -83,7 +83,7 @@ class CoreTxBuilderOpReturnBindingTest { // Handle 0 can never be a finalized transaction; the call must throw // (not crash), which also proves the JNI symbol resolves. assertThrows(DashSDKException::class.java) { - WalletManagerNative.coreSignedTransactionV2Bytes(0L) + WalletManagerNative.coreSignedTransactionBytes(0L) } } diff --git a/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/errors/DashSdkError.kt b/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/errors/DashSdkError.kt index c61be2ebff..f62d85eece 100644 --- a/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/errors/DashSdkError.kt +++ b/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/errors/DashSdkError.kt @@ -410,9 +410,9 @@ sealed class DashSdkError( // whose wallet is no longer registered in the manager, or a // signed-payment finalize whose wallet was removed while it was // being signed; - // * finalized-transaction HANDLE (V2) path — a tx-builder finalize + // * finalized-transaction HANDLE path — a tx-builder finalize // whose wallet was removed or re-created during signing (no handle - // is published), or a V2 broadcast whose generation is gone. + // is published), or a finalized-handle broadcast whose generation is gone. // Every one reconciles the build's UTXO reservation before returning. // Nothing was broadcast, and unlike ReservationWalletMismatch (36) // no other live generation holds the payment either — so it is not diff --git a/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/ffi/WalletManagerNative.kt b/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/ffi/WalletManagerNative.kt index 3d520a6912..40bdef869c 100644 --- a/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/ffi/WalletManagerNative.kt +++ b/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/ffi/WalletManagerNative.kt @@ -199,7 +199,7 @@ internal object WalletManagerNative { */ external fun coreTxBuilderSetCurrentHeight(builder: Long, height: Int) - /** Atomic V2 finalizer; consumes [builder] and returns an opaque signed-transaction V2 handle. */ + /** Atomic finalizer; consumes [builder] and returns an opaque signed-transaction handle. */ external fun coreTxBuilderFinalize( builder: Long, walletHandle: Long, @@ -218,7 +218,7 @@ internal object WalletManagerNative { /** * `platform_wallet_get_core` — resolve the transient core-wallet handle * from a `PlatformWallet` handle, for - * [coreWalletBroadcastSignedTransactionV2]. Free with [coreWalletDestroy]. + * [coreWalletBroadcastSignedTransaction]. Free with [coreWalletDestroy]. * Returns 0 after throwing. */ external fun platformWalletGetCore(walletHandle: Long): Long @@ -261,25 +261,25 @@ internal object WalletManagerNative { */ external fun coreWalletNextChangeAddress(coreHandle: Long, accountIndex: Int): String - /** Consume and broadcast an atomically finalized V2 transaction. */ - external fun coreWalletBroadcastSignedTransactionV2(coreHandle: Long, transaction: Long): String + /** Consume and broadcast an atomically finalized transaction. */ + external fun coreWalletBroadcastSignedTransaction(coreHandle: Long, transaction: Long): String /** Consume without sending and immediately release the reservation. */ - external fun coreWalletAbandonSignedTransactionV2(coreHandle: Long, transaction: Long) + external fun coreWalletAbandonSignedTransaction(coreHandle: Long, transaction: Long) /** Idempotent cleaner fallback; abandons and releases the reservation. */ - external fun coreSignedTransactionV2Free(transaction: Long) + external fun coreSignedTransactionFree(transaction: Long) /** Read the finalized transaction's fee before consumption. */ - external fun coreSignedTransactionV2Fee(transaction: Long): Long + external fun coreSignedTransactionFee(transaction: Long): Long /** - * `core_wallet_signed_transaction_v2_bytes` — the consensus-serialized + * `core_wallet_signed_transaction_bytes` — the consensus-serialized * signed transaction bytes, read WITHOUT consuming the ownership token. * Lets the caller assert the deposit shape (e.g. MAYACHAIN's * vault/OP_RETURN/change ordering) before deciding to broadcast. */ - external fun coreSignedTransactionV2Bytes(transaction: Long): ByteArray + external fun coreSignedTransactionBytes(transaction: Long): ByteArray /** `core_wallet_destroy` — release a core handle from [platformWalletGetCore]. Safe on 0. */ external fun coreWalletDestroy(coreHandle: Long) diff --git a/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/wallet/CoreTransactionBuilder.kt b/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/wallet/CoreTransactionBuilder.kt index b6c71cd84f..740649415b 100644 --- a/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/wallet/CoreTransactionBuilder.kt +++ b/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/wallet/CoreTransactionBuilder.kt @@ -141,9 +141,9 @@ class CoreTransactionBuilder internal constructor(network: Network) : AutoClosea coreSignerHandle, ) val fee = try { - WalletManagerNative.coreSignedTransactionV2Fee(transaction) + WalletManagerNative.coreSignedTransactionFee(transaction) } catch (error: Throwable) { - WalletManagerNative.coreSignedTransactionV2Free(transaction) + WalletManagerNative.coreSignedTransactionFree(transaction) throw error } return FinalizedCoreTransaction(transaction, fee) @@ -235,7 +235,7 @@ class FinalizedCoreTransaction internal constructor(handle: Long, val fee: Long) fun serializedData(): ByteArray { val handle = handleRef.get() check(handle != 0L) { "FinalizedCoreTransaction has already been consumed" } - return WalletManagerNative.coreSignedTransactionV2Bytes(handle) + return WalletManagerNative.coreSignedTransactionBytes(handle) } override fun close() = cleanable.clean() @@ -243,7 +243,7 @@ class FinalizedCoreTransaction internal constructor(handle: Long, val fee: Long) private class Cleanup(private val handleRef: AtomicLong) : Runnable { override fun run() { val handle = handleRef.getAndSet(0) - if (handle != 0L) WalletManagerNative.coreSignedTransactionV2Free(handle) + if (handle != 0L) WalletManagerNative.coreSignedTransactionFree(handle) } } } diff --git a/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/wallet/ManagedCoreWallet.kt b/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/wallet/ManagedCoreWallet.kt index 91926fc77b..dbed938ea3 100644 --- a/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/wallet/ManagedCoreWallet.kt +++ b/packages/kotlin-sdk/sdk/src/main/kotlin/org/dashfoundation/dashsdk/wallet/ManagedCoreWallet.kt @@ -27,16 +27,16 @@ class ManagedCoreWallet internal constructor(handle: Long) : AutoCloseable { check(it != 0L) { "ManagedCoreWallet has been closed" } } - /** Consume and broadcast a V2 finalized transaction. */ + /** Consume and broadcast a finalized transaction. */ fun broadcastTransaction(tx: FinalizedCoreTransaction): String = - WalletManagerNative.coreWalletBroadcastSignedTransactionV2( + WalletManagerNative.coreWalletBroadcastSignedTransaction( handle, tx.takeForBroadcast(), ) /** Consume without sending and release the selected inputs immediately. */ fun abandonTransaction(tx: FinalizedCoreTransaction) { - WalletManagerNative.coreWalletAbandonSignedTransactionV2( + WalletManagerNative.coreWalletAbandonSignedTransaction( handle, tx.takeForAbandon(), ) diff --git a/packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs b/packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs index 71d6ffc1a0..2270d73367 100644 --- a/packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs +++ b/packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs @@ -21,7 +21,7 @@ fn classify_broadcast_result( } } -/// Consume and broadcast an atomically finalized V2 transaction. +/// Consume and broadcast an atomically finalized transaction. /// /// Success and `MaybeSent` both permanently consume the handle. A definitive /// rejection also consumes it after releasing the reservation. This prevents @@ -32,7 +32,7 @@ fn classify_broadcast_result( /// **before** the network is touched; the handle is consumed and its reservation /// reconciled. This mirrors the deferred-token path's `WalletRemoved` → 98. #[no_mangle] -pub unsafe extern "C" fn core_wallet_broadcast_signed_transaction_v2( +pub unsafe extern "C" fn core_wallet_broadcast_signed_transaction( handle: Handle, transaction_handle: Handle, out_txid: *mut *mut c_char, @@ -43,7 +43,7 @@ pub unsafe extern "C" fn core_wallet_broadcast_signed_transaction_v2( // Ownership crosses into this call. Consume first; every later validation // failure explicitly abandons through the embedded originating wallet. let finalized = - unwrap_option_or_return!(CORE_SIGNED_TRANSACTION_V2_STORAGE.remove(transaction_handle)); + unwrap_option_or_return!(CORE_SIGNED_TRANSACTION_STORAGE.remove(transaction_handle)); let Some(wallet) = CORE_WALLET_STORAGE.with_item(handle, Clone::clone) else { runtime().block_on(finalized.wallet.abandon_transaction(&finalized.transaction)); return PlatformWalletFFIResult::err( @@ -109,12 +109,12 @@ pub unsafe extern "C" fn core_wallet_broadcast_signed_transaction_v2( /// reservation immediately. Repeating abandon/free for the same handle is a /// safe invalid-handle error; no freed pointer is dereferenced. #[no_mangle] -pub unsafe extern "C" fn core_wallet_abandon_signed_transaction_v2( +pub unsafe extern "C" fn core_wallet_abandon_signed_transaction( handle: Handle, transaction_handle: Handle, ) -> PlatformWalletFFIResult { let transaction = - unwrap_option_or_return!(CORE_SIGNED_TRANSACTION_V2_STORAGE.remove(transaction_handle)); + unwrap_option_or_return!(CORE_SIGNED_TRANSACTION_STORAGE.remove(transaction_handle)); let Some(wallet) = CORE_WALLET_STORAGE.with_item(handle, Clone::clone) else { runtime().block_on( transaction @@ -146,11 +146,11 @@ pub unsafe extern "C" fn core_wallet_abandon_signed_transaction_v2( PlatformWalletFFIResult::ok() } -/// Idempotent ownership cleanup for a V2 handle when no transient wallet handle +/// Idempotent ownership cleanup for a finalized handle when no transient wallet handle /// is available. It abandons the transaction and releases its reservation. #[no_mangle] -pub extern "C" fn core_wallet_signed_transaction_v2_free(transaction_handle: Handle) { - if let Some(transaction) = CORE_SIGNED_TRANSACTION_V2_STORAGE.remove(transaction_handle) { +pub extern "C" fn core_wallet_signed_transaction_free(transaction_handle: Handle) { + if let Some(transaction) = CORE_SIGNED_TRANSACTION_STORAGE.remove(transaction_handle) { runtime().block_on( transaction .wallet @@ -160,20 +160,20 @@ pub extern "C" fn core_wallet_signed_transaction_v2_free(transaction_handle: Han } #[no_mangle] -pub unsafe extern "C" fn core_wallet_signed_transaction_v2_fee( +pub unsafe extern "C" fn core_wallet_signed_transaction_fee( transaction_handle: Handle, out_fee: *mut u64, ) -> PlatformWalletFFIResult { check_ptr!(out_fee); let fee = - unwrap_option_or_return!(CORE_SIGNED_TRANSACTION_V2_STORAGE + unwrap_option_or_return!(CORE_SIGNED_TRANSACTION_STORAGE .with_item(transaction_handle, |tx| tx.transaction.fee())); *out_fee = fee; PlatformWalletFFIResult::ok() } #[no_mangle] -pub unsafe extern "C" fn core_wallet_signed_transaction_v2_bytes( +pub unsafe extern "C" fn core_wallet_signed_transaction_bytes( transaction_handle: Handle, out_bytes: *mut *mut u8, out_len: *mut usize, @@ -183,7 +183,7 @@ pub unsafe extern "C" fn core_wallet_signed_transaction_v2_bytes( *out_bytes = std::ptr::null_mut(); *out_len = 0; - let bytes = unwrap_option_or_return!(CORE_SIGNED_TRANSACTION_V2_STORAGE + let bytes = unwrap_option_or_return!(CORE_SIGNED_TRANSACTION_STORAGE .with_item(transaction_handle, |tx| dashcore::consensus::serialize( tx.transaction.transaction() ))); @@ -258,7 +258,7 @@ mod tests { use platform_wallet::{CoreWallet, SignedCoreTransaction}; use super::*; - use crate::core_wallet::FFICoreSignedTransactionV2; + use crate::core_wallet::FFICoreSignedTransaction; type TestCore = CoreWallet; @@ -277,7 +277,7 @@ mod tests { } fn insert(core: &TestCore, transaction: SignedCoreTransaction) -> Handle { - CORE_SIGNED_TRANSACTION_V2_STORAGE.insert(FFICoreSignedTransactionV2 { + CORE_SIGNED_TRANSACTION_STORAGE.insert(FFICoreSignedTransaction { wallet: core.clone(), transaction, }) @@ -294,8 +294,8 @@ mod tests { runtime().block_on(funded_spv_core_wallet(StandardAccountType::BIP44Account)); let transaction_handle = insert(&core, finalize(&core, &signer, 40)); - core_wallet_signed_transaction_v2_free(transaction_handle); - core_wallet_signed_transaction_v2_free(transaction_handle); + core_wallet_signed_transaction_free(transaction_handle); + core_wallet_signed_transaction_free(transaction_handle); assert_released(&core, &signer, 41); } @@ -306,7 +306,7 @@ mod tests { runtime().block_on(funded_spv_core_wallet(StandardAccountType::BIP44Account)); let invalid_transaction = insert(&origin, finalize(&origin, &origin_signer, 42)); let invalid = - unsafe { core_wallet_abandon_signed_transaction_v2(u64::MAX, invalid_transaction) }; + unsafe { core_wallet_abandon_signed_transaction(u64::MAX, invalid_transaction) }; assert_eq!( invalid.code, PlatformWalletFFIResultCode::ErrorInvalidHandle @@ -318,7 +318,7 @@ mod tests { let other_handle = CORE_WALLET_STORAGE.insert(other); let wrong_transaction = insert(&origin, finalize(&origin, &origin_signer, 44)); let wrong = - unsafe { core_wallet_abandon_signed_transaction_v2(other_handle, wrong_transaction) }; + unsafe { core_wallet_abandon_signed_transaction(other_handle, wrong_transaction) }; assert_eq!( wrong.code, PlatformWalletFFIResultCode::ErrorInvalidParameter @@ -335,13 +335,13 @@ mod tests { let transaction_handle = insert(&core, finalize(&core, &signer, 46)); let abandoned = - unsafe { core_wallet_abandon_signed_transaction_v2(core_handle, transaction_handle) }; + unsafe { core_wallet_abandon_signed_transaction(core_handle, transaction_handle) }; assert_eq!(abandoned.code, PlatformWalletFFIResultCode::Success); - core_wallet_signed_transaction_v2_free(transaction_handle); + core_wallet_signed_transaction_free(transaction_handle); let mut txid = ptr::null_mut(); let rebroadcast = unsafe { - core_wallet_broadcast_signed_transaction_v2(core_handle, transaction_handle, &mut txid) + core_wallet_broadcast_signed_transaction(core_handle, transaction_handle, &mut txid) }; assert_eq!(rebroadcast.code, PlatformWalletFFIResultCode::NotFound); assert!(txid.is_null()); diff --git a/packages/rs-platform-wallet-ffi/src/core_wallet/signed_payment.rs b/packages/rs-platform-wallet-ffi/src/core_wallet/signed_payment.rs index c0d4579763..bb516ccb2c 100644 --- a/packages/rs-platform-wallet-ffi/src/core_wallet/signed_payment.rs +++ b/packages/rs-platform-wallet-ffi/src/core_wallet/signed_payment.rs @@ -2,7 +2,7 @@ //! (BIP70 / BIP270 "sign now, submit on merchant ack"). //! //! The one-shot immediate send path (`core_wallet_tx_builder_finalize` + -//! `core_wallet_broadcast_signed_transaction_v2`) sends a just-built +//! `core_wallet_broadcast_signed_transaction`) sends a just-built //! transaction immediately. BIP70-style flows must split that: build and sign //! now (reserving the funding UTXOs), hand the raw bytes to a merchant server, //! then broadcast only on ack — or release the reservation on a nack / diff --git a/packages/rs-platform-wallet-ffi/src/core_wallet/transaction_builder.rs b/packages/rs-platform-wallet-ffi/src/core_wallet/transaction_builder.rs index 99b5677285..35e78ee31a 100644 --- a/packages/rs-platform-wallet-ffi/src/core_wallet/transaction_builder.rs +++ b/packages/rs-platform-wallet-ffi/src/core_wallet/transaction_builder.rs @@ -1,6 +1,6 @@ use crate::core_wallet_types::OutPointFFI; use crate::error::*; -use crate::handle::{Handle, CORE_SIGNED_TRANSACTION_V2_STORAGE, PLATFORM_WALLET_STORAGE}; +use crate::handle::{Handle, CORE_SIGNED_TRANSACTION_STORAGE, PLATFORM_WALLET_STORAGE}; use crate::runtime::runtime; use crate::types::{FFINetwork, Network}; use crate::{check_ptr, unwrap_option_or_return, unwrap_result_or_return}; @@ -46,11 +46,11 @@ pub struct FFICoreTransaction { fee: u64, } -/// Internal value behind the opaque V2 numeric handle. Keeping the originating +/// Internal value behind the opaque numeric handle. Keeping the originating /// CoreWallet with the signed transaction lets `free` perform the same safe /// reservation release as explicit abandon, even after the host discarded its /// transient CoreWallet handle. -pub struct FFICoreSignedTransactionV2 { +pub struct FFICoreSignedTransaction { pub(crate) wallet: platform_wallet::CoreWallet, pub(crate) transaction: platform_wallet::SignedCoreTransaction, } @@ -81,9 +81,9 @@ impl From for AccountTypePreference { /// invoked. This function consumes `builder` on every path after its pointer /// is accepted. /// -/// On success `out_transaction_handle` receives an opaque V2 handle. Consume -/// it with `core_wallet_broadcast_signed_transaction_v2` or -/// `core_wallet_abandon_signed_transaction_v2`. +/// On success `out_transaction_handle` receives an opaque finalized-transaction handle. Consume +/// it with `core_wallet_broadcast_signed_transaction` or +/// `core_wallet_abandon_signed_transaction`. /// /// If the host removes (or re-creates) this wallet while the external signer is /// running, no handle is published: the build's reservation is reconciled and @@ -126,13 +126,13 @@ pub unsafe extern "C" fn core_wallet_tx_builder_finalize( )); let finalized = unwrap_result_or_return!(finalized); - // Publishing the V2 handle is gated exactly like the deferred-token sibling + // Publishing the finalized handle is gated exactly like the deferred-token sibling // below (`core_wallet_signed_payment_finalize`). `finalize_transaction` drops // the wallet-manager write lock before awaiting the (external, possibly slow) // signer, so the host can have removed this wallet while we were signing — - // and that removal's V2-handle sweep has then ALREADY run. Inserting now + // and that removal's finalized-handle sweep has then ALREADY run. Inserting now // would publish a live handle for a removed generation that no later sweep - // catches, and `core_wallet_broadcast_signed_transaction_v2` would happily + // catches, and `core_wallet_broadcast_signed_transaction` would happily // push it to the network: its `is_same_generation` check compares two // handles, and a removed generation matches itself (`dashpay/platform#4185`). // @@ -162,11 +162,10 @@ pub unsafe extern "C" fn core_wallet_tx_builder_finalize( ); } - *out_transaction_handle = - CORE_SIGNED_TRANSACTION_V2_STORAGE.insert(FFICoreSignedTransactionV2 { - wallet: wallet.core().clone(), - transaction: finalized, - }); + *out_transaction_handle = CORE_SIGNED_TRANSACTION_STORAGE.insert(FFICoreSignedTransaction { + wallet: wallet.core().clone(), + transaction: finalized, + }); PlatformWalletFFIResult::ok() } diff --git a/packages/rs-platform-wallet-ffi/src/handle.rs b/packages/rs-platform-wallet-ffi/src/handle.rs index 2a5692b2a5..ad672e0d43 100644 --- a/packages/rs-platform-wallet-ffi/src/handle.rs +++ b/packages/rs-platform-wallet-ffi/src/handle.rs @@ -81,7 +81,7 @@ impl HandleStorage { /// Remove (and drop) every stored item satisfying `predicate`, returning how /// many were removed. Used to sweep a wallet generation's handles at - /// teardown (e.g. abandon every finalized-transaction V2 handle whose + /// teardown (e.g. abandon every finalized-transaction handle whose /// originating wallet was just removed from its manager — the reservation /// ceases to exist with the generation, so dropping is the correct action). pub fn remove_matching(&self, predicate: F) -> usize @@ -124,8 +124,8 @@ pub static CORE_WALLET_STORAGE: Lazy< /// Atomically funded/signed Core transactions. Handles are removed exactly /// once by broadcast or abandon; repeating either operation is a safe /// invalid-handle error instead of dereferencing a freed pointer. -pub static CORE_SIGNED_TRANSACTION_V2_STORAGE: Lazy< - HandleStorage, +pub static CORE_SIGNED_TRANSACTION_STORAGE: Lazy< + HandleStorage, > = Lazy::new(HandleStorage::new); /// Storage for AssetLockManager handles (pinned to `SpvBroadcaster`). diff --git a/packages/rs-platform-wallet-ffi/src/manager.rs b/packages/rs-platform-wallet-ffi/src/manager.rs index 7a04eba14d..caca485c56 100644 --- a/packages/rs-platform-wallet-ffi/src/manager.rs +++ b/packages/rs-platform-wallet-ffi/src/manager.rs @@ -572,7 +572,7 @@ pub(crate) async fn remove_wallet_and_tear_down_generation< // The wallet and its accounts' `ReservationSet`s are now gone from // the manager, so the deferred-payment reservations cease to exist — // there is nothing to reconcile. DROP (do not release) this - // generation's registry tokens and its finalized-tx V2 handles. This + // generation's registry tokens and its finalized-tx handles. This // is the teardown half of the single generation policy both deferred // paths share: it makes any stale handle to the removed generation // inert, so a later destroy/release of a lingering handle can never @@ -580,7 +580,7 @@ pub(crate) async fn remove_wallet_and_tear_down_generation< let core = removed.core(); crate::core_wallet::signed_payment::SIGNED_PAYMENT_REGISTRY .remove_entries_for_wallet(core); - crate::handle::CORE_SIGNED_TRANSACTION_V2_STORAGE + crate::handle::CORE_SIGNED_TRANSACTION_STORAGE .remove_matching(|tx| tx.wallet.is_same_generation(core)); }) .await?; @@ -1173,24 +1173,24 @@ mod remove_wallet_lifecycle_tests { } // --------------------------------------------------------------------- - // V2 finalized-transaction-handle path (`dashpay/platform#4185` review). + // finalized-transaction-handle path (`dashpay/platform#4185` review). // - // The registry-token path above was gated first; the V2 path - // (`core_wallet_tx_builder_finalize` → `CORE_SIGNED_TRANSACTION_V2_STORAGE` - // → `core_wallet_broadcast_signed_transaction_v2`) reaches the SAME + // The registry-token path above was gated first; the finalized-handle path + // (`core_wallet_tx_builder_finalize` → `CORE_SIGNED_TRANSACTION_STORAGE` + // → `core_wallet_broadcast_signed_transaction`) reaches the SAME // broadcaster through a retained handle and was left ungated. Its // `is_same_generation` check compares two HANDLES, and a removed generation // matches itself, so two retained handles pushed a deleted wallet's // transaction onto the network. // --------------------------------------------------------------------- - /// Publish a V2 finalized-transaction handle for `core`'s generation, the + /// Publish a finalized-transaction handle for `core`'s generation, the /// way `core_wallet_tx_builder_finalize` does. - fn publish_v2_handle( + fn publish_finalized_handle( core: &CoreWallet, ) -> Handle { - crate::handle::CORE_SIGNED_TRANSACTION_V2_STORAGE.insert( - crate::core_wallet::FFICoreSignedTransactionV2 { + crate::handle::CORE_SIGNED_TRANSACTION_STORAGE.insert( + crate::core_wallet::FFICoreSignedTransaction { wallet: core.clone(), transaction: SignedCoreTransaction::new_for_test( dummy_tx(), @@ -1205,7 +1205,7 @@ mod remove_wallet_lifecycle_tests { ) } - /// Requirement: a V2 handle whose wallet generation was removed must be + /// Requirement: a finalized handle whose wallet generation was removed must be /// refused BEFORE the network, exactly as the registry-token path is. /// /// Deterministic. The setup reproduces the late-finalizer publication @@ -1219,7 +1219,7 @@ mod remove_wallet_lifecycle_tests { /// straight to the broadcaster with no manager lookup at all — so the /// transaction went to the network. #[test] - fn broadcasting_a_v2_handle_for_a_removed_wallet_is_refused_before_the_network() { + fn broadcasting_a_finalized_handle_for_a_removed_wallet_is_refused_before_the_network() { let _registry = crate::core_wallet::signed_payment::registry_test_guard(); // The extern "C" entry points call `runtime().block_on` themselves, so @@ -1243,12 +1243,12 @@ mod remove_wallet_lifecycle_tests { core }); - let transaction_handle = publish_v2_handle(&core); + let transaction_handle = publish_finalized_handle(&core); let core_handle = crate::handle::CORE_WALLET_STORAGE.insert(core.clone()); let mut out_txid: *mut std::os::raw::c_char = std::ptr::null_mut(); let result = unsafe { - crate::core_wallet::core_wallet_broadcast_signed_transaction_v2( + crate::core_wallet::core_wallet_broadcast_signed_transaction( core_handle, transaction_handle, &mut out_txid, @@ -1258,7 +1258,7 @@ mod remove_wallet_lifecycle_tests { assert_eq!( result.code, PlatformWalletFFIResultCode::NotFound, - "a V2 handle whose wallet was removed must be refused without a send" + "a finalized handle whose wallet was removed must be refused without a send" ); assert!( out_txid.is_null(), @@ -1268,26 +1268,26 @@ mod remove_wallet_lifecycle_tests { // Refusing still CONSUMES the handle: the generation is gone, so there is // nothing to reconcile and nothing to retry. assert!( - crate::handle::CORE_SIGNED_TRANSACTION_V2_STORAGE + crate::handle::CORE_SIGNED_TRANSACTION_STORAGE .remove(transaction_handle) .is_none(), - "the refused V2 handle must have been consumed" + "the refused finalized handle must have been consumed" ); } - /// Requirement: a teardown WAITS for an in-flight V2 operation on that - /// generation, then sweeps its handle — so a V2 handle can never be published + /// Requirement: a teardown WAITS for an in-flight finalized-transaction operation on that + /// generation, then sweeps its handle — so a finalized handle can never be published /// into an already-swept storage and outlive its wallet. /// /// Deterministic. The held shared guard stands in for /// `core_wallet_tx_builder_finalize` sitting between its liveness check and - /// its insert, or `core_wallet_broadcast_signed_transaction_v2` sitting - /// between its liveness check and the send. Before the fix the V2 path took no + /// its insert, or `core_wallet_broadcast_signed_transaction` sitting + /// between its liveness check and the send. Before the fix the finalized-handle path took no /// gate at all: the teardown ran to completion — sweep included — while the /// finalizer was signing, and the handle it then published was permanently /// outside any sweep and fully broadcastable. #[test] - fn teardown_waits_for_an_in_flight_v2_operation_and_then_sweeps_its_handle() { + fn teardown_waits_for_an_in_flight_finalized_operation_and_then_sweeps_its_handle() { let _registry = crate::core_wallet::signed_payment::registry_test_guard(); let (core, transaction_handle) = runtime().block_on(async { @@ -1298,7 +1298,7 @@ mod remove_wallet_lifecycle_tests { .expect("wallet present"); let core = wallet.core().clone(); - // The V2 operation enters this generation's gate (as the FFI does + // The finalized-transaction operation enters this generation's gate (as the FFI does // after signing). let in_flight = core.generation_payment_guard().await; @@ -1313,16 +1313,16 @@ mod remove_wallet_lifecycle_tests { tokio::time::sleep(Duration::from_millis(200)).await; assert!( !teardown.is_finished(), - "teardown must wait for the in-flight V2 operation to leave the gate" + "teardown must wait for the in-flight finalized-transaction operation to leave the gate" ); // Because teardown is still waiting, the operation's liveness check // sees a live wallet and its publish is legitimate. assert!( core.is_current_generation().await, - "the wallet must still be live while a V2 operation holds the gate" + "the wallet must still be live while a finalized-transaction operation holds the gate" ); - let transaction_handle = publish_v2_handle(&core); + let transaction_handle = publish_finalized_handle(&core); drop(in_flight); teardown @@ -1334,13 +1334,13 @@ mod remove_wallet_lifecycle_tests { (core, transaction_handle) }); - // The teardown that was waiting swept the handle the V2 operation + // The teardown that was waiting swept the handle the finalized-transaction operation // published — the invariant the gate exists to restore. assert!( - crate::handle::CORE_SIGNED_TRANSACTION_V2_STORAGE + crate::handle::CORE_SIGNED_TRANSACTION_STORAGE .remove(transaction_handle) .is_none(), - "the in-flight V2 operation's handle must have been swept by teardown" + "the in-flight finalized-transaction operation's handle must have been swept by teardown" ); drop(core); } diff --git a/packages/rs-unified-sdk-jni/src/wallet_manager.rs b/packages/rs-unified-sdk-jni/src/wallet_manager.rs index d1ea887274..a06b234d34 100644 --- a/packages/rs-unified-sdk-jni/src/wallet_manager.rs +++ b/packages/rs-unified-sdk-jni/src/wallet_manager.rs @@ -892,7 +892,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c }) } -/// Atomic V2 finalizer: consumes a configured builder, performs funding and +/// Atomic finalizer: consumes a configured builder, performs funding and /// ReservationSet insertion indivisibly in platform-wallet, drops the manager /// lock, then invokes the mnemonic resolver to sign. #[no_mangle] @@ -1074,7 +1074,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c } /// `platform_wallet_get_core` — resolve the transient core-wallet `Handle` -/// (as `jlong`) from a `PlatformWallet` handle, for [coreWalletBroadcastSignedTransactionV2]. +/// (as `jlong`) from a `PlatformWallet` handle, for [coreWalletBroadcastSignedTransaction]. /// Free with [coreWalletDestroy]. Returns 0 after throwing. #[no_mangle] pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_platformWalletGetCore( @@ -1197,9 +1197,9 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c }) } -/// Consume and broadcast an atomically finalized V2 transaction handle. +/// Consume and broadcast an atomically finalized transaction handle. #[no_mangle] -pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreWalletBroadcastSignedTransactionV2( +pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreWalletBroadcastSignedTransaction( mut env: JNIEnv, _class: JClass, core_handle: jlong, @@ -1212,7 +1212,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c } let mut out_txid: *mut c_char = ptr::null_mut(); let result = unsafe { - platform_wallet_ffi::core_wallet_broadcast_signed_transaction_v2( + platform_wallet_ffi::core_wallet_broadcast_signed_transaction( core_handle as Handle, transaction_handle as Handle, &mut out_txid, @@ -1236,7 +1236,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c } #[no_mangle] -pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreWalletAbandonSignedTransactionV2( +pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreWalletAbandonSignedTransaction( mut env: JNIEnv, _class: JClass, core_handle: jlong, @@ -1247,7 +1247,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c return; } let result = unsafe { - platform_wallet_ffi::core_wallet_abandon_signed_transaction_v2( + platform_wallet_ffi::core_wallet_abandon_signed_transaction( core_handle as Handle, transaction_handle as Handle, ) @@ -1257,22 +1257,20 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c } #[no_mangle] -pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreSignedTransactionV2Free( +pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreSignedTransactionFree( mut env: JNIEnv, _class: JClass, transaction_handle: jlong, ) { guard(&mut env, (), |_| { if transaction_handle != 0 { - platform_wallet_ffi::core_wallet_signed_transaction_v2_free( - transaction_handle as Handle, - ); + platform_wallet_ffi::core_wallet_signed_transaction_free(transaction_handle as Handle); } }) } #[no_mangle] -pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreSignedTransactionV2Fee( +pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreSignedTransactionFee( mut env: JNIEnv, _class: JClass, transaction_handle: jlong, @@ -1280,7 +1278,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c guard(&mut env, 0, |env| { let mut fee = 0u64; let result = unsafe { - platform_wallet_ffi::core_wallet_signed_transaction_v2_fee( + platform_wallet_ffi::core_wallet_signed_transaction_fee( transaction_handle as Handle, &mut fee, ) @@ -1292,7 +1290,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c }) } -/// `core_wallet_signed_transaction_v2_bytes` — the consensus-serialized +/// `core_wallet_signed_transaction_bytes` — the consensus-serialized /// signed transaction bytes of a finalized-transaction handle from /// [coreTxBuilderFinalize], WITHOUT consuming the ownership token (mirror of /// Swift's `FinalizedCoreTransaction.serializedData()`). Lets the caller @@ -1300,7 +1298,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c /// order) before deciding to broadcast. The FFI-owned buffer is copied into /// the returned `byte[]` and freed here. #[no_mangle] -pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreSignedTransactionV2Bytes( +pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_coreSignedTransactionBytes( mut env: JNIEnv, _class: JClass, transaction_handle: jlong, @@ -1313,7 +1311,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c let mut bytes_ptr: *mut u8 = ptr::null_mut(); let mut bytes_len: usize = 0; let result = unsafe { - platform_wallet_ffi::core_wallet_signed_transaction_v2_bytes( + platform_wallet_ffi::core_wallet_signed_transaction_bytes( transaction_handle as Handle, &mut bytes_ptr, &mut bytes_len, @@ -1361,7 +1359,7 @@ pub extern "system" fn Java_org_dashfoundation_dashsdk_ffi_WalletManagerNative_c // ── Deferred build → broadcast/release core-send (BIP70/BIP270) ─────── // // ADDITIVE surface over the immediate [coreTxBuilderFinalize] + -// [coreWalletBroadcastSignedTransactionV2] send path: +// [coreWalletBroadcastSignedTransaction] send path: // [coreWalletFinalizeSignedPayment] atomically funds, reserves, signs, and // registers a builder in one native call, returning the raw bytes to hand to a // merchant server; the reservation is then broadcast on ack — or released on diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/CoreTransactionBuilder.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/CoreTransactionBuilder.swift index a71bdd6607..ab59b4a90c 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/CoreTransactionBuilder.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/CoreTransactionBuilder.swift @@ -9,9 +9,9 @@ public final class FinalizedCoreTransaction { init(handle: Handle) throws { var value: UInt64 = 0 do { - try core_wallet_signed_transaction_v2_fee(handle, &value).check() + try core_wallet_signed_transaction_fee(handle, &value).check() } catch { - core_wallet_signed_transaction_v2_free(handle) + core_wallet_signed_transaction_free(handle) throw error } nativeHandle = handle @@ -20,7 +20,7 @@ public final class FinalizedCoreTransaction { deinit { if nativeHandle != 0 { - core_wallet_signed_transaction_v2_free(nativeHandle) + core_wallet_signed_transaction_free(nativeHandle) } } @@ -44,7 +44,7 @@ public final class FinalizedCoreTransaction { var bytesPtr: UnsafeMutablePointer? = nil var bytesLen: UInt = 0 - try core_wallet_signed_transaction_v2_bytes(nativeHandle, &bytesPtr, &bytesLen).check() + try core_wallet_signed_transaction_bytes(nativeHandle, &bytesPtr, &bytesLen).check() guard let bytesPtr, bytesLen > 0 else { throw PlatformWalletError.unknown( diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift index ec80b6402c..69af4d0e29 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift @@ -247,7 +247,7 @@ public class ManagedCoreWallet { ) throws -> CoreTransactionBroadcastOutcome { let transactionHandle = try tx.takeForBroadcast() var txidPtr: UnsafeMutablePointer? = nil - let result = PlatformWalletResult(core_wallet_broadcast_signed_transaction_v2( + let result = PlatformWalletResult(core_wallet_broadcast_signed_transaction( handle, transactionHandle, &txidPtr @@ -264,7 +264,7 @@ public class ManagedCoreWallet { .errorTransactionBroadcastUnconfirmed: guard let txidPtr else { throw PlatformWalletError.nullPointer( - "core_wallet_broadcast_signed_transaction_v2 returned a NULL txid pointer for \(result.code)" + "core_wallet_broadcast_signed_transaction returned a NULL txid pointer for \(result.code)" ) } return try CoreTransactionBroadcastOutcome( @@ -276,7 +276,7 @@ public class ManagedCoreWallet { default: try result.throwIfError() throw PlatformWalletError.unknown( - "core_wallet_broadcast_signed_transaction_v2 returned an unexpected success state" + "core_wallet_broadcast_signed_transaction returned an unexpected success state" ) } } @@ -323,7 +323,7 @@ public class ManagedCoreWallet { /// Consume without sending and release its reservation immediately. public func abandonTransaction(_ tx: FinalizedCoreTransaction) throws { - try core_wallet_abandon_signed_transaction_v2( + try core_wallet_abandon_signed_transaction( handle, tx.takeForAbandon() ).check() diff --git a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletResult.swift b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletResult.swift index 22e653dcb8..a16377ef6f 100644 --- a/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletResult.swift +++ b/packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletResult.swift @@ -122,7 +122,7 @@ public enum PlatformWalletResultCode: Int32, Sendable { /// signed-payment finalize refuses to register a payment whose wallet was /// removed while it was being signed. /// - /// Finalized-transaction *handle* (V2) path: `finalizeAtomic` publishes no + /// Finalized-transaction *handle* path: `finalizeAtomic` publishes no /// handle when the wallet was removed or re-created during signing, and /// `broadcastTransactionWithOutcome(_: FinalizedCoreTransaction)` refuses a /// handle whose generation is gone. diff --git a/packages/swift-sdk/SwiftExampleApp/TEST_PLAN.md b/packages/swift-sdk/SwiftExampleApp/TEST_PLAN.md index d84b795873..c411bcddb8 100644 --- a/packages/swift-sdk/SwiftExampleApp/TEST_PLAN.md +++ b/packages/swift-sdk/SwiftExampleApp/TEST_PLAN.md @@ -115,7 +115,7 @@ Most Platform actions have hard preconditions. Establish these fixtures before s | CORE-02 | Restore wallet (existing mnemonic) | Core | Essential | ✅ | | `CreateWalletView` (Import Existing toggle). After sync, derived addresses + balance populate. | | CORE-03 | Backup / view recovery phrase | Core | Essential | ✅ | | `SeedBackupView`. Phrase matches creation. | | CORE-04 | Receive (derive address + QR) | Core | Essential | ✅ | | `ReceiveAddressView` → `core_wallet_next_receive_address`. Fresh external address + scannable QR. | -| CORE-05 | Send Core L1 transaction | Core | Essential | ✅ | | Send flow (`SendTransactionView`, mode Core→Core) → `CoreTransactionBuilder.addOutput` / `finalizeAtomic` → `ManagedCoreWallet.broadcastTransaction` (`core_wallet_broadcast_signed_transaction_v2`). Funding and reservation are atomic; tx broadcasts, balance drops, and it appears in history. *Anchor: the canonical Essential action.* | +| CORE-05 | Send Core L1 transaction | Core | Essential | ✅ | | Send flow (`SendTransactionView`, mode Core→Core) → `CoreTransactionBuilder.addOutput` / `finalizeAtomic` → `ManagedCoreWallet.broadcastTransaction` (`core_wallet_broadcast_signed_transaction`). Funding and reservation are atomic; tx broadcasts, balance drops, and it appears in history. *Anchor: the canonical Essential action.* | | CORE-06 | View balance / tx history / UTXOs | Core | Essential | ✅ | read-only | `WalletDetailView`, `TransactionListView`, `AccountDetailView` (SwiftData). | | CORE-07 | SPV sync (start / stop / progress) | Core | Essential | ✅ | | Global sync indicator (`ContentView`) → `platform_wallet_manager_spv_*`. Headers/filters/masternodes advance to tip. | | CORE-08 | QR scan recipient | Core | Manual | ✅ | | `QRScannerView`, reachable in the Send flow — but scanning needs a real camera the simulator doesn't have, so it can't be automated (`Tier=Manual`). On a device: Send → QR-scan button → point at a Dash address QR → recipient field populates. | From 8b81b84d986b590c556bf78d2b507d784d09c5d2 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 7 Aug 2026 03:28:47 +0700 Subject: [PATCH 2/2] docs(kotlin-sdk): drop the last v2 mention in the PARITY send record Co-Authored-By: Claude Fable 5 --- packages/kotlin-sdk/PARITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kotlin-sdk/PARITY.md b/packages/kotlin-sdk/PARITY.md index 987869e0d0..1412fd9424 100644 --- a/packages/kotlin-sdk/PARITY.md +++ b/packages/kotlin-sdk/PARITY.md @@ -158,7 +158,7 @@ verbatim. Documented deviations from iOS are listed after the table. | QRScannerView.swift | ui/scanner/QrScannerScreen.kt · `QrScanner` | ported | | ReceiveAddressView.swift | ui/wallet/ReceiveAddressSheet.kt | ported | | SeedBackupView.swift | ui/wallet/SeedBackupScreen.kt · `SeedBackup` | ported | -| SendTransactionView.swift | ui/wallet/SendTransactionScreen.kt · `SendTransaction` | ported — `ManagedPlatformWallet.sendToAddresses` drives the atomic V2 path (`CoreTransactionBuilder.finalizeAtomic` → `core_wallet_tx_builder_finalize` → `core_wallet_broadcast_signed_transaction`); shared Rust owns selection, reservation, signing, and broadcast classification | +| SendTransactionView.swift | ui/wallet/SendTransactionScreen.kt · `SendTransaction` | ported — `ManagedPlatformWallet.sendToAddresses` drives the atomic finalized-transaction path (`CoreTransactionBuilder.finalizeAtomic` → `core_wallet_tx_builder_finalize` → `core_wallet_broadcast_signed_transaction`); shared Rust owns selection, reservation, signing, and broadcast classification | | ShieldedActivityView.swift | ui/shielded/ShieldedActivityScreen.kt · `ShieldedActivity` | ported | | TransactionDetailView.swift | ui/wallet/TransactionDetailScreen.kt · `WalletTransactionDetail` | ported | | TransactionListView.swift | ui/wallet/TransactionListScreen.kt · `WalletTransactions` | ported |