From 4de91051e8d1c435c39052eec94db3b0df2b7bff Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 18 May 2023 14:08:32 -0300 Subject: [PATCH] [#1100] replace last enhancement range in internal state with database info [WIP] create enhancement methods on transaction repository closes #110 --- .../project.pbxproj | 4 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../DAO/TransactionDao.swift | 33 +++++++++-- .../Repository/TransactionRepository.swift | 57 ++++++++++++++++++- .../TestUtils/MockTransactionRepository.swift | 13 +++-- 5 files changed, 97 insertions(+), 14 deletions(-) diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj index 3efaf5d4..a99c4a34 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj +++ b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.pbxproj @@ -804,7 +804,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 6J82A38BF9; + DEVELOPMENT_TEAM = RLPRR8CPQG; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "$(inherited)"; INFOPLIST_FILE = "ZcashLightClientSample-Mainnet-Info.plist"; @@ -827,7 +827,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 6J82A38BF9; + DEVELOPMENT_TEAM = RLPRR8CPQG; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "$(inherited)"; INFOPLIST_FILE = "ZcashLightClientSample-Mainnet-Info.plist"; diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 4474fbd8..e99c48ad 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/ZcashLightClientSample/ZcashLightClientSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/grpc/grpc-swift.git", "state" : { - "revision" : "130467153ff0acd642d2f098b69c1ac33373b24e", - "version" : "1.15.0" + "revision" : "4ab02e1ae5b4dfdd723773e955b62f35ccbaa7c7", + "version" : "1.16.0" } }, { diff --git a/Sources/ZcashLightClientKit/DAO/TransactionDao.swift b/Sources/ZcashLightClientKit/DAO/TransactionDao.swift index bb5fab8c..e6224c24 100644 --- a/Sources/ZcashLightClientKit/DAO/TransactionDao.swift +++ b/Sources/ZcashLightClientKit/DAO/TransactionDao.swift @@ -48,10 +48,6 @@ class TransactionSQLDAO: TransactionRepository { func lastScannedBlock() async throws -> Block? { try blockDao.latestBlock() } - - func isInitialized() async throws -> Bool { - true - } func countAll() async throws -> Int { do { @@ -174,6 +170,35 @@ class TransactionSQLDAO: TransactionRepository { try await getTransactionOutputs(for: id).map { $0.recipient } } + func firstUnenhancedTransaction() async throws -> ZcashTransaction.Output? { + let query = transactionsView + .filter( + ZcashTransaction.Overview.Column.raw == nil && + ZcashTransaction.Overview.Column.minedHeight != nil + ) + .order((ZcashTransaction.Overview.Column.minedHeight ?? BlockHeight.max).asc) + .limit(1) + + do { + return try execute(query) { try ZcashTransaction.Output(row: $0) }.first + } catch ZcashError.transactionRepositoryEntityNotFound { + return nil + } catch { + throw error + } + } + + func unenhancedTransactions() async throws -> [ZcashTransaction.Output] { + let query = transactionsView + .select(ZcashTransaction.Overview.Column.minedHeight.max) + .filter( + ZcashTransaction.Overview.Column.raw == nil && + ZcashTransaction.Overview.Column.minedHeight != nil + ) + + return try execute(query) { try ZcashTransaction.Output(row: $0) } + } + private func execute(_ query: View, createEntity: (Row) throws -> Entity) throws -> Entity { let entities: [Entity] = try execute(query, createEntity: createEntity) guard let entity = entities.first else { throw ZcashError.transactionRepositoryEntityNotFound } diff --git a/Sources/ZcashLightClientKit/Repository/TransactionRepository.swift b/Sources/ZcashLightClientKit/Repository/TransactionRepository.swift index 6fef89df..f5bd31d8 100644 --- a/Sources/ZcashLightClientKit/Repository/TransactionRepository.swift +++ b/Sources/ZcashLightClientKit/Repository/TransactionRepository.swift @@ -9,21 +9,76 @@ import Foundation protocol TransactionRepository { func closeDBConnection() + /// count all transactions func countAll() async throws -> Int + /// count all transactions that haven't been mined func countUnmined() async throws -> Int + /// gets the block information for the given height + /// - parameter height: blockheight for the given block func blockForHeight(_ height: BlockHeight) async throws -> Block? + /// last scanned height for this wallet. func lastScannedHeight() async throws -> BlockHeight + /// last scanned block for this wallet func lastScannedBlock() async throws -> Block? - func isInitialized() async throws -> Bool + /// find transaction by internal ID in the database + /// - parameter id: internal id of the transaction in this database instance func find(id: Int) async throws -> ZcashTransaction.Overview + /// find transaction by transaction Id in the network + /// - parameter rawID: transaction id of the transaction found in the blockchain func find(rawID: Data) async throws -> ZcashTransaction.Overview + /// find transactions by `TransactionKind` + /// - parameter offset: offset of the query (used for paging results) + /// - parameter limit: limit for number of rows to be returned + /// - parameter kind: `TransactionKind` of the query + /// - Returns transactions found or empty array if none. func find(offset: Int, limit: Int, kind: TransactionKind) async throws -> [ZcashTransaction.Overview] + /// find transactions for a given `CompactBlockRange` + /// - parameter range: the range + /// - parameter limit: limit for number of rows to be returned + /// - parameter kind: `TransactionKind` of the query + /// - Returns transactions found or empty array if none. func find(in range: CompactBlockRange, limit: Int, kind: TransactionKind) async throws -> [ZcashTransaction.Overview] + /// find transactions from a given transaction onwards + /// - parameter from: the transaction known by caller to use in the query + /// - parameter limit: limit for number of rows to be returned + /// - parameter kind: `TransactionKind` of the query + /// - Returns transactions found or empty array if none. func find(from: ZcashTransaction.Overview, limit: Int, kind: TransactionKind) async throws -> [ZcashTransaction.Overview] + /// find pending transactions (of any kind) in relation from a given latest height + /// - parameter latestHeight: given latest height + /// - parameter offset: offset of the query (used for paging results) + /// - parameter limit: limit for number of rows to be returned + /// - Returns transactions found or empty array if none. func findPendingTransactions(latestHeight: BlockHeight, offset: Int, limit: Int) async throws -> [ZcashTransaction.Overview] + /// find inbound transaction for the keys being tracked on this wallet + /// - parameter offset: offset of the query (used for paging results) + /// - parameter limit: limit for number of rows to be returned + /// - Returns transactions found or empty array if none. func findReceived(offset: Int, limit: Int) async throws -> [ZcashTransaction.Overview] + /// find outbound transaction for the keys being tracked on this wallet + /// - parameter offset: offset of the query (used for paging results) + /// - parameter limit: limit for number of rows to be returned + /// - Returns transactions found or empty array if none. func findSent(offset: Int, limit: Int) async throws -> [ZcashTransaction.Overview] + /// find memos for a given transaction + /// - parameter transaction: the transaction of interest to get the memos for + /// - returns an array of `Memo` func findMemos(for transaction: ZcashTransaction.Overview) async throws -> [Memo] + /// gets the recipients for a given (internal) transaction Id + /// - parameter id: internal transaction id + /// - returns array of recipients func getRecipients(for id: Int) async throws -> [TransactionRecipient] + /// gets the transaction outputs known to this wallet for the given transactions + /// - parameter id: internal transaction id + /// - Returns transactions found or empty array if none. func getTransactionOutputs(for id: Int) async throws -> [ZcashTransaction.Output] + /// gets the last transaction that was fully downloaded and decrypted. + /// - Note: if you are useing this to establish a last completed range, this doesn't mean that there + /// could be others that hadn't been downloaded and decrypted. For that you can get the + /// `unenhancedTransactions` functions + func firstUnenhancedTransaction() async throws -> ZcashTransaction.Output? + /// get all the transactions that haven't been downloaded and decrypted. + /// - Note: we use the `raw` field of the database to consider if the raw data has been downloaded + /// - Returns transactions found or empty array if none. + func unenhancedTransactions() async throws -> [ZcashTransaction.Output] } diff --git a/Tests/TestUtils/MockTransactionRepository.swift b/Tests/TestUtils/MockTransactionRepository.swift index ab29b7aa..fb28e93d 100644 --- a/Tests/TestUtils/MockTransactionRepository.swift +++ b/Tests/TestUtils/MockTransactionRepository.swift @@ -73,6 +73,14 @@ extension MockTransactionRepository.Kind: Equatable {} // MARK: - TransactionRepository extension MockTransactionRepository: TransactionRepository { + func firstUnenhancedTransaction() async throws -> ZcashLightClientKit.ZcashTransaction.Output? { + nil + } + + func unenhancedTransactions() async throws -> [ZcashLightClientKit.ZcashTransaction.Output] { + [] + } + func getTransactionOutputs(for id: Int) async throws -> [ZcashLightClientKit.ZcashTransaction.Output] { [] } @@ -114,11 +122,6 @@ extension MockTransactionRepository: TransactionRepository { func lastScannedBlock() throws -> Block? { nil } - - func isInitialized() throws -> Bool { - true - } - func generate() { var txArray: [ZcashTransaction.Overview] = [] reference = referenceArray()