[#487] shieldFunds to async/await

- API refactored to async

[#487] shieldFunds to async/await

- unit tests refactored
This commit is contained in:
Lukas Korba 2022-09-21 14:30:06 +02:00
parent 77d11470d5
commit 2c93802828
4 changed files with 94 additions and 99 deletions

View File

@ -46,25 +46,17 @@ class GetUTXOsViewController: UIViewController {
KRProgressHUD.showMessage("🛡 Shielding 🛡")
AppDelegate.shared.sharedSynchronizer.shieldFunds(
spendingKey: spendingKey,
transparentSecretKey: transparentSecretKey,
memo: "shielding is fun!",
from: 0,
resultBlock: { result in
DispatchQueue.main.async {
KRProgressHUD.dismiss()
switch result {
case .success(let transaction):
self.messageLabel.text = "funds shielded \(transaction)"
case .failure(let error):
self.messageLabel.text = "Shielding failed: \(error)"
}
}
}
)
Task { @MainActor in
let transaction = try await AppDelegate.shared.sharedSynchronizer.shieldFunds(
spendingKey: spendingKey,
transparentSecretKey: transparentSecretKey,
memo: "shielding is fun!",
from: 0)
KRProgressHUD.dismiss()
self.messageLabel.text = "funds shielded \(transaction)"
}
} catch {
self.messageLabel.text = "Error \(error)"
self.messageLabel.text = "Shielding failed \(error)"
}
}
}

View File

@ -142,7 +142,7 @@ public protocol Synchronizer {
resultBlock: @escaping (_ result: Result<PendingTransactionEntity, Error>) -> Void
)
/// Sends zatoshi.
/// Shields zatoshi.
/// - Parameter spendingKey: the key that allows spends to occur.
/// - Parameter transparentSecretKey: the key that allows to spend transaprent funds
/// - Parameter memo: the optional memo to include as part of the transaction.
@ -151,9 +151,8 @@ public protocol Synchronizer {
spendingKey: String,
transparentSecretKey: String,
memo: String?,
from accountIndex: Int,
resultBlock: @escaping (_ result: Result<PendingTransactionEntity, Error>) -> Void
)
from accountIndex: Int
) async throws -> PendingTransactionEntity
/// Attempts to cancel a transaction that is about to be sent. Typically, cancellation is only
/// an option if the transaction has not yet been submitted to the server.

View File

@ -507,9 +507,8 @@ public class SDKSynchronizer: Synchronizer {
spendingKey: String,
transparentSecretKey: String,
memo: String?,
from accountIndex: Int,
resultBlock: @escaping (Result<PendingTransactionEntity, Error>) -> Void
) {
from accountIndex: Int
) async throws -> PendingTransactionEntity {
// let's see if there are funds to shield
let derivationTool = DerivationTool(networkType: self.network.networkType)
@ -519,32 +518,22 @@ public class SDKSynchronizer: Synchronizer {
// Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet.
guard tBalance.verified >= self.network.constants.defaultFee(for: self.latestScannedHeight) else {
resultBlock(.failure(ShieldFundsError.insuficientTransparentFunds))
return
throw ShieldFundsError.insuficientTransparentFunds
}
let viewingKey = try derivationTool.deriveViewingKey(spendingKey: spendingKey)
let zAddr = try derivationTool.deriveShieldedAddress(viewingKey: viewingKey)
let shieldingSpend = try transactionManager.initSpend(zatoshi: tBalance.verified, toAddress: zAddr, memo: memo, from: 0)
// TODO: Task will be removed when this method is changed to async, issue 487, https://github.com/zcash/ZcashLightClientKit/issues/487
Task {
do {
let transaction = try await transactionManager.encodeShieldingTransaction(
spendingKey: spendingKey,
tsk: transparentSecretKey,
pendingTransaction: shieldingSpend
)
let submittedTx = try await transactionManager.submit(pendingTransaction: transaction)
resultBlock(.success(submittedTx))
} catch {
resultBlock(.failure(error))
}
}
let transaction = try await transactionManager.encodeShieldingTransaction(
spendingKey: spendingKey,
tsk: transparentSecretKey,
pendingTransaction: shieldingSpend
)
return try await transactionManager.submit(pendingTransaction: transaction)
} catch {
resultBlock(.failure(error))
return
throw error
}
}

View File

