diff --git a/packages/swift-sdk/SwiftTests/SwiftDashSDKIntegrationTests/Core/SpvManyTxMidSyncBackfillIntegrationTests.swift b/packages/swift-sdk/SwiftTests/SwiftDashSDKIntegrationTests/Core/SpvManyTxMidSyncBackfillIntegrationTests.swift new file mode 100644 index 0000000000..e5baa41d1c --- /dev/null +++ b/packages/swift-sdk/SwiftTests/SwiftDashSDKIntegrationTests/Core/SpvManyTxMidSyncBackfillIntegrationTests.swift @@ -0,0 +1,148 @@ +import Foundation +import XCTest +import DashSDKFFI +@testable import SwiftDashSDK + +/// Wallet imported MID-sync. +final class SpvManyTxMidSyncBackfillIntegrationTests: IntegrationTestCase { + /// Number of transactions / distinct funded addresses. Parameterized. + private let numTxs = 10 + + /// Funding amount per address, in DASH. + private let amountEachDash: Double = 0.001 + private var amountEachDuffs: UInt64 { UInt64(amountEachDash * 1e8) } + + func testManyTxImportedMidSyncBackfillsAllHistory() async throws { + let mnemonic = try Mnemonic.generate(wordCount: 24) + + // 1. Derive N distinct external receive addresses from the KeyWallet + // layer (regtest-encoded — the manager's network drives encoding). + let km = try WalletManager(network: .regtest) + let walletId = try km.addWallet(mnemonic: mnemonic) + let addresses = try Self.deriveExternalAddresses( + manager: km, walletId: walletId, count: numTxs + ) + + // One funding tx per block. + for i in 0.. [String] { + var error = FFIError() + + guard let managedInfo = walletId.withUnsafeBytes({ raw in + wallet_manager_get_managed_wallet_info( + manager.ffiHandle, + raw.bindMemory(to: UInt8.self).baseAddress, + &error + ) + }) else { + throw DerivationError(description: "wallet_manager_get_managed_wallet_info failed: \(Self.take(&error))") + } + defer { managed_wallet_info_free(managedInfo) } + + // Non-owning: the manager retains ownership of the wallet handle. + guard let wallet = walletId.withUnsafeBytes({ raw in + wallet_manager_get_wallet( + manager.ffiHandle, + raw.bindMemory(to: UInt8.self).baseAddress, + &error + ) + }) else { + throw DerivationError(description: "wallet_manager_get_wallet failed: \(Self.take(&error))") + } + + var addressesOut: UnsafeMutablePointer?>? = nil + var outCount = 0 + let ok = managed_wallet_get_bip_44_external_address_range( + managedInfo, + wallet, + /* account_index */ 0, + /* start_index */ 0, + /* end_index */ UInt32(count), + &addressesOut, + &outCount, + &error + ) + guard ok, let arr = addressesOut else { + throw DerivationError(description: "managed_wallet_get_bip_44_external_address_range failed: \(Self.take(&error))") + } + defer { address_array_free(arr, outCount) } + + var result: [String] = [] + result.reserveCapacity(outCount) + for i in 0.. String { + guard let msg = error.message else { return "code \(error.code.rawValue)" } + defer { + error_message_free(msg) + error.message = nil + } + return String(cString: msg) + } +}