From e51f425c540722c506204e9f6633fc6c326123d6 Mon Sep 17 00:00:00 2001 From: Lukas Korba Date: Tue, 6 Feb 2024 10:38:38 +0100 Subject: [PATCH] [#1369] SynchronizerState refactor - plural of account balances refactor to singular [#1369] SynchronizerState refactor - transaprent balance removed from SynchronizerState - all balances are now handled with AccountBalance [#1369] SynchronizerState refactor and balances cleanup - WalletBalance has been removed from the SDK, replaced with AccountBalance - public APIs for individual balances (getTransparent, getShielded, getShieldedVerfied) have been removed from the SDK, replaced with getAccountBalance - tests refactored [#1369] SynchronizerState refactor and balances cleanup - dark side tests refactored [#1369] SynchronizerState refactor and balances cleanup (#1372) - addressed comments [#1369] SynchronizerState refactor - ZcashError for spending key does not belong to the wallet --- CHANGELOG.md | 16 ++- .../GetBalanceViewController.swift | 4 +- .../Get UTXOs/GetUTXOsViewController.swift | 6 +- .../Send/SendViewController.swift | 10 +- .../Block/CompactBlockProcessor.swift | 15 --- .../Block/Download/BlockDownloader.swift | 8 -- .../FetchUnspentTxOutputs/UTXOFetcher.swift | 1 - .../ClosureSynchronizer.swift | 8 +- .../CombineSynchronizer.swift | 4 +- .../DAO/UnspentTransactionOutputDao.swift | 27 ----- .../Error/ZcashError.swift | 5 - .../Error/ZcashErrorCode.swift | 2 - .../Error/ZcashErrorCodeDefinition.swift | 5 +- .../Model/WalletTypes.swift | 16 --- .../UnspentTransactionOutputRepository.swift | 1 - .../ZcashLightClientKit/Synchronizer.swift | 34 ++---- .../Synchronizer/ClosureSDKSynchronizer.swift | 16 +-- .../Synchronizer/CombineSDKSynchronizer.swift | 16 +-- .../Synchronizer/SDKSynchronizer.swift | 27 ++--- Tests/DarksideTests/AdvancedReOrgTests.swift | 85 ++++++++------- Tests/DarksideTests/BalanceTests.swift | 83 +++++++++------ Tests/DarksideTests/RewindRescanTests.swift | 54 ++++++---- Tests/DarksideTests/ShieldFundsTests.swift | 44 ++++---- .../SynchronizerDarksideTests.swift | 42 +++----- Tests/DarksideTests/SynchronizerTests.swift | 12 +-- .../ClosureSynchronizerOfflineTests.swift | 54 ++++++---- .../CombineSynchronizerOfflineTests.swift | 56 ++++++---- .../SynchronizerOfflineTests.swift | 3 +- .../AutoMockable.generated.swift | 100 +++--------------- Tests/TestUtils/Stubs.swift | 3 +- 30 files changed, 303 insertions(+), 454 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0e1ef97..22c53a2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,21 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Changed +### [#1369] SynchronizerState refactor and balances cleanup +`SynchronizerState` cleaned up and changed to provide only `AccountBalance`. This struct holds `saplingBalance: PoolBalance` which represents shielded balance for both total and spendable. Also holds `unshielded: Zatoshi` which represents transparent balance. + +## Removed + +### [#1369] SynchronizerState refactor and balances cleanup +- `WalletBalance` has been removed from the SDK, replaced with `AccountBalance`. +- `getTransparentBalance(accountIndex: Int)`, use `getAccountBalance(accountIndex: Int = 0)` instead +- `getShieldedBalance(accountIndex: Int)`, use `getAccountBalance(accountIndex: Int = 0)` instead +- `getShieldedVerifiedBalance(accountIndex: Int)`, use `getAccountBalance(accountIndex: Int = 0)` instead + +# 2.0.9 - 2024-01-31 + +## Changed + ### [#1363] Account balances in the SynchronizerState `shieldedBalance: WalletBalance` has been replaced with `accountBalances: AccountBalance`. `AccountBalance` provides the same values as `shieldedBalance` but adds up a pending changes. Under the hood this calls rust's `getWalletSummary` which improved also the syncing initial values of % and balances. @@ -29,7 +44,6 @@ broke shielding. ## Added - `Model.ScanSummary` - `Model.WalletSummary.{PoolBalance, AccountBalance, WalletSummary}` -- ## Changed - The `ZcashError` type has changed. diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/Get Balance/GetBalanceViewController.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/Get Balance/GetBalanceViewController.swift index 47a594d3..ccee9d6a 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/Get Balance/GetBalanceViewController.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/Get Balance/GetBalanceViewController.swift @@ -19,8 +19,8 @@ class GetBalanceViewController: UIViewController { self.title = "Account 0 Balance" Task { @MainActor in - let balanceText = (try? await synchronizer.getShieldedBalance().formattedString) ?? "0.0" - let verifiedText = (try? await synchronizer.getShieldedVerifiedBalance().formattedString) ?? "0.0" + let balanceText = (try? await synchronizer.getAccountBalance()?.saplingBalance.total().formattedString) ?? "0.0" + let verifiedText = (try? await synchronizer.getAccountBalance()?.saplingBalance.spendableValue.formattedString) ?? "0.0" self.balance.text = "\(balanceText) ZEC" self.verified.text = "\(verifiedText) ZEC" } diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift index 02a7d80e..4d62c29c 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/Get UTXOs/GetUTXOsViewController.swift @@ -31,10 +31,10 @@ class GetUTXOsViewController: UIViewController { self.transparentAddressLabel.text = tAddress // swiftlint:disable:next force_try - let balance = try! await AppDelegate.shared.sharedSynchronizer.getTransparentBalance(accountIndex: 0) + let balance = try! await AppDelegate.shared.sharedSynchronizer.getAccountBalance(accountIndex: 0)?.unshielded ?? .zero - self.totalBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.total.amount)) - self.verifiedBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.verified.amount)) + self.totalBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.amount)) + self.verifiedBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.amount)) } } diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/Send/SendViewController.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/Send/SendViewController.swift index bf6fbea7..a62865b1 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/Send/SendViewController.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/Send/SendViewController.swift @@ -103,8 +103,8 @@ class SendViewController: UIViewController { } func updateBalance() async { - balanceLabel.text = format(balance: (try? await synchronizer.getShieldedBalance(accountIndex: 0)) ?? .zero) - verifiedBalanceLabel.text = format(balance: (try? await synchronizer.getShieldedVerifiedBalance(accountIndex: 0)) ?? .zero) + balanceLabel.text = format(balance: (try? await synchronizer.getAccountBalance(accountIndex: 0))?.saplingBalance.total() ?? .zero) + verifiedBalanceLabel.text = format(balance: (try? await synchronizer.getAccountBalance(accountIndex: 0))?.saplingBalance.spendableValue ?? .zero) } func format(balance: Zatoshi = Zatoshi()) -> String { @@ -118,7 +118,7 @@ class SendViewController: UIViewController { func maxFundsOn() { Task { @MainActor in let fee = Zatoshi(10000) - let max: Zatoshi = ((try? await synchronizer.getShieldedVerifiedBalance(accountIndex: 0)) ?? .zero) - fee + let max: Zatoshi = ((try? await synchronizer.getAccountBalance(accountIndex: 0))?.saplingBalance.spendableValue ?? .zero) - fee amountTextField.text = format(balance: max) amountTextField.isEnabled = false } @@ -140,12 +140,12 @@ class SendViewController: UIViewController { } func isBalanceValid() async -> Bool { - let balance = (try? await synchronizer.getShieldedVerifiedBalance(accountIndex: 0)) ?? .zero + let balance = (try? await synchronizer.getAccountBalance(accountIndex: 0))?.saplingBalance.spendableValue ?? .zero return balance > .zero } func isAmountValid() async -> Bool { - let balance = (try? await synchronizer.getShieldedVerifiedBalance(accountIndex: 0)) ?? .zero + let balance = (try? await synchronizer.getAccountBalance(accountIndex: 0))?.saplingBalance.spendableValue ?? .zero guard let value = amountTextField.text, let amount = NumberFormatter.zcashNumberFormatter.number(from: value).flatMap({ Zatoshi($0.int64Value) }), diff --git a/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift b/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift index 72a0f729..4eb567ef 100644 --- a/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift +++ b/Sources/ZcashLightClientKit/Block/CompactBlockProcessor.swift @@ -845,21 +845,6 @@ extension CompactBlockProcessor { func getTransparentAddress(accountIndex: Int) async throws -> TransparentAddress { try await getUnifiedAddress(accountIndex: accountIndex).transparentReceiver() } - - func getTransparentBalance(accountIndex: Int) async throws -> WalletBalance { - guard accountIndex >= 0 else { - throw ZcashError.compactBlockProcessorInvalidAccount - } - - return WalletBalance( - verified: Zatoshi( - try await rustBackend.getVerifiedTransparentBalance(account: Int32(accountIndex)) - ), - total: Zatoshi( - try await rustBackend.getTransparentBalance(account: Int32(accountIndex)) - ) - ) - } } extension CompactBlockProcessor { diff --git a/Sources/ZcashLightClientKit/Block/Download/BlockDownloader.swift b/Sources/ZcashLightClientKit/Block/Download/BlockDownloader.swift index efe959b9..3d26015a 100644 --- a/Sources/ZcashLightClientKit/Block/Download/BlockDownloader.swift +++ b/Sources/ZcashLightClientKit/Block/Download/BlockDownloader.swift @@ -195,23 +195,15 @@ actor BlockDownloaderImpl { var buffer: [ZcashCompactBlock] = [] logger.debug("Downloading blocks in range: \(range.lowerBound)...\(range.upperBound)") - var startTime = Date() - var lastDownloadedBlockHeight = -1 - for _ in stride(from: range.lowerBound, to: range.upperBound + 1, by: 1) { try Task.checkCancellation() guard let block = try await stream.nextBlock() else { break } - lastDownloadedBlockHeight = block.height - buffer.append(block) if buffer.count >= maxBlockBufferSize { - let finishTime = Date() try await storage.write(blocks: buffer) try await blocksBufferWritten(buffer) buffer.removeAll(keepingCapacity: true) - - startTime = finishTime } } diff --git a/Sources/ZcashLightClientKit/Block/FetchUnspentTxOutputs/UTXOFetcher.swift b/Sources/ZcashLightClientKit/Block/FetchUnspentTxOutputs/UTXOFetcher.swift index 627a059b..bbff3986 100644 --- a/Sources/ZcashLightClientKit/Block/FetchUnspentTxOutputs/UTXOFetcher.swift +++ b/Sources/ZcashLightClientKit/Block/FetchUnspentTxOutputs/UTXOFetcher.swift @@ -62,7 +62,6 @@ extension UTXOFetcherImpl: UTXOFetcher { var refreshed: [UnspentTransactionOutputEntity] = [] var skipped: [UnspentTransactionOutputEntity] = [] - let startTime = Date() let all = Float(utxos.count) var counter = Float(0) for utxo in utxos { diff --git a/Sources/ZcashLightClientKit/ClosureSynchronizer.swift b/Sources/ZcashLightClientKit/ClosureSynchronizer.swift index 0834034c..66ad1d22 100644 --- a/Sources/ZcashLightClientKit/ClosureSynchronizer.swift +++ b/Sources/ZcashLightClientKit/ClosureSynchronizer.swift @@ -68,12 +68,8 @@ public protocol ClosureSynchronizer { func refreshUTXOs(address: TransparentAddress, from height: BlockHeight, completion: @escaping (Result) -> Void) - func getTransparentBalance(accountIndex: Int, completion: @escaping (Result) -> Void) - - func getShieldedBalance(accountIndex: Int, completion: @escaping (Result) -> Void) - - func getShieldedVerifiedBalance(accountIndex: Int, completion: @escaping (Result) -> Void) - + func getAccountBalance(accountIndex: Int, completion: @escaping (Result) -> Void) + /* It can be missleading that these two methods are returning Publisher even this protocol is closure based. Reason is that Synchronizer doesn't provide different implementations for these two methods. So Combine it is even here. diff --git a/Sources/ZcashLightClientKit/CombineSynchronizer.swift b/Sources/ZcashLightClientKit/CombineSynchronizer.swift index 95955032..2581af68 100644 --- a/Sources/ZcashLightClientKit/CombineSynchronizer.swift +++ b/Sources/ZcashLightClientKit/CombineSynchronizer.swift @@ -64,9 +64,7 @@ public protocol CombineSynchronizer { func refreshUTXOs(address: TransparentAddress, from height: BlockHeight) -> SinglePublisher - func getTransparentBalance(accountIndex: Int) -> SinglePublisher - func getShieldedBalance(accountIndex: Int) -> SinglePublisher - func getShieldedVerifiedBalance(accountIndex: Int) -> SinglePublisher + func getAccountBalance(accountIndex: Int) -> SinglePublisher func rewind(_ policy: RewindPolicy) -> CompletablePublisher func wipe() -> CompletablePublisher diff --git a/Sources/ZcashLightClientKit/DAO/UnspentTransactionOutputDao.swift b/Sources/ZcashLightClientKit/DAO/UnspentTransactionOutputDao.swift index e5ed0291..e5561c74 100644 --- a/Sources/ZcashLightClientKit/DAO/UnspentTransactionOutputDao.swift +++ b/Sources/ZcashLightClientKit/DAO/UnspentTransactionOutputDao.swift @@ -183,33 +183,6 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository { } } } - - /// - Throws: `unspentTransactionOutputDAOBalance` if sqlite query fails. - func balance(address: String, latestHeight: BlockHeight) async throws -> WalletBalance { - do { - let verified = try dbProvider.connection().scalarLocked( - table.select(TableColumns.valueZat.sum) - .filter(TableColumns.address == address) - .filter(TableColumns.height <= latestHeight - ZcashSDK.defaultStaleTolerance) - ) ?? 0 - let total = try dbProvider.connection().scalarLocked( - table.select(TableColumns.valueZat.sum) - .filter(TableColumns.address == address) - ) ?? 0 - - return WalletBalance( - verified: Zatoshi(Int64(verified)), - total: Zatoshi(Int64(total)) - ) - } catch { - throw ZcashError.unspentTransactionOutputDAOBalance(error) - } - } -} - -struct TransparentBalance { - var balance: WalletBalance - var address: String } enum UTXORepositoryBuilder { diff --git a/Sources/ZcashLightClientKit/Error/ZcashError.swift b/Sources/ZcashLightClientKit/Error/ZcashError.swift index ac83f893..8fcdfb08 100644 --- a/Sources/ZcashLightClientKit/Error/ZcashError.swift +++ b/Sources/ZcashLightClientKit/Error/ZcashError.swift @@ -584,9 +584,6 @@ public enum ZcashError: Equatable, Error { /// Indicates that this Synchronizer is disconnected from its lightwalletd server. /// ZSYNCO0006 case synchronizerDisconnected - /// The attempt to switch endpoints failed. Check that the hostname and port are correct, and are formatted as :. - /// ZSYNCO0007 - case synchronizerServerSwitch public var message: String { switch self { @@ -757,7 +754,6 @@ public enum ZcashError: Equatable, Error { case .synchronizerLatestUTXOsInvalidTAddress: return "LatestUTXOs for the address failed, invalid t-address." case .synchronizerRewindUnknownArchorHeight: return "Rewind failed, unknown archor height" case .synchronizerDisconnected: return "Indicates that this Synchronizer is disconnected from its lightwalletd server." - case .synchronizerServerSwitch: return "The attempt to switch endpoints failed. Check that the hostname and port are correct, and are formatted as :." } } @@ -930,7 +926,6 @@ public enum ZcashError: Equatable, Error { case .synchronizerLatestUTXOsInvalidTAddress: return .synchronizerLatestUTXOsInvalidTAddress case .synchronizerRewindUnknownArchorHeight: return .synchronizerRewindUnknownArchorHeight case .synchronizerDisconnected: return .synchronizerDisconnected - case .synchronizerServerSwitch: return .synchronizerServerSwitch } } diff --git a/Sources/ZcashLightClientKit/Error/ZcashErrorCode.swift b/Sources/ZcashLightClientKit/Error/ZcashErrorCode.swift index 2814f579..0bc50a73 100644 --- a/Sources/ZcashLightClientKit/Error/ZcashErrorCode.swift +++ b/Sources/ZcashLightClientKit/Error/ZcashErrorCode.swift @@ -343,6 +343,4 @@ public enum ZcashErrorCode: String { case synchronizerRewindUnknownArchorHeight = "ZSYNCO0005" /// Indicates that this Synchronizer is disconnected from its lightwalletd server. case synchronizerDisconnected = "ZSYNCO0006" - /// The attempt to switch endpoints failed. Check that the hostname and port are correct, and are formatted as :. - case synchronizerServerSwitch = "ZSYNCO0007" } diff --git a/Sources/ZcashLightClientKit/Error/ZcashErrorCodeDefinition.swift b/Sources/ZcashLightClientKit/Error/ZcashErrorCodeDefinition.swift index 730ce3c9..188577e7 100644 --- a/Sources/ZcashLightClientKit/Error/ZcashErrorCodeDefinition.swift +++ b/Sources/ZcashLightClientKit/Error/ZcashErrorCodeDefinition.swift @@ -348,7 +348,7 @@ enum ZcashErrorDefinition { /// - `rustError` contains error generated by the rust layer. // sourcery: code="ZRUST0056" case rustGetWalletSummary(_ rustError: String) - + // MARK: - Account DAO /// SQLite query failed when fetching all accounts from the database. @@ -666,4 +666,7 @@ enum ZcashErrorDefinition { /// The attempt to switch endpoints failed. Check that the hostname and port are correct, and are formatted as :. // sourcery: code="ZSYNCO0007" case synchronizerServerSwitch + /// The spending key does not belong to the wallet. + // sourcery: code="ZSYNCO0008" + case synchronizerSpendingKeyDoesNotBelongToTheWallet } diff --git a/Sources/ZcashLightClientKit/Model/WalletTypes.swift b/Sources/ZcashLightClientKit/Model/WalletTypes.swift index 2bba971b..6a6fec13 100644 --- a/Sources/ZcashLightClientKit/Model/WalletTypes.swift +++ b/Sources/ZcashLightClientKit/Model/WalletTypes.swift @@ -263,19 +263,3 @@ public enum Recipient: Equatable, StringEncoded { } } } - -public struct WalletBalance: Equatable { - public let verified: Zatoshi - public let total: Zatoshi - - public init(verified: Zatoshi, total: Zatoshi) { - self.verified = verified - self.total = total - } -} - -public extension WalletBalance { - static var zero: WalletBalance { - Self(verified: .zero, total: .zero) - } -} diff --git a/Sources/ZcashLightClientKit/Repository/UnspentTransactionOutputRepository.swift b/Sources/ZcashLightClientKit/Repository/UnspentTransactionOutputRepository.swift index 6c1f1ab3..348a69aa 100644 --- a/Sources/ZcashLightClientKit/Repository/UnspentTransactionOutputRepository.swift +++ b/Sources/ZcashLightClientKit/Repository/UnspentTransactionOutputRepository.swift @@ -10,7 +10,6 @@ import Foundation protocol UnspentTransactionOutputRepository { func initialise() async throws func getAll(address: String?) async throws -> [UnspentTransactionOutputEntity] - func balance(address: String, latestHeight: BlockHeight) async throws -> WalletBalance func store(utxos: [UnspentTransactionOutputEntity]) async throws func clearAll(address: String?) async throws } diff --git a/Sources/ZcashLightClientKit/Synchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer.swift index 83b58c16..f675d0da 100644 --- a/Sources/ZcashLightClientKit/Synchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer.swift @@ -35,10 +35,8 @@ public struct SynchronizerState: Equatable { /// given how application lifecycle varies between OS Versions, platforms, etc. /// SyncSessionIDs are provided to users public var syncSessionID: UUID - /// account (shielded) balances known to this synchronizer given the data that has processed locally - public var accountBalances: AccountBalance - /// transparent balance known to this synchronizer given the data that has processed locally - public var transparentBalance: WalletBalance + /// account balance known to this synchronizer given the data that has processed locally + public var accountBalance: AccountBalance? /// status of the whole sync process var internalSyncStatus: InternalSyncStatus public var syncStatus: SyncStatus @@ -49,8 +47,7 @@ public struct SynchronizerState: Equatable { public static var zero: SynchronizerState { SynchronizerState( syncSessionID: .nullID, - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .unprepared, latestBlockHeight: .zero ) @@ -58,14 +55,12 @@ public struct SynchronizerState: Equatable { init( syncSessionID: UUID, - accountBalances: AccountBalance, - transparentBalance: WalletBalance, + accountBalance: AccountBalance?, internalSyncStatus: InternalSyncStatus, latestBlockHeight: BlockHeight ) { self.syncSessionID = syncSessionID - self.accountBalances = accountBalances - self.transparentBalance = transparentBalance + self.accountBalance = accountBalance self.internalSyncStatus = internalSyncStatus self.latestBlockHeight = latestBlockHeight self.syncStatus = internalSyncStatus.mapToSyncStatus() @@ -236,23 +231,10 @@ public protocol Synchronizer: AnyObject { /// `SynchronizerErrors.notPrepared`. func refreshUTXOs(address: TransparentAddress, from height: BlockHeight) async throws -> RefreshedUTXOs - /// Returns the last stored transparent balance - func getTransparentBalance(accountIndex: Int) async throws -> WalletBalance - - /// get (unverified) balance from the given account index + /// Account balances from the given account index /// - Parameter accountIndex: the index of the account - /// - Returns: balance in `Zatoshi` - func getShieldedBalance(accountIndex: Int) async throws -> Zatoshi - - /// get verified balance from the given account index - /// - Parameter accountIndex: the index of the account - /// - Returns: balance in `Zatoshi` - func getShieldedVerifiedBalance(accountIndex: Int) async throws -> Zatoshi - - /// get account balances from the given account index - /// - Parameter accountIndex: the index of the account - /// - Returns: balances - func getAccountBalances(accountIndex: Int) async throws -> AccountBalance? + /// - Returns: `AccountBalance`, struct that holds sapling and unshielded balances or `nil` when no account is associated with `accountIndex` + func getAccountBalance(accountIndex: Int) async throws -> AccountBalance? /// Rescans the known blocks with the current keys. /// diff --git a/Sources/ZcashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift index c62daeb1..71b33392 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/ClosureSDKSynchronizer.swift @@ -147,21 +147,9 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer { } } - public func getTransparentBalance(accountIndex: Int, completion: @escaping (Result) -> Void) { + public func getAccountBalance(accountIndex: Int, completion: @escaping (Result) -> Void) { AsyncToClosureGateway.executeThrowingAction(completion) { - try await self.synchronizer.getTransparentBalance(accountIndex: accountIndex) - } - } - - public func getShieldedBalance(accountIndex: Int, completion: @escaping (Result) -> Void) { - AsyncToClosureGateway.executeThrowingAction(completion) { - try await self.synchronizer.getShieldedBalance(accountIndex: accountIndex) - } - } - - public func getShieldedVerifiedBalance(accountIndex: Int, completion: @escaping (Result) -> Void) { - AsyncToClosureGateway.executeThrowingAction(completion) { - try await self.synchronizer.getShieldedVerifiedBalance(accountIndex: accountIndex) + try await self.synchronizer.getAccountBalance(accountIndex: accountIndex) } } diff --git a/Sources/ZcashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift index 1e5129c5..ab3f286a 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/CombineSDKSynchronizer.swift @@ -140,21 +140,9 @@ extension CombineSDKSynchronizer: CombineSynchronizer { } } - public func getTransparentBalance(accountIndex: Int) -> SinglePublisher { + public func getAccountBalance(accountIndex: Int) -> SinglePublisher { AsyncToCombineGateway.executeThrowingAction() { - try await self.synchronizer.getTransparentBalance(accountIndex: accountIndex) - } - } - - public func getShieldedBalance(accountIndex: Int = 0) -> SinglePublisher { - AsyncToCombineGateway.executeThrowingAction() { - try await synchronizer.getShieldedBalance(accountIndex: accountIndex) - } - } - - public func getShieldedVerifiedBalance(accountIndex: Int = 0) -> SinglePublisher { - AsyncToCombineGateway.executeThrowingAction() { - try await synchronizer.getShieldedVerifiedBalance(accountIndex: accountIndex) + try await self.synchronizer.getAccountBalance(accountIndex: accountIndex) } } diff --git a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift index b11c7c7f..a6d84f77 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift @@ -302,10 +302,13 @@ public class SDKSynchronizer: Synchronizer { // let's see if there are funds to shield let accountIndex = Int(spendingKey.account) - let tBalance = try await self.getTransparentBalance(accountIndex: accountIndex) + + guard let tBalance = try await self.getAccountBalance(accountIndex: accountIndex)?.unshielded else { + throw ZcashError.synchronizerSpendingKeyDoesNotBelongToTheWallet + } // Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet. - guard tBalance.verified >= self.network.constants.defaultFee() else { + guard tBalance >= self.network.constants.defaultFee() else { throw ZcashError.synchronizerShieldFundsInsuficientTransparentFunds } @@ -414,20 +417,10 @@ public class SDKSynchronizer: Synchronizer { return try await blockProcessor.refreshUTXOs(tAddress: address, startHeight: height) } - public func getAccountBalances(accountIndex: Int = 0) async throws -> AccountBalance? { + public func getAccountBalance(accountIndex: Int = 0) async throws -> AccountBalance? { try await initializer.rustBackend.getWalletSummary()?.accountBalances[UInt32(accountIndex)] } - public func getShieldedBalance(accountIndex: Int = 0) async throws -> Zatoshi { - try await initializer.rustBackend.getWalletSummary()?.accountBalances[UInt32(accountIndex)]? - .saplingBalance.total() ?? Zatoshi.zero - } - - public func getShieldedVerifiedBalance(accountIndex: Int = 0) async throws -> Zatoshi { - try await initializer.rustBackend.getWalletSummary()?.accountBalances[UInt32(accountIndex)]? - .saplingBalance.spendableValue ?? Zatoshi.zero - } - public func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress { try await blockProcessor.getUnifiedAddress(accountIndex: accountIndex) } @@ -440,11 +433,6 @@ public class SDKSynchronizer: Synchronizer { try await blockProcessor.getTransparentAddress(accountIndex: accountIndex) } - /// Returns the last stored transparent balance - public func getTransparentBalance(accountIndex: Int) async throws -> WalletBalance { - try await blockProcessor.getTransparentBalance(accountIndex: accountIndex) - } - // MARK: Rewind public func rewind(_ policy: RewindPolicy) -> AnyPublisher { @@ -621,8 +609,7 @@ public class SDKSynchronizer: Synchronizer { private func snapshotState(status: InternalSyncStatus) async -> SynchronizerState { await SynchronizerState( syncSessionID: syncSession.value, - accountBalances: (try? await getAccountBalances()) ?? .zero, - transparentBalance: (try? await blockProcessor.getTransparentBalance(accountIndex: 0)) ?? .zero, + accountBalance: try? await getAccountBalance(), internalSyncStatus: status, latestBlockHeight: latestBlocksDataProvider.latestBlockHeight ) diff --git a/Tests/DarksideTests/AdvancedReOrgTests.swift b/Tests/DarksideTests/AdvancedReOrgTests.swift index a3b45afd..f973fcc1 100644 --- a/Tests/DarksideTests/AdvancedReOrgTests.swift +++ b/Tests/DarksideTests/AdvancedReOrgTests.swift @@ -100,8 +100,8 @@ class AdvancedReOrgTests: ZcashTestCase { try await coordinator.sync( completion: { synchro in synchronizer = synchro - initialVerifiedBalance = try await synchro.getShieldedVerifiedBalance() - initialTotalBalance = try await synchro.getShieldedBalance() + initialVerifiedBalance = try await synchro.getAccountBalance()?.saplingBalance.spendableValue ?? .zero + initialTotalBalance = try await synchro.getAccountBalance()?.saplingBalance.total() ?? .zero preTxExpectation.fulfill() shouldContinue = true }, @@ -135,8 +135,8 @@ class AdvancedReOrgTests: ZcashTestCase { try await coordinator.sync( completion: { synchro in synchronizer = synchro - receivedTxVerifiedBalance = try await synchro.getShieldedVerifiedBalance() - receivedTxTotalBalance = try await synchro.getShieldedBalance() + receivedTxVerifiedBalance = try await synchro.getAccountBalance()?.saplingBalance.spendableValue ?? .zero + receivedTxTotalBalance = try await synchro.getAccountBalance()?.saplingBalance.total() ?? .zero receivedTxExpectation.fulfill() }, error: self.handleError ) @@ -202,8 +202,8 @@ class AdvancedReOrgTests: ZcashTestCase { do { try await coordinator.sync( completion: { synchronizer in - afterReorgTxTotalBalance = try await synchronizer.getShieldedBalance() - afterReorgTxVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance() + afterReorgTxTotalBalance = try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero + afterReorgTxVerifiedBalance = try await synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero reorgSyncexpectation.fulfill() }, error: self.handleError @@ -238,8 +238,8 @@ class AdvancedReOrgTests: ZcashTestCase { do { try await coordinator.sync( completion: { synchronizer in - finalReorgTxTotalBalance = try await synchronizer.getShieldedBalance() - finalReorgTxVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance() + finalReorgTxTotalBalance = try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero + finalReorgTxVerifiedBalance = try await synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero finalsyncExpectation.fulfill() }, error: self.handleError @@ -304,7 +304,7 @@ class AdvancedReOrgTests: ZcashTestCase { do { try await coordinator.sync( completion: { synchronizer in - initialTotalBalance = try await synchronizer.getShieldedBalance() + initialTotalBalance = try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero preTxExpectation.fulfill() }, error: self.handleError @@ -450,13 +450,13 @@ class AdvancedReOrgTests: ZcashTestCase { await fulfillment(of: [lastSyncExpectation], timeout: 5) let expectedVerifiedBalance = initialTotalBalance + pendingTx.value - let currentVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() + let currentVerifiedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero // TODO: [#1247] needs to review this to properly solve, https://github.com/zcash/ZcashLightClientKit/issues/1247 // let expectedPendingTransactionsCount = await coordinator.synchronizer.pendingTransactions.count // XCTAssertEqual(expectedPendingTransactionsCount, 0) XCTAssertEqual(expectedVerifiedBalance, currentVerifiedBalance) - let resultingBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + let resultingBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero XCTAssertEqual(resultingBalance, currentVerifiedBalance) } @@ -480,8 +480,8 @@ class AdvancedReOrgTests: ZcashTestCase { var preReorgVerifiedBalance = Zatoshi.zero try await coordinator.sync( completion: { synchronizer in - preReorgTotalBalance = try await synchronizer.getShieldedBalance() - preReorgVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance() + preReorgTotalBalance = try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero + preReorgVerifiedBalance = try await synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero firstSyncExpectation.fulfill() }, error: self.handleError @@ -503,8 +503,8 @@ class AdvancedReOrgTests: ZcashTestCase { var postReorgVerifiedBalance = Zatoshi.zero try await coordinator.sync( completion: { synchronizer in - postReorgTotalBalance = try await synchronizer.getShieldedBalance() - postReorgVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance() + postReorgTotalBalance = try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero + postReorgVerifiedBalance = try await synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero afterReorgSync.fulfill() }, error: self.handleError @@ -527,8 +527,8 @@ class AdvancedReOrgTests: ZcashTestCase { try await coordinator.sync( completion: { synchronizer in - initialBalance = try await synchronizer.getShieldedBalance() - initialVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance() + initialBalance = try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero + initialVerifiedBalance = try await synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero expectation.fulfill() }, error: self.handleError @@ -546,8 +546,8 @@ class AdvancedReOrgTests: ZcashTestCase { try await coordinator.sync( completion: { synchronizer in - afterTxBalance = try await synchronizer.getShieldedBalance() - afterTxVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance() + afterTxBalance = try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero + afterTxVerifiedBalance = try await synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero let receivedTransactions = await synchronizer.receivedTransactions XCTAssertNotNil( receivedTransactions.first { $0.minedHeight == receivedTxHeight }, @@ -576,8 +576,8 @@ class AdvancedReOrgTests: ZcashTestCase { try await coordinator.sync( completion: { synchronizer in - afterReOrgBalance = try await synchronizer.getShieldedBalance() - afterReOrgVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance() + afterReOrgBalance = try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero + afterReOrgVerifiedBalance = try await synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero let receivedTransactions = await synchronizer.receivedTransactions XCTAssertNil( receivedTransactions.first { $0.minedHeight == receivedTxHeight }, @@ -653,8 +653,9 @@ class AdvancedReOrgTests: ZcashTestCase { /* 1a. save balances */ - initialBalance = try await coordinator.synchronizer.getShieldedBalance() - initialVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + initialBalance = accountBalance?.saplingBalance.total() ?? .zero + initialVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero incomingTx = await coordinator.synchronizer.receivedTransactions.first(where: { $0.minedHeight == incomingTxHeight }) let txRawData = incomingTx.raw ?? Data() @@ -701,8 +702,9 @@ class AdvancedReOrgTests: ZcashTestCase { /* 7. check that balances still match */ - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedVerifiedBalance, initialVerifiedBalance) XCTAssertEqual(expectedBalance, initialBalance) } @@ -721,8 +723,8 @@ class AdvancedReOrgTests: ZcashTestCase { try await coordinator.sync( completion: { synchronizer in - initialBalance = try await synchronizer.getShieldedBalance() - initialVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance() + initialBalance = try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero + initialVerifiedBalance = try await synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero firstSyncExpectation.fulfill() }, error: self.handleError @@ -746,8 +748,9 @@ class AdvancedReOrgTests: ZcashTestCase { await fulfillment(of: [lastSyncExpectation], timeout: 5) - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + let accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedBalance, initialBalance) XCTAssertEqual(expectedVerifiedBalance, initialVerifiedBalance) } @@ -1078,8 +1081,9 @@ class AdvancedReOrgTests: ZcashTestCase { await fulfillment(of: [firstSyncExpectation], timeout: 5) - let initialBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() - let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let initialBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero + let initialVerifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero guard let initialTxHeight = try await coordinator.synchronizer.allReceivedTransactions().first?.minedHeight else { XCTFail("no incoming transaction found!") return @@ -1108,8 +1112,9 @@ class AdvancedReOrgTests: ZcashTestCase { return } - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance) XCTAssertEqual(initialBalance, expectedBalance) XCTAssert(afterReOrgTxHeight > initialTxHeight) @@ -1158,8 +1163,9 @@ class AdvancedReOrgTests: ZcashTestCase { await fulfillment(of: [firstSyncExpectation], timeout: 5) - let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() - let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let initialTotalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero + let initialVerifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero try coordinator.applyStaged(blockheight: reorgHeight - 1) sleep(1) @@ -1196,8 +1202,9 @@ class AdvancedReOrgTests: ZcashTestCase { await fulfillment(of: [afterReorgSyncExpectation], timeout: 5) - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance) XCTAssertEqual(initialTotalBalance, expectedBalance) } @@ -1246,7 +1253,7 @@ class AdvancedReOrgTests: ZcashTestCase { await fulfillment(of: [firstSyncExpectation], timeout: 10) sleep(1) - let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero let sendExpectation = XCTestExpectation(description: "send expectation") var pendingEntity: ZcashTransaction.Overview? @@ -1366,7 +1373,7 @@ class AdvancedReOrgTests: ZcashTestCase { await fulfillment(of: [lastSyncExpectation], timeout: 5) - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + let expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedBalance, initialTotalBalance) } diff --git a/Tests/DarksideTests/BalanceTests.swift b/Tests/DarksideTests/BalanceTests.swift index ed41b0fe..15c41e7f 100644 --- a/Tests/DarksideTests/BalanceTests.swift +++ b/Tests/DarksideTests/BalanceTests.swift @@ -84,8 +84,9 @@ class BalanceTests: ZcashTestCase { await fulfillment(of: [firstSyncExpectation], timeout: 12) // 2 check that there are no unconfirmed funds - let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let verifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let totalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero XCTAssertTrue(verifiedBalance > network.constants.defaultFee()) XCTAssertEqual(verifiedBalance, totalBalance) @@ -198,8 +199,9 @@ class BalanceTests: ZcashTestCase { // // XCTAssertNil(confirmedPending, "pending, now confirmed transaction found") - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedBalance, .zero) XCTAssertEqual(expectedVerifiedBalance, .zero) } @@ -236,8 +238,9 @@ class BalanceTests: ZcashTestCase { await fulfillment(of: [firstSyncExpectation], timeout: 12) // 2 check that there are no unconfirmed funds - let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let verifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let totalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero XCTAssertTrue(verifiedBalance > network.constants.defaultFee()) XCTAssertEqual(verifiedBalance, totalBalance) @@ -351,8 +354,9 @@ class BalanceTests: ZcashTestCase { // // XCTAssertNil(confirmedPending, "pending, now confirmed transaction found") - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedBalance, .zero) XCTAssertEqual(expectedVerifiedBalance, .zero) } @@ -383,8 +387,9 @@ class BalanceTests: ZcashTestCase { await fulfillment(of: [firstSyncExpectation], timeout: 12) // 2 check that there are no unconfirmed funds - let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + let accountBalance = try await coordinator.synchronizer.getAccountBalance() + let verifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let totalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero XCTAssertTrue(verifiedBalance > network.constants.defaultFee()) XCTAssertEqual(verifiedBalance, totalBalance) @@ -448,8 +453,9 @@ class BalanceTests: ZcashTestCase { await fulfillment(of: [firstSyncExpectation], timeout: 12) // 2 check that there are no unconfirmed funds - let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let verifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let totalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero XCTAssertTrue(verifiedBalance > network.constants.defaultFee()) XCTAssertEqual(verifiedBalance, totalBalance) @@ -563,8 +569,9 @@ class BalanceTests: ZcashTestCase { // // XCTAssertNil(confirmedPending, "pending, now confirmed transaction found") - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedBalance, Zatoshi(100000)) XCTAssertEqual(expectedVerifiedBalance, Zatoshi(100000)) } @@ -608,7 +615,7 @@ class BalanceTests: ZcashTestCase { let spendingKey = coordinator.spendingKey - let presendVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() + let presendVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero /* there's more zatoshi to send than network fee @@ -626,7 +633,7 @@ class BalanceTests: ZcashTestCase { pendingTx = transaction self.sentTransactionExpectation.fulfill() - var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() + var expectedVerifiedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero XCTAssertTrue(expectedVerifiedBalance > .zero) await fulfillment(of: [sentTransactionExpectation], timeout: 12) @@ -659,8 +666,9 @@ class BalanceTests: ZcashTestCase { await fulfillment(of: [mineExpectation], timeout: 5) - expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + let accountBalance = try await coordinator.synchronizer.getAccountBalance() + expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual( presendVerifiedBalance - self.sendAmount - network.constants.defaultFee(), @@ -709,7 +717,7 @@ class BalanceTests: ZcashTestCase { spentValue: sentOutput.value, fee: fee, sentAmount: self.sendAmount, - currentVerifiedBalance: try await coordinator.synchronizer.getShieldedVerifiedBalance() + currentVerifiedBalance: try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero ) } @@ -751,7 +759,7 @@ class BalanceTests: ZcashTestCase { let spendingKey = coordinator.spendingKey - let presendBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + let presendBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero // there's more zatoshi to send than network fee XCTAssertTrue(presendBalance >= network.constants.defaultFee() + sendAmount) @@ -773,11 +781,12 @@ class BalanceTests: ZcashTestCase { XCTFail("sendToAddress failed: \(error)") } - var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() + let accountBalance = try await coordinator.synchronizer.getAccountBalance() + var expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero XCTAssertTrue(expectedVerifiedBalance > .zero) await fulfillment(of: [sentTransactionExpectation], timeout: 12) - expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() + expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero if let testError { XCTAssertEqual(expectedVerifiedBalance, presendBalance) XCTFail("error: \(testError)") @@ -790,7 +799,7 @@ class BalanceTests: ZcashTestCase { XCTAssertEqual(transaction.value, self.sendAmount) - var expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + var expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual( expectedBalance, presendBalance - self.sendAmount - network.constants.defaultFee() @@ -822,7 +831,7 @@ class BalanceTests: ZcashTestCase { await fulfillment(of: [mineExpectation], timeout: 5) - expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero XCTAssertEqual( presendBalance - self.sendAmount - network.constants.defaultFee(), expectedBalance @@ -859,7 +868,7 @@ class BalanceTests: ZcashTestCase { await fulfillment(of: [syncedExpectation], timeout: 5) let clearedTransactions = await coordinator.synchronizer.transactions - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + let expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero XCTAssertEqual(clearedTransactions.count, 2) XCTAssertEqual(expectedBalance, Zatoshi(200000)) } @@ -911,8 +920,9 @@ class BalanceTests: ZcashTestCase { await fulfillment(of: [syncedExpectation], timeout: 6) - let previousVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let previousTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + let accountBalance = try await coordinator.synchronizer.getAccountBalance() + let previousVerifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let previousTotalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero let spendingKey = coordinator.spendingKey @@ -1019,11 +1029,11 @@ class BalanceTests: ZcashTestCase { spentValue: sentOutput.value, fee: fee, sentAmount: self.sendAmount, - currentVerifiedBalance: try await synchronizer.getShieldedVerifiedBalance() + currentVerifiedBalance: try await synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero ) self.totalBalanceValidation( - totalBalance: try await synchronizer.getShieldedBalance(), + totalBalance: try await synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero, previousTotalbalance: previousTotalBalance, sentAmount: self.sendAmount ) @@ -1082,8 +1092,9 @@ class BalanceTests: ZcashTestCase { let spendingKey = coordinator.spendingKey - let previousVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let previousTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let previousVerifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let previousTotalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero let sendExpectation = XCTestExpectation(description: "send expectation") var pendingTx: ZcashTransaction.Overview? do { @@ -1097,8 +1108,9 @@ class BalanceTests: ZcashTestCase { sendExpectation.fulfill() } catch { // balance should be the same as before sending if transaction failed - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + let accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedVerifiedBalance, previousVerifiedBalance) XCTAssertEqual(expectedBalance, previousTotalBalance) XCTFail("sendToAddress failed: \(error)") @@ -1130,8 +1142,9 @@ class BalanceTests: ZcashTestCase { await fulfillment(of: [expirationSyncExpectation], timeout: 5) - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero /* Verified Balance is equal to verified balance previously shown before sending the expired transaction */ diff --git a/Tests/DarksideTests/RewindRescanTests.swift b/Tests/DarksideTests/RewindRescanTests.swift index bda733d3..05076f10 100644 --- a/Tests/DarksideTests/RewindRescanTests.swift +++ b/Tests/DarksideTests/RewindRescanTests.swift @@ -70,8 +70,9 @@ class RewindRescanTests: ZcashTestCase { try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName) try coordinator.applyStaged(blockheight: defaultLatestHeight + 50) - let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let initialVerifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let initialTotalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero sleep(1) let firstSyncExpectation = XCTestExpectation(description: "first sync expectation") @@ -87,8 +88,9 @@ class RewindRescanTests: ZcashTestCase { } await fulfillment(of: [firstSyncExpectation], timeout: 12) - let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let verifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let totalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero // 2 check that there are no unconfirmed funds XCTAssertTrue(verifiedBalance > network.constants.defaultFee()) XCTAssertEqual(verifiedBalance, totalBalance) @@ -123,8 +125,9 @@ class RewindRescanTests: ZcashTestCase { // XCTAssertEqual(lastScannedHeight, self.birthday) // check that the balance is cleared - var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - var expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + var expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + var expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance) XCTAssertEqual(initialTotalBalance, expectedBalance) let secondScanExpectation = XCTestExpectation(description: "rescan") @@ -143,8 +146,9 @@ class RewindRescanTests: ZcashTestCase { await fulfillment(of: [secondScanExpectation], timeout: 12) // verify that the balance still adds up - expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(verifiedBalance, expectedVerifiedBalance) XCTAssertEqual(totalBalance, expectedBalance) } @@ -161,7 +165,7 @@ class RewindRescanTests: ZcashTestCase { let newChaintTip = defaultLatestHeight + 10000 try coordinator.applyStaged(blockheight: newChaintTip) sleep(3) - let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() + let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero let firstSyncExpectation = XCTestExpectation(description: "first sync expectation") do { @@ -176,8 +180,9 @@ class RewindRescanTests: ZcashTestCase { } await fulfillment(of: [firstSyncExpectation], timeout: 20) - let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let verifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let totalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero // 2 check that there are no unconfirmed funds XCTAssertTrue(verifiedBalance > network.constants.defaultFee()) XCTAssertEqual(verifiedBalance, totalBalance) @@ -216,7 +221,7 @@ class RewindRescanTests: ZcashTestCase { await fulfillment(of: [rewindExpectation], timeout: 2) // check that the balance is cleared - var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() + var expectedVerifiedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance) let secondScanExpectation = XCTestExpectation(description: "rescan") @@ -235,8 +240,9 @@ class RewindRescanTests: ZcashTestCase { await fulfillment(of: [secondScanExpectation], timeout: 20) // verify that the balance still adds up - expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(verifiedBalance, expectedVerifiedBalance) XCTAssertEqual(totalBalance, expectedBalance) @@ -274,8 +280,9 @@ class RewindRescanTests: ZcashTestCase { ) await fulfillment(of: [firstSyncExpectation], timeout: 12) - let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let verifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let totalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero // 2 check that there are no unconfirmed funds XCTAssertTrue(verifiedBalance > network.constants.defaultFee()) XCTAssertEqual(verifiedBalance, totalBalance) @@ -327,8 +334,9 @@ class RewindRescanTests: ZcashTestCase { await fulfillment(of: [secondScanExpectation], timeout: 12) // verify that the balance still adds up - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedBalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(verifiedBalance, expectedVerifiedBalance) XCTAssertEqual(totalBalance, expectedBalance) } @@ -363,8 +371,9 @@ class RewindRescanTests: ZcashTestCase { await fulfillment(of: [firstSyncExpectation], timeout: 12) // 2 check that there are no unconfirmed funds - let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + var accountBalance = try await coordinator.synchronizer.getAccountBalance() + let verifiedBalance: Zatoshi = accountBalance?.saplingBalance.spendableValue ?? .zero + let totalBalance: Zatoshi = accountBalance?.saplingBalance.total() ?? .zero XCTAssertTrue(verifiedBalance > network.constants.defaultFee()) XCTAssertEqual(verifiedBalance, totalBalance) @@ -518,8 +527,9 @@ class RewindRescanTests: ZcashTestCase { // // XCTAssertNil(confirmedPending, "pending, now confirmed transaction found") - let expectedVerifiedbalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + accountBalance = try await coordinator.synchronizer.getAccountBalance() + let expectedVerifiedbalance = accountBalance?.saplingBalance.spendableValue ?? .zero + let expectedBalance = accountBalance?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedBalance, .zero) XCTAssertEqual(expectedVerifiedbalance, .zero) } diff --git a/Tests/DarksideTests/ShieldFundsTests.swift b/Tests/DarksideTests/ShieldFundsTests.swift index 2c8ba000..6b9f9a06 100644 --- a/Tests/DarksideTests/ShieldFundsTests.swift +++ b/Tests/DarksideTests/ShieldFundsTests.swift @@ -99,7 +99,7 @@ class ShieldFundsTests: ZcashTestCase { var initialTotalBalance = Zatoshi(-1) var initialVerifiedBalance = Zatoshi(-1) - var initialTransparentBalance: WalletBalance = try await coordinator.synchronizer.getTransparentBalance(accountIndex: 0) + var initialTransparentBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance(accountIndex: 0)?.unshielded ?? .zero let utxo = try GetAddressUtxosReply(jsonString: """ @@ -121,8 +121,8 @@ class ShieldFundsTests: ZcashTestCase { do { try await coordinator.sync( completion: { synchronizer in - initialVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance() - initialTotalBalance = try await synchronizer.getShieldedBalance() + initialVerifiedBalance = try await synchronizer.getAccountBalance(accountIndex: 0)?.saplingBalance.spendableValue ?? .zero + initialTotalBalance = try await synchronizer.getAccountBalance(accountIndex: 0)?.saplingBalance.total() ?? .zero preTxExpectation.fulfill() shouldContinue = true }, @@ -142,10 +142,9 @@ class ShieldFundsTests: ZcashTestCase { // at this point the balance should be all zeroes for transparent and shielded funds XCTAssertEqual(initialTotalBalance, Zatoshi.zero) XCTAssertEqual(initialVerifiedBalance, Zatoshi.zero) - initialTransparentBalance = (try? await coordinator.synchronizer.getTransparentBalance(accountIndex: 0)) ?? .zero + initialTransparentBalance = (try? await coordinator.synchronizer.getAccountBalance(accountIndex: 0))?.unshielded ?? .zero - XCTAssertEqual(initialTransparentBalance.total, .zero) - XCTAssertEqual(initialTransparentBalance.verified, .zero) + XCTAssertEqual(initialTransparentBalance, .zero) // 4. Add the UTXO to darksidewalletd fake chain try coordinator.service.addUTXO(utxo) @@ -176,10 +175,9 @@ class ShieldFundsTests: ZcashTestCase { // at this point the balance should be zero for shielded, then zero verified transparent funds // and 10000 zatoshi of total (not verified) transparent funds. - let tFundsDetectedBalance = try await coordinator.synchronizer.getTransparentBalance(accountIndex: 0) + let tFundsDetectedBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: 0)?.unshielded ?? .zero - XCTAssertEqual(tFundsDetectedBalance.total, Zatoshi(10000)) - XCTAssertEqual(tFundsDetectedBalance.verified, .zero) + XCTAssertEqual(tFundsDetectedBalance, Zatoshi(10000)) let tFundsConfirmationSyncExpectation = XCTestExpectation(description: "t funds confirmation") @@ -206,10 +204,9 @@ class ShieldFundsTests: ZcashTestCase { await fulfillment(of: [tFundsConfirmationSyncExpectation], timeout: 5) // the transparent funds should be 10000 zatoshis both total and verified - let confirmedTFundsBalance = try await coordinator.synchronizer.getTransparentBalance(accountIndex: 0) + let confirmedTFundsBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: 0)?.unshielded ?? .zero - XCTAssertEqual(confirmedTFundsBalance.total, Zatoshi(10000)) - XCTAssertEqual(confirmedTFundsBalance.verified, Zatoshi(10000)) + XCTAssertEqual(confirmedTFundsBalance, Zatoshi(10000)) // 9. shield the funds let shieldFundsExpectation = XCTestExpectation(description: "shield funds") @@ -238,15 +235,13 @@ class ShieldFundsTests: ZcashTestCase { guard shouldContinue else { return } - let postShieldingBalance = try await coordinator.synchronizer.getTransparentBalance(accountIndex: 0) + let postShieldingBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: 0)?.unshielded ?? .zero // when funds are shielded the UTXOs should be marked as spend and not shown on the balance. // now balance should be zero shielded, zero transaparent. // verify that the balance has been marked as spent regardless of confirmation // FIXME: [#720] this should be zero, https://github.com/zcash/ZcashLightClientKit/issues/720 - XCTAssertEqual(postShieldingBalance.verified, Zatoshi(10000)) - // FIXME: [#720] this should be zero, https://github.com/zcash/ZcashLightClientKit/issues/720 - XCTAssertEqual(postShieldingBalance.total, Zatoshi(10000)) - var expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + XCTAssertEqual(postShieldingBalance, Zatoshi(10000)) + var expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedBalance, .zero) // 10. clear the UTXO from darksidewalletd's cache @@ -293,13 +288,11 @@ class ShieldFundsTests: ZcashTestCase { // Now it should verify that the balance has been shielded. The resulting balance should be zero // transparent funds and `10000 - fee` total shielded funds, zero verified shielded funds. - let postShieldingShieldedBalance = try await coordinator.synchronizer.getTransparentBalance(accountIndex: 0) + let postShieldingShieldedBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: 0)?.unshielded ?? .zero - XCTAssertEqual(postShieldingShieldedBalance.total, .zero) - - XCTAssertEqual(postShieldingShieldedBalance.verified, .zero) + XCTAssertEqual(postShieldingShieldedBalance, .zero) - expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedBalance, Zatoshi(9000)) // 14. proceed confirm the shielded funds by staging ten more blocks @@ -335,11 +328,10 @@ class ShieldFundsTests: ZcashTestCase { XCTAssertNotNil(clearedTransaction) - expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero XCTAssertEqual(expectedBalance, Zatoshi(9000)) - let postShieldingConfirmationShieldedBalance = try await coordinator.synchronizer.getTransparentBalance(accountIndex: 0) - XCTAssertEqual(postShieldingConfirmationShieldedBalance.total, .zero) - XCTAssertEqual(postShieldingConfirmationShieldedBalance.verified, .zero) + let postShieldingConfirmationShieldedBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: 0)?.unshielded ?? .zero + XCTAssertEqual(postShieldingConfirmationShieldedBalance, .zero) } func handleError(_ error: Error?) async { diff --git a/Tests/DarksideTests/SynchronizerDarksideTests.swift b/Tests/DarksideTests/SynchronizerDarksideTests.swift index 85f629a7..381d8d06 100644 --- a/Tests/DarksideTests/SynchronizerDarksideTests.swift +++ b/Tests/DarksideTests/SynchronizerDarksideTests.swift @@ -190,36 +190,31 @@ class SynchronizerDarksideTests: ZcashTestCase { let expectedStates: [SynchronizerState] = [ SynchronizerState( syncSessionID: .nullID, - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .unprepared, latestBlockHeight: 0 ), SynchronizerState( syncSessionID: uuids[0], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .syncing(0), latestBlockHeight: 0 ), SynchronizerState( syncSessionID: uuids[0], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .syncing(0.9), latestBlockHeight: 663189 ), SynchronizerState( syncSessionID: uuids[0], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .syncing(1.0), latestBlockHeight: 663189 ), SynchronizerState( syncSessionID: uuids[0], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .synced, latestBlockHeight: 663189 ) @@ -267,36 +262,31 @@ class SynchronizerDarksideTests: ZcashTestCase { let expectedStates: [SynchronizerState] = [ SynchronizerState( syncSessionID: .nullID, - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .unprepared, latestBlockHeight: 0 ), SynchronizerState( syncSessionID: uuids[0], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .syncing(0), latestBlockHeight: 0 ), SynchronizerState( syncSessionID: uuids[0], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .syncing(0.9), latestBlockHeight: 663189 ), SynchronizerState( syncSessionID: uuids[0], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .syncing(1.0), latestBlockHeight: 663189 ), SynchronizerState( syncSessionID: uuids[0], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .synced, latestBlockHeight: 663189 ) @@ -329,29 +319,25 @@ class SynchronizerDarksideTests: ZcashTestCase { let secondBatchOfExpectedStates: [SynchronizerState] = [ SynchronizerState( syncSessionID: uuids[1], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .syncing(0), latestBlockHeight: 663189 ), SynchronizerState( syncSessionID: uuids[1], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .syncing(0.9), latestBlockHeight: 663200 ), SynchronizerState( syncSessionID: uuids[1], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .syncing(1.0), latestBlockHeight: 663200 ), SynchronizerState( syncSessionID: uuids[1], - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: .synced, latestBlockHeight: 663200 ) diff --git a/Tests/DarksideTests/SynchronizerTests.swift b/Tests/DarksideTests/SynchronizerTests.swift index 448fb6d8..73990e1a 100644 --- a/Tests/DarksideTests/SynchronizerTests.swift +++ b/Tests/DarksideTests/SynchronizerTests.swift @@ -258,8 +258,8 @@ final class SynchronizerTests: ZcashTestCase { try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName) try coordinator.applyStaged(blockheight: 663200) - let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero + let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero sleep(1) let firstSyncExpectation = XCTestExpectation(description: "first sync expectation") @@ -276,8 +276,8 @@ final class SynchronizerTests: ZcashTestCase { await fulfillment(of: [firstSyncExpectation], timeout: 12) - let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance() + let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero + let totalBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero // 2 check that there are no unconfirmed funds XCTAssertTrue(verifiedBalance > network.constants.defaultFee()) XCTAssertEqual(verifiedBalance, totalBalance) @@ -332,8 +332,8 @@ final class SynchronizerTests: ZcashTestCase { // XCTAssertEqual(lastScannedHeight, self.birthday) // check that the balance is cleared - let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance() - let expectedBalance = try await coordinator.synchronizer.getShieldedBalance() + let expectedVerifiedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.spendableValue ?? .zero + let expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance) XCTAssertEqual(initialTotalBalance, expectedBalance) } diff --git a/Tests/OfflineTests/ClosureSynchronizerOfflineTests.swift b/Tests/OfflineTests/ClosureSynchronizerOfflineTests.swift index 5ff8b664..c54e631b 100644 --- a/Tests/OfflineTests/ClosureSynchronizerOfflineTests.swift +++ b/Tests/OfflineTests/ClosureSynchronizerOfflineTests.swift @@ -638,19 +638,19 @@ class ClosureSynchronizerOfflineTests: XCTestCase { } func testGetTransparentBalanceSucceed() { - let expectedWalletBalance = WalletBalance(verified: Zatoshi(100), total: Zatoshi(200)) + let expectedBalance = AccountBalance(saplingBalance: .zero, unshielded: Zatoshi(200)) - synchronizerMock.getTransparentBalanceAccountIndexClosure = { receivedAccountIndex in + synchronizerMock.getAccountBalanceAccountIndexClosure = { receivedAccountIndex in XCTAssertEqual(receivedAccountIndex, 3) - return expectedWalletBalance + return expectedBalance } let expectation = XCTestExpectation() - synchronizer.getTransparentBalance(accountIndex: 3) { result in + synchronizer.getAccountBalance(accountIndex: 3) { result in switch result { case let .success(receivedBalance): - XCTAssertEqual(receivedBalance, expectedWalletBalance) + XCTAssertEqual(receivedBalance, expectedBalance) expectation.fulfill() case let .failure(error): XCTFail("Unpected failure with error: \(error)") @@ -661,13 +661,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase { } func testGetTransparentBalanceThrowsError() { - synchronizerMock.getTransparentBalanceAccountIndexClosure = { _ in + synchronizerMock.getAccountBalanceAccountIndexClosure = { _ in throw "Some error" } let expectation = XCTestExpectation() - synchronizer.getTransparentBalance(accountIndex: 3) { result in + synchronizer.getAccountBalance(accountIndex: 3) { result in switch result { case .success: XCTFail("Error should be thrown.") @@ -680,17 +680,25 @@ class ClosureSynchronizerOfflineTests: XCTestCase { } func testGetShieldedBalanceSucceed() { - synchronizerMock.getShieldedBalanceAccountIndexClosure = { receivedAccountIndex in + let expectedBalance = AccountBalance( + saplingBalance: + PoolBalance( + spendableValue: Zatoshi(333), + changePendingConfirmation: .zero, + valuePendingSpendability: .zero), unshielded: .zero + ) + + synchronizerMock.getAccountBalanceAccountIndexClosure = { receivedAccountIndex in XCTAssertEqual(receivedAccountIndex, 3) - return Zatoshi(333) + return expectedBalance } let expectation = XCTestExpectation() - synchronizer.getShieldedBalance(accountIndex: 3) { result in + synchronizer.getAccountBalance(accountIndex: 3) { result in switch result { case let .success(receivedBalance): - XCTAssertEqual(receivedBalance, Zatoshi(333)) + XCTAssertEqual(receivedBalance, expectedBalance) expectation.fulfill() case let .failure(error): XCTFail("Unpected failure with error: \(error)") @@ -701,13 +709,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase { } func testGetShieldedBalanceThrowsError() { - synchronizerMock.getShieldedBalanceAccountIndexClosure = { _ in + synchronizerMock.getAccountBalanceAccountIndexClosure = { _ in throw "Some error" } let expectation = XCTestExpectation() - synchronizer.getShieldedBalance(accountIndex: 3) { result in + synchronizer.getAccountBalance(accountIndex: 3) { result in switch result { case .success: XCTFail("Error should be thrown.") @@ -720,17 +728,25 @@ class ClosureSynchronizerOfflineTests: XCTestCase { } func testGetShieldedVerifiedBalanceSucceed() { - synchronizerMock.getShieldedVerifiedBalanceAccountIndexClosure = { receivedAccountIndex in + let expectedBalance = AccountBalance( + saplingBalance: + PoolBalance( + spendableValue: .zero, + changePendingConfirmation: Zatoshi(333), + valuePendingSpendability: .zero), unshielded: .zero + ) + + synchronizerMock.getAccountBalanceAccountIndexClosure = { receivedAccountIndex in XCTAssertEqual(receivedAccountIndex, 3) - return Zatoshi(333) + return expectedBalance } let expectation = XCTestExpectation() - synchronizer.getShieldedVerifiedBalance(accountIndex: 3) { result in + synchronizer.getAccountBalance(accountIndex: 3) { result in switch result { case let .success(receivedBalance): - XCTAssertEqual(receivedBalance, Zatoshi(333)) + XCTAssertEqual(receivedBalance, expectedBalance) expectation.fulfill() case let .failure(error): XCTFail("Unpected failure with error: \(error)") @@ -741,13 +757,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase { } func testGetShieldedVerifiedBalanceThrowsError() { - synchronizerMock.getShieldedVerifiedBalanceAccountIndexClosure = { _ in + synchronizerMock.getAccountBalanceAccountIndexClosure = { _ in throw "Some error" } let expectation = XCTestExpectation() - synchronizer.getShieldedVerifiedBalance(accountIndex: 3) { result in + synchronizer.getAccountBalance(accountIndex: 3) { result in switch result { case .success: XCTFail("Error should be thrown.") diff --git a/Tests/OfflineTests/CombineSynchronizerOfflineTests.swift b/Tests/OfflineTests/CombineSynchronizerOfflineTests.swift index 013c3b5e..07cec75a 100644 --- a/Tests/OfflineTests/CombineSynchronizerOfflineTests.swift +++ b/Tests/OfflineTests/CombineSynchronizerOfflineTests.swift @@ -748,16 +748,16 @@ class CombineSynchronizerOfflineTests: XCTestCase { } func testGetTransparentBalanceSucceed() { - let expectedWalletBalance = WalletBalance(verified: Zatoshi(100), total: Zatoshi(200)) + let expectedBalance = AccountBalance(saplingBalance: .zero, unshielded: Zatoshi(100)) - synchronizerMock.getTransparentBalanceAccountIndexClosure = { receivedAccountIndex in + synchronizerMock.getAccountBalanceAccountIndexClosure = { receivedAccountIndex in XCTAssertEqual(receivedAccountIndex, 3) - return expectedWalletBalance + return expectedBalance } let expectation = XCTestExpectation() - synchronizer.getTransparentBalance(accountIndex: 3) + synchronizer.getAccountBalance(accountIndex: 3) .sink( receiveCompletion: { result in switch result { @@ -768,7 +768,7 @@ class CombineSynchronizerOfflineTests: XCTestCase { } }, receiveValue: { value in - XCTAssertEqual(value, expectedWalletBalance) + XCTAssertEqual(value, expectedBalance) } ) .store(in: &cancellables) @@ -777,13 +777,13 @@ class CombineSynchronizerOfflineTests: XCTestCase { } func testGetTransparentBalanceThrowsError() { - synchronizerMock.getTransparentBalanceAccountIndexClosure = { _ in + synchronizerMock.getAccountBalanceAccountIndexClosure = { _ in throw "Some error" } let expectation = XCTestExpectation() - synchronizer.getTransparentBalance(accountIndex: 3) + synchronizer.getAccountBalance(accountIndex: 3) .sink( receiveCompletion: { result in switch result { @@ -803,14 +803,23 @@ class CombineSynchronizerOfflineTests: XCTestCase { } func testGetShieldedBalanceSucceed() { - synchronizerMock.getShieldedBalanceAccountIndexClosure = { receivedAccountIndex in + let expectedBalance = AccountBalance( + saplingBalance: + PoolBalance( + spendableValue: .zero, + changePendingConfirmation: Zatoshi(333), + valuePendingSpendability: .zero), + unshielded: .zero + ) + + synchronizerMock.getAccountBalanceAccountIndexClosure = { receivedAccountIndex in XCTAssertEqual(receivedAccountIndex, 3) - return Zatoshi(333) + return expectedBalance } let expectation = XCTestExpectation() - synchronizer.getShieldedBalance(accountIndex: 3) + synchronizer.getAccountBalance(accountIndex: 3) .sink( receiveCompletion: { result in switch result { @@ -821,7 +830,7 @@ class CombineSynchronizerOfflineTests: XCTestCase { } }, receiveValue: { value in - XCTAssertEqual(value, Zatoshi(333)) + XCTAssertEqual(value, expectedBalance) } ) .store(in: &cancellables) @@ -830,13 +839,13 @@ class CombineSynchronizerOfflineTests: XCTestCase { } func testGetShieldedBalanceThrowsError() { - synchronizerMock.getShieldedBalanceAccountIndexClosure = { _ in + synchronizerMock.getAccountBalanceAccountIndexClosure = { _ in throw "Some error" } let expectation = XCTestExpectation() - synchronizer.getShieldedBalance(accountIndex: 3) + synchronizer.getAccountBalance(accountIndex: 3) .sink( receiveCompletion: { result in switch result { @@ -856,14 +865,23 @@ class CombineSynchronizerOfflineTests: XCTestCase { } func testGetShieldedVerifiedBalanceSucceed() { - synchronizerMock.getShieldedVerifiedBalanceAccountIndexClosure = { receivedAccountIndex in + let expectedBalance = AccountBalance( + saplingBalance: + PoolBalance( + spendableValue: Zatoshi(333), + changePendingConfirmation: .zero, + valuePendingSpendability: .zero), + unshielded: .zero + ) + + synchronizerMock.getAccountBalanceAccountIndexClosure = { receivedAccountIndex in XCTAssertEqual(receivedAccountIndex, 3) - return Zatoshi(333) + return expectedBalance } let expectation = XCTestExpectation() - synchronizer.getShieldedVerifiedBalance(accountIndex: 3) + synchronizer.getAccountBalance(accountIndex: 3) .sink( receiveCompletion: { result in switch result { @@ -874,7 +892,7 @@ class CombineSynchronizerOfflineTests: XCTestCase { } }, receiveValue: { value in - XCTAssertEqual(value, Zatoshi(333)) + XCTAssertEqual(value, expectedBalance) } ) .store(in: &cancellables) @@ -883,13 +901,13 @@ class CombineSynchronizerOfflineTests: XCTestCase { } func testGetShieldedVerifiedBalanceThrowsError() { - synchronizerMock.getShieldedVerifiedBalanceAccountIndexClosure = { _ in + synchronizerMock.getAccountBalanceAccountIndexClosure = { _ in throw "Some error" } let expectation = XCTestExpectation() - synchronizer.getShieldedVerifiedBalance(accountIndex: 3) + synchronizer.getAccountBalance(accountIndex: 3) .sink( receiveCompletion: { result in switch result { diff --git a/Tests/OfflineTests/SynchronizerOfflineTests.swift b/Tests/OfflineTests/SynchronizerOfflineTests.swift index bdb8cec5..826e98ae 100644 --- a/Tests/OfflineTests/SynchronizerOfflineTests.swift +++ b/Tests/OfflineTests/SynchronizerOfflineTests.swift @@ -472,8 +472,7 @@ class SynchronizerOfflineTests: ZcashTestCase { func synchronizerState(for internalSyncStatus: InternalSyncStatus) -> SynchronizerState { SynchronizerState( syncSessionID: .nullID, - accountBalances: .zero, - transparentBalance: .zero, + accountBalance: .zero, internalSyncStatus: internalSyncStatus, latestBlockHeight: .zero ) diff --git a/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift b/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift index 4f14bb0b..afbe16a6 100644 --- a/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift +++ b/Tests/TestUtils/Sourcery/GeneratedMocks/AutoMockable.generated.swift @@ -1599,99 +1599,27 @@ class SynchronizerMock: Synchronizer { } } - // MARK: - getTransparentBalance + // MARK: - getAccountBalance - var getTransparentBalanceAccountIndexThrowableError: Error? - var getTransparentBalanceAccountIndexCallsCount = 0 - var getTransparentBalanceAccountIndexCalled: Bool { - return getTransparentBalanceAccountIndexCallsCount > 0 + var getAccountBalanceAccountIndexThrowableError: Error? + var getAccountBalanceAccountIndexCallsCount = 0 + var getAccountBalanceAccountIndexCalled: Bool { + return getAccountBalanceAccountIndexCallsCount > 0 } - var getTransparentBalanceAccountIndexReceivedAccountIndex: Int? - var getTransparentBalanceAccountIndexReturnValue: WalletBalance! - var getTransparentBalanceAccountIndexClosure: ((Int) async throws -> WalletBalance)? + var getAccountBalanceAccountIndexReceivedAccountIndex: Int? + var getAccountBalanceAccountIndexReturnValue: AccountBalance? + var getAccountBalanceAccountIndexClosure: ((Int) async throws -> AccountBalance?)? - func getTransparentBalance(accountIndex: Int) async throws -> WalletBalance { - if let error = getTransparentBalanceAccountIndexThrowableError { + func getAccountBalance(accountIndex: Int) async throws -> AccountBalance? { + if let error = getAccountBalanceAccountIndexThrowableError { throw error } - getTransparentBalanceAccountIndexCallsCount += 1 - getTransparentBalanceAccountIndexReceivedAccountIndex = accountIndex - if let closure = getTransparentBalanceAccountIndexClosure { + getAccountBalanceAccountIndexCallsCount += 1 + getAccountBalanceAccountIndexReceivedAccountIndex = accountIndex + if let closure = getAccountBalanceAccountIndexClosure { return try await closure(accountIndex) } else { - return getTransparentBalanceAccountIndexReturnValue - } - } - - // MARK: - getShieldedBalance - - var getShieldedBalanceAccountIndexThrowableError: Error? - var getShieldedBalanceAccountIndexCallsCount = 0 - var getShieldedBalanceAccountIndexCalled: Bool { - return getShieldedBalanceAccountIndexCallsCount > 0 - } - var getShieldedBalanceAccountIndexReceivedAccountIndex: Int? - var getShieldedBalanceAccountIndexReturnValue: Zatoshi! - var getShieldedBalanceAccountIndexClosure: ((Int) async throws -> Zatoshi)? - - func getShieldedBalance(accountIndex: Int) async throws -> Zatoshi { - if let error = getShieldedBalanceAccountIndexThrowableError { - throw error - } - getShieldedBalanceAccountIndexCallsCount += 1 - getShieldedBalanceAccountIndexReceivedAccountIndex = accountIndex - if let closure = getShieldedBalanceAccountIndexClosure { - return try await closure(accountIndex) - } else { - return getShieldedBalanceAccountIndexReturnValue - } - } - - // MARK: - getShieldedVerifiedBalance - - var getShieldedVerifiedBalanceAccountIndexThrowableError: Error? - var getShieldedVerifiedBalanceAccountIndexCallsCount = 0 - var getShieldedVerifiedBalanceAccountIndexCalled: Bool { - return getShieldedVerifiedBalanceAccountIndexCallsCount > 0 - } - var getShieldedVerifiedBalanceAccountIndexReceivedAccountIndex: Int? - var getShieldedVerifiedBalanceAccountIndexReturnValue: Zatoshi! - var getShieldedVerifiedBalanceAccountIndexClosure: ((Int) async throws -> Zatoshi)? - - func getShieldedVerifiedBalance(accountIndex: Int) async throws -> Zatoshi { - if let error = getShieldedVerifiedBalanceAccountIndexThrowableError { - throw error - } - getShieldedVerifiedBalanceAccountIndexCallsCount += 1 - getShieldedVerifiedBalanceAccountIndexReceivedAccountIndex = accountIndex - if let closure = getShieldedVerifiedBalanceAccountIndexClosure { - return try await closure(accountIndex) - } else { - return getShieldedVerifiedBalanceAccountIndexReturnValue - } - } - - // MARK: - getAccountBalances - - var getAccountBalancesAccountIndexThrowableError: Error? - var getAccountBalancesAccountIndexCallsCount = 0 - var getAccountBalancesAccountIndexCalled: Bool { - return getAccountBalancesAccountIndexCallsCount > 0 - } - var getAccountBalancesAccountIndexReceivedAccountIndex: Int? - var getAccountBalancesAccountIndexReturnValue: AccountBalance? - var getAccountBalancesAccountIndexClosure: ((Int) async throws -> AccountBalance?)? - - func getAccountBalances(accountIndex: Int) async throws -> AccountBalance? { - if let error = getAccountBalancesAccountIndexThrowableError { - throw error - } - getAccountBalancesAccountIndexCallsCount += 1 - getAccountBalancesAccountIndexReceivedAccountIndex = accountIndex - if let closure = getAccountBalancesAccountIndexClosure { - return try await closure(accountIndex) - } else { - return getAccountBalancesAccountIndexReturnValue + return getAccountBalanceAccountIndexReturnValue } } diff --git a/Tests/TestUtils/Stubs.swift b/Tests/TestUtils/Stubs.swift index 9957adc7..660aac76 100644 --- a/Tests/TestUtils/Stubs.swift +++ b/Tests/TestUtils/Stubs.swift @@ -145,8 +145,7 @@ extension SynchronizerState { static var mock: SynchronizerState { SynchronizerState( syncSessionID: .nullID, - accountBalances: .zero, - transparentBalance: WalletBalance(verified: Zatoshi(200), total: Zatoshi(300)), + accountBalance: AccountBalance(saplingBalance: .zero, unshielded: Zatoshi(200)), internalSyncStatus: .syncing(0), latestBlockHeight: 222222 )