@ -9,6 +9,7 @@
import XCTest
@testable import TestUtils
@testable import ZcashLightClientKit
class ShieldFundsTests: XCTestCase {
// TODO: Parameterize this from environment?
// swiftlint:disable:next line_length
@ -82,7 +83,7 @@ class ShieldFundsTests: XCTestCase {
/// 15. sync up to the new chain tip
/// verify that the shielded transactions are confirmed
///
func testShieldFunds() throws {
func testShieldFunds() async throws {
// 1. load the dataset
try coordinator.service.useDataset(from: "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/shielding-dataset/shield-funds/1631000.txt")
@ -110,15 +111,19 @@ class ShieldFundsTests: XCTestCase {
let preTxExpectation = XCTestExpectation(description: "pre receive")
// 3. sync up to that height
try coordinator.sync(
completion: { synchro in
initialVerifiedBalance = synchro.initializer.getVerifiedBalance()
initialTotalBalance = synchro.initializer.getBalance()
preTxExpectation.fulfill()
shouldContinue = true
},
error: self.handleError
)
try await withCheckedThrowingContinuation { continuation in
do {
try coordinator.sync(completion: { synchronizer in
initialVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
initialTotalBalance = synchronizer.initializer.getBalance()
preTxExpectation.fulfill()
shouldContinue = true
continuation.resume()
}, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [preTxExpectation], timeout: 10)
@ -149,14 +154,17 @@ class ShieldFundsTests: XCTestCase {
shouldContinue = false
// 6. Sync and find the UXTO on chain.
try coordinator.sync(
completion: { synchro in
tFundsDetectionExpectation.fulfill()
shouldContinue = true
},
error: self.handleError
)
try await withCheckedThrowingContinuation { continuation in
do {
try coordinator.sync(completion: { synchronizer in
shouldContinue = true
tFundsDetectionExpectation.fulfill()
continuation.resume()
}, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [tFundsDetectionExpectation], timeout: 2)
// at this point the balance should be zero for shielded, then zero verified transparent funds
@ -176,13 +184,17 @@ class ShieldFundsTests: XCTestCase {
sleep(2)
// 8. sync up to chain tip.
try coordinator.sync(
completion: { synchro in
tFundsConfirmationSyncExpectation.fulfill()
shouldContinue = true
},
error: self.handleError
)
try await withCheckedThrowingContinuation { continuation in
do {
try coordinator.sync(completion: { synchronizer in
shouldContinue = true
tFundsConfirmationSyncExpectation.fulfill()
continuation.resume()
}, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [tFundsConfirmationSyncExpectation], timeout: 5)
@ -209,22 +221,18 @@ class ShieldFundsTests: XCTestCase {
var shieldingPendingTx: PendingTransactionEntity?
// shield the funds
coordinator.synchronizer.shieldFunds(
spendingKey: coordinator.spendingKey,
transparentSecretKey: transparentSecretKey,
memo: "shield funds",
from: 0
) { result in
switch result {
case .failure(let error):
XCTFail("Failed With error: \(error.localizedDescription)")
case .success(let pendingTx):
shouldContinue = true
XCTAssertEqual(pendingTx.value, Zatoshi(10000))
shieldingPendingTx = pendingTx
}
do {
let pendingTx = try await coordinator.synchronizer.shieldFunds(
spendingKey: coordinator.spendingKey,
transparentSecretKey: transparentSecretKey,
memo: "shield funds",
from: 0)
shouldContinue = true
XCTAssertEqual(pendingTx.value, Zatoshi(10000))
shieldingPendingTx = pendingTx
shieldFundsExpectation.fulfill()
} catch {
XCTFail("Failed With error: \(error.localizedDescription)")
}
wait(for: [shieldFundsExpectation], timeout: 30)
@ -264,14 +272,17 @@ class ShieldFundsTests: XCTestCase {
// 13. sync up to chain tip
let postShieldSyncExpectation = XCTestExpectation(description: "sync Post shield")
shouldContinue = false
try coordinator.sync(
completion: { synchro in
postShieldSyncExpectation.fulfill()
shouldContinue = true
},
error: self.handleError
)
try await withCheckedThrowingContinuation { continuation in
do {
try coordinator.sync(completion: { synchronizer in
shouldContinue = true
postShieldSyncExpectation.fulfill()
continuation.resume()
}, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [postShieldSyncExpectation], timeout: 3)
guard shouldContinue else { return }
@ -294,13 +305,17 @@ class ShieldFundsTests: XCTestCase {
shouldContinue = false
// 15. sync up to the new chain tip
try coordinator.sync(
completion: { synchro in
confirmationExpectation.fulfill()
shouldContinue = true
},
error: self.handleError
)
try await withCheckedThrowingContinuation { continuation in
do {
try coordinator.sync(completion: { synchronizer in
shouldContinue = true
confirmationExpectation.fulfill()
continuation.resume()
}, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [confirmationExpectation], timeout: 5)