2020-06-03 16:18:57 -07:00
|
|
|
|
//
|
|
|
|
|
// BalanceTests.swift
|
|
|
|
|
// ZcashLightClientKit-Unit-Tests
|
|
|
|
|
//
|
|
|
|
|
// Created by Francisco Gindre on 4/28/20.
|
|
|
|
|
//
|
|
|
|
|
|
2023-03-15 04:17:43 -07:00
|
|
|
|
import Combine
|
2020-06-03 16:18:57 -07:00
|
|
|
|
import XCTest
|
2022-02-28 09:03:20 -08:00
|
|
|
|
@testable import TestUtils
|
2020-06-03 16:18:57 -07:00
|
|
|
|
@testable import ZcashLightClientKit
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-05-01 07:28:59 -07:00
|
|
|
|
class BalanceTests: ZcashTestCase {
|
2022-06-22 12:45:37 -07:00
|
|
|
|
let sendAmount = Zatoshi(1000)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
let defaultLatestHeight: BlockHeight = 663188
|
2021-05-18 14:22:29 -07:00
|
|
|
|
let branchID = "2bb40e60"
|
|
|
|
|
let chainName = "main"
|
2021-07-28 09:59:10 -07:00
|
|
|
|
let network: ZcashNetwork = DarksideWalletDNetwork()
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
|
|
|
|
var birthday: BlockHeight = 663150
|
|
|
|
|
var sentTransactionExpectation = XCTestExpectation(description: "sent")
|
|
|
|
|
var syncedExpectation = XCTestExpectation(description: "synced")
|
|
|
|
|
var coordinator: TestCoordinator!
|
2023-03-15 04:17:43 -07:00
|
|
|
|
var cancellables: [AnyCancellable] = []
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-03-30 10:01:47 -07:00
|
|
|
|
override func setUp() async throws {
|
|
|
|
|
try await super.setUp()
|
2023-05-01 07:28:59 -07:00
|
|
|
|
self.coordinator = try await TestCoordinator(
|
|
|
|
|
container: mockContainer,
|
|
|
|
|
walletBirthday: birthday,
|
|
|
|
|
network: network
|
|
|
|
|
)
|
2022-11-28 22:40:45 -08:00
|
|
|
|
try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
|
2020-06-03 16:18:57 -07:00
|
|
|
|
}
|
2023-02-16 08:14:31 -08:00
|
|
|
|
|
2023-03-30 10:01:47 -07:00
|
|
|
|
override func tearDown() async throws {
|
|
|
|
|
try await super.tearDown()
|
|
|
|
|
let coordinator = self.coordinator!
|
|
|
|
|
self.coordinator = nil
|
|
|
|
|
cancellables = []
|
|
|
|
|
|
|
|
|
|
try await coordinator.stop()
|
2023-02-16 08:14:31 -08:00
|
|
|
|
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
|
|
|
|
|
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
|
|
|
|
|
}
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2021-03-25 10:43:20 -07:00
|
|
|
|
/**
|
2021-09-23 06:26:41 -07:00
|
|
|
|
verify that when sending the maximum amount, the transactions are broadcasted properly
|
|
|
|
|
*/
|
2023-02-14 02:30:08 -08:00
|
|
|
|
// FIXME [#783]: Fix test
|
|
|
|
|
func disabled_testMaxAmountSend() async throws {
|
2021-03-25 10:43:20 -07:00
|
|
|
|
let notificationHandler = SDKSynchonizerListener()
|
|
|
|
|
let foundTransactionsExpectation = XCTestExpectation(description: "found transactions expectation")
|
|
|
|
|
let transactionMinedExpectation = XCTestExpectation(description: "transaction mined expectation")
|
|
|
|
|
|
|
|
|
|
// 0 subscribe to updated transactions events
|
|
|
|
|
notificationHandler.subscribeToSynchronizer(coordinator.synchronizer)
|
|
|
|
|
// 1 sync and get spendable funds
|
2021-05-18 14:22:29 -07:00
|
|
|
|
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
try coordinator.applyStaged(blockheight: defaultLatestHeight + 10)
|
|
|
|
|
|
|
|
|
|
sleep(1)
|
|
|
|
|
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
firstSyncExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [firstSyncExpectation], timeout: 12)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
// 2 check that there are no unconfirmed funds
|
|
|
|
|
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
|
2021-07-28 09:59:10 -07:00
|
|
|
|
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
2021-03-25 10:43:20 -07:00
|
|
|
|
XCTAssertEqual(verifiedBalance, totalBalance)
|
|
|
|
|
|
2022-06-22 12:45:37 -07:00
|
|
|
|
let maxBalance = verifiedBalance - network.constants.defaultFee(for: defaultLatestHeight)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
// 3 create a transaction for the max amount possible
|
|
|
|
|
// 4 send the transaction
|
2023-03-10 03:58:28 -08:00
|
|
|
|
let spendingKey = coordinator.spendingKey
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
var pendingTx: ZcashTransaction.Overview?
|
2022-09-13 03:19:56 -07:00
|
|
|
|
do {
|
|
|
|
|
let transaction = try await coordinator.synchronizer.sendToAddress(
|
|
|
|
|
spendingKey: spendingKey,
|
|
|
|
|
zatoshi: maxBalance,
|
2023-02-13 01:34:41 -08:00
|
|
|
|
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
|
2022-10-02 19:11:17 -07:00
|
|
|
|
memo: try Memo(string: "this is a test")
|
|
|
|
|
)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
pendingTx = transaction
|
|
|
|
|
self.sentTransactionExpectation.fulfill()
|
|
|
|
|
} catch {
|
|
|
|
|
XCTFail("sendToAddress failed: \(error)")
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [sentTransactionExpectation], timeout: 20)
|
2023-03-14 05:11:17 -07:00
|
|
|
|
guard let pendingTx else {
|
2021-03-25 10:43:20 -07:00
|
|
|
|
XCTFail("transaction creation failed")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
|
notificationHandler.synchronizerMinedTransaction = { transaction in
|
2023-05-05 10:30:47 -07:00
|
|
|
|
XCTAssertNotNil(transaction.rawID)
|
|
|
|
|
XCTAssertNotNil(pendingTx.rawID)
|
|
|
|
|
XCTAssertEqual(transaction.rawID, pendingTx.rawID)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
transactionMinedExpectation.fulfill()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5 apply to height
|
|
|
|
|
// 6 mine the block
|
|
|
|
|
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
|
|
|
|
XCTFail("no incoming transaction after")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-27 04:40:32 -07:00
|
|
|
|
let latestHeight = try await coordinator.latestHeight()
|
2021-03-25 10:43:20 -07:00
|
|
|
|
let sentTxHeight = latestHeight + 1
|
|
|
|
|
|
|
|
|
|
notificationHandler.transactionsFound = { txs in
|
2023-05-05 10:30:47 -07:00
|
|
|
|
let foundTx = txs.first(where: { $0.rawID == pendingTx.rawID })
|
2021-03-25 10:43:20 -07:00
|
|
|
|
XCTAssertNotNil(foundTx)
|
|
|
|
|
XCTAssertEqual(foundTx?.minedHeight, sentTxHeight)
|
|
|
|
|
|
|
|
|
|
foundTransactionsExpectation.fulfill()
|
|
|
|
|
}
|
|
|
|
|
try coordinator.stageBlockCreate(height: sentTxHeight, count: 100)
|
|
|
|
|
sleep(1)
|
|
|
|
|
try coordinator.stageTransaction(rawTx, at: sentTxHeight)
|
|
|
|
|
try coordinator.applyStaged(blockheight: sentTxHeight)
|
|
|
|
|
sleep(2) // add enhance breakpoint here
|
|
|
|
|
let mineExpectation = XCTestExpectation(description: "mineTxExpectation")
|
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { synchronizer in
|
2023-05-05 10:30:47 -07:00
|
|
|
|
let pendingEntity = try await synchronizer.allPendingTransactions().first(where: { $0.rawID == pendingTx.rawID })
|
2023-03-16 02:11:18 -07:00
|
|
|
|
XCTAssertNotNil(pendingEntity, "pending transaction should have been mined by now")
|
2023-05-05 10:30:47 -07:00
|
|
|
|
XCTAssertNotNil(pendingEntity?.minedHeight)
|
2023-03-16 02:11:18 -07:00
|
|
|
|
XCTAssertEqual(pendingEntity?.minedHeight, sentTxHeight)
|
|
|
|
|
mineExpectation.fulfill()
|
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [mineExpectation, transactionMinedExpectation, foundTransactionsExpectation], timeout: 5)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
// 7 advance to confirmation
|
|
|
|
|
|
|
|
|
|
try coordinator.applyStaged(blockheight: sentTxHeight + 10)
|
|
|
|
|
|
|
|
|
|
sleep(2)
|
|
|
|
|
|
|
|
|
|
let confirmExpectation = XCTestExpectation(description: "confirm expectation")
|
|
|
|
|
notificationHandler.transactionsFound = { txs in
|
|
|
|
|
XCTFail("We shouldn't find any transactions at this point but found \(txs)")
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
notificationHandler.synchronizerMinedTransaction = { transaction in
|
|
|
|
|
XCTFail("We shouldn't find any mined transactions at this point but found \(transaction)")
|
2021-03-25 10:43:20 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
confirmExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [confirmExpectation], timeout: 5)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
2023-03-31 01:49:06 -07:00
|
|
|
|
let confirmedPending = try await coordinator.synchronizer.allPendingTransactions()
|
2023-05-05 10:30:47 -07:00
|
|
|
|
.first(where: { $0.rawID == pendingTx.rawID })
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
|
|
|
|
|
XCTAssertEqual(expectedBalance, .zero)
|
|
|
|
|
XCTAssertEqual(expectedVerifiedBalance, .zero)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-09-23 06:26:41 -07:00
|
|
|
|
verify that when sending the maximum amount minus one zatoshi, the transactions are broadcasted properly
|
|
|
|
|
*/
|
2023-02-14 02:30:08 -08:00
|
|
|
|
// FIXME [#781]: Fix test
|
|
|
|
|
func disabled_testMaxAmountMinusOneSend() async throws {
|
2021-03-25 10:43:20 -07:00
|
|
|
|
let notificationHandler = SDKSynchonizerListener()
|
|
|
|
|
let foundTransactionsExpectation = XCTestExpectation(description: "found transactions expectation")
|
|
|
|
|
let transactionMinedExpectation = XCTestExpectation(description: "transaction mined expectation")
|
|
|
|
|
|
|
|
|
|
// 0 subscribe to updated transactions events
|
|
|
|
|
notificationHandler.subscribeToSynchronizer(coordinator.synchronizer)
|
|
|
|
|
// 1 sync and get spendable funds
|
2021-05-18 14:22:29 -07:00
|
|
|
|
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
try coordinator.applyStaged(blockheight: defaultLatestHeight + 10)
|
|
|
|
|
|
|
|
|
|
sleep(1)
|
|
|
|
|
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
firstSyncExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [firstSyncExpectation], timeout: 12)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
// 2 check that there are no unconfirmed funds
|
|
|
|
|
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
|
2021-07-28 09:59:10 -07:00
|
|
|
|
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
2021-03-25 10:43:20 -07:00
|
|
|
|
XCTAssertEqual(verifiedBalance, totalBalance)
|
|
|
|
|
|
2022-06-22 12:45:37 -07:00
|
|
|
|
let maxBalanceMinusOne = verifiedBalance - network.constants.defaultFee(for: defaultLatestHeight) - Zatoshi(1)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
// 3 create a transaction for the max amount possible
|
|
|
|
|
// 4 send the transaction
|
2023-03-10 03:58:28 -08:00
|
|
|
|
let spendingKey = coordinator.spendingKey
|
2023-05-05 10:30:47 -07:00
|
|
|
|
var pendingTx: ZcashTransaction.Overview?
|
2022-09-13 03:19:56 -07:00
|
|
|
|
do {
|
|
|
|
|
let transaction = try await coordinator.synchronizer.sendToAddress(
|
|
|
|
|
spendingKey: spendingKey,
|
|
|
|
|
zatoshi: maxBalanceMinusOne,
|
2023-02-13 01:34:41 -08:00
|
|
|
|
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
|
2022-10-02 19:11:17 -07:00
|
|
|
|
memo: try Memo(string: "\(self.description) \(Date().description)")
|
|
|
|
|
)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
pendingTx = transaction
|
|
|
|
|
self.sentTransactionExpectation.fulfill()
|
|
|
|
|
} catch {
|
|
|
|
|
XCTFail("sendToAddress failed: \(error)")
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [sentTransactionExpectation], timeout: 20)
|
2023-03-14 05:11:17 -07:00
|
|
|
|
guard let pendingTx else {
|
2021-03-25 10:43:20 -07:00
|
|
|
|
XCTFail("transaction creation failed")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
|
notificationHandler.synchronizerMinedTransaction = { transaction in
|
2023-05-05 10:30:47 -07:00
|
|
|
|
XCTAssertNotNil(transaction.rawID)
|
|
|
|
|
XCTAssertNotNil(pendingTx.rawID)
|
|
|
|
|
XCTAssertEqual(transaction.rawID, pendingTx.rawID)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
transactionMinedExpectation.fulfill()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5 apply to height
|
|
|
|
|
// 6 mine the block
|
|
|
|
|
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
|
|
|
|
XCTFail("no incoming transaction after")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-27 04:40:32 -07:00
|
|
|
|
let latestHeight = try await coordinator.latestHeight()
|
2021-03-25 10:43:20 -07:00
|
|
|
|
let sentTxHeight = latestHeight + 1
|
|
|
|
|
|
|
|
|
|
notificationHandler.transactionsFound = { txs in
|
2023-05-05 10:30:47 -07:00
|
|
|
|
let foundTx = txs.first(where: { $0.rawID == pendingTx.rawID })
|
2021-03-25 10:43:20 -07:00
|
|
|
|
XCTAssertNotNil(foundTx)
|
|
|
|
|
XCTAssertEqual(foundTx?.minedHeight, sentTxHeight)
|
|
|
|
|
|
|
|
|
|
foundTransactionsExpectation.fulfill()
|
|
|
|
|
}
|
|
|
|
|
try coordinator.stageBlockCreate(height: sentTxHeight, count: 100)
|
|
|
|
|
sleep(1)
|
|
|
|
|
try coordinator.stageTransaction(rawTx, at: sentTxHeight)
|
|
|
|
|
try coordinator.applyStaged(blockheight: sentTxHeight)
|
|
|
|
|
sleep(2) // add enhance breakpoint here
|
|
|
|
|
let mineExpectation = XCTestExpectation(description: "mineTxExpectation")
|
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { synchronizer in
|
2023-05-05 10:30:47 -07:00
|
|
|
|
let pendingEntity = try await synchronizer.allPendingTransactions().first(where: { $0.rawID == pendingTx.rawID })
|
2023-03-16 02:11:18 -07:00
|
|
|
|
XCTAssertNotNil(pendingEntity, "pending transaction should have been mined by now")
|
2023-05-05 10:30:47 -07:00
|
|
|
|
XCTAssertNotNil(pendingEntity?.minedHeight)
|
2023-03-16 02:11:18 -07:00
|
|
|
|
XCTAssertEqual(pendingEntity?.minedHeight, sentTxHeight)
|
|
|
|
|
mineExpectation.fulfill()
|
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [mineExpectation, transactionMinedExpectation, foundTransactionsExpectation], timeout: 5)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
// 7 advance to confirmation
|
2023-05-05 10:30:47 -07:00
|
|
|
|
|
|
|
|
|
let advanceToConfirmationHeight = sentTxHeight + 10
|
|
|
|
|
try coordinator.applyStaged(blockheight: advanceToConfirmationHeight)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
sleep(2)
|
|
|
|
|
|
|
|
|
|
let confirmExpectation = XCTestExpectation(description: "confirm expectation")
|
|
|
|
|
notificationHandler.transactionsFound = { txs in
|
|
|
|
|
XCTFail("We shouldn't find any transactions at this point but found \(txs)")
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
notificationHandler.synchronizerMinedTransaction = { transaction in
|
|
|
|
|
XCTFail("We shouldn't find any mined transactions at this point but found \(transaction)")
|
2021-03-25 10:43:20 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
confirmExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [confirmExpectation], timeout: 5)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
2023-03-31 01:49:06 -07:00
|
|
|
|
let confirmedPending = try await coordinator.synchronizer
|
2021-09-23 06:26:41 -07:00
|
|
|
|
.allPendingTransactions()
|
2023-05-05 10:30:47 -07:00
|
|
|
|
.first(where: { $0.rawID == pendingTx.rawID })
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
|
|
|
|
|
XCTAssertEqual(expectedBalance, Zatoshi(1))
|
|
|
|
|
XCTAssertEqual(expectedVerifiedBalance, Zatoshi(1))
|
2021-03-25 10:43:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-09-23 06:26:41 -07:00
|
|
|
|
verify that when sending the a no change transaction, the transactions are broadcasted properly
|
|
|
|
|
*/
|
2023-02-14 02:30:08 -08:00
|
|
|
|
// FIXME [#785]: Fix test
|
|
|
|
|
func disabled_testSingleNoteNoChangeTransaction() async throws {
|
2021-03-25 10:43:20 -07:00
|
|
|
|
let notificationHandler = SDKSynchonizerListener()
|
|
|
|
|
let foundTransactionsExpectation = XCTestExpectation(description: "found transactions expectation")
|
|
|
|
|
let transactionMinedExpectation = XCTestExpectation(description: "transaction mined expectation")
|
|
|
|
|
|
|
|
|
|
// 0 subscribe to updated transactions events
|
|
|
|
|
notificationHandler.subscribeToSynchronizer(coordinator.synchronizer)
|
|
|
|
|
// 1 sync and get spendable funds
|
2021-05-18 14:22:29 -07:00
|
|
|
|
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
try coordinator.applyStaged(blockheight: defaultLatestHeight + 10)
|
|
|
|
|
|
|
|
|
|
sleep(1)
|
|
|
|
|
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
firstSyncExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [firstSyncExpectation], timeout: 12)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
// 2 check that there are no unconfirmed funds
|
|
|
|
|
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let verifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let totalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
|
2021-07-28 09:59:10 -07:00
|
|
|
|
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
2021-03-25 10:43:20 -07:00
|
|
|
|
XCTAssertEqual(verifiedBalance, totalBalance)
|
|
|
|
|
|
2022-06-22 12:45:37 -07:00
|
|
|
|
let maxBalanceMinusOne = Zatoshi(100000) - network.constants.defaultFee(for: defaultLatestHeight)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
// 3 create a transaction for the max amount possible
|
|
|
|
|
// 4 send the transaction
|
2023-03-10 03:58:28 -08:00
|
|
|
|
let spendingKey = coordinator.spendingKey
|
2023-05-05 10:30:47 -07:00
|
|
|
|
var pendingTx: ZcashTransaction.Overview?
|
2022-09-13 03:19:56 -07:00
|
|
|
|
do {
|
|
|
|
|
let transaction = try await coordinator.synchronizer.sendToAddress(
|
|
|
|
|
spendingKey: spendingKey,
|
|
|
|
|
zatoshi: maxBalanceMinusOne,
|
2023-02-13 01:34:41 -08:00
|
|
|
|
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
|
2022-10-02 19:11:17 -07:00
|
|
|
|
memo: try Memo(string: "test send \(self.description) \(Date().description)")
|
|
|
|
|
)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
pendingTx = transaction
|
|
|
|
|
self.sentTransactionExpectation.fulfill()
|
|
|
|
|
} catch {
|
|
|
|
|
XCTFail("sendToAddress failed: \(error)")
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [sentTransactionExpectation], timeout: 20)
|
2023-03-14 05:11:17 -07:00
|
|
|
|
guard let pendingTx else {
|
2021-03-25 10:43:20 -07:00
|
|
|
|
XCTFail("transaction creation failed")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
|
notificationHandler.synchronizerMinedTransaction = { transaction in
|
2023-05-05 10:30:47 -07:00
|
|
|
|
XCTAssertNotNil(transaction.rawID)
|
|
|
|
|
XCTAssertNotNil(pendingTx.rawID)
|
|
|
|
|
XCTAssertEqual(transaction.rawID, pendingTx.rawID)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
transactionMinedExpectation.fulfill()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5 apply to height
|
|
|
|
|
// 6 mine the block
|
|
|
|
|
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
|
|
|
|
XCTFail("no incoming transaction after")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-27 04:40:32 -07:00
|
|
|
|
let latestHeight = try await coordinator.latestHeight()
|
2021-03-25 10:43:20 -07:00
|
|
|
|
let sentTxHeight = latestHeight + 1
|
|
|
|
|
|
|
|
|
|
notificationHandler.transactionsFound = { txs in
|
2023-05-05 10:30:47 -07:00
|
|
|
|
let foundTx = txs.first(where: { $0.rawID == pendingTx.rawID })
|
2021-03-25 10:43:20 -07:00
|
|
|
|
XCTAssertNotNil(foundTx)
|
|
|
|
|
XCTAssertEqual(foundTx?.minedHeight, sentTxHeight)
|
|
|
|
|
|
|
|
|
|
foundTransactionsExpectation.fulfill()
|
|
|
|
|
}
|
|
|
|
|
try coordinator.stageBlockCreate(height: sentTxHeight, count: 100)
|
|
|
|
|
sleep(1)
|
|
|
|
|
try coordinator.stageTransaction(rawTx, at: sentTxHeight)
|
|
|
|
|
try coordinator.applyStaged(blockheight: sentTxHeight)
|
|
|
|
|
sleep(2) // add enhance breakpoint here
|
|
|
|
|
let mineExpectation = XCTestExpectation(description: "mineTxExpectation")
|
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { synchronizer in
|
2023-05-05 10:30:47 -07:00
|
|
|
|
let pendingEntity = try await synchronizer.allPendingTransactions().first(where: { $0.rawID == pendingTx.rawID })
|
2023-03-16 02:11:18 -07:00
|
|
|
|
XCTAssertNotNil(pendingEntity, "pending transaction should have been mined by now")
|
2023-05-05 10:30:47 -07:00
|
|
|
|
XCTAssertTrue(pendingEntity?.minedHeight != nil)
|
2023-03-16 02:11:18 -07:00
|
|
|
|
XCTAssertEqual(pendingEntity?.minedHeight, sentTxHeight)
|
|
|
|
|
mineExpectation.fulfill()
|
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [mineExpectation, transactionMinedExpectation, foundTransactionsExpectation], timeout: 5)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
// 7 advance to confirmation
|
2023-05-05 10:30:47 -07:00
|
|
|
|
let advanceToConfirmation = sentTxHeight + 10
|
|
|
|
|
|
|
|
|
|
try coordinator.applyStaged(blockheight: advanceToConfirmation)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
sleep(2)
|
|
|
|
|
|
|
|
|
|
let confirmExpectation = XCTestExpectation(description: "confirm expectation")
|
|
|
|
|
notificationHandler.transactionsFound = { txs in
|
|
|
|
|
XCTFail("We shouldn't find any transactions at this point but found \(txs)")
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
notificationHandler.synchronizerMinedTransaction = { transaction in
|
|
|
|
|
XCTFail("We shouldn't find any mined transactions at this point but found \(transaction)")
|
2021-03-25 10:43:20 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
confirmExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [confirmExpectation], timeout: 5)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
2023-03-31 01:49:06 -07:00
|
|
|
|
let confirmedPending = try await coordinator.synchronizer
|
2021-09-23 06:26:41 -07:00
|
|
|
|
.allPendingTransactions()
|
2023-05-05 10:30:47 -07:00
|
|
|
|
.first(where: { $0.rawID == pendingTx.rawID })
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
|
|
|
|
|
XCTAssertEqual(expectedBalance, Zatoshi(100000))
|
|
|
|
|
XCTAssertEqual(expectedVerifiedBalance, Zatoshi(100000))
|
2021-03-25 10:43:20 -07:00
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2020-06-03 16:18:57 -07:00
|
|
|
|
/**
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Verify available balance is correct in all wallet states during a send
|
|
|
|
|
|
|
|
|
|
This can be either a Wallet test or a Synchronizer test. The latter is supposed to be simpler because it involves no UI testing whatsoever.
|
|
|
|
|
|
|
|
|
|
Precondition:
|
|
|
|
|
Account has spendable funds
|
|
|
|
|
Librustzcash is ‘synced’ up to ‘current tip’
|
|
|
|
|
|
|
|
|
|
Action:
|
|
|
|
|
Send Amount(*) to zAddr
|
|
|
|
|
|
|
|
|
|
Success per state:
|
|
|
|
|
Sent: (previous available funds - spent note + change) equals to (previous available funds - sent amount)
|
|
|
|
|
Error: previous available funds equals to current funds
|
|
|
|
|
*/
|
2023-02-14 02:30:08 -08:00
|
|
|
|
// FIXME [#782]: Fix tests
|
|
|
|
|
func disabled_testVerifyAvailableBalanceDuringSend() async throws {
|
2021-05-18 14:22:29 -07:00
|
|
|
|
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
|
|
|
|
try coordinator.applyStaged(blockheight: defaultLatestHeight)
|
2022-11-23 10:05:49 -08:00
|
|
|
|
|
|
|
|
|
sleep(1)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
self.syncedExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [syncedExpectation], timeout: 60)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-03-10 03:58:28 -08:00
|
|
|
|
let spendingKey = coordinator.spendingKey
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let presendVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
there's more zatoshi to send than network fee
|
|
|
|
|
*/
|
2022-06-22 12:45:37 -07:00
|
|
|
|
XCTAssertTrue(presendVerifiedBalance >= network.constants.defaultFee(for: defaultLatestHeight) + sendAmount)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
var pendingTx: ZcashTransaction.Overview?
|
|
|
|
|
|
2022-09-13 03:19:56 -07:00
|
|
|
|
do {
|
|
|
|
|
let transaction = try await coordinator.synchronizer.sendToAddress(
|
|
|
|
|
spendingKey: spendingKey,
|
|
|
|
|
zatoshi: sendAmount,
|
2023-02-13 01:34:41 -08:00
|
|
|
|
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
|
2022-10-02 19:11:17 -07:00
|
|
|
|
memo: try Memo(string: "this is a test")
|
|
|
|
|
)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
pendingTx = transaction
|
|
|
|
|
self.sentTransactionExpectation.fulfill()
|
|
|
|
|
} catch {
|
2023-01-18 08:09:04 -08:00
|
|
|
|
// balance should be the same as before sending if transaction failed
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
XCTAssertEqual(expectedVerifiedBalance, presendVerifiedBalance)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
XCTFail("sendToAddress failed: \(error)")
|
|
|
|
|
}
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
XCTAssertTrue(expectedVerifiedBalance > .zero)
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [sentTransactionExpectation], timeout: 12)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
|
|
|
|
// sync and mine
|
|
|
|
|
|
|
|
|
|
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
|
|
|
|
XCTFail("no incoming transaction after")
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
2023-03-27 04:40:32 -07:00
|
|
|
|
let latestHeight = try await coordinator.latestHeight()
|
2020-06-03 16:18:57 -07:00
|
|
|
|
let sentTxHeight = latestHeight + 1
|
|
|
|
|
try coordinator.stageBlockCreate(height: sentTxHeight)
|
|
|
|
|
|
|
|
|
|
try coordinator.stageTransaction(rawTx, at: sentTxHeight)
|
|
|
|
|
try coordinator.applyStaged(blockheight: sentTxHeight)
|
|
|
|
|
sleep(1)
|
|
|
|
|
let mineExpectation = XCTestExpectation(description: "mineTxExpectation")
|
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
|
|
|
|
mineExpectation.fulfill()
|
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [mineExpectation], timeout: 5)
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
|
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
|
XCTAssertEqual(
|
|
|
|
|
presendVerifiedBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),
|
2023-03-30 03:49:28 -07:00
|
|
|
|
expectedBalance
|
2021-09-23 06:26:41 -07:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
XCTAssertEqual(
|
|
|
|
|
presendVerifiedBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),
|
2023-03-30 03:49:28 -07:00
|
|
|
|
expectedVerifiedBalance
|
2021-09-23 06:26:41 -07:00
|
|
|
|
)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
|
|
|
|
guard let transaction = pendingTx else {
|
|
|
|
|
XCTFail("pending transaction nil")
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2020-06-03 16:18:57 -07:00
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
basic health check
|
|
|
|
|
*/
|
2022-06-22 12:45:37 -07:00
|
|
|
|
XCTAssertEqual(transaction.value, self.sendAmount)
|
2023-05-05 10:30:47 -07:00
|
|
|
|
|
|
|
|
|
let outputs = await coordinator.synchronizer.getTransactionOutputs(for: transaction)
|
|
|
|
|
|
|
|
|
|
guard outputs.count == 2 else {
|
|
|
|
|
XCTFail("Expected sent transaction to have 2 outputs")
|
2020-06-03 16:18:57 -07:00
|
|
|
|
return
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
guard let changeOutput = outputs.first(where: { $0.isChange }) else {
|
|
|
|
|
XCTFail("Sent transaction has no change")
|
2020-06-03 16:18:57 -07:00
|
|
|
|
return
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
guard let sentOutput = outputs.first(where: { !$0.isChange }) else {
|
|
|
|
|
XCTFail("sent transaction does not have a 'sent' output")
|
2020-06-03 16:18:57 -07:00
|
|
|
|
return
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2020-06-03 16:18:57 -07:00
|
|
|
|
// (previous available funds - spent note + change) equals to (previous available funds - sent amount)
|
2021-09-23 06:26:41 -07:00
|
|
|
|
self.verifiedBalanceValidation(
|
|
|
|
|
previousBalance: presendVerifiedBalance,
|
2023-05-05 10:30:47 -07:00
|
|
|
|
spentNoteValue: sentOutput.value,
|
|
|
|
|
changeValue: changeOutput.value,
|
2022-06-22 12:45:37 -07:00
|
|
|
|
sentAmount: self.sendAmount,
|
2023-03-30 03:49:28 -07:00
|
|
|
|
currentVerifiedBalance: try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
2021-09-23 06:26:41 -07:00
|
|
|
|
)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Verify total balance in all wallet states during a send
|
|
|
|
|
This can be either a Wallet test or a Synchronizer test. The latter is supposed to be simpler because it involves no UI testing whatsoever.
|
|
|
|
|
|
|
|
|
|
Precondition:
|
|
|
|
|
Account has spendable funds
|
|
|
|
|
Librustzcash is ‘synced’ up to ‘current tip’
|
|
|
|
|
|
|
|
|
|
Action:
|
|
|
|
|
Send Amount to zAddr
|
|
|
|
|
|
|
|
|
|
Success per state:
|
|
|
|
|
Sent: (total balance funds - sentAmount) equals to (previous available funds - sent amount)
|
|
|
|
|
Error: previous total balance funds equals to current total balance
|
|
|
|
|
|
|
|
|
|
*/
|
2023-02-14 02:30:08 -08:00
|
|
|
|
// FIXME [#787]: Fix test
|
|
|
|
|
func disabled_testVerifyTotalBalanceDuringSend() async throws {
|
2021-05-18 14:22:29 -07:00
|
|
|
|
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
2020-06-04 14:36:25 -07:00
|
|
|
|
|
2020-06-03 16:18:57 -07:00
|
|
|
|
try coordinator.applyStaged(blockheight: defaultLatestHeight)
|
|
|
|
|
|
|
|
|
|
sleep(2)
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
self.syncedExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [syncedExpectation], timeout: 5)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-03-10 03:58:28 -08:00
|
|
|
|
let spendingKey = coordinator.spendingKey
|
|
|
|
|
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let presendBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
|
|
|
|
// there's more zatoshi to send than network fee
|
2022-06-22 12:45:37 -07:00
|
|
|
|
XCTAssertTrue(presendBalance >= network.constants.defaultFee(for: defaultLatestHeight) + sendAmount)
|
2023-05-05 10:30:47 -07:00
|
|
|
|
var pendingTx: ZcashTransaction.Overview?
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2022-09-13 03:19:56 -07:00
|
|
|
|
var testError: Error?
|
|
|
|
|
do {
|
|
|
|
|
let transaction = try await coordinator.synchronizer.sendToAddress(
|
|
|
|
|
spendingKey: spendingKey,
|
|
|
|
|
zatoshi: sendAmount,
|
2023-02-13 01:34:41 -08:00
|
|
|
|
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
|
2022-10-02 19:11:17 -07:00
|
|
|
|
memo: try Memo(string: "test send \(self.description) \(Date().description)")
|
|
|
|
|
)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
pendingTx = transaction
|
|
|
|
|
self.sentTransactionExpectation.fulfill()
|
|
|
|
|
} catch {
|
|
|
|
|
// balance should be the same as before sending if transaction failed
|
|
|
|
|
testError = error
|
|
|
|
|
XCTFail("sendToAddress failed: \(error)")
|
|
|
|
|
}
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
var expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
XCTAssertTrue(expectedVerifiedBalance > .zero)
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [sentTransactionExpectation], timeout: 12)
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
2022-09-13 03:19:56 -07:00
|
|
|
|
if let testError {
|
2023-03-30 03:49:28 -07:00
|
|
|
|
XCTAssertEqual(expectedVerifiedBalance, presendBalance)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
XCTFail("error: \(testError)")
|
2020-06-03 16:18:57 -07:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
guard let transaction = pendingTx else {
|
|
|
|
|
XCTFail("pending transaction nil after send")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-22 12:45:37 -07:00
|
|
|
|
XCTAssertEqual(transaction.value, self.sendAmount)
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
var expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
|
2021-09-23 06:26:41 -07:00
|
|
|
|
XCTAssertEqual(
|
2023-03-30 03:49:28 -07:00
|
|
|
|
expectedBalance,
|
2022-06-22 12:45:37 -07:00
|
|
|
|
presendBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight)
|
2021-09-23 06:26:41 -07:00
|
|
|
|
)
|
2020-06-04 14:36:25 -07:00
|
|
|
|
|
2023-03-27 04:40:32 -07:00
|
|
|
|
let latestHeight = try await coordinator.latestHeight()
|
2020-06-03 16:18:57 -07:00
|
|
|
|
let sentTxHeight = latestHeight + 1
|
|
|
|
|
try coordinator.stageBlockCreate(height: sentTxHeight)
|
|
|
|
|
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
|
|
|
|
XCTFail("no incoming transaction after send")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
|
try coordinator.stageTransaction(rawTx, at: latestHeight + 1)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
try coordinator.applyStaged(blockheight: latestHeight + 1)
|
|
|
|
|
sleep(2)
|
|
|
|
|
let mineExpectation = XCTestExpectation(description: "mineTxExpectation")
|
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
|
|
|
|
mineExpectation.fulfill()
|
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [mineExpectation], timeout: 5)
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
|
2021-09-23 06:26:41 -07:00
|
|
|
|
XCTAssertEqual(
|
2022-06-22 12:45:37 -07:00
|
|
|
|
presendBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),
|
2023-03-30 03:49:28 -07:00
|
|
|
|
expectedBalance
|
2021-09-23 06:26:41 -07:00
|
|
|
|
)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Verify incoming transactions
|
|
|
|
|
This can be either a Wallet test or a Synchronizer test. The latter is supposed to be simpler because it involves no UI testing whatsoever.
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Precondition:
|
|
|
|
|
Librustzcash is ‘synced’ up to ‘current tip’
|
|
|
|
|
Known list of expected transactions on the block range to sync the wallet up to.
|
|
|
|
|
Known expected balance on the block range to sync the wallet up to.
|
|
|
|
|
Action:
|
|
|
|
|
sync to latest height
|
|
|
|
|
Success criteria:
|
|
|
|
|
The transaction list matches the expected one
|
|
|
|
|
Balance matches expected balance
|
|
|
|
|
|
|
|
|
|
*/
|
2023-03-16 02:11:18 -07:00
|
|
|
|
func testVerifyIncomingTransaction() async throws {
|
2021-05-18 14:22:29 -07:00
|
|
|
|
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
try coordinator.applyStaged(blockheight: defaultLatestHeight)
|
2022-11-23 10:05:49 -08:00
|
|
|
|
sleep(1)
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
|
|
|
|
self.syncedExpectation.fulfill()
|
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [syncedExpectation], timeout: 5)
|
2023-03-27 07:12:06 -07:00
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
let clearedTransactions = await coordinator.synchronizer.transactions
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
|
2023-03-27 07:12:06 -07:00
|
|
|
|
XCTAssertEqual(clearedTransactions.count, 2)
|
2023-03-30 03:49:28 -07:00
|
|
|
|
XCTAssertEqual(expectedBalance, Zatoshi(200000))
|
2020-06-03 16:18:57 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Verify change transactions
|
|
|
|
|
|
|
|
|
|
This can be either a Wallet test or a Synchronizer test. The latter is supposed to be simpler because it involves no UI testing whatsoever.
|
|
|
|
|
|
|
|
|
|
Precondition
|
|
|
|
|
Librustzcash is ‘synced’ up to ‘current tip’
|
|
|
|
|
Known list of expected transactions on the block range to sync the wallet up to.
|
|
|
|
|
Known expected balance on the block range to sync the wallet up to.
|
|
|
|
|
There’s a spendable note with value > send amount that generates change
|
|
|
|
|
|
|
|
|
|
Action:
|
|
|
|
|
Send amount to zAddr
|
|
|
|
|
sync to minedHeight + 1
|
|
|
|
|
|
|
|
|
|
Success Criteria:
|
|
|
|
|
There’s a sent transaction matching the amount sent to the given zAddr
|
|
|
|
|
minedHeight is not -1
|
|
|
|
|
Balance meets verified Balance and total balance criteria
|
|
|
|
|
There’s a change note of value (previous note value - sent amount)
|
|
|
|
|
|
|
|
|
|
*/
|
2023-02-14 02:30:08 -08:00
|
|
|
|
// FIXME [#786]: Fix test
|
|
|
|
|
func disabled_testVerifyChangeTransaction() async throws {
|
2021-05-18 14:22:29 -07:00
|
|
|
|
try FakeChainBuilder.buildSingleNoteChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
|
|
|
|
try coordinator.applyStaged(blockheight: defaultLatestHeight)
|
2022-11-23 10:05:49 -08:00
|
|
|
|
sleep(1)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
let sendExpectation = XCTestExpectation(description: "send expectation")
|
|
|
|
|
let createToAddressExpectation = XCTestExpectation(description: "create to address")
|
|
|
|
|
|
|
|
|
|
try coordinator.setLatestHeight(height: defaultLatestHeight)
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2020-06-03 16:18:57 -07:00
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
sync to current tip
|
|
|
|
|
*/
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
self.syncedExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [syncedExpectation], timeout: 6)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let previousVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let previousTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-03-10 03:58:28 -08:00
|
|
|
|
let spendingKey = coordinator.spendingKey
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Send
|
|
|
|
|
*/
|
2022-05-31 05:27:24 -07:00
|
|
|
|
let memo = try Memo(string: "shielding is fun!")
|
2023-05-05 10:30:47 -07:00
|
|
|
|
var pendingTx: ZcashTransaction.Overview?
|
|
|
|
|
|
2022-09-13 03:19:56 -07:00
|
|
|
|
do {
|
|
|
|
|
let transaction = try await coordinator.synchronizer.sendToAddress(
|
2023-03-10 03:58:28 -08:00
|
|
|
|
spendingKey: spendingKey,
|
2022-09-13 03:19:56 -07:00
|
|
|
|
zatoshi: sendAmount,
|
2023-02-13 01:34:41 -08:00
|
|
|
|
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
|
2022-10-02 19:11:17 -07:00
|
|
|
|
memo: memo
|
|
|
|
|
)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
pendingTx = transaction
|
|
|
|
|
sendExpectation.fulfill()
|
|
|
|
|
} catch {
|
|
|
|
|
XCTFail("error sending \(error)")
|
|
|
|
|
}
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [createToAddressExpectation], timeout: 30)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
|
|
|
|
let syncToMinedheightExpectation = XCTestExpectation(description: "sync to mined height + 1")
|
|
|
|
|
|
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
include sent transaction in block
|
|
|
|
|
*/
|
2020-06-03 16:18:57 -07:00
|
|
|
|
guard let rawTx = try coordinator.getIncomingTransactions()?.first else {
|
|
|
|
|
XCTFail("pending transaction nil after send")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-27 04:40:32 -07:00
|
|
|
|
let latestHeight = try await coordinator.latestHeight()
|
2020-06-03 16:18:57 -07:00
|
|
|
|
let sentTxHeight = latestHeight + 1
|
|
|
|
|
try coordinator.stageBlockCreate(height: sentTxHeight, count: 12)
|
|
|
|
|
try coordinator.stageTransaction(rawTx, at: sentTxHeight)
|
|
|
|
|
try coordinator.applyStaged(blockheight: sentTxHeight + 11 )
|
|
|
|
|
sleep(2)
|
|
|
|
|
|
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Sync to that block
|
|
|
|
|
*/
|
2023-03-16 02:11:18 -07:00
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { synchronizer in
|
|
|
|
|
let confirmedTx: ZcashTransaction.Overview!
|
|
|
|
|
do {
|
2023-05-05 10:30:47 -07:00
|
|
|
|
confirmedTx = try await synchronizer.allTransactions().first(where: { confirmed -> Bool in
|
|
|
|
|
confirmed.rawID == pendingTx?.rawID
|
2023-03-16 02:11:18 -07:00
|
|
|
|
})
|
|
|
|
|
} catch {
|
|
|
|
|
XCTFail("Error retrieving cleared transactions")
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
/*
|
|
|
|
|
There’s a sent transaction matching the amount sent to the given zAddr
|
|
|
|
|
*/
|
|
|
|
|
XCTAssertEqual(confirmedTx.value, self.sendAmount)
|
|
|
|
|
// TODO [#683]: Add API to SDK to fetch memos.
|
|
|
|
|
// let confirmedMemo = try confirmedTx.memo?.intoMemoBytes()?.intoMemo()
|
|
|
|
|
// XCTAssertEqual(confirmedMemo, memo)
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
/*
|
|
|
|
|
Find out what note was used
|
|
|
|
|
*/
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
let outputs = await self.coordinator.synchronizer.getTransactionOutputs(for: confirmedTx)
|
|
|
|
|
|
|
|
|
|
guard outputs.count == 2 else {
|
|
|
|
|
XCTFail("Expected sent transaction to have 2 outputs")
|
2023-03-16 02:11:18 -07:00
|
|
|
|
return
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
guard let changeOutput = outputs.first(where: { $0.isChange }) else {
|
|
|
|
|
XCTFail("Sent transaction has no change")
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
guard let sentOutput = outputs.first(where: { !$0.isChange }) else {
|
|
|
|
|
XCTFail("sent transaction does not have a 'sent' output")
|
2023-03-16 02:11:18 -07:00
|
|
|
|
return
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
/*
|
|
|
|
|
There’s a change note of value (previous note value - sent amount)
|
|
|
|
|
*/
|
|
|
|
|
XCTAssertEqual(
|
|
|
|
|
previousVerifiedBalance - self.sendAmount - self.network.constants.defaultFee(for: self.defaultLatestHeight),
|
2023-05-05 10:30:47 -07:00
|
|
|
|
changeOutput.value
|
2023-03-16 02:11:18 -07:00
|
|
|
|
)
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
/*
|
|
|
|
|
Balance meets verified Balance and total balance criteria
|
|
|
|
|
*/
|
|
|
|
|
self.verifiedBalanceValidation(
|
|
|
|
|
previousBalance: previousVerifiedBalance,
|
2023-05-05 10:30:47 -07:00
|
|
|
|
spentNoteValue: sentOutput.value,
|
|
|
|
|
changeValue: changeOutput.value,
|
2023-03-16 02:11:18 -07:00
|
|
|
|
sentAmount: self.sendAmount,
|
2023-03-30 03:49:28 -07:00
|
|
|
|
currentVerifiedBalance: try await synchronizer.getShieldedVerifiedBalance()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
)
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
self.totalBalanceValidation(
|
2023-03-30 03:49:28 -07:00
|
|
|
|
totalBalance: try await synchronizer.getShieldedBalance(),
|
2023-03-16 02:11:18 -07:00
|
|
|
|
previousTotalbalance: previousTotalBalance,
|
|
|
|
|
sentAmount: self.sendAmount
|
|
|
|
|
)
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-03-16 02:11:18 -07:00
|
|
|
|
syncToMinedheightExpectation.fulfill()
|
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [syncToMinedheightExpectation], timeout: 5)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-12-31 02:50:16 -08:00
|
|
|
|
Verify transactions that expire are reflected accurately in balance
|
2021-09-23 06:26:41 -07:00
|
|
|
|
This test requires the transaction to expire.
|
|
|
|
|
|
|
|
|
|
How can we mock or cause this? Would createToAddress and faking a network submission through lightwalletService and syncing 10 more blocks work?
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Precondition:
|
|
|
|
|
Account has spendable funds
|
|
|
|
|
Librustzcash is ‘synced’ up to ‘current tip’ †
|
|
|
|
|
Current tip can be scanned 10 blocks past the generated to be expired transaction
|
|
|
|
|
|
|
|
|
|
Action:
|
|
|
|
|
Sync to current tip
|
|
|
|
|
Create transaction to zAddr
|
|
|
|
|
Mock send success
|
|
|
|
|
Sync 10 blocks more
|
|
|
|
|
|
|
|
|
|
Success Criteria:
|
|
|
|
|
There’s a pending transaction that has expired
|
|
|
|
|
Total Balance is equal to total balance previously shown before sending the expired transaction
|
|
|
|
|
Verified Balance is equal to verified balance previously shown before sending the expired transaction
|
|
|
|
|
*/
|
2023-02-17 02:51:48 -08:00
|
|
|
|
func testVerifyBalanceAfterExpiredTransaction() async throws {
|
2021-05-18 14:22:29 -07:00
|
|
|
|
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-02-17 02:51:48 -08:00
|
|
|
|
try coordinator.applyStaged(blockheight: self.defaultLatestHeight + 10)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
sleep(2)
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
self.syncedExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [syncedExpectation], timeout: 5)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-03-10 03:58:28 -08:00
|
|
|
|
let spendingKey = coordinator.spendingKey
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let previousVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let previousTotalBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
|
2020-06-03 16:18:57 -07:00
|
|
|
|
let sendExpectation = XCTestExpectation(description: "send expectation")
|
2023-05-05 10:30:47 -07:00
|
|
|
|
var pendingTx: ZcashTransaction.Overview?
|
2022-09-13 03:19:56 -07:00
|
|
|
|
do {
|
|
|
|
|
let pending = try await coordinator.synchronizer.sendToAddress(
|
|
|
|
|
spendingKey: spendingKey,
|
|
|
|
|
zatoshi: sendAmount,
|
2023-02-13 01:34:41 -08:00
|
|
|
|
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
|
2022-10-02 19:11:17 -07:00
|
|
|
|
memo: try Memo(string: "test send \(self.description)")
|
|
|
|
|
)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
pendingTx = pending
|
2023-02-17 02:51:48 -08:00
|
|
|
|
sendExpectation.fulfill()
|
2022-09-13 03:19:56 -07:00
|
|
|
|
} catch {
|
|
|
|
|
// balance should be the same as before sending if transaction failed
|
2023-03-30 03:49:28 -07:00
|
|
|
|
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
|
|
|
|
|
XCTAssertEqual(expectedVerifiedBalance, previousVerifiedBalance)
|
|
|
|
|
XCTAssertEqual(expectedBalance, previousTotalBalance)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
XCTFail("sendToAddress failed: \(error)")
|
|
|
|
|
}
|
2021-09-23 06:26:41 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [sendExpectation], timeout: 12)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
guard let pendingTransaction = pendingTx, let expiryHeight = pendingTransaction.expiryHeight, expiryHeight > defaultLatestHeight else {
|
2020-06-03 16:18:57 -07:00
|
|
|
|
XCTFail("No pending transaction")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let expirationSyncExpectation = XCTestExpectation(description: "expiration sync expectation")
|
2023-05-05 10:30:47 -07:00
|
|
|
|
|
2020-06-04 14:36:25 -07:00
|
|
|
|
try coordinator.applyStaged(blockheight: expiryHeight + 1)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
|
|
|
|
|
sleep(2)
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
try await coordinator.sync(
|
|
|
|
|
completion: { _ in
|
2022-09-13 03:19:56 -07:00
|
|
|
|
expirationSyncExpectation.fulfill()
|
2023-03-16 02:11:18 -07:00
|
|
|
|
},
|
|
|
|
|
error: self.handleError
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
handleError(error)
|
2022-09-13 03:19:56 -07:00
|
|
|
|
}
|
2023-03-16 02:11:18 -07:00
|
|
|
|
|
2023-04-03 06:30:08 -07:00
|
|
|
|
await fulfillment(of: [expirationSyncExpectation], timeout: 5)
|
2023-03-30 03:49:28 -07:00
|
|
|
|
|
|
|
|
|
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
|
|
|
|
|
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
|
2020-06-04 14:36:25 -07:00
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Verified Balance is equal to verified balance previously shown before sending the expired transaction
|
|
|
|
|
*/
|
2023-03-30 03:49:28 -07:00
|
|
|
|
XCTAssertEqual(expectedVerifiedBalance, previousVerifiedBalance)
|
2020-06-04 14:36:25 -07:00
|
|
|
|
|
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
Total Balance is equal to total balance previously shown before sending the expired transaction
|
|
|
|
|
*/
|
2023-03-30 03:49:28 -07:00
|
|
|
|
XCTAssertEqual(expectedBalance, previousTotalBalance)
|
2023-05-05 10:30:47 -07:00
|
|
|
|
|
2023-05-08 02:04:29 -07:00
|
|
|
|
let transactionRepo = TransactionSQLDAO(
|
|
|
|
|
dbProvider: SimpleConnectionProvider(
|
|
|
|
|
path: coordinator.synchronizer.initializer.dataDbURL.absoluteString
|
2023-05-05 10:30:47 -07:00
|
|
|
|
)
|
2021-09-23 06:26:41 -07:00
|
|
|
|
)
|
2023-05-05 10:30:47 -07:00
|
|
|
|
|
|
|
|
|
let expiredPending = try await transactionRepo.find(id: pendingTransaction.id)
|
2020-06-04 14:36:25 -07:00
|
|
|
|
|
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
there no sent transaction displayed
|
|
|
|
|
*/
|
|
|
|
|
|
2023-03-27 07:12:06 -07:00
|
|
|
|
let sentTransactions = try await coordinator.synchronizer.allSentTransactions()
|
2023-05-05 10:30:47 -07:00
|
|
|
|
XCTAssertNil(sentTransactions.first(where: { $0.id == pendingTransaction.id }))
|
2020-06-04 14:36:25 -07:00
|
|
|
|
/*
|
2021-09-23 06:26:41 -07:00
|
|
|
|
There’s a pending transaction that has expired
|
|
|
|
|
*/
|
2023-05-05 10:30:47 -07:00
|
|
|
|
XCTAssertNil(expiredPending.minedHeight)
|
2020-06-03 16:18:57 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func handleError(_ error: Error?) {
|
|
|
|
|
guard let testError = error else {
|
|
|
|
|
XCTFail("failed with nil error")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
XCTFail("Failed with error: \(testError)")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-09-23 06:26:41 -07:00
|
|
|
|
check if (previous available funds - spent note + change) equals to (previous available funds - sent amount)
|
|
|
|
|
*/
|
|
|
|
|
func verifiedBalanceValidation(
|
2022-06-22 12:45:37 -07:00
|
|
|
|
previousBalance: Zatoshi,
|
|
|
|
|
spentNoteValue: Zatoshi,
|
|
|
|
|
changeValue: Zatoshi,
|
|
|
|
|
sentAmount: Zatoshi,
|
|
|
|
|
currentVerifiedBalance: Zatoshi
|
2021-09-23 06:26:41 -07:00
|
|
|
|
) {
|
2020-06-03 16:18:57 -07:00
|
|
|
|
XCTAssertEqual(previousBalance - spentNoteValue + changeValue, currentVerifiedBalance - sentAmount)
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-23 06:26:41 -07:00
|
|
|
|
func totalBalanceValidation(
|
2022-06-22 12:45:37 -07:00
|
|
|
|
totalBalance: Zatoshi,
|
|
|
|
|
previousTotalbalance: Zatoshi,
|
|
|
|
|
sentAmount: Zatoshi
|
2021-09-23 06:26:41 -07:00
|
|
|
|
) {
|
2022-06-22 12:45:37 -07:00
|
|
|
|
XCTAssertEqual(totalBalance, previousTotalbalance - sentAmount - network.constants.defaultFee(for: defaultLatestHeight))
|
2020-06-03 16:18:57 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
class SDKSynchonizerListener {
|
2023-01-23 01:01:07 -08:00
|
|
|
|
var transactionsFound: (([ZcashTransaction.Overview]) -> Void)?
|
2023-05-05 10:30:47 -07:00
|
|
|
|
var synchronizerMinedTransaction: ((ZcashTransaction.Overview) -> Void)?
|
2023-03-15 04:17:43 -07:00
|
|
|
|
var cancellables: [AnyCancellable] = []
|
2021-03-25 10:43:20 -07:00
|
|
|
|
|
|
|
|
|
func subscribeToSynchronizer(_ synchronizer: SDKSynchronizer) {
|
2023-03-15 04:17:43 -07:00
|
|
|
|
synchronizer.eventStream
|
|
|
|
|
.sink(
|
|
|
|
|
receiveValue: { [weak self] event in
|
|
|
|
|
switch event {
|
|
|
|
|
case let .minedTransaction(transaction):
|
|
|
|
|
self?.txMined(transaction)
|
|
|
|
|
|
|
|
|
|
case let .foundTransactions(transactions, _):
|
|
|
|
|
self?.txFound(transactions)
|
|
|
|
|
|
|
|
|
|
case .storedUTXOs, .connectionStateChanged:
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
.store(in: &cancellables)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func unsubscribe() {
|
2023-03-31 02:04:39 -07:00
|
|
|
|
cancellables = []
|
2021-03-25 10:43:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-15 04:17:43 -07:00
|
|
|
|
func txFound(_ txs: [ZcashTransaction.Overview]) {
|
2021-03-25 10:43:20 -07:00
|
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
|
|
|
self?.transactionsFound?(txs)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-05 10:30:47 -07:00
|
|
|
|
func txMined(_ transaction: ZcashTransaction.Overview) {
|
2021-03-25 10:43:20 -07:00
|
|
|
|
DispatchQueue.main.async { [weak self] in
|
2021-09-23 06:26:41 -07:00
|
|
|
|
self?.synchronizerMinedTransaction?(transaction)
|
2021-03-25 10:43:20 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|