Merge branch 'main' into release/0.20.1-beta

This commit is contained in:
Michal Fousek 2023-04-03 17:21:10 +02:00
commit ab603802bb
62 changed files with 1182 additions and 957 deletions

39
.github/workflows/code_ql.yml vendored Normal file
View File

@ -0,0 +1,39 @@
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
env:
CODEQL_ENABLE_EXPERIMENTAL_FEATURES_SWIFT: true
jobs:
analyze:
name: Analyze
runs-on: macos-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'swift' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- run: swift build --arch arm64
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

View File

@ -1,3 +1,20 @@
# unreleased
### [#469] ZcashRustBackendWelding to Async
This is mostly internal change. But it also touches the public API.
These methods previously returned Optional and now those methods return non-optional value and those methods can an throw error:
- `getSaplingAddress(accountIndex: Int) async throws -> SaplingAddress`
- `func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress`
- `func getTransparentAddress(accountIndex: Int) async throws -> TransparentAddress`
These methods are now async:
- `func getShieldedBalance(accountIndex: Int) async throws -> Zatoshi`
- `func getShieldedVerifiedBalance(accountIndex: Int) async throws -> Zatoshi`
`Initializer` no longer have methods to get balance. Use `SDKSynchronizer` (or it's alternative APIs) to get balance.
# 0.20.0-beta
### New Checkpoints:

View File

@ -19,7 +19,7 @@ class GetAddressViewController: UIViewController {
let synchronizer = SDKSynchronizer.shared
Task { @MainActor in
guard let uAddress = await synchronizer.getUnifiedAddress(accountIndex: 0) else {
guard let uAddress = try? await synchronizer.getUnifiedAddress(accountIndex: 0) else {
unifiedAddressLabel.text = "could not derive UA"
tAddressLabel.text = "could not derive tAddress"
saplingAddress.text = "could not derive zAddress"
@ -29,8 +29,8 @@ class GetAddressViewController: UIViewController {
// you can either try to extract receivers from the UA itself or request the Synchronizer to do it for you. Certain UAs might not contain all the receivers you expect.
unifiedAddressLabel.text = uAddress.stringEncoded
tAddressLabel.text = uAddress.transparentReceiver()?.stringEncoded ?? "could not extract transparent receiver from UA"
saplingAddress.text = uAddress.saplingReceiver()?.stringEncoded ?? "could not extract sapling receiver from UA"
tAddressLabel.text = (try? uAddress.transparentReceiver())?.stringEncoded ?? "could not extract transparent receiver from UA"
saplingAddress.text = (try? uAddress.saplingReceiver())?.stringEncoded ?? "could not extract sapling receiver from UA"
unifiedAddressLabel.addGestureRecognizer(
UITapGestureRecognizer(

View File

@ -15,9 +15,15 @@ class GetBalanceViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let synchronizer = AppDelegate.shared.sharedSynchronizer
self.title = "Account 0 Balance"
self.balance.text = "\(Initializer.shared.getBalance().formattedString ?? "0.0") ZEC"
self.verified.text = "\(Initializer.shared.getVerifiedBalance().formattedString ?? "0.0") ZEC"
Task { @MainActor in
let balanceText = (try? await synchronizer.getShieldedBalance().formattedString) ?? "0.0"
let verifiedText = (try? await synchronizer.getShieldedVerifiedBalance().formattedString) ?? "0.0"
self.balance.text = "\(balanceText) ZEC"
self.verified.text = "\(verifiedText) ZEC"
}
}
}

View File

@ -26,7 +26,7 @@ class GetUTXOsViewController: UIViewController {
let synchronizer = SDKSynchronizer.shared
Task { @MainActor in
let tAddress = await synchronizer.getTransparentAddress(accountIndex: 0)?.stringEncoded ?? "no t-address found"
let tAddress = (try? await synchronizer.getTransparentAddress(accountIndex: 0))?.stringEncoded ?? "no t-address found"
self.transparentAddressLabel.text = tAddress

View File

@ -79,9 +79,11 @@ class SendViewController: UIViewController {
}
func setUp() {
balanceLabel.text = format(balance: wallet.getBalance())
verifiedBalanceLabel.text = format(balance: wallet.getVerifiedBalance())
toggleSendButton()
Task { @MainActor in
balanceLabel.text = format(balance: (try? await synchronizer.getShieldedBalance(accountIndex: 0)) ?? .zero)
verifiedBalanceLabel.text = format(balance: (try? await synchronizer.getShieldedVerifiedBalance(accountIndex: 0)) ?? .zero)
await toggleSendButton()
}
memoField.text = ""
memoField.layer.borderColor = UIColor.gray.cgColor
memoField.layer.borderWidth = 1
@ -102,39 +104,45 @@ class SendViewController: UIViewController {
"Zec \(balance.formattedString ?? "0.0")"
}
func toggleSendButton() {
sendButton.isEnabled = isFormValid()
func toggleSendButton() async {
sendButton.isEnabled = await isFormValid()
}
func maxFundsOn() {
let fee = Zatoshi(10000)
let max: Zatoshi = wallet.getVerifiedBalance() - fee
amountTextField.text = format(balance: max)
amountTextField.isEnabled = false
Task { @MainActor in
let fee = Zatoshi(10000)
let max: Zatoshi = ((try? await synchronizer.getShieldedVerifiedBalance(accountIndex: 0)) ?? .zero) - fee
amountTextField.text = format(balance: max)
amountTextField.isEnabled = false
}
}
func maxFundsOff() {
amountTextField.isEnabled = true
}
func isFormValid() -> Bool {
func isFormValid() async -> Bool {
switch synchronizer.latestState.syncStatus {
case .synced:
return isBalanceValid() && isAmountValid() && isRecipientValid()
let isBalanceValid = await self.isBalanceValid()
let isAmountValid = await self.isAmountValid()
return isBalanceValid && isAmountValid && isRecipientValid()
default:
return false
}
}
func isBalanceValid() -> Bool {
wallet.getVerifiedBalance() > .zero
func isBalanceValid() async -> Bool {
let balance = (try? await synchronizer.getShieldedVerifiedBalance(accountIndex: 0)) ?? .zero
return balance > .zero
}
func isAmountValid() -> Bool {
func isAmountValid() async -> Bool {
let balance = (try? await synchronizer.getShieldedVerifiedBalance(accountIndex: 0)) ?? .zero
guard
let value = amountTextField.text,
let amount = NumberFormatter.zcashNumberFormatter.number(from: value).flatMap({ Zatoshi($0.int64Value) }),
amount <= wallet.getVerifiedBalance()
amount <= balance
else {
return false
}
@ -158,68 +166,70 @@ class SendViewController: UIViewController {
}
@IBAction func send(_ sender: Any) {
guard isFormValid() else {
loggerProxy.warn("WARNING: Form is invalid")
return
}
Task { @MainActor in
guard await isFormValid() else {
loggerProxy.warn("WARNING: Form is invalid")
return
}
let alert = UIAlertController(
title: "About To send funds!",
message: """
let alert = UIAlertController(
title: "About To send funds!",
message: """
This is an ugly confirmation message. You should come up with something fancier that lets the user be sure about sending funds without \
disturbing the user experience with an annoying alert like this one
""",
preferredStyle: UIAlertController.Style.alert
)
preferredStyle: UIAlertController.Style.alert
)
let sendAction = UIAlertAction(
title: "Send!",
style: UIAlertAction.Style.default,
handler: { _ in
self.send()
}
)
let sendAction = UIAlertAction(
title: "Send!",
style: UIAlertAction.Style.default,
handler: { _ in
self.send()
}
)
let cancelAction = UIAlertAction(
title: "Go back! I'm not sure about this.",
style: UIAlertAction.Style.destructive,
handler: { _ in
self.cancel()
}
)
let cancelAction = UIAlertAction(
title: "Go back! I'm not sure about this.",
style: UIAlertAction.Style.destructive,
handler: { _ in
self.cancel()
}
)
alert.addAction(sendAction)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
alert.addAction(sendAction)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
}
}
func send() {
guard
isFormValid(),
let amount = amountTextField.text,
let zec = NumberFormatter.zcashNumberFormatter.number(from: amount).flatMap({ Zatoshi($0.int64Value) }),
let recipient = addressTextField.text
else {
loggerProxy.warn("WARNING: Form is invalid")
return
}
guard let spendingKey = try? DerivationTool(
networkType: kZcashNetwork.networkType
)
.deriveUnifiedSpendingKey(
seed: DemoAppConfig.defaultSeed,
accountIndex: 0
)
else {
loggerProxy.error("NO SPENDING KEY")
return
}
KRProgressHUD.show()
Task { @MainActor in
guard
await isFormValid(),
let amount = amountTextField.text,
let zec = NumberFormatter.zcashNumberFormatter.number(from: amount).flatMap({ Zatoshi($0.int64Value) }),
let recipient = addressTextField.text
else {
loggerProxy.warn("WARNING: Form is invalid")
return
}
guard let spendingKey = try? DerivationTool(
networkType: kZcashNetwork.networkType
)
.deriveUnifiedSpendingKey(
seed: DemoAppConfig.defaultSeed,
accountIndex: 0
)
else {
loggerProxy.error("NO SPENDING KEY")
return
}
KRProgressHUD.show()
do {
let pendingTransaction = try await synchronizer.sendToAddress(
spendingKey: spendingKey,
@ -267,7 +277,9 @@ extension SendViewController: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
textField.resignFirstResponder()
toggleSendButton()
Task { @MainActor in
await toggleSendButton()
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {

View File

@ -631,7 +631,7 @@ actor CompactBlockProcessor {
logger.debug("Executing rewind.")
let lastDownloaded = await internalSyncProgress.latestDownloadedBlockHeight
let height = Int32(context.height ?? lastDownloaded)
let nearestHeight = rustBackend.getNearestRewindHeight(
let nearestHeight = await rustBackend.getNearestRewindHeight(
dbData: config.dataDb,
height: height,
networkType: self.config.network.networkType
@ -647,7 +647,7 @@ actor CompactBlockProcessor {
// FIXME: [#719] this should be done on the rust layer, https://github.com/zcash/ZcashLightClientKit/issues/719
let rewindHeight = max(Int32(nearestHeight - 1), Int32(config.walletBirthday))
guard rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight, networkType: self.config.network.networkType) else {
guard await rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight, networkType: self.config.network.networkType) else {
let error = rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)")
await fail(error)
return await context.completion(.failure(error))
@ -758,7 +758,7 @@ actor CompactBlockProcessor {
try await storage.clear()
await internalSyncProgress.set(newLatestDownloadedHeight, .latestDownloadedBlockHeight)
} else {
try storage.create()
try await storage.create()
}
if let range = ranges.downloadedButUnscannedRange {
@ -1055,7 +1055,13 @@ actor CompactBlockProcessor {
self.consecutiveChainValidationErrors += 1
guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(rewindHeight), networkType: self.config.network.networkType) else {
let rewindResult = await rustBackend.rewindToHeight(
dbData: config.dataDb,
height: Int32(rewindHeight),
networkType: self.config.network.networkType
)
guard rewindResult else {
await fail(rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)"))
return
}
@ -1198,37 +1204,37 @@ extension CompactBlockProcessor.State: Equatable {
}
extension CompactBlockProcessor {
func getUnifiedAddress(accountIndex: Int) -> UnifiedAddress? {
try? rustBackend.getCurrentAddress(
func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress {
try await rustBackend.getCurrentAddress(
dbData: config.dataDb,
account: Int32(accountIndex),
networkType: config.network.networkType
)
}
func getSaplingAddress(accountIndex: Int) -> SaplingAddress? {
getUnifiedAddress(accountIndex: accountIndex)?.saplingReceiver()
func getSaplingAddress(accountIndex: Int) async throws -> SaplingAddress {
try await getUnifiedAddress(accountIndex: accountIndex).saplingReceiver()
}
func getTransparentAddress(accountIndex: Int) -> TransparentAddress? {
getUnifiedAddress(accountIndex: accountIndex)?.transparentReceiver()
func getTransparentAddress(accountIndex: Int) async throws -> TransparentAddress {
try await getUnifiedAddress(accountIndex: accountIndex).transparentReceiver()
}
func getTransparentBalance(accountIndex: Int) throws -> WalletBalance {
func getTransparentBalance(accountIndex: Int) async throws -> WalletBalance {
guard accountIndex >= 0 else {
throw CompactBlockProcessorError.invalidAccount
}
return WalletBalance(
verified: Zatoshi(
try rustBackend.getVerifiedTransparentBalance(
try await rustBackend.getVerifiedTransparentBalance(
dbData: config.dataDb,
account: Int32(accountIndex),
networkType: config.network.networkType
)
),
total: Zatoshi(
try rustBackend.getTransparentBalance(
try await rustBackend.getTransparentBalance(
dbData: config.dataDb,
account: Int32(accountIndex),
networkType: config.network.networkType
@ -1252,18 +1258,18 @@ extension CompactBlockProcessor {
for try await utxo in stream {
utxos.append(utxo)
}
return storeUTXOs(utxos, in: dataDb)
return await storeUTXOs(utxos, in: dataDb)
} catch {
throw mapError(error)
}
}
private func storeUTXOs(_ utxos: [UnspentTransactionOutputEntity], in dataDb: URL) -> RefreshedUTXOs {
private func storeUTXOs(_ utxos: [UnspentTransactionOutputEntity], in dataDb: URL) async -> RefreshedUTXOs {
var refreshed: [UnspentTransactionOutputEntity] = []
var skipped: [UnspentTransactionOutputEntity] = []
for utxo in utxos {
do {
if try self.rustBackend.putUnspentTransparentOutput(
if try await rustBackend.putUnspentTransparentOutput(
dbData: dataDb,
txid: utxo.txid.bytes,
index: utxo.index,
@ -1464,7 +1470,7 @@ extension CompactBlockProcessor {
// create the storage
do {
try self.storage.create()
try await self.storage.create()
} catch {
throw CacheDbMigrationError.failedToInitFsBlockDb(error)
}

View File

@ -41,7 +41,7 @@ struct BlockEnhancerImpl {
let block = String(describing: transaction.minedHeight)
logger.debug("Decrypting and storing transaction id: \(transactionID) block: \(block)")
let decryptionResult = rustBackend.decryptAndStoreTransaction(
let decryptionResult = await rustBackend.decryptAndStoreTransaction(
dbData: config.dataDb,
txBytes: fetchedTransaction.raw.bytes,
minedHeight: Int32(fetchedTransaction.minedHeight),

View File

@ -36,16 +36,17 @@ extension UTXOFetcherImpl: UTXOFetcher {
func fetch(at range: CompactBlockRange) async throws -> (inserted: [UnspentTransactionOutputEntity], skipped: [UnspentTransactionOutputEntity]) {
try Task.checkCancellation()
let tAddresses = try accountRepository.getAll()
let accounts = try accountRepository.getAll()
.map { $0.account }
.map {
try rustBackend.listTransparentReceivers(
dbData: config.dataDb,
account: Int32($0),
networkType: config.networkType
)
}
.flatMap({ $0 })
var tAddresses: [TransparentAddress] = []
for account in accounts {
tAddresses += try await rustBackend.listTransparentReceivers(
dbData: config.dataDb,
account: Int32(account),
networkType: config.networkType
)
}
var utxos: [UnspentTransactionOutputEntity] = []
let stream: AsyncThrowingStream<UnspentTransactionOutputEntity, Error> = blockDownloaderService.fetchUnspentTransactionOutputs(
@ -63,7 +64,7 @@ extension UTXOFetcherImpl: UTXOFetcher {
let startTime = Date()
for utxo in utxos {
do {
if try rustBackend.putUnspentTransparentOutput(
if try await rustBackend.putUnspentTransparentOutput(
dbData: config.dataDb,
txid: utxo.txid.bytes,
index: utxo.index,

View File

@ -47,12 +47,12 @@ class FSCompactBlockRepository {
}
extension FSCompactBlockRepository: CompactBlockRepository {
func create() throws {
func create() async throws {
if !fileManager.fileExists(atPath: blocksDirectory.path) {
try fileManager.createDirectory(at: blocksDirectory, withIntermediateDirectories: true)
}
guard try self.metadataStore.initFsBlockDbRoot(self.fsBlockDbRoot) else {
guard try await self.metadataStore.initFsBlockDbRoot(self.fsBlockDbRoot) else {
throw CompactBlockRepositoryError.failedToInitializeCache
}
}
@ -99,7 +99,7 @@ extension FSCompactBlockRepository: CompactBlockRepository {
}
func rewind(to height: BlockHeight) async throws {
try metadataStore.rewindToHeight(height)
try await metadataStore.rewindToHeight(height)
// Reverse the cached contents to browse from higher to lower heights
let sortedCachedContents = try contentProvider.listContents(of: blocksDirectory)
@ -121,7 +121,7 @@ extension FSCompactBlockRepository: CompactBlockRepository {
if self.fileManager.fileExists(atPath: self.fsBlockDbRoot.path) {
try self.fileManager.removeItem(at: self.fsBlockDbRoot)
}
try create()
try await create()
}
}
@ -209,8 +209,8 @@ extension FSBlockFileWriter {
struct FSMetadataStore {
var saveBlocksMeta: ([ZcashCompactBlock]) async throws -> Void
var rewindToHeight: (BlockHeight) throws -> Void
var initFsBlockDbRoot: (URL) throws -> Bool
var rewindToHeight: (BlockHeight) async throws -> Void
var initFsBlockDbRoot: (URL) async throws -> Bool
var latestHeight: () async -> BlockHeight
}
@ -224,13 +224,13 @@ extension FSMetadataStore {
logger: logger
)
} rewindToHeight: { height in
guard rustBackend.rewindCacheToHeight(fsBlockDbRoot: fsBlockDbRoot, height: Int32(height)) else {
guard await rustBackend.rewindCacheToHeight(fsBlockDbRoot: fsBlockDbRoot, height: Int32(height)) else {
throw CompactBlockRepositoryError.failedToRewind(height)
}
} initFsBlockDbRoot: { dbRootURL in
try rustBackend.initBlockMetadataDb(fsBlockDbRoot: dbRootURL)
try await rustBackend.initBlockMetadataDb(fsBlockDbRoot: dbRootURL)
} latestHeight: {
rustBackend.latestCachedBlockHeight(fsBlockDbRoot: fsBlockDbRoot)
await rustBackend.latestCachedBlockHeight(fsBlockDbRoot: fsBlockDbRoot)
}
}
}
@ -250,7 +250,7 @@ extension FSMetadataStore {
guard !blocks.isEmpty else { return }
do {
guard try rustBackend.writeBlocksMetadata(fsBlockDbRoot: fsBlockDbRoot, blocks: blocks) else {
guard try await rustBackend.writeBlocksMetadata(fsBlockDbRoot: fsBlockDbRoot, blocks: blocks) else {
throw CompactBlockRepositoryError.failedToWriteMetadata
}
} catch {

View File

@ -30,12 +30,12 @@ extension SaplingParametersHandlerImpl: SaplingParametersHandler {
try Task.checkCancellation()
do {
let totalShieldedBalance = try rustBackend.getBalance(
let totalShieldedBalance = try await rustBackend.getBalance(
dbData: config.dataDb,
account: Int32(0),
networkType: config.networkType
)
let totalTransparentBalance = try rustBackend.getTransparentBalance(
let totalTransparentBalance = try await rustBackend.getTransparentBalance(
dbData: config.dataDb,
account: Int32(0),
networkType: config.networkType

View File

@ -45,7 +45,7 @@ extension BlockScannerImpl: BlockScanner {
let batchSize = scanBatchSize(startScanHeight: previousScannedHeight + 1, network: self.config.networkType)
let scanStartTime = Date()
guard self.rustBackend.scanBlocks(
guard await self.rustBackend.scanBlocks(
fsBlockDbRoot: config.fsBlockCacheRoot,
dbData: config.dataDB,
limit: batchSize,

View File

@ -1,24 +0,0 @@
//
// NotificationSender.swift
//
//
// Created by Michal Fousek on 21.11.2022.
//
import Foundation
class NotificationSender {
static let `default` = NotificationSender()
private let queue = DispatchQueue(label: "NotificationsSender")
func post(name aName: Notification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable: Any]? = nil) {
let notification = Notification(name: aName, object: anObject, userInfo: aUserInfo)
post(notification: notification)
}
func post(notification: Notification) {
queue.async {
NotificationCenter.default.post(notification)
}
}
}

View File

@ -37,7 +37,7 @@ extension BlockValidatorImpl: BlockValidator {
try Task.checkCancellation()
let startTime = Date()
let result = rustBackend.validateCombinedChain(
let result = await rustBackend.validateCombinedChain(
fsBlockDbRoot: config.fsBlockCacheRoot,
dbData: config.dataDB,
networkType: config.networkType,

View File

@ -32,9 +32,9 @@ public protocol ClosureSynchronizer {
func start(retry: Bool, completion: @escaping (Error?) -> Void)
func stop(completion: @escaping () -> Void)
func getSaplingAddress(accountIndex: Int, completion: @escaping (SaplingAddress?) -> Void)
func getUnifiedAddress(accountIndex: Int, completion: @escaping (UnifiedAddress?) -> Void)
func getTransparentAddress(accountIndex: Int, completion: @escaping (TransparentAddress?) -> Void)
func getSaplingAddress(accountIndex: Int, completion: @escaping (Result<SaplingAddress, Error>) -> Void)
func getUnifiedAddress(accountIndex: Int, completion: @escaping (Result<UnifiedAddress, Error>) -> Void)
func getTransparentAddress(accountIndex: Int, completion: @escaping (Result<TransparentAddress, Error>) -> Void)
func sendToAddress(
spendingKey: UnifiedSpendingKey,
@ -79,9 +79,9 @@ public protocol ClosureSynchronizer {
func getTransparentBalance(accountIndex: Int, completion: @escaping (Result<WalletBalance, Error>) -> Void)
func getShieldedBalance(accountIndex: Int) -> Zatoshi
func getShieldedBalance(accountIndex: Int, completion: @escaping (Result<Zatoshi, Error>) -> Void)
func getShieldedVerifiedBalance(accountIndex: Int) -> Zatoshi
func getShieldedVerifiedBalance(accountIndex: Int, completion: @escaping (Result<Zatoshi, Error>) -> Void)
/*
It can be missleading that these two methods are returning Publisher even this protocol is closure based. Reason is that Synchronizer doesn't

View File

@ -38,9 +38,9 @@ public protocol CombineSynchronizer {
func start(retry: Bool) -> CompletablePublisher<Error>
func stop() -> CompletablePublisher<Never>
func getSaplingAddress(accountIndex: Int) -> SinglePublisher<SaplingAddress?, Never>
func getUnifiedAddress(accountIndex: Int) -> SinglePublisher<UnifiedAddress?, Never>
func getTransparentAddress(accountIndex: Int) -> SinglePublisher<TransparentAddress?, Never>
func getSaplingAddress(accountIndex: Int) -> SinglePublisher<SaplingAddress, Error>
func getUnifiedAddress(accountIndex: Int) -> SinglePublisher<UnifiedAddress, Error>
func getTransparentAddress(accountIndex: Int) -> SinglePublisher<TransparentAddress, Error>
func sendToAddress(
spendingKey: UnifiedSpendingKey,
@ -78,10 +78,8 @@ public protocol CombineSynchronizer {
func refreshUTXOs(address: TransparentAddress, from height: BlockHeight) -> SinglePublisher<RefreshedUTXOs, Error>
func getTransparentBalance(accountIndex: Int) -> SinglePublisher<WalletBalance, Error>
func getShieldedBalance(accountIndex: Int) -> Zatoshi
func getShieldedVerifiedBalance(accountIndex: Int) -> Zatoshi
func getShieldedBalance(accountIndex: Int) -> SinglePublisher<Zatoshi, Error>
func getShieldedVerifiedBalance(accountIndex: Int) -> SinglePublisher<Zatoshi, Error>
func rewind(_ policy: RewindPolicy) -> CompletablePublisher<Error>
func wipe() -> CompletablePublisher<Error>

View File

@ -87,11 +87,11 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
self.dbProvider = dbProvider
}
func initialise() throws {
try createTableIfNeeded()
func initialise() async throws {
try await createTableIfNeeded()
}
func createTableIfNeeded() throws {
func createTableIfNeeded() async throws {
let stringStatement =
"""
CREATE TABLE IF NOT EXISTS utxos (
@ -111,7 +111,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
try dbProvider.connection().run(stringStatement)
}
func store(utxos: [UnspentTransactionOutputEntity]) throws {
func store(utxos: [UnspentTransactionOutputEntity]) async throws {
do {
let db = try dbProvider.connection()
try dbProvider.connection().transaction {
@ -124,7 +124,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
}
}
func clearAll(address: String?) throws {
func clearAll(address: String?) async throws {
if let tAddr = address {
do {
try dbProvider.connection().run(table.filter(TableColumns.address == tAddr).delete())
@ -140,7 +140,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
}
}
func getAll(address: String?) throws -> [UnspentTransactionOutputEntity] {
func getAll(address: String?) async throws -> [UnspentTransactionOutputEntity] {
if let tAddress = address {
let allTxs: [UTXO] = try dbProvider.connection()
.prepare(table.filter(TableColumns.address == tAddress))
@ -158,7 +158,7 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
}
}
func balance(address: String, latestHeight: BlockHeight) throws -> WalletBalance {
func balance(address: String, latestHeight: BlockHeight) async throws -> WalletBalance {
do {
let verified = try dbProvider.connection().scalar(
table.select(TableColumns.valueZat.sum)

View File

@ -55,10 +55,6 @@ public struct LightWalletEndpoint {
}
}
extension Notification.Name {
static let connectionStatusChanged = Notification.Name("LightWalletServiceConnectivityStatusChanged")
}
/// This contains URLs from which can the SDK fetch files that contain sapling parameters.
/// Use `SaplingParamsSourceURL.default` when initilizing the SDK.
public struct SaplingParamsSourceURL {
@ -102,7 +98,6 @@ class initializes the Rust backend and the supporting data required to exercise
The [cash.z.wallet.sdk.block.CompactBlockProcessor] handles all the remaining Rust backend
functionality, related to processing blocks.
*/
// swiftlint:disable type_body_length
public class Initializer {
struct URLs {
let fsBlockDbRoot: URL
@ -338,15 +333,15 @@ public class Initializer {
/// - Parameter seed: ZIP-32 Seed bytes for the wallet that will be initialized
/// - Throws: `InitializerError.dataDbInitFailed` if the creation of the dataDb fails
/// `InitializerError.accountInitFailed` if the account table can't be initialized.
func initialize(with seed: [UInt8]?, viewingKeys: [UnifiedFullViewingKey], walletBirthday: BlockHeight) throws -> InitializationResult {
func initialize(with seed: [UInt8]?, viewingKeys: [UnifiedFullViewingKey], walletBirthday: BlockHeight) async throws -> InitializationResult {
do {
try storage.create()
try await storage.create()
} catch {
throw InitializerError.fsCacheInitFailed(error)
}
do {
if case .seedRequired = try rustBackend.initDataDb(dbData: dataDbURL, seed: seed, networkType: network.networkType) {
if case .seedRequired = try await rustBackend.initDataDb(dbData: dataDbURL, seed: seed, networkType: network.networkType) {
return .seedRequired
}
} catch {
@ -355,7 +350,7 @@ public class Initializer {
let checkpoint = Checkpoint.birthday(with: walletBirthday, network: network)
do {
try rustBackend.initBlocksTable(
try await rustBackend.initBlocksTable(
dbData: dataDbURL,
height: Int32(checkpoint.height),
hash: checkpoint.hash,
@ -372,7 +367,7 @@ public class Initializer {
self.walletBirthday = checkpoint.height
do {
try rustBackend.initAccountsTable(
try await rustBackend.initAccountsTable(
dbData: dataDbURL,
ufvks: viewingKeys,
networkType: network.networkType
@ -395,34 +390,6 @@ public class Initializer {
return .success
}
/// get (unverified) balance from the given account index
/// - Parameter account: the index of the account
/// - Returns: balance in `Zatoshi`
public func getBalance(account index: Int = 0) -> Zatoshi {
guard let balance = try? rustBackend.getBalance(
dbData: dataDbURL,
account: Int32(index),
networkType: network.networkType
) else {
return .zero
}
return Zatoshi(balance)
}
/// get verified balance from the given account index
/// - Parameter account: the index of the account
/// - Returns: balance in `Zatoshi`
public func getVerifiedBalance(account index: Int = 0) -> Zatoshi {
guard let balance = try? rustBackend.getVerifiedBalance(
dbData: dataDbURL,
account: Int32(index),
networkType: network.networkType
) else { return .zero }
return Zatoshi(balance)
}
/**
checks if the provided address is a valid sapling address
@ -460,14 +427,3 @@ extension InitializerError: LocalizedError {
}
}
}
/// Synchronous helpers that support clients that don't use structured concurrency yet
extension Initializer {
func getCurrentAddress(accountIndex: Int) -> UnifiedAddress? {
try? self.rustBackend.getCurrentAddress(
dbData: self.dataDbURL,
account: Int32(accountIndex),
networkType: self.network.networkType
)
}
}

View File

@ -29,7 +29,7 @@ enum CompactBlockRepositoryError: Error, Equatable {
protocol CompactBlockRepository {
/// Creates the underlying repository
func create() throws
func create() async throws
/**
Gets the height of the highest block that is currently stored.

View File

@ -8,9 +8,9 @@
import Foundation
protocol UnspentTransactionOutputRepository {
func initialise() throws
func getAll(address: String?) throws -> [UnspentTransactionOutputEntity]
func balance(address: String, latestHeight: BlockHeight) throws -> WalletBalance
func store(utxos: [UnspentTransactionOutputEntity]) throws
func clearAll(address: String?) throws
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
}

View File

@ -12,7 +12,7 @@ import libzcashlc
class ZcashRustBackend: ZcashRustBackendWelding {
static let minimumConfirmations: UInt32 = 10
static let useZIP317Fees = false
static func createAccount(dbData: URL, seed: [UInt8], networkType: NetworkType) throws -> UnifiedSpendingKey {
static func createAccount(dbData: URL, seed: [UInt8], networkType: NetworkType) async throws -> UnifiedSpendingKey {
let dbData = dbData.osStr()
guard let ffiBinaryKeyPtr = zcashlc_create_account(
@ -40,7 +40,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
spendParamsPath: String,
outputParamsPath: String,
networkType: NetworkType
) -> Int64 {
) async -> Int64 {
let dbData = dbData.osStr()
return usk.bytes.withUnsafeBufferPointer { uskPtr in
@ -63,7 +63,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
}
}
static func decryptAndStoreTransaction(dbData: URL, txBytes: [UInt8], minedHeight: Int32, networkType: NetworkType) -> Bool {
static func decryptAndStoreTransaction(dbData: URL, txBytes: [UInt8], minedHeight: Int32, networkType: NetworkType) async -> Bool {
let dbData = dbData.osStr()
return zcashlc_decrypt_and_store_transaction(
dbData.0,
@ -98,7 +98,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return binaryKey.unsafeToUnifiedSpendingKey(network: networkType)
}
static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) throws -> Int64 {
static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) async throws -> Int64 {
let dbData = dbData.osStr()
let balance = zcashlc_get_balance(dbData.0, dbData.1, account, networkType.networkId)
@ -114,7 +114,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> UnifiedAddress {
) async throws -> UnifiedAddress {
let dbData = dbData.osStr()
guard let addressCStr = zcashlc_get_current_address(
@ -139,7 +139,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData: URL,
height: Int32,
networkType: NetworkType
) -> Int32 {
) async -> Int32 {
let dbData = dbData.osStr()
return zcashlc_get_nearest_rewind_height(
@ -154,7 +154,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> UnifiedAddress {
) async throws -> UnifiedAddress {
let dbData = dbData.osStr()
guard let addressCStr = zcashlc_get_next_available_address(
@ -179,7 +179,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData: URL,
idNote: Int64,
networkType: NetworkType
) -> Memo? {
) async -> Memo? {
let dbData = dbData.osStr()
var contiguousMemoBytes = ContiguousArray<UInt8>(MemoBytes.empty().bytes)
@ -194,7 +194,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return (try? MemoBytes(contiguousBytes: contiguousMemoBytes)).flatMap { try? $0.intoMemo() }
}
static func getSaplingReceiver(for uAddr: UnifiedAddress) throws -> SaplingAddress? {
static func getSaplingReceiver(for uAddr: UnifiedAddress) throws -> SaplingAddress {
guard let saplingCStr = zcashlc_get_sapling_receiver_for_unified_address(
[CChar](uAddr.encoding.utf8CString)
) else {
@ -214,7 +214,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData: URL,
idNote: Int64,
networkType: NetworkType
) -> Memo? {
) async -> Memo? {
let dbData = dbData.osStr()
var contiguousMemoBytes = ContiguousArray<UInt8>(MemoBytes.empty().bytes)
@ -233,7 +233,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> Int64 {
) async throws -> Int64 {
guard account >= 0 else {
throw RustWeldingError.invalidInput(message: "Account index must be non-negative")
}
@ -253,7 +253,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return balance
}
static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) throws -> Int64 {
static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) async throws -> Int64 {
let dbData = dbData.osStr()
let balance = zcashlc_get_verified_balance(
dbData.0,
@ -274,7 +274,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> Int64 {
) async throws -> Int64 {
guard account >= 0 else {
throw RustWeldingError.invalidInput(message: "`account` must be non-negative")
}
@ -336,7 +336,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return AddressMetadata(network: network, addrType: addrType)
}
static func getTransparentReceiver(for uAddr: UnifiedAddress) throws -> TransparentAddress? {
static func getTransparentReceiver(for uAddr: UnifiedAddress) throws -> TransparentAddress {
guard let transparentCStr = zcashlc_get_transparent_receiver_for_unified_address(
[CChar](uAddr.encoding.utf8CString)
) else {
@ -364,7 +364,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
}
}
static func initDataDb(dbData: URL, seed: [UInt8]?, networkType: NetworkType) throws -> DbInitResult {
static func initDataDb(dbData: URL, seed: [UInt8]?, networkType: NetworkType) async throws -> DbInitResult {
let dbData = dbData.osStr()
switch zcashlc_init_data_database(dbData.0, dbData.1, seed, UInt(seed?.count ?? 0), networkType.networkId) {
case 0: // ok
@ -428,7 +428,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData: URL,
ufvks: [UnifiedFullViewingKey],
networkType: NetworkType
) throws {
) async throws {
let dbData = dbData.osStr()
var ffiUfvks: [FFIEncodedKey] = []
@ -476,7 +476,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
}
}
static func initBlockMetadataDb(fsBlockDbRoot: URL) throws -> Bool {
static func initBlockMetadataDb(fsBlockDbRoot: URL) async throws -> Bool {
let blockDb = fsBlockDbRoot.osPathStr()
let result = zcashlc_init_block_metadata_db(blockDb.0, blockDb.1)
@ -488,7 +488,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return result
}
static func writeBlocksMetadata(fsBlockDbRoot: URL, blocks: [ZcashCompactBlock]) throws -> Bool {
static func writeBlocksMetadata(fsBlockDbRoot: URL, blocks: [ZcashCompactBlock]) async throws -> Bool {
var ffiBlockMetaVec: [FFIBlockMeta] = []
for block in blocks {
@ -563,7 +563,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
time: UInt32,
saplingTree: String,
networkType: NetworkType
) throws {
) async throws {
let dbData = dbData.osStr()
guard !hash.containsCStringNullBytesBeforeStringEnding() else {
@ -587,7 +587,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
}
}
static func latestCachedBlockHeight(fsBlockDbRoot: URL) -> BlockHeight {
static func latestCachedBlockHeight(fsBlockDbRoot: URL) async -> BlockHeight {
let fsBlockDb = fsBlockDbRoot.osPathStr()
return BlockHeight(zcashlc_latest_cached_block_height(fsBlockDb.0, fsBlockDb.1))
@ -597,7 +597,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> [TransparentAddress] {
) async throws -> [TransparentAddress] {
let dbData = dbData.osStr()
guard let encodedKeysPtr = zcashlc_list_transparent_receivers(
@ -628,7 +628,15 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return addresses
}
static func putUnspentTransparentOutput(dbData: URL, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight, networkType: NetworkType) throws -> Bool {
static func putUnspentTransparentOutput(
dbData: URL,
txid: [UInt8],
index: Int,
script: [UInt8],
value: Int64,
height: BlockHeight,
networkType: NetworkType
) async throws -> Bool {
let dbData = dbData.osStr()
guard zcashlc_put_utxo(
@ -649,7 +657,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return true
}
static func validateCombinedChain(fsBlockDbRoot: URL, dbData: URL, networkType: NetworkType, limit: UInt32 = 0) -> Int32 {
static func validateCombinedChain(fsBlockDbRoot: URL, dbData: URL, networkType: NetworkType, limit: UInt32 = 0) async -> Int32 {
let dbCache = fsBlockDbRoot.osPathStr()
let dbData = dbData.osStr()
return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1, networkType.networkId, limit)
@ -669,7 +677,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return zcashlc_rewind_fs_block_cache_to_height(fsBlockCache.0, fsBlockCache.1, height)
}
static func scanBlocks(fsBlockDbRoot: URL, dbData: URL, limit: UInt32 = 0, networkType: NetworkType) -> Bool {
static func scanBlocks(fsBlockDbRoot: URL, dbData: URL, limit: UInt32 = 0, networkType: NetworkType) async -> Bool {
let dbCache = fsBlockDbRoot.osPathStr()
let dbData = dbData.osStr()
return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1, limit, networkType.networkId) != 0
@ -683,7 +691,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
spendParamsPath: String,
outputParamsPath: String,
networkType: NetworkType
) -> Int64 {
) async -> Int64 {
let dbData = dbData.osStr()
return usk.bytes.withUnsafeBufferPointer { uskBuffer in

View File

@ -55,7 +55,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
seed: [UInt8],
networkType: NetworkType
) throws -> UnifiedSpendingKey
) async throws -> UnifiedSpendingKey
/// Creates a transaction to the given address from the given account
/// - Parameter dbData: URL for the Data DB
@ -76,7 +76,7 @@ protocol ZcashRustBackendWelding {
spendParamsPath: String,
outputParamsPath: String,
networkType: NetworkType
) -> Int64 // swiftlint:disable function_parameter_count
) async -> Int64 // swiftlint:disable function_parameter_count
/// Scans a transaction for any information that can be decrypted by the accounts in the
/// wallet, and saves it to the wallet.
@ -90,7 +90,7 @@ protocol ZcashRustBackendWelding {
txBytes: [UInt8],
minedHeight: Int32,
networkType: NetworkType
) -> Bool
) async -> Bool
/// Derives and returns a unified spending key from the given seed for the given account ID.
/// Returns the binary encoding of the spending key. The caller should manage the memory of (and store, if necessary) the returned spending key in a secure fashion.
@ -112,7 +112,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> Int64
) async throws -> Int64
/// Returns the most-recently-generated unified payment address for the specified account.
/// - parameter dbData: location of the data db
@ -122,7 +122,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> UnifiedAddress
) async throws -> UnifiedAddress
/// Wallets might need to be rewound because of a reorg, or by user request.
/// There are times where the wallet could get out of sync for many reasons and
@ -140,7 +140,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
height: Int32,
networkType: NetworkType
) -> Int32
) async -> Int32
/// Returns a newly-generated unified payment address for the specified account, with the next available diversifier.
/// - parameter dbData: location of the data db
@ -150,7 +150,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> UnifiedAddress
) async throws -> UnifiedAddress
/// get received memo from note
/// - parameter dbData: location of the data db file
@ -160,13 +160,13 @@ protocol ZcashRustBackendWelding {
dbData: URL,
idNote: Int64,
networkType: NetworkType
) -> Memo?
) async -> Memo?
/// Returns the Sapling receiver within the given Unified Address, if any.
/// - Parameter uAddr: a `UnifiedAddress`
/// - Returns a `SaplingAddress` if any
/// - Throws `receiverNotFound` when the receiver is not found. `invalidUnifiedAddress` if the UA provided is not valid
static func getSaplingReceiver(for uAddr: UnifiedAddress) throws -> SaplingAddress?
static func getSaplingReceiver(for uAddr: UnifiedAddress) throws -> SaplingAddress
/// get sent memo from note
/// - parameter dbData: location of the data db file
@ -177,7 +177,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
idNote: Int64,
networkType: NetworkType
) -> Memo?
) async -> Memo?
/// Get the verified cached transparent balance for the given address
/// - parameter dbData: location of the data db file
@ -187,13 +187,13 @@ protocol ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> Int64
) async throws -> Int64
/// Returns the transparent receiver within the given Unified Address, if any.
/// - parameter uAddr: a `UnifiedAddress`
/// - Returns a `TransparentAddress` if any
/// - Throws `receiverNotFound` when the receiver is not found. `invalidUnifiedAddress` if the UA provided is not valid
static func getTransparentReceiver(for uAddr: UnifiedAddress) throws -> TransparentAddress?
static func getTransparentReceiver(for uAddr: UnifiedAddress) throws -> TransparentAddress
/// gets the latest error if available. Clear the existing error
/// - Returns a `RustWeldingError` if exists
@ -212,7 +212,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
ufvks: [UnifiedFullViewingKey],
networkType: NetworkType
) throws
) async throws
/// initializes the data db. This will performs any migrations needed on the sqlite file
/// provided. Some migrations might need that callers provide the seed bytes.
@ -226,7 +226,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
seed: [UInt8]?,
networkType: NetworkType
) throws -> DbInitResult
) async throws -> DbInitResult
/// Returns the network and address type for the given Zcash address string,
/// if the string represents a valid Zcash address.
@ -288,7 +288,7 @@ protocol ZcashRustBackendWelding {
time: UInt32,
saplingTree: String,
networkType: NetworkType
) throws // swiftlint:disable function_parameter_count
) async throws // swiftlint:disable function_parameter_count
/// Returns a list of the transparent receivers for the diversified unified addresses that have
/// been allocated for the provided account.
@ -299,7 +299,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> [TransparentAddress]
) async throws -> [TransparentAddress]
/// get the verified balance from the given account
/// - parameter dbData: location of the data db
@ -309,7 +309,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> Int64
) async throws -> Int64
/// Get the verified cached transparent balance for the given account
/// - parameter dbData: location of the data db
@ -319,7 +319,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
account: Int32,
networkType: NetworkType
) throws -> Int64
) async throws -> Int64
/// Checks that the scanned blocks in the data database, when combined with the recent
/// `CompactBlock`s in the cache database, form a valid chain.
@ -344,7 +344,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
networkType: NetworkType,
limit: UInt32
) -> Int32
) async -> Int32
/// Resets the state of the database to only contain block and transaction information up to the given height. clears up all derived data as well
/// - parameter dbData: `URL` pointing to the filesystem root directory where the fsBlock cache is.
@ -355,7 +355,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
height: Int32,
networkType: NetworkType
) -> Bool
) async -> Bool
/// Resets the state of the FsBlock database to only contain block and transaction information up to the given height.
/// - Note: this does not delete the files. Only rolls back the database.
@ -365,7 +365,7 @@ protocol ZcashRustBackendWelding {
static func rewindCacheToHeight(
fsBlockDbRoot: URL,
height: Int32
) -> Bool
) async -> Bool
/// Scans new blocks added to the cache for any transactions received by the tracked
/// accounts.
@ -391,7 +391,7 @@ protocol ZcashRustBackendWelding {
dbData: URL,
limit: UInt32,
networkType: NetworkType
) -> Bool
) async -> Bool
/// Upserts a UTXO into the data db database
/// - parameter dbData: location of the data db file
@ -410,7 +410,7 @@ protocol ZcashRustBackendWelding {
value: Int64,
height: BlockHeight,
networkType: NetworkType
) throws -> Bool
) async throws -> Bool
/// Creates a transaction to shield all found UTXOs in data db for the account the provided `UnifiedSpendingKey` has spend authority for.
/// - Parameter dbData: URL for the Data DB
@ -427,7 +427,7 @@ protocol ZcashRustBackendWelding {
spendParamsPath: String,
outputParamsPath: String,
networkType: NetworkType
) -> Int64
) async -> Int64
/// Obtains the available receiver typecodes for the given String encoded Unified Address
/// - Parameter address: public key represented as a String
@ -459,7 +459,7 @@ protocol ZcashRustBackendWelding {
/// format `{height}-{hash}-block`. This directory has must be granted both write and read permissions.
/// - returns `true` when successful, `false` when fails but no throwing information was found
/// - throws `RustWeldingError` when fails to initialize
static func initBlockMetadataDb(fsBlockDbRoot: URL) throws -> Bool
static func initBlockMetadataDb(fsBlockDbRoot: URL) async throws -> Bool
/// Write compact block metadata to a database known to the Rust layer
/// - Parameter fsBlockDbRoot: `URL` pointing to the filesystem root directory where the fsBlock cache is.
@ -468,12 +468,12 @@ protocol ZcashRustBackendWelding {
/// - Parameter blocks: The `ZcashCompactBlock`s that are going to be marked as stored by the
/// metadata Db.
/// - Returns `true` if the operation was successful, `false` otherwise.
static func writeBlocksMetadata(fsBlockDbRoot: URL, blocks: [ZcashCompactBlock]) throws -> Bool
static func writeBlocksMetadata(fsBlockDbRoot: URL, blocks: [ZcashCompactBlock]) async throws -> Bool
/// Gets the latest block height stored in the filesystem based cache.
/// - Parameter fsBlockDbRoot: `URL` pointing to the filesystem root directory where the fsBlock cache is.
/// this directory is expected to contain a `/blocks` sub-directory with the blocks stored in the convened filename
/// format `{height}-{hash}-block`. This directory has must be granted both write and read permissions.
/// - Returns `BlockHeight` of the latest cached block or `.empty` if no blocks are stored.
static func latestCachedBlockHeight(fsBlockDbRoot: URL) -> BlockHeight
static func latestCachedBlockHeight(fsBlockDbRoot: URL) async -> BlockHeight
}

View File

@ -156,17 +156,17 @@ public protocol Synchronizer: AnyObject {
/// Gets the sapling shielded address for the given account.
/// - Parameter accountIndex: the optional accountId whose address is of interest. By default, the first account is used.
/// - Returns the address or nil if account index is incorrect
func getSaplingAddress(accountIndex: Int) async -> SaplingAddress?
func getSaplingAddress(accountIndex: Int) async throws -> SaplingAddress
/// Gets the unified address for the given account.
/// - Parameter accountIndex: the optional accountId whose address is of interest. By default, the first account is used.
/// - Returns the address or nil if account index is incorrect
func getUnifiedAddress(accountIndex: Int) async -> UnifiedAddress?
func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress
/// Gets the transparent address for the given account.
/// - Parameter accountIndex: the optional accountId whose address is of interest. By default, the first account is used.
/// - Returns the address or nil if account index is incorrect
func getTransparentAddress(accountIndex: Int) async -> TransparentAddress?
func getTransparentAddress(accountIndex: Int) async throws -> TransparentAddress
/// Sends zatoshi.
/// - Parameter spendingKey: the `UnifiedSpendingKey` that allows spends to occur.
@ -258,11 +258,15 @@ public protocol Synchronizer: AnyObject {
/// Returns the last stored transparent balance
func getTransparentBalance(accountIndex: Int) async throws -> WalletBalance
/// Returns the shielded total balance (includes verified and unverified balance)
func getShieldedBalance(accountIndex: Int) -> Zatoshi
/// get (unverified) balance from the given account index
/// - Parameter accountIndex: the index of the account
/// - Returns: balance in `Zatoshi`
func getShieldedBalance(accountIndex: Int) async throws -> Zatoshi
/// Returns the shielded verified balance (anchor is 10 blocks back)
func getShieldedVerifiedBalance(accountIndex: Int) -> 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
/// Rescans the known blocks with the current keys.
///

View File

@ -54,21 +54,21 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
}
}
public func getSaplingAddress(accountIndex: Int, completion: @escaping (SaplingAddress?) -> Void) {
executeAction(completion) {
await self.synchronizer.getSaplingAddress(accountIndex: accountIndex)
public func getSaplingAddress(accountIndex: Int, completion: @escaping (Result<SaplingAddress, Error>) -> Void) {
executeThrowingAction(completion) {
try await self.synchronizer.getSaplingAddress(accountIndex: accountIndex)
}
}
public func getUnifiedAddress(accountIndex: Int, completion: @escaping (UnifiedAddress?) -> Void) {
executeAction(completion) {
await self.synchronizer.getUnifiedAddress(accountIndex: accountIndex)
public func getUnifiedAddress(accountIndex: Int, completion: @escaping (Result<UnifiedAddress, Error>) -> Void) {
executeThrowingAction(completion) {
try await self.synchronizer.getUnifiedAddress(accountIndex: accountIndex)
}
}
public func getTransparentAddress(accountIndex: Int, completion: @escaping (TransparentAddress?) -> Void) {
executeAction(completion) {
await self.synchronizer.getTransparentAddress(accountIndex: accountIndex)
public func getTransparentAddress(accountIndex: Int, completion: @escaping (Result<TransparentAddress, Error>) -> Void) {
executeThrowingAction(completion) {
try await self.synchronizer.getTransparentAddress(accountIndex: accountIndex)
}
}
@ -185,9 +185,17 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
}
}
public func getShieldedBalance(accountIndex: Int) -> Zatoshi { synchronizer.getShieldedBalance(accountIndex: accountIndex) }
public func getShieldedBalance(accountIndex: Int, completion: @escaping (Result<Zatoshi, Error>) -> Void) {
executeThrowingAction(completion) {
try await self.synchronizer.getShieldedBalance(accountIndex: accountIndex)
}
}
public func getShieldedVerifiedBalance(accountIndex: Int) -> Zatoshi { synchronizer.getShieldedVerifiedBalance(accountIndex: accountIndex) }
public func getShieldedVerifiedBalance(accountIndex: Int, completion: @escaping (Result<Zatoshi, Error>) -> Void) {
executeThrowingAction(completion) {
try await self.synchronizer.getShieldedVerifiedBalance(accountIndex: accountIndex)
}
}
/*
It can be missleading that these two methods are returning Publisher even this protocol is closure based. Reason is that Synchronizer doesn't

View File

@ -53,21 +53,21 @@ extension CombineSDKSynchronizer: CombineSynchronizer {
}
}
public func getSaplingAddress(accountIndex: Int) -> SinglePublisher<SaplingAddress?, Never> {
return executeAction() {
await self.synchronizer.getSaplingAddress(accountIndex: accountIndex)
public func getSaplingAddress(accountIndex: Int) -> SinglePublisher<SaplingAddress, Error> {
return executeThrowingAction() {
try await self.synchronizer.getSaplingAddress(accountIndex: accountIndex)
}
}
public func getUnifiedAddress(accountIndex: Int) -> SinglePublisher<UnifiedAddress?, Never> {
return executeAction() {
await self.synchronizer.getUnifiedAddress(accountIndex: accountIndex)
public func getUnifiedAddress(accountIndex: Int) -> SinglePublisher<UnifiedAddress, Error> {
return executeThrowingAction() {
try await self.synchronizer.getUnifiedAddress(accountIndex: accountIndex)
}
}
public func getTransparentAddress(accountIndex: Int) -> SinglePublisher<TransparentAddress?, Never> {
return executeAction() {
await self.synchronizer.getTransparentAddress(accountIndex: accountIndex)
public func getTransparentAddress(accountIndex: Int) -> SinglePublisher<TransparentAddress, Error> {
return executeThrowingAction() {
try await self.synchronizer.getTransparentAddress(accountIndex: accountIndex)
}
}
@ -178,9 +178,17 @@ extension CombineSDKSynchronizer: CombineSynchronizer {
}
}
public func getShieldedBalance(accountIndex: Int) -> Zatoshi { synchronizer.getShieldedBalance(accountIndex: accountIndex) }
public func getShieldedBalance(accountIndex: Int = 0) -> SinglePublisher<Zatoshi, Error> {
return executeThrowingAction() {
try await synchronizer.getShieldedBalance(accountIndex: accountIndex)
}
}
public func getShieldedVerifiedBalance(accountIndex: Int) -> Zatoshi { synchronizer.getShieldedVerifiedBalance(accountIndex: accountIndex) }
public func getShieldedVerifiedBalance(accountIndex: Int = 0) -> SinglePublisher<Zatoshi, Error> {
return executeThrowingAction() {
try await synchronizer.getShieldedVerifiedBalance(accountIndex: accountIndex)
}
}
public func rewind(_ policy: RewindPolicy) -> CompletablePublisher<Error> { synchronizer.rewind(policy) }
public func wipe() -> CompletablePublisher<Error> { synchronizer.wipe() }

View File

@ -94,7 +94,6 @@ public class SDKSynchronizer: Synchronizer {
deinit {
UsedAliasesChecker.stopUsing(alias: initializer.alias, id: initializer.id)
NotificationCenter.default.removeObserver(self)
Task { [blockProcessor] in
await blockProcessor.stop()
}
@ -134,9 +133,9 @@ public class SDKSynchronizer: Synchronizer {
throw error
}
try utxoRepository.initialise()
try await utxoRepository.initialise()
if case .seedRequired = try self.initializer.initialize(with: seed, viewingKeys: viewingKeys, walletBirthday: walletBirthday) {
if case .seedRequired = try await self.initializer.initialize(with: seed, viewingKeys: viewingKeys, walletBirthday: walletBirthday) {
return .seedRequired
}
@ -255,7 +254,7 @@ public class SDKSynchronizer: Synchronizer {
logger.debug("handling reorg at: \(reorgHeight) with rewind height: \(rewindHeight)")
do {
try transactionManager.handleReorg(at: rewindHeight)
try await transactionManager.handleReorg(at: rewindHeight)
} catch {
logger.debug("error handling reorg: \(error)")
}
@ -323,7 +322,7 @@ public class SDKSynchronizer: Synchronizer {
throw ShieldFundsError.insuficientTransparentFunds
}
let shieldingSpend = try transactionManager.initSpend(
let shieldingSpend = try await transactionManager.initSpend(
zatoshi: tBalance.verified,
recipient: .internalAccount(spendingKey.account),
memo: try memo.asMemoBytes(),
@ -350,7 +349,7 @@ public class SDKSynchronizer: Synchronizer {
memo: Memo?
) async throws -> PendingTransactionEntity {
do {
let spend = try transactionManager.initSpend(
let spend = try await transactionManager.initSpend(
zatoshi: zatoshi,
recipient: .address(recipient),
memo: memo?.asMemoBytes(),
@ -368,16 +367,16 @@ public class SDKSynchronizer: Synchronizer {
}
}
public func cancelSpend(transaction: PendingTransactionEntity) -> Bool {
transactionManager.cancel(pendingTransaction: transaction)
public func cancelSpend(transaction: PendingTransactionEntity) async -> Bool {
await transactionManager.cancel(pendingTransaction: transaction)
}
public func allReceivedTransactions() async throws -> [ZcashTransaction.Received] {
try await transactionRepository.findReceived(offset: 0, limit: Int.max)
}
public func allPendingTransactions() throws -> [PendingTransactionEntity] {
try transactionManager.allPendingTransactions()
public func allPendingTransactions() async throws -> [PendingTransactionEntity] {
try await transactionManager.allPendingTransactions()
}
public func allClearedTransactions() async throws -> [ZcashTransaction.Overview] {
@ -435,8 +434,8 @@ public class SDKSynchronizer: Synchronizer {
for try await transactionEntity in stream {
utxos.append(transactionEntity)
}
try self.utxoRepository.clearAll(address: address)
try self.utxoRepository.store(utxos: utxos)
try await self.utxoRepository.clearAll(address: address)
try await self.utxoRepository.store(utxos: utxos)
return utxos
} catch {
throw SynchronizerError.generalError(message: "\(error)")
@ -447,25 +446,37 @@ public class SDKSynchronizer: Synchronizer {
try throwIfUnprepared()
return try await blockProcessor.refreshUTXOs(tAddress: address, startHeight: height)
}
public func getShieldedBalance(accountIndex: Int = 0) -> Zatoshi {
initializer.getBalance(account: accountIndex)
public func getShieldedBalance(accountIndex: Int = 0) async throws -> Zatoshi {
let balance = try await initializer.rustBackend.getBalance(
dbData: initializer.dataDbURL,
account: Int32(accountIndex),
networkType: network.networkType
)
return Zatoshi(balance)
}
public func getShieldedVerifiedBalance(accountIndex: Int = 0) -> Zatoshi {
initializer.getVerifiedBalance(account: accountIndex)
public func getShieldedVerifiedBalance(accountIndex: Int = 0) async throws -> Zatoshi {
let balance = try await initializer.rustBackend.getVerifiedBalance(
dbData: initializer.dataDbURL,
account: Int32(accountIndex),
networkType: network.networkType
)
return Zatoshi(balance)
}
public func getSaplingAddress(accountIndex: Int) async -> SaplingAddress? {
await blockProcessor.getSaplingAddress(accountIndex: accountIndex)
public func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress {
try await blockProcessor.getUnifiedAddress(accountIndex: accountIndex)
}
public func getUnifiedAddress(accountIndex: Int) async -> UnifiedAddress? {
await blockProcessor.getUnifiedAddress(accountIndex: accountIndex)
public func getSaplingAddress(accountIndex: Int) async throws -> SaplingAddress {
try await blockProcessor.getSaplingAddress(accountIndex: accountIndex)
}
public func getTransparentAddress(accountIndex: Int) async -> TransparentAddress? {
await blockProcessor.getTransparentAddress(accountIndex: accountIndex)
public func getTransparentAddress(accountIndex: Int) async throws -> TransparentAddress {
try await blockProcessor.getTransparentAddress(accountIndex: accountIndex)
}
/// Returns the last stored transparent balance
@ -509,7 +520,7 @@ public class SDKSynchronizer: Synchronizer {
switch result {
case let .success(rewindHeight):
do {
try self?.transactionManager.handleReorg(at: rewindHeight)
try await self?.transactionManager.handleReorg(at: rewindHeight)
subject.send(completion: .finished)
} catch {
subject.send(completion: .failure(SynchronizerError.rewindError(underlyingError: error)))
@ -563,8 +574,8 @@ public class SDKSynchronizer: Synchronizer {
private func snapshotState(status: SyncStatus) async -> SynchronizerState {
SynchronizerState(
shieldedBalance: WalletBalance(
verified: initializer.getVerifiedBalance(),
total: initializer.getBalance()
verified: (try? await getShieldedVerifiedBalance()) ?? .zero,
total: (try? await getShieldedBalance()) ?? .zero
),
transparentBalance: (try? await blockProcessor.getTransparentBalance(accountIndex: 0)) ?? .zero,
syncStatus: status,
@ -622,7 +633,7 @@ public class SDKSynchronizer: Synchronizer {
// MARK: book keeping
private func updateMinedTransactions() async throws {
let transactions = try transactionManager.allPendingTransactions()
let transactions = try await transactionManager.allPendingTransactions()
.filter { $0.isSubmitSuccess && !$0.isMined }
for pendingTx in transactions {
@ -630,7 +641,7 @@ public class SDKSynchronizer: Synchronizer {
let transaction = try await transactionRepository.find(rawID: rawID)
guard let minedHeight = transaction.minedHeight else { return }
let minedTx = try transactionManager.applyMinedHeight(pendingTransaction: pendingTx, minedHeight: minedHeight)
let minedTx = try await transactionManager.applyMinedHeight(pendingTransaction: pendingTx, minedHeight: minedHeight)
notifyMinedTransaction(minedTx)
}
@ -639,9 +650,12 @@ public class SDKSynchronizer: Synchronizer {
private func removeConfirmedTransactions() async throws {
let latestHeight = try await transactionRepository.lastScannedHeight()
try transactionManager.allPendingTransactions()
let transactions = try await transactionManager.allPendingTransactions()
.filter { $0.minedHeight > 0 && abs($0.minedHeight - latestHeight) >= ZcashSDK.defaultStaleTolerance }
.forEach { try transactionManager.delete(pendingTransaction: $0) }
for transaction in transactions {
try await transactionManager.delete(pendingTransaction: transaction)
}
}
private func refreshPendingTransactions() async {
@ -702,7 +716,9 @@ public class SDKSynchronizer: Synchronizer {
extension SDKSynchronizer {
public var pendingTransactions: [PendingTransactionEntity] {
(try? self.allPendingTransactions()) ?? [PendingTransactionEntity]()
get async {
(try? await self.allPendingTransactions()) ?? [PendingTransactionEntity]()
}
}
public var clearedTransactions: [ZcashTransaction.Overview] {
@ -723,17 +739,3 @@ extension SDKSynchronizer {
}
}
}
extension SDKSynchronizer {
public func getUnifiedAddress(accountIndex: Int) -> UnifiedAddress? {
self.initializer.getCurrentAddress(accountIndex: accountIndex)
}
public func getSaplingAddress(accountIndex: Int) -> SaplingAddress? {
self.getUnifiedAddress(accountIndex: accountIndex)?.saplingReceiver()
}
public func getTransparentAddress(accountIndex: Int) -> TransparentAddress? {
self.getUnifiedAddress(accountIndex: accountIndex)?.transparentReceiver()
}
}

View File

@ -30,12 +30,12 @@ public protocol KeyDeriving {
/// Extracts the `SaplingAddress` from the given `UnifiedAddress`
/// - Parameter address: the `UnifiedAddress`
/// - Throws `KeyDerivationErrors.receiverNotFound` if the receiver is not present
static func saplingReceiver(from unifiedAddress: UnifiedAddress) throws -> SaplingAddress?
static func saplingReceiver(from unifiedAddress: UnifiedAddress) throws -> SaplingAddress
/// Extracts the `TransparentAddress` from the given `UnifiedAddress`
/// - Parameter address: the `UnifiedAddress`
/// - Throws `KeyDerivationErrors.receiverNotFound` if the receiver is not present
static func transparentReceiver(from unifiedAddress: UnifiedAddress) throws -> TransparentAddress?
static func transparentReceiver(from unifiedAddress: UnifiedAddress) throws -> TransparentAddress
/// Extracts the `UnifiedAddress.ReceiverTypecodes` from the given `UnifiedAddress`
/// - Parameter address: the `UnifiedAddress`
@ -60,11 +60,11 @@ public class DerivationTool: KeyDeriving {
self.networkType = networkType
}
public static func saplingReceiver(from unifiedAddress: UnifiedAddress) throws -> SaplingAddress? {
public static func saplingReceiver(from unifiedAddress: UnifiedAddress) throws -> SaplingAddress {
try rustwelding.getSaplingReceiver(for: unifiedAddress)
}
public static func transparentReceiver(from unifiedAddress: UnifiedAddress) throws -> TransparentAddress? {
public static func transparentReceiver(from unifiedAddress: UnifiedAddress) throws -> TransparentAddress {
try rustwelding.getTransparentReceiver(for: unifiedAddress)
}
@ -215,13 +215,13 @@ public extension UnifiedSpendingKey {
public extension UnifiedAddress {
/// Extracts the sapling receiver from this UA if available
/// - Returns: an `Optional<SaplingAddress>`
func saplingReceiver() -> SaplingAddress? {
try? DerivationTool.saplingReceiver(from: self)
func saplingReceiver() throws -> SaplingAddress {
try DerivationTool.saplingReceiver(from: self)
}
/// Extracts the transparent receiver from this UA if available
/// - Returns: an `Optional<TransparentAddress>`
func transparentReceiver() -> TransparentAddress? {
try? DerivationTool.transparentReceiver(from: self)
func transparentReceiver() throws -> TransparentAddress {
try DerivationTool.transparentReceiver(from: self)
}
}

View File

@ -144,7 +144,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
throw TransactionManagerError.updateFailed(pendingTransaction)
} catch {
do {
try self.updateOnFailure(transaction: pendingTransaction, error: error)
try await self.updateOnFailure(transaction: pendingTransaction, error: error)
} catch {
throw TransactionManagerError.updateFailed(pendingTransaction)
}
@ -175,7 +175,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
}
let response = try await self.service.submit(spendTransaction: raw)
let transaction = try self.update(transaction: storedTx, on: response)
let transaction = try await self.update(transaction: storedTx, on: response)
guard response.errorCode >= 0 else {
throw TransactionManagerError.submitFailed(transaction, errorCode: Int(response.errorCode))
@ -183,12 +183,12 @@ class PersistentTransactionManager: OutboundTransactionManager {
return transaction
} catch {
try? self.updateOnFailure(transaction: pendingTransaction, error: error)
try? await self.updateOnFailure(transaction: pendingTransaction, error: error)
throw error
}
}
func applyMinedHeight(pendingTransaction: PendingTransactionEntity, minedHeight: BlockHeight) throws -> PendingTransactionEntity {
func applyMinedHeight(pendingTransaction: PendingTransactionEntity, minedHeight: BlockHeight) async throws -> PendingTransactionEntity {
guard let id = pendingTransaction.id else {
throw TransactionManagerError.internalInconsistency(pendingTransaction)
}
@ -209,8 +209,8 @@ class PersistentTransactionManager: OutboundTransactionManager {
return transaction
}
func handleReorg(at height: BlockHeight) throws {
let affectedTxs = try allPendingTransactions()
func handleReorg(at height: BlockHeight) async throws {
let affectedTxs = try await allPendingTransactions()
.filter({ $0.minedHeight >= height })
try affectedTxs
@ -222,7 +222,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
.forEach { try self.repository.update($0) }
}
func cancel(pendingTransaction: PendingTransactionEntity) -> Bool {
func cancel(pendingTransaction: PendingTransactionEntity) async -> Bool {
guard let id = pendingTransaction.id else { return false }
guard let transaction = try? repository.find(by: id) else { return false }
@ -234,19 +234,19 @@ class PersistentTransactionManager: OutboundTransactionManager {
return true
}
func allPendingTransactions() throws -> [PendingTransactionEntity] {
func allPendingTransactions() async throws -> [PendingTransactionEntity] {
try repository.getAll()
}
// MARK: other functions
private func updateOnFailure(transaction: PendingTransactionEntity, error: Error) throws {
private func updateOnFailure(transaction: PendingTransactionEntity, error: Error) async throws {
var pending = transaction
pending.errorMessage = error.localizedDescription
pending.encodeAttempts = transaction.encodeAttempts + 1
try self.repository.update(pending)
}
private func update(transaction: PendingTransactionEntity, on sendResponse: LightWalletServiceResponse) throws -> PendingTransactionEntity {
private func update(transaction: PendingTransactionEntity, on sendResponse: LightWalletServiceResponse) async throws -> PendingTransactionEntity {
var pendingTx = transaction
pendingTx.submitAttempts += 1
let error = sendResponse.errorCode < 0
@ -256,7 +256,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
return pendingTx
}
func delete(pendingTransaction: PendingTransactionEntity) throws {
func delete(pendingTransaction: PendingTransactionEntity) async throws {
do {
try repository.delete(pendingTransaction)
} catch {

View File

@ -19,7 +19,7 @@ protocol OutboundTransactionManager {
recipient: PendingTransactionRecipient,
memo: MemoBytes?,
from accountIndex: Int
) throws -> PendingTransactionEntity
) async throws -> PendingTransactionEntity
func encodeShieldingTransaction(
spendingKey: UnifiedSpendingKey,
@ -39,21 +39,21 @@ protocol OutboundTransactionManager {
func applyMinedHeight(
pendingTransaction: PendingTransactionEntity,
minedHeight: BlockHeight
) throws -> PendingTransactionEntity
) async throws -> PendingTransactionEntity
/**
Attempts to Cancel a transaction. Returns true if successful
*/
func cancel(pendingTransaction: PendingTransactionEntity) -> Bool
func cancel(pendingTransaction: PendingTransactionEntity) async -> Bool
func allPendingTransactions() throws -> [PendingTransactionEntity]
func allPendingTransactions() async throws -> [PendingTransactionEntity]
func handleReorg(at blockHeight: BlockHeight) throws
func handleReorg(at blockHeight: BlockHeight) async throws
/**
Deletes a pending transaction from the database
*/
func delete(pendingTransaction: PendingTransactionEntity) throws
func delete(pendingTransaction: PendingTransactionEntity) async throws
func closeDBConnection()
}

View File

@ -58,7 +58,7 @@ class WalletTransactionEncoder: TransactionEncoder {
memoBytes: MemoBytes?,
from accountIndex: Int
) async throws -> ZcashTransaction.Overview {
let txId = try createSpend(
let txId = try await createSpend(
spendingKey: spendingKey,
zatoshi: zatoshi,
to: address,
@ -80,12 +80,12 @@ class WalletTransactionEncoder: TransactionEncoder {
to address: String,
memoBytes: MemoBytes?,
from accountIndex: Int
) throws -> Int {
) async throws -> Int {
guard ensureParams(spend: self.spendParamsURL, output: self.outputParamsURL) else {
throw TransactionEncoderError.missingParams
}
let txId = rustBackend.createToAddress(
let txId = await rustBackend.createToAddress(
dbData: self.dataDbURL,
usk: spendingKey,
to: address,
@ -109,7 +109,7 @@ class WalletTransactionEncoder: TransactionEncoder {
memoBytes: MemoBytes?,
from accountIndex: Int
) async throws -> ZcashTransaction.Overview {
let txId = try createShieldingSpend(
let txId = try await createShieldingSpend(
spendingKey: spendingKey,
shieldingThreshold: shieldingThreshold,
memo: memoBytes,
@ -129,12 +129,12 @@ class WalletTransactionEncoder: TransactionEncoder {
shieldingThreshold: Zatoshi,
memo: MemoBytes?,
accountIndex: Int
) throws -> Int {
) async throws -> Int {
guard ensureParams(spend: self.spendParamsURL, output: self.outputParamsURL) else {
throw TransactionEncoderError.missingParams
}
let txId = rustBackend.shieldFunds(
let txId = await rustBackend.shieldFunds(
dbData: self.dataDbURL,
usk: spendingKey,
memo: memo,

View File

@ -25,24 +25,23 @@ class AdvancedReOrgTests: XCTestCase {
let network = DarksideWalletDNetwork()
var cancellables: [AnyCancellable] = []
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = TestCoordinator.make(
walletBirthday: birthday + 50, // don't use an exact birthday, users never do.
network: network
)
override func setUp() async throws {
try await super.setUp()
// don't use an exact birthday, users never do.
self.coordinator = try await TestCoordinator(walletBirthday: birthday + 50, network: network)
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
cancellables = []
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
cancellables = []
}
func handleReorg(event: CompactBlockProcessor.Event) {
@ -90,8 +89,8 @@ class AdvancedReOrgTests: XCTestCase {
try await coordinator.sync(
completion: { synchro in
synchronizer = synchro
initialVerifiedBalance = synchro.initializer.getVerifiedBalance()
initialTotalBalance = synchro.initializer.getBalance()
initialVerifiedBalance = try await synchro.getShieldedVerifiedBalance()
initialTotalBalance = try await synchro.getShieldedBalance()
preTxExpectation.fulfill()
shouldContinue = true
},
@ -125,8 +124,8 @@ class AdvancedReOrgTests: XCTestCase {
try await coordinator.sync(
completion: { synchro in
synchronizer = synchro
receivedTxVerifiedBalance = synchro.initializer.getVerifiedBalance()
receivedTxTotalBalance = synchro.initializer.getBalance()
receivedTxVerifiedBalance = try await synchro.getShieldedVerifiedBalance()
receivedTxTotalBalance = try await synchro.getShieldedBalance()
receivedTxExpectation.fulfill()
}, error: self.handleError
)
@ -192,8 +191,8 @@ class AdvancedReOrgTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
afterReorgTxTotalBalance = synchronizer.initializer.getBalance()
afterReorgTxVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
afterReorgTxTotalBalance = try await synchronizer.getShieldedBalance()
afterReorgTxVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
reorgSyncexpectation.fulfill()
},
error: self.handleError
@ -228,8 +227,8 @@ class AdvancedReOrgTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
finalReorgTxTotalBalance = synchronizer.initializer.getBalance()
finalReorgTxVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
finalReorgTxTotalBalance = try await synchronizer.getShieldedBalance()
finalReorgTxVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
finalsyncExpectation.fulfill()
},
error: self.handleError
@ -294,7 +293,7 @@ class AdvancedReOrgTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
initialTotalBalance = synchronizer.initializer.getBalance()
initialTotalBalance = try await synchronizer.getShieldedBalance()
preTxExpectation.fulfill()
},
error: self.handleError
@ -365,7 +364,7 @@ class AdvancedReOrgTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
let pMinedHeight = synchronizer.pendingTransactions.first?.minedHeight
let pMinedHeight = await synchronizer.pendingTransactions.first?.minedHeight
XCTAssertEqual(pMinedHeight, sentTxHeight)
sentTxSyncExpectation.fulfill()
},
@ -399,10 +398,11 @@ class AdvancedReOrgTests: XCTestCase {
/*
11. verify that the sent tx is mined and balance is correct
*/
let pMinedHeight = synchronizer.pendingTransactions.first?.minedHeight
let pMinedHeight = await synchronizer.pendingTransactions.first?.minedHeight
XCTAssertEqual(pMinedHeight, sentTxHeight)
// fee change on this branch
XCTAssertEqual(initialTotalBalance - sendAmount - Zatoshi(1000), synchronizer.initializer.getBalance())
let expectedBalance = try await synchronizer.getShieldedBalance()
XCTAssertEqual(initialTotalBalance - sendAmount - Zatoshi(1000), expectedBalance)
afterReOrgExpectation.fulfill()
},
error: self.handleError
@ -435,12 +435,14 @@ class AdvancedReOrgTests: XCTestCase {
}
wait(for: [lastSyncExpectation], timeout: 5)
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 0)
XCTAssertEqual(initialTotalBalance - pendingTx.value - Zatoshi(1000), coordinator.synchronizer.initializer.getVerifiedBalance())
let resultingBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
XCTAssertEqual(resultingBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedPendingTransactionsCount = await coordinator.synchronizer.pendingTransactions.count
XCTAssertEqual(expectedPendingTransactionsCount, 0)
XCTAssertEqual(initialTotalBalance - pendingTx.value - Zatoshi(1000), expectedVerifiedBalance)
let resultingBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(resultingBalance, expectedVerifiedBalance)
}
func testIncomingTransactionIndexChange() async throws {
@ -457,8 +459,8 @@ class AdvancedReOrgTests: XCTestCase {
var preReorgVerifiedBalance = Zatoshi.zero
try await coordinator.sync(
completion: { synchronizer in
preReorgTotalBalance = synchronizer.initializer.getBalance()
preReorgVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
preReorgTotalBalance = try await synchronizer.getShieldedBalance()
preReorgVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
firstSyncExpectation.fulfill()
},
error: self.handleError
@ -480,8 +482,8 @@ class AdvancedReOrgTests: XCTestCase {
var postReorgVerifiedBalance = Zatoshi.zero
try await coordinator.sync(
completion: { synchronizer in
postReorgTotalBalance = synchronizer.initializer.getBalance()
postReorgVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
postReorgTotalBalance = try await synchronizer.getShieldedBalance()
postReorgVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
afterReorgSync.fulfill()
},
error: self.handleError
@ -504,8 +506,8 @@ class AdvancedReOrgTests: XCTestCase {
try await coordinator.sync(
completion: { synchronizer in
initialBalance = synchronizer.initializer.getBalance()
initialVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
initialBalance = try await synchronizer.getShieldedBalance()
initialVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
expectation.fulfill()
},
error: self.handleError
@ -523,8 +525,8 @@ class AdvancedReOrgTests: XCTestCase {
try await coordinator.sync(
completion: { synchronizer in
afterTxBalance = synchronizer.initializer.getBalance()
afterTxVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
afterTxBalance = try await synchronizer.getShieldedBalance()
afterTxVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
let receivedTransactions = await synchronizer.receivedTransactions
XCTAssertNotNil(
receivedTransactions.first { $0.minedHeight == receivedTxHeight },
@ -553,8 +555,8 @@ class AdvancedReOrgTests: XCTestCase {
try await coordinator.sync(
completion: { synchronizer in
afterReOrgBalance = synchronizer.initializer.getBalance()
afterReOrgVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
afterReOrgBalance = try await synchronizer.getShieldedBalance()
afterReOrgVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
let receivedTransactions = await synchronizer.receivedTransactions
XCTAssertNil(
receivedTransactions.first { $0.minedHeight == receivedTxHeight },
@ -609,8 +611,8 @@ class AdvancedReOrgTests: XCTestCase {
/*
1a. save balances
*/
initialBalance = coordinator.synchronizer.initializer.getBalance()
initialVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
initialBalance = try await coordinator.synchronizer.getShieldedBalance()
initialVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
incomingTx = await coordinator.synchronizer.receivedTransactions.first(where: { $0.minedHeight == incomingTxHeight })
let txRawData = incomingTx.raw ?? Data()
@ -659,8 +661,10 @@ class AdvancedReOrgTests: XCTestCase {
/*
7. check that balances still match
*/
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), initialVerifiedBalance)
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), initialBalance)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedVerifiedBalance, initialVerifiedBalance)
XCTAssertEqual(expectedBalance, initialBalance)
wait(for: [lastSyncExpectation], timeout: 5)
}
@ -679,8 +683,8 @@ class AdvancedReOrgTests: XCTestCase {
try await coordinator.sync(
completion: { synchronizer in
initialBalance = synchronizer.initializer.getBalance()
initialVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
initialBalance = try await synchronizer.getShieldedBalance()
initialVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
firstSyncExpectation.fulfill()
},
error: self.handleError
@ -703,9 +707,11 @@ class AdvancedReOrgTests: XCTestCase {
)
wait(for: [lastSyncExpectation], timeout: 5)
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), initialBalance)
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), initialVerifiedBalance)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, initialBalance)
XCTAssertEqual(expectedVerifiedBalance, initialVerifiedBalance)
}
/// A Re Org occurs and changes the height of an outbound transaction
@ -760,7 +766,7 @@ class AdvancedReOrgTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 5)
sleep(1)
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
let sendExpectation = XCTestExpectation(description: "send expectation")
var pendingEntity: PendingTransactionEntity?
@ -831,9 +837,10 @@ class AdvancedReOrgTests: XCTestCase {
}
wait(for: [secondSyncExpectation], timeout: 5)
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 1)
guard let afterStagePendingTx = coordinator.synchronizer.pendingTransactions.first else {
var pendingTransactionsCount = await coordinator.synchronizer.pendingTransactions.count
XCTAssertEqual(pendingTransactionsCount, 1)
guard let afterStagePendingTx = await coordinator.synchronizer.pendingTransactions.first else {
return
}
@ -880,7 +887,7 @@ class AdvancedReOrgTests: XCTestCase {
/*
10. verify that there's a pending transaction with -1 mined height
*/
guard let newPendingTx = coordinator.synchronizer.pendingTransactions.first else {
guard let newPendingTx = await coordinator.synchronizer.pendingTransactions.first else {
XCTFail("No pending transaction")
try await coordinator.stop()
return
@ -915,8 +922,9 @@ class AdvancedReOrgTests: XCTestCase {
/*
12. verify that there's a pending transaction with a mined height of sentTxHeight + 2
*/
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 1)
guard let newlyPendingTx = try coordinator.synchronizer.allPendingTransactions().first else {
pendingTransactionsCount = await coordinator.synchronizer.pendingTransactions.count
XCTAssertEqual(pendingTransactionsCount, 1)
guard let newlyPendingTx = try await coordinator.synchronizer.allPendingTransactions().first else {
XCTFail("no pending transaction")
try await coordinator.stop()
return
@ -952,7 +960,8 @@ class AdvancedReOrgTests: XCTestCase {
/*
15. verify that there's no pending transaction and that the tx is displayed on the sentTransactions collection
*/
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 0)
let pendingTranscationsCount = await coordinator.synchronizer.pendingTransactions.count
XCTAssertEqual(pendingTranscationsCount, 0)
let sentTransactions = await coordinator.synchronizer.sentTransactions
.first(
@ -965,15 +974,18 @@ class AdvancedReOrgTests: XCTestCase {
sentTransactions,
"Sent Tx is not on sent transactions"
)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(
initialTotalBalance - newlyPendingTx.value - Zatoshi(1000),
coordinator.synchronizer.initializer.getBalance()
expectedBalance
)
XCTAssertEqual(
initialTotalBalance - newlyPendingTx.value - Zatoshi(1000),
coordinator.synchronizer.initializer.getVerifiedBalance()
expectedVerifiedBalance
)
}
@ -1008,8 +1020,8 @@ class AdvancedReOrgTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 5)
let initialBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let initialBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
guard let initialTxHeight = try await coordinator.synchronizer.allReceivedTransactions().first?.minedHeight else {
XCTFail("no incoming transaction found!")
return
@ -1037,8 +1049,11 @@ class AdvancedReOrgTests: XCTestCase {
XCTFail("no incoming transaction found after re org!")
return
}
XCTAssertEqual(initialVerifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(initialBalance, coordinator.synchronizer.initializer.getBalance())
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance)
XCTAssertEqual(initialBalance, expectedBalance)
XCTAssert(afterReOrgTxHeight > initialTxHeight)
}
@ -1078,8 +1093,8 @@ class AdvancedReOrgTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 5)
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
try coordinator.applyStaged(blockheight: reorgHeight)
sleep(1)
@ -1115,9 +1130,11 @@ class AdvancedReOrgTests: XCTestCase {
)
wait(for: [afterReorgSyncExpectation], timeout: 5)
XCTAssertEqual(initialVerifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(initialTotalBalance, coordinator.synchronizer.initializer.getBalance())
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance)
XCTAssertEqual(initialTotalBalance, expectedBalance)
}
/// Transaction was included in a block, and then is not included in a block after a reorg, and expires.
@ -1164,7 +1181,7 @@ class AdvancedReOrgTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 10)
sleep(1)
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
let sendExpectation = XCTestExpectation(description: "send expectation")
var pendingEntity: PendingTransactionEntity?
@ -1256,7 +1273,7 @@ class AdvancedReOrgTests: XCTestCase {
wait(for: [reorgExpectation, reorgSyncExpectation], timeout: 5)
guard let pendingTx = coordinator.synchronizer.pendingTransactions.first else {
guard let pendingTx = await coordinator.synchronizer.pendingTransactions.first else {
XCTFail("no pending transaction after reorg sync")
return
}
@ -1282,8 +1299,9 @@ class AdvancedReOrgTests: XCTestCase {
}
wait(for: [lastSyncExpectation], timeout: 5)
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), initialTotalBalance)
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, initialTotalBalance)
}
func testLongSync() async throws {

View File

@ -23,25 +23,22 @@ class BalanceTests: XCTestCase {
var coordinator: TestCoordinator!
var cancellables: [AnyCancellable] = []
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = TestCoordinator.make(
walletBirthday: self.birthday,
network: self.network
)
override func setUp() async throws {
try await super.setUp()
self.coordinator = try await TestCoordinator(walletBirthday: birthday, network: network)
try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
cancellables = []
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
cancellables = []
}
/**
@ -77,8 +74,8 @@ class BalanceTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 12)
// 2 check that there are no unconfirmed funds
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
@ -142,7 +139,7 @@ class BalanceTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
let pendingEntity = synchronizer.pendingTransactions.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
let pendingEntity = await synchronizer.pendingTransactions.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
XCTAssertNotNil(pendingEntity, "pending transaction should have been mined by now")
XCTAssertTrue(pendingEntity?.isMined ?? false)
XCTAssertEqual(pendingEntity?.minedHeight, sentTxHeight)
@ -183,13 +180,15 @@ class BalanceTests: XCTestCase {
wait(for: [confirmExpectation], timeout: 5)
let confirmedPending = try coordinator.synchronizer.allPendingTransactions()
let confirmedPending = try await coordinator.synchronizer.allPendingTransactions()
.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), .zero)
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), .zero)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, .zero)
XCTAssertEqual(expectedVerifiedBalance, .zero)
}
/**
@ -225,8 +224,8 @@ class BalanceTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 12)
// 2 check that there are no unconfirmed funds
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
@ -289,7 +288,7 @@ class BalanceTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
let pendingEntity = synchronizer.pendingTransactions.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
let pendingEntity = await synchronizer.pendingTransactions.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
XCTAssertNotNil(pendingEntity, "pending transaction should have been mined by now")
XCTAssertTrue(pendingEntity?.isMined ?? false)
XCTAssertEqual(pendingEntity?.minedHeight, sentTxHeight)
@ -330,14 +329,16 @@ class BalanceTests: XCTestCase {
wait(for: [confirmExpectation], timeout: 5)
let confirmedPending = try coordinator.synchronizer
let confirmedPending = try await coordinator.synchronizer
.allPendingTransactions()
.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), Zatoshi(1))
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), Zatoshi(1))
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, Zatoshi(1))
XCTAssertEqual(expectedVerifiedBalance, Zatoshi(1))
}
/**
@ -373,8 +374,8 @@ class BalanceTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 12)
// 2 check that there are no unconfirmed funds
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
@ -437,7 +438,7 @@ class BalanceTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
let pendingEntity = synchronizer.pendingTransactions.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
let pendingEntity = await synchronizer.pendingTransactions.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
XCTAssertNotNil(pendingEntity, "pending transaction should have been mined by now")
XCTAssertTrue(pendingEntity?.isMined ?? false)
XCTAssertEqual(pendingEntity?.minedHeight, sentTxHeight)
@ -478,14 +479,16 @@ class BalanceTests: XCTestCase {
wait(for: [confirmExpectation], timeout: 5)
let confirmedPending = try coordinator.synchronizer
let confirmedPending = try await coordinator.synchronizer
.allPendingTransactions()
.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), Zatoshi(100000))
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), Zatoshi(100000))
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, Zatoshi(100000))
XCTAssertEqual(expectedVerifiedBalance, Zatoshi(100000))
}
/**
@ -527,7 +530,7 @@ class BalanceTests: XCTestCase {
let spendingKey = coordinator.spendingKey
let presendVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let presendVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
/*
there's more zatoshi to send than network fee
@ -546,11 +549,13 @@ class BalanceTests: XCTestCase {
self.sentTransactionExpectation.fulfill()
} catch {
// balance should be the same as before sending if transaction failed
XCTAssertEqual(self.coordinator.synchronizer.initializer.getVerifiedBalance(), presendVerifiedBalance)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
XCTAssertEqual(expectedVerifiedBalance, presendVerifiedBalance)
XCTFail("sendToAddress failed: \(error)")
}
XCTAssertTrue(coordinator.synchronizer.initializer.getVerifiedBalance() > .zero)
var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
XCTAssertTrue(expectedVerifiedBalance > .zero)
wait(for: [sentTransactionExpectation], timeout: 12)
// sync and mine
@ -581,15 +586,18 @@ class BalanceTests: XCTestCase {
}
wait(for: [mineExpectation], timeout: 5)
expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(
presendVerifiedBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),
coordinator.synchronizer.initializer.getBalance()
expectedBalance
)
XCTAssertEqual(
presendVerifiedBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),
coordinator.synchronizer.initializer.getVerifiedBalance()
expectedVerifiedBalance
)
guard let transaction = pendingTx else {
@ -655,7 +663,7 @@ class BalanceTests: XCTestCase {
spentNoteValue: Zatoshi(Int64(sentNote.value)),
changeValue: Zatoshi(Int64(receivedNote.value)),
sentAmount: self.sendAmount,
currentVerifiedBalance: self.coordinator.synchronizer.initializer.getVerifiedBalance()
currentVerifiedBalance: try await coordinator.synchronizer.getShieldedVerifiedBalance()
)
}
@ -697,7 +705,7 @@ class BalanceTests: XCTestCase {
let spendingKey = coordinator.spendingKey
let presendBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let presendBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
// there's more zatoshi to send than network fee
XCTAssertTrue(presendBalance >= network.constants.defaultFee(for: defaultLatestHeight) + sendAmount)
@ -718,12 +726,14 @@ class BalanceTests: XCTestCase {
testError = error
XCTFail("sendToAddress failed: \(error)")
}
XCTAssertTrue(coordinator.synchronizer.initializer.getVerifiedBalance() > .zero)
var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
XCTAssertTrue(expectedVerifiedBalance > .zero)
wait(for: [sentTransactionExpectation], timeout: 12)
expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
if let testError {
XCTAssertEqual(self.coordinator.synchronizer.initializer.getVerifiedBalance(), presendBalance)
XCTAssertEqual(expectedVerifiedBalance, presendBalance)
XCTFail("error: \(testError)")
return
}
@ -733,9 +743,10 @@ class BalanceTests: XCTestCase {
}
XCTAssertEqual(transaction.value, self.sendAmount)
var expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(
self.coordinator.synchronizer.initializer.getBalance(),
expectedBalance,
presendBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight)
)
@ -766,10 +777,11 @@ class BalanceTests: XCTestCase {
}
wait(for: [mineExpectation], timeout: 5)
expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(
presendBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),
coordinator.synchronizer.initializer.getBalance()
expectedBalance
)
}
@ -803,8 +815,9 @@ class BalanceTests: XCTestCase {
wait(for: [syncedExpectation], timeout: 5)
let clearedTransactions = await coordinator.synchronizer.clearedTransactions
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(clearedTransactions.count, 2)
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), Zatoshi(200000))
XCTAssertEqual(expectedBalance, Zatoshi(200000))
}
/**
@ -856,8 +869,8 @@ class BalanceTests: XCTestCase {
wait(for: [syncedExpectation], timeout: 6)
let previousVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let previousTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let previousVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let previousTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
let spendingKey = coordinator.spendingKey
@ -967,11 +980,11 @@ class BalanceTests: XCTestCase {
spentNoteValue: Zatoshi(Int64(sentNote.value)),
changeValue: Zatoshi(Int64(receivedNote.value)),
sentAmount: self.sendAmount,
currentVerifiedBalance: synchronizer.initializer.getVerifiedBalance()
currentVerifiedBalance: try await synchronizer.getShieldedVerifiedBalance()
)
self.totalBalanceValidation(
totalBalance: synchronizer.initializer.getBalance(),
totalBalance: try await synchronizer.getShieldedBalance(),
previousTotalbalance: previousTotalBalance,
sentAmount: self.sendAmount
)
@ -1030,8 +1043,8 @@ class BalanceTests: XCTestCase {
let spendingKey = coordinator.spendingKey
let previousVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let previousTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let previousVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let previousTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
let sendExpectation = XCTestExpectation(description: "send expectation")
var pendingTx: PendingTransactionEntity?
do {
@ -1045,8 +1058,10 @@ class BalanceTests: XCTestCase {
sendExpectation.fulfill()
} catch {
// balance should be the same as before sending if transaction failed
XCTAssertEqual(self.coordinator.synchronizer.initializer.getVerifiedBalance(), previousVerifiedBalance)
XCTAssertEqual(self.coordinator.synchronizer.initializer.getBalance(), previousTotalBalance)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedVerifiedBalance, previousVerifiedBalance)
XCTAssertEqual(expectedBalance, previousTotalBalance)
XCTFail("sendToAddress failed: \(error)")
}
@ -1075,16 +1090,18 @@ class BalanceTests: XCTestCase {
}
wait(for: [expirationSyncExpectation], timeout: 5)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
/*
Verified Balance is equal to verified balance previously shown before sending the expired transaction
*/
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), previousVerifiedBalance)
XCTAssertEqual(expectedVerifiedBalance, previousVerifiedBalance)
/*
Total Balance is equal to total balance previously shown before sending the expired transaction
*/
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), previousTotalBalance)
XCTAssertEqual(expectedBalance, previousTotalBalance)
let pendingRepo = PendingTransactionSQLDAO(
dbProvider: SimpleConnectionProvider(
@ -1168,7 +1185,7 @@ class SDKSynchonizerListener {
}
func unsubscribe() {
NotificationCenter.default.removeObserver(self)
cancellables = []
}
func txFound(_ txs: [ZcashTransaction.Overview]) {

View File

@ -25,8 +25,8 @@ class BlockDownloaderTests: XCTestCase {
var storage: CompactBlockRepository!
var network = DarksideWalletDNetwork()
override func setUpWithError() throws {
try super.setUpWithError()
override func setUp() async throws {
try await super.setUp()
service = LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.default).make()
storage = FSCompactBlockRepository(
@ -40,7 +40,7 @@ class BlockDownloaderTests: XCTestCase {
contentProvider: DirectoryListingProviders.defaultSorted,
logger: logger
)
try storage.create()
try await storage.create()
downloader = BlockDownloaderServiceImpl(service: service, storage: storage)
darksideWalletService = DarksideWalletService(endpoint: LightWalletEndpointBuilder.default, service: service as! LightWalletGRPCService)

View File

@ -23,25 +23,25 @@ class DarksideSanityCheckTests: XCTestCase {
var reorgExpectation = XCTestExpectation(description: "reorg")
let branchID = "2bb40e60"
let chainName = "main"
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = TestCoordinator.make(
walletBirthday: self.birthday,
network: self.network
)
override func setUp() async throws {
try await super.setUp()
self.coordinator = try await TestCoordinator(walletBirthday: birthday, network: network)
try self.coordinator.reset(saplingActivation: self.birthday, branchID: self.branchID, chainName: self.chainName)
try self.coordinator.resetBlocks(dataset: .default)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
}
func testDarkside() async throws {

View File

@ -24,25 +24,24 @@ final class InternalStateConsistencyTests: XCTestCase {
let network = DarksideWalletDNetwork()
var sdkSynchronizerSyncStatusHandler: SDKSynchronizerSyncStatusHandler! = SDKSynchronizerSyncStatusHandler()
override func setUpWithError() throws {
try super.setUpWithError()
override func setUp() async throws {
try await super.setUp()
self.coordinator = TestCoordinator.make(
walletBirthday: birthday + 50, // don't use an exact birthday, users never do.
network: network
)
// don't use an exact birthday, users never do.
self.coordinator = try await TestCoordinator(walletBirthday: birthday + 50, network: network)
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
sdkSynchronizerSyncStatusHandler = nil
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
sdkSynchronizerSyncStatusHandler = nil
}
func testInternalStateIsConsistentWhenMigrating() async throws {

View File

@ -21,25 +21,23 @@ class PendingTransactionUpdatesTest: XCTestCase {
let branchID = "2bb40e60"
let chainName = "main"
let network = DarksideWalletDNetwork()
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = TestCoordinator.make(
walletBirthday: self.birthday,
network: self.network
)
override func setUp() async throws {
try await super.setUp()
self.coordinator = try await TestCoordinator(walletBirthday: birthday, network: network)
try self.coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
}
func testPendingTransactionMinedHeightUpdated() async throws {
@ -161,9 +159,10 @@ class PendingTransactionUpdatesTest: XCTestCase {
}
wait(for: [secondSyncExpectation], timeout: 5)
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 1)
guard let afterStagePendingTx = coordinator.synchronizer.pendingTransactions.first else {
let pendingTransactionsCount = await coordinator.synchronizer.pendingTransactions.count
XCTAssertEqual(pendingTransactionsCount, 1)
guard let afterStagePendingTx = await coordinator.synchronizer.pendingTransactions.first else {
return
}
@ -205,9 +204,7 @@ class PendingTransactionUpdatesTest: XCTestCase {
}
wait(for: [syncToConfirmExpectation], timeout: 6)
var supposedlyPendingUnexistingTransaction: PendingTransactionEntity?
XCTAssertNoThrow(try { supposedlyPendingUnexistingTransaction = try coordinator.synchronizer.allPendingTransactions().first }())
let supposedlyPendingUnexistingTransaction = try await coordinator.synchronizer.allPendingTransactions().first
XCTAssertNil(supposedlyPendingUnexistingTransaction)
}

View File

@ -41,10 +41,10 @@ class ReOrgTests: XCTestCase {
var expectedRewindHeight: BlockHeight = 665188
var cancellables: [AnyCancellable] = []
override func setUpWithError() throws {
try super.setUpWithError()
override func setUp() async throws {
try await super.setUp()
self.coordinator = TestCoordinator.make(walletBirthday: self.birthday, network: self.network)
self.coordinator = try await TestCoordinator(walletBirthday: self.birthday, network: self.network)
try self.coordinator.reset(saplingActivation: self.birthday, branchID: self.branchID, chainName: self.chainName)
@ -57,17 +57,19 @@ class ReOrgTests: XCTestCase {
}
}
XCTestCase.wait { await self.coordinator.synchronizer.blockProcessor.updateEventClosure(identifier: "tests", closure: eventClosure) }
await self.coordinator.synchronizer.blockProcessor.updateEventClosure(identifier: "tests", closure: eventClosure)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
cancellables = []
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
cancellables = []
try await coordinator.stop()
}
func handleReOrgNotification(event: CompactBlockProcessor.Event) {

View File

@ -27,25 +27,23 @@ class RewindRescanTests: XCTestCase {
var reorgExpectation = XCTestExpectation(description: "reorg")
var network = ZcashNetworkBuilder.network(for: .mainnet)
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = TestCoordinator.make(
walletBirthday: self.birthday,
network: self.network
)
override func setUp() async throws {
try await super.setUp()
self.coordinator = try await TestCoordinator(walletBirthday: birthday, network: network)
try self.coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
cancellables = []
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
cancellables = []
}
func handleError(_ error: Error?) {
@ -62,8 +60,8 @@ class RewindRescanTests: XCTestCase {
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
try coordinator.applyStaged(blockheight: defaultLatestHeight + 50)
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
sleep(1)
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
@ -79,8 +77,8 @@ class RewindRescanTests: XCTestCase {
}
wait(for: [firstSyncExpectation], timeout: 12)
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
// 2 check that there are no unconfirmed funds
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
@ -114,8 +112,10 @@ class RewindRescanTests: XCTestCase {
XCTAssertEqual(lastScannedHeight, self.birthday)
// check that the balance is cleared
XCTAssertEqual(initialVerifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(initialTotalBalance, coordinator.synchronizer.initializer.getBalance())
var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
var expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance)
XCTAssertEqual(initialTotalBalance, expectedBalance)
let secondScanExpectation = XCTestExpectation(description: "rescan")
do {
@ -132,8 +132,10 @@ class RewindRescanTests: XCTestCase {
wait(for: [secondScanExpectation], timeout: 12)
// verify that the balance still adds up
XCTAssertEqual(verifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(totalBalance, coordinator.synchronizer.initializer.getBalance())
expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(verifiedBalance, expectedVerifiedBalance)
XCTAssertEqual(totalBalance, expectedBalance)
}
// FIXME [#789]: Fix test
@ -148,7 +150,7 @@ class RewindRescanTests: XCTestCase {
let newChaintTip = defaultLatestHeight + 10000
try coordinator.applyStaged(blockheight: newChaintTip)
sleep(3)
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
do {
@ -163,15 +165,15 @@ class RewindRescanTests: XCTestCase {
}
wait(for: [firstSyncExpectation], timeout: 20)
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
// 2 check that there are no unconfirmed funds
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
// rewind to birthday
let targetHeight: BlockHeight = newChaintTip - 8000
let rewindHeight = ZcashRustBackend.getNearestRewindHeight(
let rewindHeight = await ZcashRustBackend.getNearestRewindHeight(
dbData: coordinator.databases.dataDB,
height: Int32(targetHeight),
networkType: network.networkType
@ -206,7 +208,8 @@ class RewindRescanTests: XCTestCase {
}
// check that the balance is cleared
XCTAssertEqual(initialVerifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance)
let secondScanExpectation = XCTestExpectation(description: "rescan")
@ -224,8 +227,10 @@ class RewindRescanTests: XCTestCase {
wait(for: [secondScanExpectation], timeout: 20)
// verify that the balance still adds up
XCTAssertEqual(verifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(totalBalance, coordinator.synchronizer.initializer.getBalance())
expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(verifiedBalance, expectedVerifiedBalance)
XCTAssertEqual(totalBalance, expectedBalance)
// try to spend the funds
let sendExpectation = XCTestExpectation(description: "after rewind expectation")
@ -262,8 +267,8 @@ class RewindRescanTests: XCTestCase {
)
wait(for: [firstSyncExpectation], timeout: 12)
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
// 2 check that there are no unconfirmed funds
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
@ -314,8 +319,10 @@ class RewindRescanTests: XCTestCase {
wait(for: [secondScanExpectation], timeout: 12)
// verify that the balance still adds up
XCTAssertEqual(verifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(totalBalance, coordinator.synchronizer.initializer.getBalance())
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(verifiedBalance, expectedVerifiedBalance)
XCTAssertEqual(totalBalance, expectedBalance)
}
// FIXME [#791]: Fix test
@ -348,8 +355,8 @@ class RewindRescanTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 12)
// 2 check that there are no unconfirmed funds
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
@ -412,7 +419,7 @@ class RewindRescanTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
let pendingTransaction = synchronizer.pendingTransactions
let pendingTransaction = await synchronizer.pendingTransactions
.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
XCTAssertNotNil(pendingTransaction, "pending transaction should have been mined by now")
XCTAssertTrue(pendingTransaction?.isMined ?? false)
@ -457,7 +464,7 @@ class RewindRescanTests: XCTestCase {
wait(for: [rewindExpectation], timeout: 2)
guard
let pendingEntity = try coordinator.synchronizer.allPendingTransactions()
let pendingEntity = try await coordinator.synchronizer.allPendingTransactions()
.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
else {
XCTFail("sent pending transaction not found after rewind")
@ -493,11 +500,14 @@ class RewindRescanTests: XCTestCase {
wait(for: [confirmExpectation], timeout: 10)
let confirmedPending = try coordinator.synchronizer.allPendingTransactions()
let confirmedPending = try await coordinator.synchronizer.allPendingTransactions()
.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), .zero)
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), .zero)
let expectedVerifiedbalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, .zero)
XCTAssertEqual(expectedVerifiedbalance, .zero)
}
}

View File

@ -22,24 +22,23 @@ class ShieldFundsTests: XCTestCase {
let chainName = "main"
let network = DarksideWalletDNetwork()
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = TestCoordinator.make(
walletBirthday: birthday,
network: network
)
override func setUp() async throws {
try await super.setUp()
self.coordinator = try await TestCoordinator(walletBirthday: birthday, network: network)
try coordinator.reset(saplingActivation: birthday, branchID: self.branchID, chainName: self.chainName)
try coordinator.service.clearAddedUTXOs()
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
}
/// Tests shielding funds from a UTXO
@ -112,8 +111,8 @@ class ShieldFundsTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
initialVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
initialTotalBalance = synchronizer.initializer.getBalance()
initialVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
initialTotalBalance = try await synchronizer.getShieldedBalance()
preTxExpectation.fulfill()
shouldContinue = true
},
@ -237,7 +236,8 @@ class ShieldFundsTests: XCTestCase {
XCTAssertEqual(postShieldingBalance.verified, Zatoshi(10000))
// FIXME: [#720] this should be zero, https://github.com/zcash/ZcashLightClientKit/issues/720
XCTAssertEqual(postShieldingBalance.total, Zatoshi(10000))
XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), .zero)
var expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, .zero)
// 10. clear the UTXO from darksidewalletd's cache
try coordinator.service.clearAddedUTXOs()
@ -290,7 +290,8 @@ class ShieldFundsTests: XCTestCase {
XCTAssertEqual(postShieldingShieldedBalance.verified, .zero)
XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), Zatoshi(9000))
expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, Zatoshi(9000))
// 14. proceed confirm the shielded funds by staging ten more blocks
try coordinator.service.applyStaged(nextLatestHeight: utxoHeight + 10 + 1 + 10)
@ -325,7 +326,8 @@ class ShieldFundsTests: XCTestCase {
XCTAssertNotNil(clearedTransaction)
XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), Zatoshi(9000))
expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, Zatoshi(9000))
let postShieldingConfirmationShieldedBalance = try await coordinator.synchronizer.getTransparentBalance(accountIndex: 0)
XCTAssertEqual(postShieldingConfirmationShieldedBalance.total, .zero)
XCTAssertEqual(postShieldingConfirmationShieldedBalance.verified, .zero)

View File

@ -27,26 +27,24 @@ class SychronizerDarksideTests: XCTestCase {
var foundTransactions: [ZcashTransaction.Overview] = []
var cancellables: [AnyCancellable] = []
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = TestCoordinator.make(
walletBirthday: self.birthday,
network: self.network
)
override func setUp() async throws {
try await super.setUp()
self.coordinator = try await TestCoordinator(walletBirthday: birthday, network: network)
try self.coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
foundTransactions = []
cancellables = []
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
foundTransactions = []
cancellables = []
}
func testFoundTransactions() async throws {

View File

@ -24,13 +24,11 @@ final class SynchronizerTests: XCTestCase {
var cancellables: [AnyCancellable] = []
var sdkSynchronizerSyncStatusHandler: SDKSynchronizerSyncStatusHandler! = SDKSynchronizerSyncStatusHandler()
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = TestCoordinator.make(
walletBirthday: self.birthday + 50, // don't use an exact birthday, users never do.
network: self.network
)
override func setUp() async throws {
try await super.setUp()
// don't use an exact birthday, users never do.
self.coordinator = try await TestCoordinator(walletBirthday: birthday + 50, network: network)
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
let eventClosure: CompactBlockProcessor.EventClosure = { [weak self] event in
@ -40,19 +38,20 @@ final class SynchronizerTests: XCTestCase {
}
}
XCTestCase.wait { await self.coordinator.synchronizer.blockProcessor.updateEventClosure(identifier: "tests", closure: eventClosure) }
await self.coordinator.synchronizer.blockProcessor.updateEventClosure(identifier: "tests", closure: eventClosure)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
sdkSynchronizerSyncStatusHandler = nil
cancellables = []
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
sdkSynchronizerSyncStatusHandler = nil
cancellables = []
}
func handleReorg(event: CompactBlockProcessor.Event) {
@ -264,8 +263,8 @@ final class SynchronizerTests: XCTestCase {
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
try coordinator.applyStaged(blockheight: defaultLatestHeight)
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let initialTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
sleep(1)
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
@ -306,8 +305,8 @@ final class SynchronizerTests: XCTestCase {
wait(for: [waitExpectation], timeout: 1)
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
// 2 check that there are no unconfirmed funds
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
@ -338,7 +337,9 @@ final class SynchronizerTests: XCTestCase {
XCTAssertEqual(lastScannedHeight, self.birthday)
// check that the balance is cleared
XCTAssertEqual(initialVerifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(initialTotalBalance, coordinator.synchronizer.initializer.getBalance())
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance)
XCTAssertEqual(initialTotalBalance, expectedBalance)
}
}

View File

@ -40,16 +40,16 @@ class TransactionEnhancementTests: XCTestCase {
var txFoundNotificationExpectation: XCTestExpectation!
var waitExpectation: XCTestExpectation!
override func setUpWithError() throws {
try super.setUpWithError()
override func setUp() async throws {
try await super.setUp()
try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false)
XCTestCase.wait {
await InternalSyncProgress(
alias: .default,
storage: UserDefaults.standard,
logger: logger
).rewind(to: 0)
}
await InternalSyncProgress(
alias: .default,
storage: UserDefaults.standard,
logger: logger
).rewind(to: 0)
logger = OSLogger(logLevel: .debug)
@ -81,7 +81,7 @@ class TransactionEnhancementTests: XCTestCase {
try? FileManager.default.removeItem(at: processorConfig.fsBlockCacheRoot)
try? FileManager.default.removeItem(at: processorConfig.dataDb)
let dbInit = try rustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: network.networkType)
let dbInit = try await rustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: network.networkType)
let ufvks = [
try DerivationTool(networkType: network.networkType)
@ -92,7 +92,7 @@ class TransactionEnhancementTests: XCTestCase {
}
]
do {
try rustBackend.initAccountsTable(
try await rustBackend.initAccountsTable(
dbData: processorConfig.dataDb,
ufvks: ufvks,
networkType: network.networkType
@ -107,7 +107,7 @@ class TransactionEnhancementTests: XCTestCase {
return
}
_ = try rustBackend.initBlocksTable(
_ = try await rustBackend.initBlocksTable(
dbData: processorConfig.dataDb,
height: Int32(birthday.height),
hash: birthday.hash,
@ -130,7 +130,7 @@ class TransactionEnhancementTests: XCTestCase {
contentProvider: DirectoryListingProviders.defaultSorted,
logger: logger
)
try! storage.create()
try! await storage.create()
downloader = BlockDownloaderServiceImpl(service: service, storage: storage)
processor = CompactBlockProcessor(
@ -149,15 +149,14 @@ class TransactionEnhancementTests: XCTestCase {
}
}
XCTestCase.wait { await self.processor.updateEventClosure(identifier: "tests", closure: eventClosure) }
await self.processor.updateEventClosure(identifier: "tests", closure: eventClosure)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
XCTestCase.wait { await self.processor.stop() }
override func tearDown() async throws {
try await super.tearDown()
await self.processor.stop()
try? FileManager.default.removeItem(at: processorConfig.fsBlockCacheRoot)
try? FileManager.default.removeItem(at: processorConfig.dataDb)
NotificationCenter.default.removeObserver(self)
processorEventHandler = nil
initializer = nil
processorConfig = nil

View File

@ -24,26 +24,24 @@ class Z2TReceiveTests: XCTestCase {
var cancellables: [AnyCancellable] = []
let network = DarksideWalletDNetwork()
override func setUpWithError() throws {
try super.setUpWithError()
self.coordinator = TestCoordinator.make(
walletBirthday: self.birthday,
network: self.network
)
override func setUp() async throws {
try await super.setUp()
self.coordinator = try await TestCoordinator(walletBirthday: birthday, network: network)
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
wait { try await self.coordinator.stop() }
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
cancellables = []
try await coordinator.stop()
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
coordinator = nil
cancellables = []
}
func subscribeToFoundTransactions() {
@ -198,7 +196,7 @@ class Z2TReceiveTests: XCTestCase {
do {
try await coordinator.sync(
completion: { synchronizer in
let pMinedHeight = synchronizer.pendingTransactions.first?.minedHeight
let pMinedHeight = await synchronizer.pendingTransactions.first?.minedHeight
XCTAssertEqual(pMinedHeight, sentTxHeight)
sentTxSyncExpectation.fulfill()

View File

@ -68,7 +68,7 @@ class BlockScanTests: XCTestCase {
func testSingleDownloadAndScan() async throws {
logger = OSLogger(logLevel: .debug)
XCTAssertNoThrow(try rustWelding.initDataDb(dbData: dataDbURL, seed: nil, networkType: network.networkType))
_ = try await rustWelding.initDataDb(dbData: dataDbURL, seed: nil, networkType: network.networkType)
let endpoint = LightWalletEndpoint(address: "lightwalletd.testnet.electriccoin.co", port: 9067)
let service = LightWalletServiceFactory(endpoint: endpoint).make()
@ -90,7 +90,7 @@ class BlockScanTests: XCTestCase {
logger: logger
)
try fsBlockRepository.create()
try await fsBlockRepository.create()
let processorConfig = CompactBlockProcessor.Configuration(
alias: .default,
@ -139,7 +139,7 @@ class BlockScanTests: XCTestCase {
let metrics = SDKMetrics()
metrics.enableMetrics()
guard try self.rustWelding.initDataDb(dbData: dataDbURL, seed: nil, networkType: network.networkType) == .success else {
guard try await self.rustWelding.initDataDb(dbData: dataDbURL, seed: nil, networkType: network.networkType) == .success else {
XCTFail("Seed should not be required for this test")
return
}
@ -150,7 +150,7 @@ class BlockScanTests: XCTestCase {
.map { try derivationTool.deriveUnifiedFullViewingKey(from: $0) }
do {
try self.rustWelding.initAccountsTable(
try await self.rustWelding.initAccountsTable(
dbData: self.dataDbURL,
ufvks: [ufvk],
networkType: network.networkType
@ -160,7 +160,7 @@ class BlockScanTests: XCTestCase {
return
}
try self.rustWelding.initBlocksTable(
try await self.rustWelding.initBlocksTable(
dbData: dataDbURL,
height: Int32(walletBirthDay.height),
hash: walletBirthDay.hash,
@ -185,7 +185,7 @@ class BlockScanTests: XCTestCase {
logger: logger
)
try fsBlockRepository.create()
try await fsBlockRepository.create()
var processorConfig = CompactBlockProcessor.Configuration(
alias: .default,

View File

@ -82,7 +82,7 @@ class BlockStreamingTest: XCTestCase {
logger: logger
)
try storage.create()
try await storage.create()
let latestBlockHeight = try await service.latestBlockHeight()
let startHeight = latestBlockHeight - 100_000
@ -146,7 +146,7 @@ class BlockStreamingTest: XCTestCase {
logger: logger
)
try storage.create()
try await storage.create()
let latestBlockHeight = try await service.latestBlockHeight()

View File

@ -42,18 +42,16 @@ class CompactBlockProcessorTests: XCTestCase {
let testFileManager = FileManager()
override func setUpWithError() throws {
try super.setUpWithError()
override func setUp() async throws {
try await super.setUp()
logger = OSLogger(logLevel: .debug)
try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false)
XCTestCase.wait {
await InternalSyncProgress(
alias: .default,
storage: UserDefaults.standard,
logger: logger
).rewind(to: 0)
}
await InternalSyncProgress(
alias: .default,
storage: UserDefaults.standard,
logger: logger
).rewind(to: 0)
let liveService = LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet).make()
let service = MockLightWalletService(
@ -86,7 +84,7 @@ class CompactBlockProcessorTests: XCTestCase {
logger: logger
)
try storage.create()
try await storage.create()
processor = CompactBlockProcessor(
service: service,
@ -97,7 +95,7 @@ class CompactBlockProcessorTests: XCTestCase {
logger: logger
)
let dbInit = try realRustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: .testnet)
let dbInit = try await realRustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: .testnet)
guard case .success = dbInit else {
XCTFail("Failed to initDataDb. Expected `.success` got: \(dbInit)")
@ -116,15 +114,14 @@ class CompactBlockProcessorTests: XCTestCase {
}
}
XCTestCase.wait { await self.processor.updateEventClosure(identifier: "tests", closure: eventClosure) }
await self.processor.updateEventClosure(identifier: "tests", closure: eventClosure)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
XCTestCase.wait { await self.processor.stop() }
override func tearDown() async throws {
try await super.tearDown()
await self.processor.stop()
try FileManager.default.removeItem(at: processorConfig.fsBlockCacheRoot)
try? FileManager.default.removeItem(at: processorConfig.dataDb)
NotificationCenter.default.removeObserver(self)
cancellables = []
processor = nil
processorEventHandler = nil

View File

@ -43,19 +43,17 @@ class CompactBlockReorgTests: XCTestCase {
var reorgNotificationExpectation: XCTestExpectation!
let network = ZcashNetworkBuilder.network(for: .testnet)
let mockLatestHeight = ZcashNetworkBuilder.network(for: .testnet).constants.saplingActivationHeight + 2000
override func setUpWithError() throws {
try super.setUpWithError()
override func setUp() async throws {
try await super.setUp()
logger = OSLogger(logLevel: .debug)
try self.testFileManager.createDirectory(at: self.testTempDirectory, withIntermediateDirectories: false)
XCTestCase.wait {
await InternalSyncProgress(
alias: .default,
storage: UserDefaults.standard,
logger: logger
).rewind(to: 0)
}
await InternalSyncProgress(
alias: .default,
storage: UserDefaults.standard,
logger: logger
).rewind(to: 0)
let liveService = LightWalletServiceFactory(endpoint: LightWalletEndpointBuilder.eccTestnet).make()
let service = MockLightWalletService(
@ -89,9 +87,10 @@ class CompactBlockReorgTests: XCTestCase {
logger: logger
)
try realCache.create()
try await realCache.create()
guard case .success = try realRustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: .testnet) else {
let initResult = try await realRustBackend.initDataDb(dbData: processorConfig.dataDb, seed: nil, networkType: .testnet)
guard case .success = initResult else {
XCTFail("initDataDb failed. Expected Success but got .seedRequired")
return
}
@ -124,15 +123,14 @@ class CompactBlockReorgTests: XCTestCase {
}
}
XCTestCase.wait { await self.processor.updateEventClosure(identifier: "tests", closure: eventClosure) }
await self.processor.updateEventClosure(identifier: "tests", closure: eventClosure)
}
override func tearDownWithError() throws {
try super.tearDownWithError()
XCTestCase.wait { await self.processor.stop() }
override func tearDown() async throws {
try await super.tearDown()
await self.processor.stop()
try! FileManager.default.removeItem(at: processorConfig.fsBlockCacheRoot)
try? FileManager.default.removeItem(at: processorConfig.dataDb)
NotificationCenter.default.removeObserver(self)
cancellables = []
processorEventHandler = nil
processor = nil

View File

@ -49,7 +49,7 @@ class DownloadTests: XCTestCase {
logger: logger
)
try storage.create()
try await storage.create()
let blockCount = 100
let activationHeight = network.constants.saplingActivationHeight

View File

@ -48,7 +48,7 @@ class BlockBatchValidationTests: XCTestCase {
logger: logger
)
try storage.create()
try await storage.create()
let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000)
let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository)
@ -123,7 +123,7 @@ class BlockBatchValidationTests: XCTestCase {
logger: logger
)
try storage.create()
try await storage.create()
let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000)
let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository)
@ -198,7 +198,7 @@ class BlockBatchValidationTests: XCTestCase {
logger: logger
)
try storage.create()
try await storage.create()
let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000)
let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository)
@ -273,7 +273,7 @@ class BlockBatchValidationTests: XCTestCase {
logger: logger
)
try storage.create()
try await storage.create()
let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000)
let downloaderService = BlockDownloaderServiceImpl(service: service, storage: repository)

View File

@ -210,9 +210,33 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
let expectation = XCTestExpectation()
synchronizer.getSaplingAddress(accountIndex: 3) { receivedAddress in
XCTAssertEqual(receivedAddress, self.data.saplingAddress)
expectation.fulfill()
synchronizer.getSaplingAddress(accountIndex: 3) { result in
switch result {
case let .success(address):
XCTAssertEqual(address, self.data.saplingAddress)
expectation.fulfill()
case let .failure(error):
XCTFail("getSaplingAddress failed with error: \(error)")
}
}
wait(for: [expectation], timeout: 0.5)
}
func testGetSaplingAddressThrowsError() {
synchronizerMock.getSaplingAddressAccountIndexClosure = { _ in
throw "Some error"
}
let expectation = XCTestExpectation()
synchronizer.getSaplingAddress(accountIndex: 3) { result in
switch result {
case .success:
XCTFail("Error should be thrown.")
case .failure:
expectation.fulfill()
}
}
wait(for: [expectation], timeout: 0.5)
@ -226,9 +250,33 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
let expectation = XCTestExpectation()
synchronizer.getUnifiedAddress(accountIndex: 3) { receivedAddress in
XCTAssertEqual(receivedAddress, self.data.unifiedAddress)
expectation.fulfill()
synchronizer.getUnifiedAddress(accountIndex: 3) { result in
switch result {
case let .success(address):
XCTAssertEqual(address, self.data.unifiedAddress)
expectation.fulfill()
case let .failure(error):
XCTFail("getSaplingAddress failed with error: \(error)")
}
}
wait(for: [expectation], timeout: 0.5)
}
func testGetUnifiedAddressThrowsError() {
synchronizerMock.getUnifiedAddressAccountIndexClosure = { _ in
throw "Some error"
}
let expectation = XCTestExpectation()
synchronizer.getUnifiedAddress(accountIndex: 3) { result in
switch result {
case .success:
XCTFail("Error should be thrown.")
case .failure:
expectation.fulfill()
}
}
wait(for: [expectation], timeout: 0.5)
@ -242,9 +290,33 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
let expectation = XCTestExpectation()
synchronizer.getTransparentAddress(accountIndex: 3) { receivedAddress in
XCTAssertEqual(receivedAddress, self.data.transparentAddress)
expectation.fulfill()
synchronizer.getTransparentAddress(accountIndex: 3) { result in
switch result {
case let .success(address):
XCTAssertEqual(address, self.data.transparentAddress)
expectation.fulfill()
case let .failure(error):
XCTFail("getSaplingAddress failed with error: \(error)")
}
}
wait(for: [expectation], timeout: 0.5)
}
func testGetTransparentAddressThrowsError() {
synchronizerMock.getTransparentAddressAccountIndexClosure = { _ in
throw "Some error"
}
let expectation = XCTestExpectation()
synchronizer.getTransparentAddress(accountIndex: 3) { result in
switch result {
case .success:
XCTFail("Error should be thrown.")
case .failure:
expectation.fulfill()
}
}
wait(for: [expectation], timeout: 0.5)
@ -762,7 +834,38 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
return Zatoshi(333)
}
XCTAssertEqual(synchronizer.getShieldedBalance(accountIndex: 3), Zatoshi(333))
let expectation = XCTestExpectation()
synchronizer.getShieldedBalance(accountIndex: 3) { result in
switch result {
case let .success(receivedBalance):
XCTAssertEqual(receivedBalance, Zatoshi(333))
expectation.fulfill()
case let .failure(error):
XCTFail("Unpected failure with error: \(error)")
}
}
wait(for: [expectation], timeout: 0.5)
}
func testGetShieldedBalanceThrowsError() {
synchronizerMock.getShieldedBalanceAccountIndexClosure = { _ in
throw "Some error"
}
let expectation = XCTestExpectation()
synchronizer.getShieldedBalance(accountIndex: 3) { result in
switch result {
case .success:
XCTFail("Error should be thrown.")
case .failure:
expectation.fulfill()
}
}
wait(for: [expectation], timeout: 0.5)
}
func testGetShieldedVerifiedBalanceSucceed() {
@ -771,7 +874,38 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
return Zatoshi(333)
}
XCTAssertEqual(synchronizer.getShieldedVerifiedBalance(accountIndex: 3), Zatoshi(333))
let expectation = XCTestExpectation()
synchronizer.getShieldedVerifiedBalance(accountIndex: 3) { result in
switch result {
case let .success(receivedBalance):
XCTAssertEqual(receivedBalance, Zatoshi(333))
expectation.fulfill()
case let .failure(error):
XCTFail("Unpected failure with error: \(error)")
}
}
wait(for: [expectation], timeout: 0.5)
}
func testGetShieldedVerifiedBalanceThrowsError() {
synchronizerMock.getShieldedVerifiedBalanceAccountIndexClosure = { _ in
throw "Some error"
}
let expectation = XCTestExpectation()
synchronizer.getShieldedVerifiedBalance(accountIndex: 3) { result in
switch result {
case .success:
XCTFail("Error should be thrown.")
case .failure:
expectation.fulfill()
}
}
wait(for: [expectation], timeout: 0.5)
}
func testRewindSucceed() {

View File

@ -1023,7 +1023,51 @@ class CombineSynchronizerOfflineTests: XCTestCase {
return Zatoshi(333)
}
XCTAssertEqual(synchronizer.getShieldedBalance(accountIndex: 3), Zatoshi(333))
let expectation = XCTestExpectation()
synchronizer.getShieldedBalance(accountIndex: 3)
.sink(
receiveCompletion: { result in
switch result {
case .finished:
expectation.fulfill()
case let .failure(error):
XCTFail("Unpected failure with error: \(error)")
}
},
receiveValue: { value in
XCTAssertEqual(value, Zatoshi(333))
}
)
.store(in: &cancellables)
wait(for: [expectation], timeout: 0.5)
}
func testGetShieldedBalanceThrowsError() {
synchronizerMock.getShieldedBalanceAccountIndexClosure = { _ in
throw "Some error"
}
let expectation = XCTestExpectation()
synchronizer.getShieldedBalance(accountIndex: 3)
.sink(
receiveCompletion: { result in
switch result {
case .finished:
XCTFail("Error should be thrown.")
case .failure:
expectation.fulfill()
}
},
receiveValue: { _ in
XCTFail("No value is expected")
}
)
.store(in: &cancellables)
wait(for: [expectation], timeout: 0.5)
}
func testGetShieldedVerifiedBalanceSucceed() {
@ -1032,7 +1076,51 @@ class CombineSynchronizerOfflineTests: XCTestCase {
return Zatoshi(333)
}
XCTAssertEqual(synchronizer.getShieldedVerifiedBalance(accountIndex: 3), Zatoshi(333))
let expectation = XCTestExpectation()
synchronizer.getShieldedVerifiedBalance(accountIndex: 3)
.sink(
receiveCompletion: { result in
switch result {
case .finished:
expectation.fulfill()
case let .failure(error):
XCTFail("Unpected failure with error: \(error)")
}
},
receiveValue: { value in
XCTAssertEqual(value, Zatoshi(333))
}
)
.store(in: &cancellables)
wait(for: [expectation], timeout: 0.5)
}
func testGetShieldedVerifiedBalanceThrowsError() {
synchronizerMock.getShieldedVerifiedBalanceAccountIndexClosure = { _ in
throw "Some error"
}
let expectation = XCTestExpectation()
synchronizer.getShieldedVerifiedBalance(accountIndex: 3)
.sink(
receiveCompletion: { result in
switch result {
case .finished:
XCTFail("Error should be thrown.")
case .failure:
expectation.fulfill()
}
},
receiveValue: { _ in
XCTFail("No value is expected")
}
)
.store(in: &cancellables)
wait(for: [expectation], timeout: 0.5)
}
func testRewindSucceed() {

View File

@ -44,7 +44,7 @@ class CompactBlockRepositoryTests: XCTestCase {
logger: logger
)
try compactBlockRepository.create()
try await compactBlockRepository.create()
let latestHeight = await compactBlockRepository.latestHeight()
XCTAssertEqual(latestHeight, BlockHeight.empty())
@ -63,7 +63,7 @@ class CompactBlockRepositoryTests: XCTestCase {
logger: logger
)
try compactBlockRepository.create()
try await compactBlockRepository.create()
let initialHeight = await compactBlockRepository.latestHeight()
let startHeight = self.network.constants.saplingActivationHeight
@ -90,7 +90,7 @@ class CompactBlockRepositoryTests: XCTestCase {
logger: logger
)
try compactBlockRepository.create()
try await compactBlockRepository.create()
let expectedHeight = BlockHeight(123_456)
guard let block = StubBlockCreator.createRandomDataBlock(with: expectedHeight) else {
@ -116,7 +116,7 @@ class CompactBlockRepositoryTests: XCTestCase {
logger: logger
)
try compactBlockRepository.create()
try await compactBlockRepository.create()
let startHeight = self.network.constants.saplingActivationHeight
let blockCount = Int(1_000)

View File

@ -36,7 +36,7 @@ final class FsBlockStorageTests: XCTestCase {
func testLatestHeightEmptyCache() async throws {
let emptyCache: FSCompactBlockRepository = .emptyTemporaryCache
try emptyCache.create()
try await emptyCache.create()
let latestHeight = await emptyCache.latestHeight()
XCTAssertEqual(latestHeight, .empty())
@ -45,7 +45,7 @@ final class FsBlockStorageTests: XCTestCase {
func testRewindEmptyCacheDoesNothing() async throws {
let emptyCache: FSCompactBlockRepository = .emptyTemporaryCache
try emptyCache.create()
try await emptyCache.create()
try await emptyCache.rewind(to: 1000000)
}
@ -65,7 +65,7 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try freshCache.create()
try await freshCache.create()
let fakeBlock = StubBlockCreator.createRandomDataBlock(with: 1234)!
@ -87,7 +87,7 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try freshCache.create()
try await freshCache.create()
let fakeBlock = StubBlockCreator.createRandomDataBlock(with: 1234)!
let fakeBlockHash = fakeBlock.meta.hash.toHexStringTxId()
@ -113,7 +113,7 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try freshCache.create()
try await freshCache.create()
let blockRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
@ -176,7 +176,7 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try freshCache.create()
try await freshCache.create()
let blockRange = CompactBlockRange(uncheckedBounds: (1000, 2000))
@ -288,7 +288,7 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try fsBlockCache.create()
try await fsBlockCache.create()
guard let stubBlocks = StubBlockCreator.createBlockRange(1000 ... 1010) else {
XCTFail("Something Happened. Creating Stub blocks failed")
@ -305,7 +305,7 @@ final class FsBlockStorageTests: XCTestCase {
XCTAssertEqual(latestHeight, .empty())
}
func testCreateDoesntFailWhenAlreadyCreated() throws {
func testCreateDoesntFailWhenAlreadyCreated() async throws {
let freshCache = FSCompactBlockRepository(
fsBlockDbRoot: testTempDirectory,
metadataStore: .mock,
@ -314,9 +314,8 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try freshCache.create()
XCTAssertNoThrow(try freshCache.create())
try await freshCache.create()
try await freshCache.create()
}
func disabled_testStoringTenSandblastedBlocks() async throws {
@ -330,7 +329,7 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try realCache.create()
try await realCache.create()
guard let sandblastedBlocks = try SandblastSimulator().sandblast(with: CompactBlockRange(uncheckedBounds: (10, 19))) else {
XCTFail("failed to create sandblasted blocks")
@ -362,7 +361,7 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try realCache.create()
try await realCache.create()
guard let sandblastedBlocks = try SandblastSimulator().sandblast(with: CompactBlockRange(uncheckedBounds: (10, 19))) else {
XCTFail("failed to create sandblasted blocks")
@ -388,7 +387,7 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try realCache.create()
try await realCache.create()
guard let sandblastedBlocks = try SandblastSimulator().sandblast(with: CompactBlockRange(uncheckedBounds: (10, 19))) else {
XCTFail("failed to create sandblasted blocks")
@ -465,18 +464,19 @@ final class FsBlockStorageTests: XCTestCase {
}
}
func testMetadataStoreThrowsWhenRewindFails() {
func testMetadataStoreThrowsWhenRewindFails() async {
MockRustBackend.rewindCacheToHeightResult = { false }
let expectedHeight = BlockHeight(1000)
XCTAssertThrowsError(
try FSMetadataStore.live(
do {
try await FSMetadataStore.live(
fsBlockDbRoot: testTempDirectory,
rustBackend: MockRustBackend.self,
logger: logger
)
.rewindToHeight(expectedHeight)
) { error in
XCTFail("rewindToHeight should fail")
} catch {
guard let repositoryError = error as? CompactBlockRepositoryError else {
XCTFail("Expected CompactBlockRepositoryError. Found \(error)")
return
@ -502,7 +502,7 @@ final class FsBlockStorageTests: XCTestCase {
logger: logger
)
try freshCache.create()
try await freshCache.create()
let blockRange = CompactBlockRange(uncheckedBounds: (1000, 2000))

View File

@ -13,10 +13,10 @@ class NotesRepositoryTests: XCTestCase {
var sentNotesRepository: SentNotesRepository!
var receivedNotesRepository: ReceivedNoteRepository!
override func setUp() {
super.setUp()
sentNotesRepository = try! TestDbBuilder.sentNotesRepository()
receivedNotesRepository = try! TestDbBuilder.receivedNotesRepository()
override func setUp() async throws {
try await super.setUp()
sentNotesRepository = try! await TestDbBuilder.sentNotesRepository()
receivedNotesRepository = try! await TestDbBuilder.receivedNotesRepository()
}
override func tearDown() {

View File

@ -28,7 +28,7 @@ class NullBytesTests: XCTestCase {
XCTAssertFalse(ZcashRustBackend.isValidTransparentAddress(tAddrWithNullBytes, networkType: networkType))
}
func testInitAccountTableNullBytes() throws {
func testInitAccountTableNullBytes() async throws {
let wrongHash = "000000000\015c597fab53f\058b9e1ededbe8bd83ca0203788e2039eceeb0d65ca6"
let goodHash = "00000000015c597fab53f58b9e1ededbe8bd83ca0203788e2039eceeb0d65ca6"
let time: UInt32 = 1582235356
@ -49,23 +49,23 @@ class NullBytesTests: XCTestCase {
bccb48b14b544e770f21d48f2d3ad8d6ca54eccc92f60634e3078eb48013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb\
934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260
"""
XCTAssertThrowsError(
try ZcashRustBackend.initBlocksTable(
do {
_ = try await ZcashRustBackend.initBlocksTable(
dbData: __dataDbURL(),
height: height,
hash: wrongHash,
time: time,
saplingTree: goodTree,
networkType: networkType
),
"InitBlocksTable with Null bytes on hash string should have failed"
) { error in
)
XCTFail("InitBlocksTable with Null bytes on hash string should have failed")
} catch {
guard let rustError = error as? RustWeldingError else {
XCTFail("Expected RustWeldingError")
return
}
switch rustError {
case .invalidInput:
XCTAssertTrue(true)
@ -73,23 +73,23 @@ class NullBytesTests: XCTestCase {
XCTFail("expected \(String(describing: RustWeldingError.invalidInput)) and got \(rustError)")
}
}
XCTAssertThrowsError(
try ZcashRustBackend.initBlocksTable(
do {
try await ZcashRustBackend.initBlocksTable(
dbData: __dataDbURL(),
height: height,
hash: goodHash,
time: time,
saplingTree: wrongTree,
networkType: networkType
),
"InitBlocksTable with Null bytes on saplingTree string should have failed"
) { error in
)
XCTFail("InitBlocksTable with Null bytes on saplingTree string should have failed")
} catch {
guard let rustError = error as? RustWeldingError else {
XCTFail("Expected RustWeldingError")
return
}
switch rustError {
case .invalidInput:
XCTAssertTrue(true)

View File

@ -11,11 +11,10 @@ import XCTest
class TransactionRepositoryTests: XCTestCase {
var transactionRepository: TransactionRepository!
override func setUp() {
super.setUp()
transactionRepository = try! TestDbBuilder.transactionRepository()
override func setUp() async throws {
try await super.setUp()
transactionRepository = try! await TestDbBuilder.transactionRepository()
}
override func tearDown() {

View File

@ -37,18 +37,20 @@ class ZcashRustBackendTests: XCTestCase {
dataDbHandle.dispose()
}
func testInitWithShortSeedAndFail() throws {
func testInitWithShortSeedAndFail() async throws {
let seed = "testreferencealice"
var dbInit: DbInitResult!
XCTAssertNoThrow(try { dbInit = try ZcashRustBackend.initDataDb(dbData: self.dbData!, seed: nil, networkType: self.networkType) }())
let dbInit = try await ZcashRustBackend.initDataDb(dbData: self.dbData!, seed: nil, networkType: self.networkType)
guard case .success = dbInit else {
XCTFail("Failed to initDataDb. Expected `.success` got: \(String(describing: dbInit))")
return
}
XCTAssertThrowsError(try ZcashRustBackend.createAccount(dbData: dbData!, seed: Array(seed.utf8), networkType: networkType))
do {
_ = try await ZcashRustBackend.createAccount(dbData: dbData!, seed: Array(seed.utf8), networkType: networkType)
XCTFail("createAccount should fail here.")
} catch { }
}
func testIsValidTransparentAddressFalse() {
@ -87,7 +89,7 @@ class ZcashRustBackendTests: XCTestCase {
)
}
func testListTransparentReceivers() throws {
func testListTransparentReceivers() async throws {
let testVector = [TestVector](TestVector.testVectors![0 ... 2])
let network = NetworkType.mainnet
let tempDBs = TemporaryDbBuilder.build()
@ -95,29 +97,24 @@ class ZcashRustBackendTests: XCTestCase {
try? FileManager.default.removeItem(at: tempDBs.dataDB)
XCTAssertEqual(
try ZcashRustBackend.initDataDb(
dbData: tempDBs.dataDB,
seed: seed,
networkType: network
),
.success
let initResult = try await ZcashRustBackend.initDataDb(
dbData: tempDBs.dataDB,
seed: seed,
networkType: network
)
XCTAssertEqual(initResult, .success)
var usk: UnifiedSpendingKey?
XCTAssertNoThrow(
usk = try ZcashRustBackend.createAccount(
dbData: tempDBs.dataDB,
seed: seed,
networkType: network
)
let usk = try await ZcashRustBackend.createAccount(
dbData: tempDBs.dataDB,
seed: seed,
networkType: network
)
XCTAssertEqual(usk?.account, 0)
XCTAssertEqual(usk.account, 0)
let expectedReceivers = testVector.map {
let expectedReceivers = try testVector.map {
UnifiedAddress(validatedEncoding: $0.unified_addr!)
}
.compactMap({ $0.transparentReceiver() })
.map { try $0.transparentReceiver() }
let expectedUAs = testVector.map {
UnifiedAddress(validatedEncoding: $0.unified_addr!)
@ -130,7 +127,7 @@ class ZcashRustBackendTests: XCTestCase {
var uAddresses: [UnifiedAddress] = []
for i in 0...2 {
uAddresses.append(
try ZcashRustBackend.getCurrentAddress(
try await ZcashRustBackend.getCurrentAddress(
dbData: tempDBs.dataDB,
account: 0,
networkType: network
@ -138,7 +135,7 @@ class ZcashRustBackendTests: XCTestCase {
)
if i < 2 {
_ = try ZcashRustBackend.getNextAvailableAddress(
_ = try await ZcashRustBackend.getNextAvailableAddress(
dbData: tempDBs.dataDB,
account: 0,
networkType: network
@ -151,7 +148,7 @@ class ZcashRustBackendTests: XCTestCase {
expectedUAs
)
let actualReceivers = try ZcashRustBackend.listTransparentReceivers(
let actualReceivers = try await ZcashRustBackend.listTransparentReceivers(
dbData: tempDBs.dataDB,
account: 0,
networkType: network

View File

@ -71,25 +71,25 @@ class MockRustBackend: ZcashRustBackendWelding {
static var consensusBranchID: Int32?
static var writeBlocksMetadataResult: () throws -> Bool = { true }
static var rewindCacheToHeightResult: () -> Bool = { true }
static func latestCachedBlockHeight(fsBlockDbRoot: URL) -> ZcashLightClientKit.BlockHeight {
static func latestCachedBlockHeight(fsBlockDbRoot: URL) async -> ZcashLightClientKit.BlockHeight {
.empty()
}
static func rewindCacheToHeight(fsBlockDbRoot: URL, height: Int32) -> Bool {
static func rewindCacheToHeight(fsBlockDbRoot: URL, height: Int32) async -> Bool {
rewindCacheToHeightResult()
}
static func initBlockMetadataDb(fsBlockDbRoot: URL) throws -> Bool {
static func initBlockMetadataDb(fsBlockDbRoot: URL) async throws -> Bool {
true
}
static func writeBlocksMetadata(fsBlockDbRoot: URL, blocks: [ZcashLightClientKit.ZcashCompactBlock]) throws -> Bool {
static func writeBlocksMetadata(fsBlockDbRoot: URL, blocks: [ZcashLightClientKit.ZcashCompactBlock]) async throws -> Bool {
try writeBlocksMetadataResult()
}
static func initAccountsTable(dbData: URL, ufvks: [ZcashLightClientKit.UnifiedFullViewingKey], networkType: ZcashLightClientKit.NetworkType) throws { }
static func initAccountsTable(dbData: URL, ufvks: [ZcashLightClientKit.UnifiedFullViewingKey], networkType: ZcashLightClientKit.NetworkType) async throws { }
static func createToAddress(dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, to address: String, value: Int64, memo: ZcashLightClientKit.MemoBytes?, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) -> Int64 {
static func createToAddress(dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, to address: String, value: Int64, memo: ZcashLightClientKit.MemoBytes?, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) async -> Int64 {
-1
}
@ -101,7 +101,7 @@ class MockRustBackend: ZcashRustBackendWelding {
spendParamsPath: String,
outputParamsPath: String,
networkType: ZcashLightClientKit.NetworkType
) -> Int64 {
) async -> Int64 {
-1
}
@ -109,15 +109,15 @@ class MockRustBackend: ZcashRustBackendWelding {
nil
}
static func clearUtxos(dbData: URL, address: ZcashLightClientKit.TransparentAddress, sinceHeight: ZcashLightClientKit.BlockHeight, networkType: ZcashLightClientKit.NetworkType) throws -> Int32 {
static func clearUtxos(dbData: URL, address: ZcashLightClientKit.TransparentAddress, sinceHeight: ZcashLightClientKit.BlockHeight, networkType: ZcashLightClientKit.NetworkType) async throws -> Int32 {
0
}
static func getTransparentBalance(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) throws -> Int64 { 0 }
static func getTransparentBalance(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) async throws -> Int64 { 0 }
static func getVerifiedTransparentBalance(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) throws -> Int64 { 0 }
static func getVerifiedTransparentBalance(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) async throws -> Int64 { 0 }
static func listTransparentReceivers(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) throws -> [ZcashLightClientKit.TransparentAddress] {
static func listTransparentReceivers(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) async throws -> [ZcashLightClientKit.TransparentAddress] {
[]
}
@ -129,23 +129,23 @@ class MockRustBackend: ZcashRustBackendWelding {
throw KeyDerivationErrors.unableToDerive
}
static func getCurrentAddress(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) throws -> ZcashLightClientKit.UnifiedAddress {
static func getCurrentAddress(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) async throws -> ZcashLightClientKit.UnifiedAddress {
throw KeyDerivationErrors.unableToDerive
}
static func getNextAvailableAddress(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) throws -> ZcashLightClientKit.UnifiedAddress {
static func getNextAvailableAddress(dbData: URL, account: Int32, networkType: ZcashLightClientKit.NetworkType) async throws -> ZcashLightClientKit.UnifiedAddress {
throw KeyDerivationErrors.unableToDerive
}
static func getSaplingReceiver(for uAddr: ZcashLightClientKit.UnifiedAddress) throws -> ZcashLightClientKit.SaplingAddress? {
static func getSaplingReceiver(for uAddr: ZcashLightClientKit.UnifiedAddress) throws -> ZcashLightClientKit.SaplingAddress {
throw KeyDerivationErrors.unableToDerive
}
static func getTransparentReceiver(for uAddr: ZcashLightClientKit.UnifiedAddress) throws -> ZcashLightClientKit.TransparentAddress? {
static func getTransparentReceiver(for uAddr: ZcashLightClientKit.UnifiedAddress) throws -> ZcashLightClientKit.TransparentAddress {
throw KeyDerivationErrors.unableToDerive
}
static func shieldFunds(dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, memo: ZcashLightClientKit.MemoBytes, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) -> Int64 {
static func shieldFunds(dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, memo: ZcashLightClientKit.MemoBytes, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) async -> Int64 {
-1
}
@ -153,19 +153,19 @@ class MockRustBackend: ZcashRustBackendWelding {
throw KeyDerivationErrors.receiverNotFound
}
static func createAccount(dbData: URL, seed: [UInt8], networkType: ZcashLightClientKit.NetworkType) throws -> ZcashLightClientKit.UnifiedSpendingKey {
static func createAccount(dbData: URL, seed: [UInt8], networkType: ZcashLightClientKit.NetworkType) async throws -> ZcashLightClientKit.UnifiedSpendingKey {
throw KeyDerivationErrors.unableToDerive
}
static func getReceivedMemo(dbData: URL, idNote: Int64, networkType: ZcashLightClientKit.NetworkType) -> ZcashLightClientKit.Memo? { nil }
static func getReceivedMemo(dbData: URL, idNote: Int64, networkType: ZcashLightClientKit.NetworkType) async -> ZcashLightClientKit.Memo? { nil }
static func getSentMemo(dbData: URL, idNote: Int64, networkType: ZcashLightClientKit.NetworkType) -> ZcashLightClientKit.Memo? { nil }
static func getSentMemo(dbData: URL, idNote: Int64, networkType: ZcashLightClientKit.NetworkType) async -> ZcashLightClientKit.Memo? { nil }
static func createToAddress(dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, to address: String, value: Int64, memo: ZcashLightClientKit.MemoBytes, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) -> Int64 {
static func createToAddress(dbData: URL, usk: ZcashLightClientKit.UnifiedSpendingKey, to address: String, value: Int64, memo: ZcashLightClientKit.MemoBytes, spendParamsPath: String, outputParamsPath: String, networkType: ZcashLightClientKit.NetworkType) async -> Int64 {
-1
}
static func initDataDb(dbData: URL, seed: [UInt8]?, networkType: ZcashLightClientKit.NetworkType) throws -> ZcashLightClientKit.DbInitResult {
static func initDataDb(dbData: URL, seed: [UInt8]?, networkType: ZcashLightClientKit.NetworkType) async throws -> ZcashLightClientKit.DbInitResult {
.seedRequired
}
@ -189,11 +189,11 @@ class MockRustBackend: ZcashRustBackendWelding {
public func deriveViewingKeys(seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedFullViewingKey] { [] }
static func getNearestRewindHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Int32 { -1 }
static func getNearestRewindHeight(dbData: URL, height: Int32, networkType: NetworkType) async -> Int32 { -1 }
static func network(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) throws -> Int32 { -1 }
static func network(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) async throws -> Int32 { -1 }
static func initAccountsTable(dbData: URL, ufvks: [UnifiedFullViewingKey], networkType: NetworkType) throws -> Bool { false }
static func initAccountsTable(dbData: URL, ufvks: [UnifiedFullViewingKey], networkType: NetworkType) async throws -> Bool { false }
static func putUnspentTransparentOutput(
dbData: URL,
@ -203,11 +203,11 @@ class MockRustBackend: ZcashRustBackendWelding {
value: Int64,
height: BlockHeight,
networkType: NetworkType
) throws -> Bool {
) async throws -> Bool {
false
}
static func downloadedUtxoBalance(dbData: URL, address: String, networkType: NetworkType) throws -> WalletBalance {
static func downloadedUtxoBalance(dbData: URL, address: String, networkType: NetworkType) async throws -> WalletBalance {
throw RustWeldingError.genericError(message: "unimplemented")
}
@ -221,7 +221,7 @@ class MockRustBackend: ZcashRustBackendWelding {
spendParamsPath: String,
outputParamsPath: String,
networkType: NetworkType
) -> Int64 {
) async -> Int64 {
-1
}
@ -262,9 +262,9 @@ class MockRustBackend: ZcashRustBackendWelding {
true
}
static func initDataDb(dbData: URL, networkType: NetworkType) throws {
static func initDataDb(dbData: URL, networkType: NetworkType) async throws {
if !mockDataDb {
_ = try rustBackend.initDataDb(dbData: dbData, seed: nil, networkType: networkType)
_ = try await rustBackend.initDataDb(dbData: dbData, seed: nil, networkType: networkType)
}
}
@ -275,9 +275,9 @@ class MockRustBackend: ZcashRustBackendWelding {
time: UInt32,
saplingTree: String,
networkType: NetworkType
) throws {
) async throws {
if !mockDataDb {
try rustBackend.initBlocksTable(
try await rustBackend.initBlocksTable(
dbData: dbData,
height: height,
hash: hash,
@ -288,66 +288,66 @@ class MockRustBackend: ZcashRustBackendWelding {
}
}
static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) throws -> Int64 {
static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) async throws -> Int64 {
if let balance = mockBalance {
return balance
}
return try rustBackend.getBalance(dbData: dbData, account: account, networkType: networkType)
return try await rustBackend.getBalance(dbData: dbData, account: account, networkType: networkType)
}
static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) throws -> Int64 {
static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) async throws -> Int64 {
if let balance = mockVerifiedBalance {
return balance
}
return try rustBackend.getVerifiedBalance(dbData: dbData, account: account, networkType: networkType)
return try await rustBackend.getVerifiedBalance(dbData: dbData, account: account, networkType: networkType)
}
static func validateCombinedChain(fsBlockDbRoot: URL, dbData: URL, networkType: NetworkType, limit: UInt32 = 0) -> Int32 {
static func validateCombinedChain(fsBlockDbRoot: URL, dbData: URL, networkType: NetworkType, limit: UInt32 = 0) async -> Int32 {
if let rate = self.mockValidateCombinedChainSuccessRate {
if shouldSucceed(successRate: rate) {
return validationResult(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
return await validationResult(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
} else {
return Int32(mockValidateCombinedChainFailureHeight)
}
} else if let attempts = self.mockValidateCombinedChainFailAfterAttempts {
self.mockValidateCombinedChainFailAfterAttempts = attempts - 1
if attempts > 0 {
return validationResult(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
return await validationResult(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
} else {
if attempts == 0 {
return Int32(mockValidateCombinedChainFailureHeight)
} else if attempts < 0 && mockValidateCombinedChainKeepFailing {
return Int32(mockValidateCombinedChainFailureHeight)
} else {
return validationResult(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
return await validationResult(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
}
}
}
return rustBackend.validateCombinedChain(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
return await rustBackend.validateCombinedChain(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
}
private static func validationResult(fsBlockDbRoot: URL, dbData: URL, networkType: NetworkType) -> Int32 {
private static func validationResult(fsBlockDbRoot: URL, dbData: URL, networkType: NetworkType) async -> Int32 {
if mockDataDb {
return -1
} else {
return rustBackend.validateCombinedChain(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
return await rustBackend.validateCombinedChain(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
}
}
static func rewindToHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Bool {
static func rewindToHeight(dbData: URL, height: Int32, networkType: NetworkType) async -> Bool {
mockDataDb ? true : rustBackend.rewindToHeight(dbData: dbData, height: height, networkType: networkType)
}
static func scanBlocks(fsBlockDbRoot: URL, dbData: URL, limit: UInt32, networkType: NetworkType) -> Bool {
static func scanBlocks(fsBlockDbRoot: URL, dbData: URL, limit: UInt32, networkType: NetworkType) async -> Bool {
if let rate = mockScanblocksSuccessRate {
if shouldSucceed(successRate: rate) {
return mockDataDb ? true : rustBackend.scanBlocks(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
return mockDataDb ? true : await rustBackend.scanBlocks(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: networkType)
} else {
return false
}
}
return rustBackend.scanBlocks(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: Self.networkType)
return await rustBackend.scanBlocks(fsBlockDbRoot: fsBlockDbRoot, dbData: dbData, networkType: Self.networkType)
}
static func createToAddress(
@ -361,7 +361,7 @@ class MockRustBackend: ZcashRustBackendWelding {
spendParamsPath: String,
outputParamsPath: String,
networkType: NetworkType
) -> Int64 {
) async -> Int64 {
-1
}
@ -382,7 +382,7 @@ class MockRustBackend: ZcashRustBackendWelding {
nil
}
static func decryptAndStoreTransaction(dbData: URL, txBytes: [UInt8], minedHeight: Int32, networkType: NetworkType) -> Bool {
static func decryptAndStoreTransaction(dbData: URL, txBytes: [UInt8], minedHeight: Int32, networkType: NetworkType) async -> Bool {
false
}
}

View File

@ -50,19 +50,19 @@ class SynchronizerMock: Synchronizer {
await stopClosure()
}
var getSaplingAddressAccountIndexClosure: ((Int) async -> SaplingAddress?)! = nil
func getSaplingAddress(accountIndex: Int) async -> SaplingAddress? {
return await getSaplingAddressAccountIndexClosure(accountIndex)
var getSaplingAddressAccountIndexClosure: ((Int) async throws -> SaplingAddress)! = nil
func getSaplingAddress(accountIndex: Int) async throws -> SaplingAddress {
return try await getSaplingAddressAccountIndexClosure(accountIndex)
}
var getUnifiedAddressAccountIndexClosure: ((Int) async -> UnifiedAddress?)! = nil
func getUnifiedAddress(accountIndex: Int) async -> UnifiedAddress? {
return await getUnifiedAddressAccountIndexClosure(accountIndex)
var getUnifiedAddressAccountIndexClosure: ((Int) async throws -> UnifiedAddress)! = nil
func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress {
return try await getUnifiedAddressAccountIndexClosure(accountIndex)
}
var getTransparentAddressAccountIndexClosure: ((Int) async -> TransparentAddress?)! = nil
func getTransparentAddress(accountIndex: Int) async -> TransparentAddress? {
return await getTransparentAddressAccountIndexClosure(accountIndex)
var getTransparentAddressAccountIndexClosure: ((Int) async throws -> TransparentAddress)! = nil
func getTransparentAddress(accountIndex: Int) async throws -> TransparentAddress {
return try await getTransparentAddressAccountIndexClosure(accountIndex)
}
var sendToAddressSpendingKeyZatoshiToAddressMemoClosure: (
@ -152,14 +152,14 @@ class SynchronizerMock: Synchronizer {
return try await getTransparentBalanceAccountIndexClosure(accountIndex)
}
var getShieldedBalanceAccountIndexClosure: ((Int) -> Zatoshi)! = nil
func getShieldedBalance(accountIndex: Int) -> Zatoshi {
return getShieldedBalanceAccountIndexClosure(accountIndex)
var getShieldedBalanceAccountIndexClosure: ((Int) async throws -> Zatoshi)! = nil
func getShieldedBalance(accountIndex: Int) async throws -> Zatoshi {
try await getShieldedBalanceAccountIndexClosure(accountIndex)
}
var getShieldedVerifiedBalanceAccountIndexClosure: ((Int) -> Zatoshi)! = nil
func getShieldedVerifiedBalance(accountIndex: Int) -> Zatoshi {
return getShieldedVerifiedBalanceAccountIndexClosure(accountIndex)
var getShieldedVerifiedBalanceAccountIndexClosure: ((Int) async throws -> Zatoshi)! = nil
func getShieldedVerifiedBalance(accountIndex: Int) async throws -> Zatoshi {
try await getShieldedVerifiedBalanceAccountIndexClosure(accountIndex)
}
var rewindPolicyClosure: ((RewindPolicy) -> AnyPublisher<Void, Error>)! = nil

View File

@ -53,50 +53,6 @@ class TestCoordinator {
streamingCallTimeoutInMillis: 1000000
)
static func make(
alias: ZcashSynchronizerAlias = .default,
walletBirthday: BlockHeight,
network: ZcashNetwork,
callPrepareInConstructor: Bool = true,
endpoint: LightWalletEndpoint = TestCoordinator.defaultEndpoint
) -> TestCoordinator {
var coordinator: TestCoordinator!
XCTestCase.wait {
coordinator = try await TestCoordinator(
alias: alias,
walletBirthday: walletBirthday,
network: network,
callPrepareInConstructor: callPrepareInConstructor,
endpoint: endpoint
)
}
return coordinator
}
static func make(
alias: ZcashSynchronizerAlias = .default,
spendingKey: UnifiedSpendingKey,
unifiedFullViewingKey: UnifiedFullViewingKey,
walletBirthday: BlockHeight,
network: ZcashNetwork,
callPrepareInConstructor: Bool = true,
endpoint: LightWalletEndpoint = TestCoordinator.defaultEndpoint
) -> TestCoordinator {
var coordinator: TestCoordinator!
XCTestCase.wait {
coordinator = try await TestCoordinator(
alias: alias,
spendingKey: spendingKey,
unifiedFullViewingKey: unifiedFullViewingKey,
walletBirthday: walletBirthday,
network: network,
callPrepareInConstructor: callPrepareInConstructor,
endpoint: endpoint
)
}
return coordinator
}
convenience init(
alias: ZcashSynchronizerAlias = .default,
walletBirthday: BlockHeight,

View File

@ -58,12 +58,12 @@ enum TestDbBuilder {
Bundle.module.url(forResource: "darkside_caches", withExtension: "db")
}
static func prepopulatedDataDbProvider() throws -> ConnectionProvider? {
static func prepopulatedDataDbProvider() async throws -> ConnectionProvider? {
guard let url = prePopulatedMainnetDataDbURL() else { return nil }
let provider = SimpleConnectionProvider(path: url.absoluteString, readonly: true)
let initResult = try ZcashRustBackend.initDataDb(
let initResult = try await ZcashRustBackend.initDataDb(
dbData: url,
seed: Environment.seedBytes,
networkType: .mainnet
@ -76,19 +76,19 @@ enum TestDbBuilder {
}
}
static func transactionRepository() throws -> TransactionRepository? {
guard let provider = try prepopulatedDataDbProvider() else { return nil }
static func transactionRepository() async throws -> TransactionRepository? {
guard let provider = try await prepopulatedDataDbProvider() else { return nil }
return TransactionSQLDAO(dbProvider: provider)
}
static func sentNotesRepository() throws -> SentNotesRepository? {
guard let provider = try prepopulatedDataDbProvider() else { return nil }
static func sentNotesRepository() async throws -> SentNotesRepository? {
guard let provider = try await prepopulatedDataDbProvider() else { return nil }
return SentNotesSQLDAO(dbProvider: provider)
}
static func receivedNotesRepository() throws -> ReceivedNoteRepository? {
guard let provider = try prepopulatedDataDbProvider() else { return nil }
static func receivedNotesRepository() async throws -> ReceivedNoteRepository? {
guard let provider = try await prepopulatedDataDbProvider() else { return nil }
return ReceivedNotesSQLDAO(dbProvider: provider)
}

View File

@ -1,26 +0,0 @@
//
// XCAsyncTestCase.swift
//
//
// credits: https://betterprogramming.pub/async-setup-and-teardown-in-xctestcase-dc7a2cdb9fb
//
///
/// A subclass of ``XCTestCase`` that supports async setup and teardown.
///
import Foundation
import XCTest
extension XCTestCase {
static func wait(asyncBlock: @escaping (() async throws -> Void)) {
let semaphore = DispatchSemaphore(value: 0)
Task.init {
try! await asyncBlock()
semaphore.signal()
}
semaphore.wait()
}
func wait(asyncBlock: @escaping (() async throws -> Void)) {
XCTestCase.wait(asyncBlock: asyncBlock)
}
}