diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockEnhancementOperation.swift b/ZcashLightClientKit/Block/Processor/CompactBlockEnhancementOperation.swift index 860124a9..3fdfee0d 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockEnhancementOperation.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockEnhancementOperation.swift @@ -18,7 +18,7 @@ class CompactBlockEnhancementOperation: ZcashOperation { override var isAsynchronous: Bool { false } var rustBackend: ZcashRustBackendWelding.Type - var txFoundHandler: (([TransactionEntity]) -> Void)? + var txFoundHandler: (([ConfirmedTransactionEntity]) -> Void)? var downloader: CompactBlockDownloading var repository: TransactionRepository var maxRetries: Int = 5 @@ -72,7 +72,7 @@ class CompactBlockEnhancementOperation: ZcashOperation { return } - if let handler = self.txFoundHandler, let foundTxs = try? repository.findTransactions(in: self.range, limit: Int.max) { + if let handler = self.txFoundHandler, let foundTxs = try? repository.findConfirmedTransactions(in: self.range, offset: 0, limit: Int.max) { handler(foundTxs) } } diff --git a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift index d454a048..fc59ce5e 100644 --- a/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift +++ b/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift @@ -91,7 +91,7 @@ public extension Notification.Name { /** Notification sent when the compact block processor enhanced a bunch of transactions - Query the user info object for CompactBlockProcessorNotificationKey.foundTransactions which will contain an [TransactionEntity] Array with the found transactions + Query the user info object for CompactBlockProcessorNotificationKey.foundTransactions which will contain an [ConfirmedTransactionEntity] Array with the found transactions */ static let blockProcessorFoundTransactions = Notification.Name(rawValue: "CompactBlockProcessorFoundTransactions") } @@ -532,7 +532,7 @@ public class CompactBlockProcessor { CompactBlockProcessorNotificationKey.progressHeight : self.latestBlockHeight]) } - func notifyTransactions(_ txs: [TransactionEntity]) { + func notifyTransactions(_ txs: [ConfirmedTransactionEntity]) { NotificationCenter.default.post(name: .blockProcessorFoundTransactions, object: self, userInfo: [ CompactBlockProcessorNotificationKey.foundTransactions : txs]) diff --git a/ZcashLightClientKit/DAO/TransactionDao.swift b/ZcashLightClientKit/DAO/TransactionDao.swift index 81702772..b5889c2b 100644 --- a/ZcashLightClientKit/DAO/TransactionDao.swift +++ b/ZcashLightClientKit/DAO/TransactionDao.swift @@ -273,6 +273,52 @@ class TransactionSQLDAO: TransactionRepository { return tx }) } + + func findConfirmedTransactions(in range: BlockRange, offset: Int = 0, limit: Int = Int.max) throws -> [ConfirmedTransactionEntity]? { + try dbProvider.connection().run(""" + SELECT transactions.id_tx AS id, + transactions.block AS minedHeight, + transactions.tx_index AS transactionIndex, + transactions.txid AS rawTransactionId, + transactions.expiry_height AS expiryHeight, + transactions.raw AS raw, + sent_notes.address AS toAddress, + CASE + WHEN sent_notes.value IS NOT NULL THEN sent_notes.value + ELSE received_notes.value + end AS value, + CASE + WHEN sent_notes.memo IS NOT NULL THEN sent_notes.memo + ELSE received_notes.memo + end AS memo, + CASE + WHEN sent_notes.id_note IS NOT NULL THEN sent_notes.id_note + ELSE received_notes.id_note + end AS noteId, + blocks.time AS blockTimeInSeconds + FROM transactions + LEFT JOIN received_notes + ON transactions.id_tx = received_notes.tx + LEFT JOIN sent_notes + ON transactions.id_tx = sent_notes.tx + LEFT JOIN blocks + ON transactions.block = blocks.height + WHERE \(range.start.height) <= minedheight + AND minedheight <= \(range.end.height) AND + (sent_notes.address IS NULL AND received_notes.is_change != 1) + OR sent_notes.address IS NOT NULL + ORDER BY ( minedheight IS NOT NULL ), + minedheight DESC, + blocktimeinseconds DESC, + id DESC + LIMIT \(limit) OFFSET \(offset) + """).compactMap({ (bindings) -> ConfirmedTransactionEntity? in + guard let tx = TransactionBuilder.createConfirmedTransaction(from: bindings) else { + return nil + } + return tx + }) + } } extension Data { diff --git a/ZcashLightClientKit/Repository/TransactionRepository.swift b/ZcashLightClientKit/Repository/TransactionRepository.swift index 74054676..30b7d2c4 100644 --- a/ZcashLightClientKit/Repository/TransactionRepository.swift +++ b/ZcashLightClientKit/Repository/TransactionRepository.swift @@ -24,4 +24,5 @@ protocol TransactionRepository { func isInitialized() throws -> Bool func findEncodedTransactionBy(txId: Int) -> EncodedTransaction? func findTransactions(in range: BlockRange, limit: Int) throws -> [TransactionEntity]? + func findConfirmedTransactions(in range: BlockRange, offset: Int, limit: Int) throws -> [ConfirmedTransactionEntity]? } diff --git a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift index ebbdc2d6..2841d05d 100644 --- a/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift +++ b/ZcashLightClientKit/UIKit/Synchronizer/SDKSynchronizer.swift @@ -48,10 +48,17 @@ public extension Notification.Name { */ static let synchronizerSyncing = Notification.Name("SDKSyncronizerSyncing") /** - Posted when the synchronizer finds a mined transaction + Posted when the synchronizer finds a pendingTransaction that hast been newly mined - Note: query userInfo on NotificationKeys.minedTransaction for the transaction */ static let synchronizerMinedTransaction = Notification.Name("synchronizerMinedTransaction") + + /** + Posted when the synchronizer finds a mined transaction + - Note: query userInfo on NotificationKeys.foundTransactions for the [ConfirmedTransactionEntity]. This notification could arrive in a background thread. + */ + static let synchronizerFoundTransactions = Notification.Name("synchronizerFoundTransactions") + /** Posted when the synchronizer presents an error - Note: query userInfo on NotificationKeys.error for an error @@ -68,6 +75,7 @@ public class SDKSynchronizer: Synchronizer { public static let progress = "SDKSynchronizer.progress" public static let blockHeight = "SDKSynchronizer.blockHeight" public static let minedTransaction = "SDKSynchronizer.minedTransaction" + public static let foundTransactions = "SDKSynchronizer.foundTransactions" public static let error = "SDKSynchronizer.error" } @@ -267,10 +275,23 @@ public class SDKSynchronizer: Synchronizer { name: Notification.Name.blockProcessorHandledReOrg, object: processor) + center.addObserver(self, + selector: #selector(transactionsFound(_:)), + name: Notification.Name.blockProcessorFoundTransactions, + object: processor) + } // MARK: Block Processor notifications + @objc func transactionsFound(_ notification: Notification) { + guard let userInfo = notification.userInfo, + let foundTransactions = userInfo[CompactBlockProcessorNotificationKey.foundTransactions] as? [ConfirmedTransactionEntity] else { + return + } + NotificationCenter.default.post(name: .synchronizerFoundTransactions, object: self, userInfo: [ NotificationKeys.foundTransactions : foundTransactions]) + } + @objc func reorgDetected(_ notification: Notification) { guard let userInfo = notification.userInfo, let progress = userInfo[CompactBlockProcessorNotificationKey.reorgHeight] as? BlockHeight,