Merge pull request #1275 from nuttycom/fix/transparent_history

Update zcash-light-client-ffi to adopt fix for missing transparent history
This commit is contained in:
Kris Nuttycombe 2023-09-19 16:42:27 -06:00 committed by GitHub
commit 17a36bb02d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 125 additions and 174 deletions

View File

@ -158,8 +158,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi",
"state" : {
"revision" : "8607dc26a637697e53e0be1fb09b81cba9d8475a",
"version" : "0.4.0-rc.2"
"revision" : "d085da2f5cae103fe88e727713071644a4bfa5a2",
"version" : "0.4.0-rc.3"
}
}
],

View File

@ -81,7 +81,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
options: NotificationBubble.sucessOptions(
animation: NotificationBubble.Animation.fade(duration: 1)
),
attributedText: NSAttributedString(string: "Transaction \(String(describing: transaction.id))mined!"),
attributedText: NSAttributedString(string: "Transaction \(String(describing: transaction.rawID))mined!"),
handleTap: {}
)
}

View File

@ -37,8 +37,10 @@ class TransactionsDataSource: NSObject {
case .cleared:
let rawTransactions = await synchronizer.transactions
for transaction in rawTransactions {
let memos = try await synchronizer.getMemos(for: transaction)
transactions.append(TransactionDetailModel(transaction: transaction, memos: memos))
if transaction.minedHeight != nil {
let memos = try await synchronizer.getMemos(for: transaction)
transactions.append(TransactionDetailModel(transaction: transaction, memos: memos))
}
}
case .received:
let rawTransactions = await synchronizer.receivedTransactions

View File

@ -10,6 +10,10 @@ import UIKit
import ZcashLightClientKit
final class TransactionDetailModel {
// FIXME: This enumeration does not represent a sensible set of potential transaction states.
// A transaction may be both sent from and received by the same wallet, and in either
// case this designation is orthogonal with respect to whether the transaction is
// in a pending, mined, or expired state.
enum Transaction {
case sent(ZcashTransaction.Overview)
case received(ZcashTransaction.Overview)
@ -62,7 +66,11 @@ final class TransactionDetailModel {
}
init(transaction: ZcashTransaction.Overview, memos: [Memo]) {
self.transaction = .cleared(transaction)
if transaction.minedHeight == nil {
self.transaction = .pending(transaction)
} else {
self.transaction = .cleared(transaction)
}
self.id = transaction.rawID
self.minedHeight = transaction.minedHeight
self.expiryHeight = transaction.expiryHeight

View File

@ -1,14 +1,5 @@
{
"pins" : [
{
"identity" : "csqlite",
"kind" : "remoteSourceControl",
"location" : "https://github.com/stephencelis/CSQLite.git",
"state" : {
"revision" : "9106e983d5e3d5149ee35281ec089484b0def018",
"version" : "0.0.3"
}
},
{
"identity" : "grpc-swift",
"kind" : "remoteSourceControl",
@ -113,8 +104,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi",
"state" : {
"revision" : "8607dc26a637697e53e0be1fb09b81cba9d8475a",
"version" : "0.4.0-rc.2"
"revision" : "d085da2f5cae103fe88e727713071644a4bfa5a2",
"version" : "0.4.0-rc.3"
}
}
],

View File

@ -16,7 +16,7 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.14.0"),
.package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1"),
.package(url: "https://github.com/zcash-hackworks/zcash-light-client-ffi", from: "0.4.0-rc.2")
.package(url: "https://github.com/zcash-hackworks/zcash-light-client-ffi", from: "0.4.0-rc.3")
],
targets: [
.target(

View File

@ -46,7 +46,7 @@ public struct EnhancementProgress: Equatable {
return
lhs.totalTransactions == rhs.totalTransactions &&
lhs.enhancedTransactions == rhs.enhancedTransactions &&
lhs.lastFoundTransaction?.id == rhs.lastFoundTransaction?.id &&
lhs.lastFoundTransaction?.rawID == rhs.lastFoundTransaction?.rawID &&
lhs.range == rhs.range
}
}

View File

@ -55,14 +55,6 @@ class TransactionSQLDAO: TransactionRepository {
}
}
func find(id: Int) async throws -> ZcashTransaction.Overview {
let query = transactionsView
.filter(ZcashTransaction.Overview.Column.id == id)
.limit(1)
return try execute(query) { try ZcashTransaction.Overview(row: $0) }
}
func find(rawID: Data) async throws -> ZcashTransaction.Overview {
let query = transactionsView
.filter(ZcashTransaction.Overview.Column.rawID == Blob(bytes: rawID.bytes))
@ -73,7 +65,7 @@ class TransactionSQLDAO: TransactionRepository {
func find(offset: Int, limit: Int, kind: TransactionKind) async throws -> [ZcashTransaction.Overview] {
let query = transactionsView
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc, ZcashTransaction.Overview.Column.id.desc)
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc)
.filterQueryFor(kind: kind)
.limit(limit, offset: offset)
@ -82,7 +74,7 @@ class TransactionSQLDAO: TransactionRepository {
func find(in range: CompactBlockRange, limit: Int, kind: TransactionKind) async throws -> [ZcashTransaction.Overview] {
let query = transactionsView
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc, ZcashTransaction.Overview.Column.id.desc)
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc)
.filter(
ZcashTransaction.Overview.Column.minedHeight >= BlockHeight(range.lowerBound) &&
ZcashTransaction.Overview.Column.minedHeight <= BlockHeight(range.upperBound)
@ -95,17 +87,18 @@ class TransactionSQLDAO: TransactionRepository {
func find(from transaction: ZcashTransaction.Overview, limit: Int, kind: TransactionKind) async throws -> [ZcashTransaction.Overview] {
guard
let transactionIndex = transaction.index,
let transactionBlockTime = transaction.blockTime
let transactionBlockHeight = transaction.minedHeight
else { throw ZcashError.transactionRepositoryTransactionMissingRequiredFields }
let transactionIndex = transaction.index ?? Int.max
let query = transactionsView
.order(
(ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc, ZcashTransaction.Overview.Column.id.desc
)
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc)
.filter(
Int64(transactionBlockTime) > ZcashTransaction.Overview.Column.blockTime
&& transactionIndex > ZcashTransaction.Overview.Column.index
transactionBlockHeight > ZcashTransaction.Overview.Column.minedHeight
|| (
transactionBlockHeight == ZcashTransaction.Overview.Column.minedHeight &&
transactionIndex > (ZcashTransaction.Overview.Column.index ?? -1)
)
)
.filterQueryFor(kind: kind)
.limit(limit)
@ -116,7 +109,7 @@ class TransactionSQLDAO: TransactionRepository {
func findReceived(offset: Int, limit: Int) async throws -> [ZcashTransaction.Overview] {
let query = transactionsView
.filterQueryFor(kind: .received)
.order(ZcashTransaction.Overview.Column.id.desc, (ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc)
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc)
.limit(limit, offset: offset)
return try execute(query) { try ZcashTransaction.Overview(row: $0) }
@ -125,7 +118,7 @@ class TransactionSQLDAO: TransactionRepository {
func findSent(offset: Int, limit: Int) async throws -> [ZcashTransaction.Overview] {
let query = transactionsView
.filterQueryFor(kind: .sent)
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc, ZcashTransaction.Overview.Column.id.desc)
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc)
.limit(limit, offset: offset)
return try execute(query) { try ZcashTransaction.Overview(row: $0) }
@ -134,7 +127,7 @@ class TransactionSQLDAO: TransactionRepository {
func findPendingTransactions(latestHeight: BlockHeight, offset: Int, limit: Int) async throws -> [ZcashTransaction.Overview] {
let query = transactionsView
.filterPendingFrom(latestHeight)
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc, ZcashTransaction.Overview.Column.id.desc)
.order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).desc)
.limit(limit, offset: offset)
return try execute(query) { try ZcashTransaction.Overview(row: $0) }
@ -142,22 +135,22 @@ class TransactionSQLDAO: TransactionRepository {
func findMemos(for transaction: ZcashTransaction.Overview) async throws -> [Memo] {
do {
return try await getTransactionOutputs(for: transaction.id)
return try await getTransactionOutputs(for: transaction.rawID)
.compactMap { $0.memo }
} catch {
throw ZcashError.transactionRepositoryFindMemos(error)
}
}
func getTransactionOutputs(for id: Int) async throws -> [ZcashTransaction.Output] {
func getTransactionOutputs(for rawID: Data) async throws -> [ZcashTransaction.Output] {
let query = self.txOutputsView
.filter(ZcashTransaction.Output.Column.idTx == id)
.filter(ZcashTransaction.Output.Column.rawID == Blob(bytes: rawID.bytes))
return try execute(query) { try ZcashTransaction.Output(row: $0) }
}
func getRecipients(for id: Int) async throws -> [TransactionRecipient] {
try await getTransactionOutputs(for: id).map { $0.recipient }
func getRecipients(for rawID: Data) async throws -> [TransactionRecipient] {
try await getTransactionOutputs(for: rawID).map { $0.recipient }
}
private func execute<Entity>(_ query: View, createEntity: (Row) throws -> Entity) throws -> Entity {

View File

@ -25,9 +25,9 @@ public enum ZcashTransaction {
init(
currentHeight: BlockHeight,
minedHeight: BlockHeight?,
expiredUnmined: Bool
expiredUnmined: Bool?
) {
guard !expiredUnmined else {
guard let expiredUnmined, !expiredUnmined else {
self = .expired
return
}
@ -48,7 +48,6 @@ public enum ZcashTransaction {
public let blockTime: TimeInterval?
public let expiryHeight: BlockHeight?
public let fee: Zatoshi?
public let id: Int
public let index: Int?
public var isSentTransaction: Bool { value < Zatoshi(0) }
public let hasChange: Bool
@ -59,7 +58,7 @@ public enum ZcashTransaction {
public let receivedNoteCount: Int
public let sentNoteCount: Int
public let value: Zatoshi
public let isExpiredUmined: Bool
public let isExpiredUmined: Bool?
}
public struct Output {
@ -79,7 +78,7 @@ public enum ZcashTransaction {
}
}
public let idTx: Int
public let rawID: Data
public let pool: Pool
public let index: Int
public let fromAccount: Int?
@ -99,7 +98,7 @@ public enum ZcashTransaction {
extension ZcashTransaction.Output {
enum Column {
static let idTx = Expression<Int>("id_tx")
static let rawID = Expression<Blob>("txid")
static let pool = Expression<Int>("output_pool")
static let index = Expression<Int>("output_index")
static let toAccount = Expression<Int?>("to_account")
@ -112,7 +111,7 @@ extension ZcashTransaction.Output {
init(row: Row) throws {
do {
idTx = try row.get(Column.idTx)
rawID = Data(blob: try row.get(Column.rawID))
pool = .init(rawValue: try row.get(Column.pool))
index = try row.get(Column.index)
fromAccount = try row.get(Column.fromAccount)
@ -144,7 +143,6 @@ extension ZcashTransaction.Output {
extension ZcashTransaction.Overview {
enum Column {
static let accountId = Expression<Int>("account_id")
static let id = Expression<Int>("id_tx")
static let minedHeight = Expression<BlockHeight?>("mined_height")
static let index = Expression<Int?>("tx_index")
static let rawID = Expression<Blob>("txid")
@ -157,14 +155,13 @@ extension ZcashTransaction.Overview {
static let receivedNoteCount = Expression<Int>("received_note_count")
static let memoCount = Expression<Int>("memo_count")
static let blockTime = Expression<Int64?>("block_time")
static let expiredUnmined = Expression<Bool>("expired_unmined")
static let expiredUnmined = Expression<Bool?>("expired_unmined")
}
init(row: Row) throws {
do {
self.accountId = try row.get(Column.accountId)
self.expiryHeight = try row.get(Column.expiryHeight)
self.id = try row.get(Column.id)
self.index = try row.get(Column.index)
self.hasChange = try row.get(Column.hasChange)
self.memoCount = try row.get(Column.memoCount)

View File

@ -12,7 +12,6 @@ protocol TransactionRepository {
func countAll() async throws -> Int
func countUnmined() async throws -> Int
func isInitialized() async throws -> Bool
func find(id: Int) async throws -> ZcashTransaction.Overview
func find(rawID: Data) async throws -> ZcashTransaction.Overview
func find(offset: Int, limit: Int, kind: TransactionKind) async throws -> [ZcashTransaction.Overview]
func find(in range: CompactBlockRange, limit: Int, kind: TransactionKind) async throws -> [ZcashTransaction.Overview]
@ -21,6 +20,6 @@ protocol TransactionRepository {
func findReceived(offset: Int, limit: Int) async throws -> [ZcashTransaction.Overview]
func findSent(offset: Int, limit: Int) async throws -> [ZcashTransaction.Overview]
func findMemos(for transaction: ZcashTransaction.Overview) async throws -> [Memo]
func getRecipients(for id: Int) async throws -> [TransactionRecipient]
func getTransactionOutputs(for id: Int) async throws -> [ZcashTransaction.Output]
func getRecipients(for rawID: Data) async throws -> [TransactionRecipient]
func getTransactionOutputs(for rawID: Data) async throws -> [ZcashTransaction.Output]
}

View File

@ -386,11 +386,11 @@ public class SDKSynchronizer: Synchronizer {
}
public func getRecipients(for transaction: ZcashTransaction.Overview) async -> [TransactionRecipient] {
return (try? await transactionRepository.getRecipients(for: transaction.id)) ?? []
return (try? await transactionRepository.getRecipients(for: transaction.rawID)) ?? []
}
public func getTransactionOutputs(for transaction: ZcashTransaction.Overview) async -> [ZcashTransaction.Output] {
return (try? await transactionRepository.getTransactionOutputs(for: transaction.id)) ?? []
return (try? await transactionRepository.getTransactionOutputs(for: transaction.rawID)) ?? []
}
public func latestHeight() async throws -> BlockHeight {

View File

@ -10,8 +10,8 @@ import Foundation
typealias TransactionEncoderResultBlock = (_ result: Result<EncodedTransaction, Error>) -> Void
public enum TransactionEncoderError: Error {
case notFound(transactionId: Int)
case notEncoded(transactionId: Int)
case notFound(txId: Data)
case notEncoded(txId: Data)
case missingParams
case spendingKeyWrongNetwork
case couldNotExpand(txId: Data)

View File

@ -157,7 +157,7 @@ class WalletTransactionEncoder: TransactionEncoder {
extension ZcashTransaction.Overview {
func encodedTransaction() throws -> EncodedTransaction {
guard let raw else {
throw TransactionEncoderError.notEncoded(transactionId: self.id)
throw TransactionEncoderError.notEncoded(txId: self.rawID)
}
return EncodedTransaction(transactionId: self.rawID, raw: raw)

View File

@ -1148,14 +1148,14 @@ class BalanceTests: ZcashTestCase {
)
)
let expiredPending = try await transactionRepo.find(id: pendingTransaction.id)
let expiredPending = try await transactionRepo.find(rawID: pendingTransaction.rawID)
/*
there no sent transaction displayed
*/
let sentTransactions = try await coordinator.synchronizer.allSentTransactions()
XCTAssertNil(sentTransactions.first(where: { $0.id == pendingTransaction.id }))
XCTAssertNil(sentTransactions.first(where: { $0.rawID == pendingTransaction.rawID }))
/*
Theres a pending transaction that has expired
*/

View File

@ -415,7 +415,7 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
synchronizer.clearedTransactions() { transactions in
XCTAssertEqual(transactions.count, 1)
XCTAssertEqual(transactions[0].id, self.data.clearedTransaction.id)
XCTAssertEqual(transactions[0].rawID, self.data.clearedTransaction.rawID)
expectation.fulfill()
}
@ -429,7 +429,7 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
synchronizer.sentTranscations() { transactions in
XCTAssertEqual(transactions.count, 1)
XCTAssertEqual(transactions[0].id, self.data.sentTransaction.id)
XCTAssertEqual(transactions[0].rawID, self.data.sentTransaction.rawID)
expectation.fulfill()
}
@ -443,7 +443,7 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
synchronizer.receivedTransactions() { transactions in
XCTAssertEqual(transactions.count, 1)
XCTAssertEqual(transactions[0].id, self.data.receivedTransaction.id)
XCTAssertEqual(transactions[0].rawID, self.data.receivedTransaction.rawID)
expectation.fulfill()
}
@ -454,7 +454,7 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
let memo: Memo = .text(try MemoText("Some message"))
synchronizerMock.getMemosForClearedTransactionClosure = { receivedTransaction in
XCTAssertEqual(receivedTransaction.id, self.data.clearedTransaction.id)
XCTAssertEqual(receivedTransaction.rawID, self.data.clearedTransaction.rawID)
return [memo]
}
@ -497,7 +497,7 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
let expectedRecipient: TransactionRecipient = .address(.transparent(data.transparentAddress))
synchronizerMock.getRecipientsForClearedTransactionClosure = { receivedTransaction in
XCTAssertEqual(receivedTransaction.id, self.data.clearedTransaction.id)
XCTAssertEqual(receivedTransaction.rawID, self.data.clearedTransaction.rawID)
return [expectedRecipient]
}
@ -514,7 +514,7 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
func testAllConfirmedTransactionsSucceed() throws {
synchronizerMock.allTransactionsFromLimitClosure = { receivedTransaction, limit in
XCTAssertEqual(receivedTransaction.id, self.data.clearedTransaction.id)
XCTAssertEqual(receivedTransaction.rawID, self.data.clearedTransaction.rawID)
XCTAssertEqual(limit, 3)
return [self.data.clearedTransaction]
}
@ -525,7 +525,7 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
switch result {
case let .success(transactions):
XCTAssertEqual(transactions.count, 1)
XCTAssertEqual(transactions[0].id, self.data.clearedTransaction.id)
XCTAssertEqual(transactions[0].rawID, self.data.clearedTransaction.rawID)
expectation.fulfill()
case let .failure(error):
XCTFail("Unpected failure with error: \(error)")

View File

@ -390,7 +390,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
}
},
receiveValue: { value in
XCTAssertEqual(value.id, self.data.pendingTransactionEntity.id)
XCTAssertEqual(value.rawID, self.data.pendingTransactionEntity.rawID)
}
)
.store(in: &cancellables)
@ -444,7 +444,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
}
},
receiveValue: { value in
XCTAssertEqual(value.map { $0.id }, [self.data.clearedTransaction.id])
XCTAssertEqual(value.map { $0.rawID }, [self.data.clearedTransaction.rawID])
}
)
.store(in: &cancellables)
@ -468,7 +468,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
}
},
receiveValue: { value in
XCTAssertEqual(value.map { $0.id }, [self.data.sentTransaction.id])
XCTAssertEqual(value.map { $0.rawID }, [self.data.sentTransaction.rawID])
}
)
.store(in: &cancellables)
@ -492,7 +492,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
}
},
receiveValue: { value in
XCTAssertEqual(value.map { $0.id }, [self.data.receivedTransaction.id])
XCTAssertEqual(value.map { $0.rawID }, [self.data.receivedTransaction.rawID])
}
)
.store(in: &cancellables)
@ -504,7 +504,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
let memo: Memo = .text(try MemoText("Some message"))
synchronizerMock.getMemosForClearedTransactionClosure = { receivedTransaction in
XCTAssertEqual(receivedTransaction.id, self.data.clearedTransaction.id)
XCTAssertEqual(receivedTransaction.rawID, self.data.clearedTransaction.rawID)
return [memo]
}
@ -559,7 +559,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
let expectedRecipient = TransactionRecipient.address(.transparent(self.data.transparentAddress))
synchronizerMock.getRecipientsForClearedTransactionClosure = { receivedTransaction in
XCTAssertEqual(receivedTransaction.id, self.data.clearedTransaction.id)
XCTAssertEqual(receivedTransaction.rawID, self.data.clearedTransaction.rawID)
return [expectedRecipient]
}
@ -586,7 +586,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
func testAllConfirmedTransactionsSucceed() throws {
synchronizerMock.allTransactionsFromLimitClosure = { receivedTransaction, limit in
XCTAssertEqual(receivedTransaction.id, self.data.clearedTransaction.id)
XCTAssertEqual(receivedTransaction.rawID, self.data.clearedTransaction.rawID)
XCTAssertEqual(limit, 3)
return [self.data.clearedTransaction]
}
@ -604,7 +604,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
}
},
receiveValue: { value in
XCTAssertEqual(value.map { $0.id }, [self.data.clearedTransaction.id])
XCTAssertEqual(value.map { $0.rawID }, [self.data.clearedTransaction.rawID])
}
)
.store(in: &cancellables)

View File

@ -141,18 +141,18 @@ final class EnhanceActionTests: ZcashTestCase {
func testEnhanceAction_EnhancementOfBlocksCalled_FoundTransactions() async throws {
let blockEnhancerMock = BlockEnhancerMock()
let rawID = Data(fromHexEncodedString: "90058596ae18adedfd74681aee3812c2a7d3d361934347fb05550c77b677a615")!
let transaction = ZcashTransaction.Overview(
accountId: 0,
blockTime: 1.0,
expiryHeight: 663206,
fee: Zatoshi(0),
id: 2,
index: 1,
hasChange: false,
memoCount: 1,
minedHeight: 663188,
raw: Data(),
rawID: Data(),
rawID: rawID,
receivedNoteCount: 1,
sentNoteCount: 0,
value: Zatoshi(100000),
@ -197,19 +197,19 @@ final class EnhanceActionTests: ZcashTestCase {
func testEnhanceAction_EnhancementOfBlocksCalled_minedTransaction() async throws {
let blockEnhancerMock = BlockEnhancerMock()
let rawID = Data(fromHexEncodedString: "90058596ae18adedfd74681aee3812c2a7d3d361934347fb05550c77b677a615")!
let transaction = ZcashTransaction.Overview(
accountId: 0,
blockTime: 1.0,
expiryHeight: 663206,
fee: Zatoshi(0),
id: 2,
index: 1,
hasChange: false,
memoCount: 1,
minedHeight: 663188,
raw: Data(),
rawID: Data(),
rawID: rawID,
receivedNoteCount: 1,
sentNoteCount: 0,
value: Zatoshi(100000),
@ -259,18 +259,18 @@ final class EnhanceActionTests: ZcashTestCase {
func testEnhanceAction_EnhancementOfBlocksCalled_usingSmallRange_minedTransaction() async throws {
let blockEnhancerMock = BlockEnhancerMock()
let rawID = Data(fromHexEncodedString: "90058596ae18adedfd74681aee3812c2a7d3d361934347fb05550c77b677a615")!
let transaction = ZcashTransaction.Overview(
accountId: 0,
blockTime: 1.0,
expiryHeight: 663206,
fee: Zatoshi(0),
id: 2,
index: 1,
hasChange: false,
memoCount: 1,
minedHeight: 663188,
raw: Data(),
rawID: Data(),
rawID: rawID,
receivedNoteCount: 1,
sentNoteCount: 0,
value: Zatoshi(100000),

View File

@ -14,7 +14,11 @@ class TransactionRepositoryTests: XCTestCase {
override func setUp() async throws {
try await super.setUp()
let rustBackend = ZcashRustBackend.makeForTests(fsBlockDbRoot: Environment.uniqueTestTempDirectory, networkType: .testnet)
let rustBackend = ZcashRustBackend.makeForTests(
dbData: TestDbBuilder.prePopulatedMainnetDataDbURL()!,
fsBlockDbRoot: Environment.uniqueTestTempDirectory,
networkType: .mainnet
)
transactionRepository = try! await TestDbBuilder.transactionRepository(rustBackend: rustBackend)
}
@ -46,17 +50,10 @@ class TransactionRepositoryTests: XCTestCase {
XCTAssertEqual(transactions[2].isSentTransaction, false)
}
func testFindById() async throws {
let transaction = try await self.transactionRepository.find(id: 10)
XCTAssertEqual(transaction.id, 10)
XCTAssertEqual(transaction.minedHeight, 663942)
XCTAssertEqual(transaction.index, 5)
}
func testFindByTxId() async throws {
let id = Data(fromHexEncodedString: "01af48bcc4e9667849a073b8b5c539a0fc19de71aac775377929dc6567a36eff")!
let transaction = try await self.transactionRepository.find(rawID: id)
XCTAssertEqual(transaction.id, 8)
XCTAssertEqual(transaction.rawID, id)
XCTAssertEqual(transaction.minedHeight, 663922)
XCTAssertEqual(transaction.index, 1)
}
@ -94,19 +91,26 @@ class TransactionRepositoryTests: XCTestCase {
XCTAssertEqual(transactions[2].minedHeight, 663956)
}
func testGetTransactionOutputs() async throws {
let rawID = Data(fromHexEncodedString: "08cb5838ffd2c18ce15e7e8c50174940cd9526fff37601986f5480b7ca07e534")!
let outputs = try await self.transactionRepository.getTransactionOutputs(for: rawID)
XCTAssertEqual(outputs.count, 2)
}
func testFindMemoForTransaction() async throws {
let rawID = Data(fromHexEncodedString: "08cb5838ffd2c18ce15e7e8c50174940cd9526fff37601986f5480b7ca07e534")!
let transaction = ZcashTransaction.Overview(
accountId: 0,
blockTime: nil,
expiryHeight: nil,
fee: nil,
id: 9,
index: nil,
hasChange: false,
memoCount: 0,
minedHeight: nil,
raw: nil,
rawID: Data(),
rawID: rawID,
receivedNoteCount: 0,
sentNoteCount: 0,
value: Zatoshi(-1000),
@ -116,7 +120,7 @@ class TransactionRepositoryTests: XCTestCase {
let memos = try await self.transactionRepository.findMemos(for: transaction)
guard memos.count == 1 else {
XCTFail("Expected transaction to have one memo")
XCTFail("Expected transaction to have one memo, found \(memos.count)")
return
}
@ -124,18 +128,18 @@ class TransactionRepositoryTests: XCTestCase {
}
func testFindMemoForReceivedTransaction() async throws {
let rawID = Data(fromHexEncodedString: "1f49cfcfcdebd5cb9085d9ff2efbcda87121dda13f2c791113fcf2e79ba82108")!
let transaction = ZcashTransaction.Overview(
accountId: 0,
blockTime: 1,
expiryHeight: nil,
fee: nil,
id: 5,
index: 0,
hasChange: false,
memoCount: 1,
minedHeight: 0,
raw: nil,
rawID: Data(),
rawID: rawID,
receivedNoteCount: 1,
sentNoteCount: 0,
value: .zero,
@ -148,18 +152,18 @@ class TransactionRepositoryTests: XCTestCase {
}
func testFindMemoForSentTransaction() async throws {
let rawID = Data(fromHexEncodedString: "08cb5838ffd2c18ce15e7e8c50174940cd9526fff37601986f5480b7ca07e534")!
let transaction = ZcashTransaction.Overview(
accountId: 0,
blockTime: 1,
expiryHeight: nil,
fee: nil,
id: 9,
index: 0,
hasChange: false,
memoCount: 1,
minedHeight: nil,
raw: nil,
rawID: Data(),
rawID: rawID,
receivedNoteCount: 0,
sentNoteCount: 2,
value: .zero,
@ -189,24 +193,25 @@ class TransactionRepositoryTests: XCTestCase {
}
func testFindAllFrom() async throws {
let transaction = try await self.transactionRepository.find(id: 16)
let rawID = Data(fromHexEncodedString: "5d9b91e31a6d3f94844a4c330e727a2d5d0643f6caa6c75573b28aefe859e8d2")!
let transaction = try await self.transactionRepository.find(rawID: rawID)
let transactionsFrom = try await self.transactionRepository.find(from: transaction, limit: Int.max, kind: .all)
XCTAssertEqual(transactionsFrom.count, 8)
XCTAssertEqual(transactionsFrom.count, 15)
transactionsFrom.forEach { preceededTransaction in
guard let preceededTransactionIndex = preceededTransaction.index, let transactionIndex = transaction.index else {
XCTFail("Transactions are missing indexes.")
guard let precedingHeight = preceededTransaction.minedHeight, let transactionHeight = transaction.minedHeight else {
XCTFail("Transactions are missing mined heights.")
return
}
guard let preceededTransactionBlockTime = preceededTransaction.blockTime, let transactionBlockTime = transaction.blockTime else {
guard let precedingBlockTime = preceededTransaction.blockTime, let transactionBlockTime = transaction.blockTime else {
XCTFail("Transactions are missing block time.")
return
}
XCTAssertLessThan(preceededTransactionIndex, transactionIndex)
XCTAssertLessThan(preceededTransactionBlockTime, transactionBlockTime)
XCTAssertLessThanOrEqual(precedingHeight, transactionHeight)
XCTAssertLessThan(precedingBlockTime, transactionBlockTime)
}
}
}

View File

@ -73,7 +73,7 @@ extension MockTransactionRepository.Kind: Equatable {}
// MARK: - TransactionRepository
extension MockTransactionRepository: TransactionRepository {
func getTransactionOutputs(for id: Int) async throws -> [ZcashLightClientKit.ZcashTransaction.Output] {
func getTransactionOutputs(for rawID: Data) async throws -> [ZcashLightClientKit.ZcashTransaction.Output] {
[]
}
@ -81,7 +81,7 @@ extension MockTransactionRepository: TransactionRepository {
[]
}
func getRecipients(for id: Int) -> [TransactionRecipient] {
func getRecipients(for rawID: Data) -> [TransactionRecipient] {
[]
}
@ -95,10 +95,6 @@ extension MockTransactionRepository: TransactionRepository {
unminedCount
}
func findBy(id: Int) throws -> ZcashTransaction.Overview? {
transactions.first(where: { $0.id == id })
}
func findBy(rawId: Data) throws -> ZcashTransaction.Overview? {
transactions.first(where: { $0.rawID == rawId })
}
@ -139,7 +135,6 @@ extension MockTransactionRepository: TransactionRepository {
blockTime: randomTimeInterval(),
expiryHeight: BlockHeight.max,
fee: Zatoshi(2),
id: index,
index: index,
hasChange: true,
memoCount: 0,
@ -159,7 +154,6 @@ extension MockTransactionRepository: TransactionRepository {
blockTime: randomTimeInterval(),
expiryHeight: BlockHeight.max,
fee: Zatoshi(2),
id: index,
index: index,
hasChange: true,
memoCount: 0,
@ -179,14 +173,6 @@ extension MockTransactionRepository: TransactionRepository {
return Array(txs[offset ..< min(offset + limit, txs.count - offset)])
}
func find(id: Int) throws -> ZcashTransaction.Overview {
guard let transaction = transactions.first(where: { $0.id == id }) else {
throw ZcashError.transactionRepositoryEntityNotFound
}
return transaction
}
func find(rawID: Data) throws -> ZcashTransaction.Overview {
guard let transaction = transactions.first(where: { $0.rawID == rawID }) else {
throw ZcashError.transactionRepositoryEntityNotFound

View File

@ -1708,30 +1708,6 @@ class TransactionRepositoryMock: TransactionRepository {
// MARK: - find
var findIdThrowableError: Error?
var findIdCallsCount = 0
var findIdCalled: Bool {
return findIdCallsCount > 0
}
var findIdReceivedId: Int?
var findIdReturnValue: ZcashTransaction.Overview!
var findIdClosure: ((Int) async throws -> ZcashTransaction.Overview)?
func find(id: Int) async throws -> ZcashTransaction.Overview {
if let error = findIdThrowableError {
throw error
}
findIdCallsCount += 1
findIdReceivedId = id
if let closure = findIdClosure {
return try await closure(id)
} else {
return findIdReturnValue
}
}
// MARK: - find
var findRawIDThrowableError: Error?
var findRawIDCallsCount = 0
var findRawIDCalled: Bool {
@ -1929,18 +1905,18 @@ class TransactionRepositoryMock: TransactionRepository {
var getRecipientsForCalled: Bool {
return getRecipientsForCallsCount > 0
}
var getRecipientsForReceivedId: Int?
var getRecipientsForReceivedRawID: Data?
var getRecipientsForReturnValue: [TransactionRecipient]!
var getRecipientsForClosure: ((Int) async throws -> [TransactionRecipient])?
var getRecipientsForClosure: ((Data) async throws -> [TransactionRecipient])?
func getRecipients(for id: Int) async throws -> [TransactionRecipient] {
func getRecipients(for rawID: Data) async throws -> [TransactionRecipient] {
if let error = getRecipientsForThrowableError {
throw error
}
getRecipientsForCallsCount += 1
getRecipientsForReceivedId = id
getRecipientsForReceivedRawID = rawID
if let closure = getRecipientsForClosure {
return try await closure(id)
return try await closure(rawID)
} else {
return getRecipientsForReturnValue
}
@ -1953,18 +1929,18 @@ class TransactionRepositoryMock: TransactionRepository {
var getTransactionOutputsForCalled: Bool {
return getTransactionOutputsForCallsCount > 0
}
var getTransactionOutputsForReceivedId: Int?
var getTransactionOutputsForReceivedRawID: Data?
var getTransactionOutputsForReturnValue: [ZcashTransaction.Output]!
var getTransactionOutputsForClosure: ((Int) async throws -> [ZcashTransaction.Output])?
var getTransactionOutputsForClosure: ((Data) async throws -> [ZcashTransaction.Output])?
func getTransactionOutputs(for id: Int) async throws -> [ZcashTransaction.Output] {
func getTransactionOutputs(for rawID: Data) async throws -> [ZcashTransaction.Output] {
if let error = getTransactionOutputsForThrowableError {
throw error
}
getTransactionOutputsForCallsCount += 1
getTransactionOutputsForReceivedId = id
getTransactionOutputsForReceivedRawID = rawID
if let closure = getTransactionOutputsForClosure {
return try await closure(id)
return try await closure(rawID)
} else {
return getTransactionOutputsForReturnValue
}

View File

@ -54,10 +54,8 @@ enum TestDbBuilder {
Bundle.module.url(forResource: "darkside_caches", withExtension: "db")
}
static func prepopulatedDataDbProvider(rustBackend: ZcashRustBackendWelding) async throws -> ConnectionProvider? {
guard let url = prePopulatedMainnetDataDbURL() else { return nil }
let provider = SimpleConnectionProvider(path: url.absoluteString, readonly: true)
static func prepopulatedDataDbProvider(rustBackend: ZcashRustBackend) async throws -> ConnectionProvider? {
let provider = SimpleConnectionProvider(path: (await rustBackend.dbData).0, readonly: true)
let initResult = try await rustBackend.initDataDb(seed: Environment.seedBytes)
@ -68,13 +66,13 @@ enum TestDbBuilder {
}
}
static func transactionRepository(rustBackend: ZcashRustBackendWelding) async throws -> TransactionRepository? {
static func transactionRepository(rustBackend: ZcashRustBackend) async throws -> TransactionRepository? {
guard let provider = try await prepopulatedDataDbProvider(rustBackend: rustBackend) else { return nil }
return TransactionSQLDAO(dbProvider: provider)
}
static func transactionRepository(rustBackend: ZcashRustBackendWelding, withTrace closure: @escaping ((String) -> Void)) async throws -> TransactionRepository? {
static func transactionRepository(rustBackend: ZcashRustBackend, withTrace closure: @escaping ((String) -> Void)) async throws -> TransactionRepository? {
guard let provider = try await prepopulatedDataDbProvider(rustBackend: rustBackend) else { return nil }
return TransactionSQLDAO(dbProvider: provider, traceClosure: closure)

View File

@ -146,7 +146,7 @@ extension ZcashRustBackend {
spendParamsPath: URL = SaplingParamsSourceURL.default.spendParamFileURL,
outputParamsPath: URL = SaplingParamsSourceURL.default.outputParamFileURL,
networkType: NetworkType
) -> ZcashRustBackendWelding {
) -> ZcashRustBackend {
ZcashRustBackend(
dbData: dbData,
fsBlockDbRoot: fsBlockDbRoot,

View File

@ -39,13 +39,12 @@ class TestsData {
blockTime: nil,
expiryHeight: nil,
fee: Zatoshi(1000),
id: 0,
index: nil,
hasChange: true,
memoCount: 0,
minedHeight: nil,
raw: nil,
rawID: Data(),
rawID: Data(repeating: 1, count: 32),
receivedNoteCount: 0,
sentNoteCount: 0,
value: Zatoshi(10),
@ -59,13 +58,12 @@ class TestsData {
blockTime: Date().timeIntervalSince1970,
expiryHeight: 123000,
fee: Zatoshi(10),
id: 333,
index: nil,
hasChange: false,
memoCount: 0,
minedHeight: 120000,
raw: nil,
rawID: Data(),
rawID: Data(repeating: 2, count: 32),
receivedNoteCount: 0,
sentNoteCount: 0,
value: Zatoshi(100),
@ -79,13 +77,12 @@ class TestsData {
blockTime: 1,
expiryHeight: nil,
fee: Zatoshi(10000),
id: 9,
index: 0,
hasChange: true,
memoCount: 0,
minedHeight: 0,
raw: nil,
rawID: Data(),
rawID: Data(repeating: 3, count: 32),
receivedNoteCount: 0,
sentNoteCount: 2,
value: .zero,
@ -99,13 +96,12 @@ class TestsData {
blockTime: 1,
expiryHeight: nil,
fee: nil,
id: 9,
index: 0,
hasChange: true,
memoCount: 0,
minedHeight: 0,
raw: nil,
rawID: Data(),
rawID: Data(repeating: 4, count: 32),
receivedNoteCount: 0,
sentNoteCount: 2,
value: .zero,