Merge pull request #1291 from zcash/release-2.0.0
Post-Release 2.0.0 merge to `main`
This commit is contained in:
commit
494a060469
|
@ -4,7 +4,7 @@ All notable changes to this library will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
# 2.0.0-rc.1 - 2023-09-08
|
||||
# 2.0.0 - 2023-09-25
|
||||
|
||||
## Notable Changes
|
||||
|
||||
|
@ -13,7 +13,8 @@ synchronization algorithm.
|
|||
|
||||
## Changed
|
||||
|
||||
Updated to `zcash-light-client-ffi 0.4.0-rc.1`
|
||||
Updated dependencies:
|
||||
- `zcash-light-client-ffi 0.4.0`
|
||||
|
||||
`CompactBlockProcessor` now processes compact blocks from the lightwalletd server with Spend-before-Sync algorithm (i.e. non-linear order). This feature shortens the time after which a wallet's spendable balance can be used.
|
||||
|
||||
|
|
|
@ -86,8 +86,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-crypto.git",
|
||||
"state" : {
|
||||
"revision" : "33a20e650c33f6d72d822d558333f2085effa3dc",
|
||||
"version" : "2.5.0"
|
||||
"revision" : "60f13f60c4d093691934dc6cfdf5f508ada1f894",
|
||||
"version" : "2.6.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -95,8 +95,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-log.git",
|
||||
"state" : {
|
||||
"revision" : "32e8d724467f8fe623624570367e3d50c5638e46",
|
||||
"version" : "1.5.2"
|
||||
"revision" : "532d8b529501fb73a2455b179e0bbb6d49b652ed",
|
||||
"version" : "1.5.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -104,8 +104,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio.git",
|
||||
"state" : {
|
||||
"revision" : "cf281631ff10ec6111f2761052aa81896a83a007",
|
||||
"version" : "2.58.0"
|
||||
"revision" : "3db5c4aeee8100d2db6f1eaf3864afdad5dc68fd",
|
||||
"version" : "2.59.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -113,8 +113,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-extras.git",
|
||||
"state" : {
|
||||
"revision" : "0e0d0aab665ff1a0659ce75ac003081f2b1c8997",
|
||||
"version" : "1.19.0"
|
||||
"revision" : "fb70a0f5e984f23be48b11b4f1909f3bee016178",
|
||||
"version" : "1.19.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -122,8 +122,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-http2.git",
|
||||
"state" : {
|
||||
"revision" : "6d021a48483dbb273a9be43f65234bdc9185b364",
|
||||
"version" : "1.26.0"
|
||||
"revision" : "a8ccf13fa62775277a5d56844878c828bbb3be1a",
|
||||
"version" : "1.27.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -131,8 +131,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-ssl.git",
|
||||
"state" : {
|
||||
"revision" : "e866a626e105042a6a72a870c88b4c531ba05f83",
|
||||
"version" : "2.24.0"
|
||||
"revision" : "320bd978cceb8e88c125dcbb774943a92f6286e9",
|
||||
"version" : "2.25.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -140,8 +140,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-transport-services.git",
|
||||
"state" : {
|
||||
"revision" : "41f4098903878418537020075a4d8a6e20a0b182",
|
||||
"version" : "1.17.0"
|
||||
"revision" : "e7403c35ca6bb539a7ca353b91cc2d8ec0362d58",
|
||||
"version" : "1.19.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -149,8 +149,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-protobuf.git",
|
||||
"state" : {
|
||||
"revision" : "0af9125c4eae12a4973fb66574c53a54962a9e1e",
|
||||
"version" : "1.21.0"
|
||||
"revision" : "cf62cdaea48b77f1a631e5cb3aeda6047c2cba1d",
|
||||
"version" : "1.23.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -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" : "9bc5877ef6302e877922f79ebead52e50bce94fd",
|
||||
"version" : "0.4.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -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: {}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -316,6 +316,9 @@ extension SDKSynchronizer {
|
|||
case .unprepared:
|
||||
return "Unprepared 😅"
|
||||
|
||||
case .stopped:
|
||||
return "Stopped"
|
||||
|
||||
case .error(ZcashError.synchronizerDisconnected):
|
||||
return "disconnected 💔"
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ class SyncBlocksListViewController: UIViewController {
|
|||
loggerProxy.debug("Processing synchronizer with alias \(synchronizer.alias.description) \(index)")
|
||||
|
||||
switch syncStatus {
|
||||
case .unprepared, .upToDate, .error(ZcashError.synchronizerDisconnected), .error:
|
||||
case .unprepared, .upToDate, .error(ZcashError.synchronizerDisconnected), .error, .stopped:
|
||||
do {
|
||||
if syncStatus == .unprepared {
|
||||
_ = try! await synchronizer.prepare(
|
||||
|
@ -145,7 +145,7 @@ extension SyncBlocksListViewController: UITableViewDataSource {
|
|||
|
||||
let image: UIImage?
|
||||
switch synchronizerStatus {
|
||||
case .unprepared, .upToDate, .error(ZcashError.synchronizerDisconnected), .error:
|
||||
case .unprepared, .upToDate, .error(ZcashError.synchronizerDisconnected), .error, .stopped:
|
||||
image = UIImage(systemName: "play.circle")
|
||||
case .syncing:
|
||||
image = UIImage(systemName: "stop.circle")
|
||||
|
@ -176,6 +176,8 @@ extension SyncStatus {
|
|||
return "Up to Date 😎"
|
||||
case .unprepared:
|
||||
return "Unprepared"
|
||||
case .stopped:
|
||||
return "Stopped"
|
||||
case .error(ZcashError.synchronizerDisconnected):
|
||||
return "Disconnected"
|
||||
case let .error(error):
|
||||
|
|
|
@ -93,7 +93,7 @@ class SyncBlocksViewController: UIViewController {
|
|||
metricLabel.text = currentMetricName + report.debugDescription
|
||||
}
|
||||
|
||||
case .upToDate:
|
||||
case .upToDate, .stopped:
|
||||
accumulateMetrics()
|
||||
summaryLabel.text = "enhancement: \(accumulatedMetrics.debugDescription)"
|
||||
overallSummary()
|
||||
|
@ -205,7 +205,7 @@ class SyncBlocksViewController: UIViewController {
|
|||
switch state {
|
||||
case .syncing:
|
||||
return "Pause"
|
||||
case .unprepared:
|
||||
case .unprepared, .stopped:
|
||||
return "Start"
|
||||
case .upToDate:
|
||||
return "Chill!"
|
||||
|
@ -222,6 +222,8 @@ class SyncBlocksViewController: UIViewController {
|
|||
return "Up to Date 😎"
|
||||
case .unprepared:
|
||||
return "Unprepared"
|
||||
case .stopped:
|
||||
return "Stopped"
|
||||
case .error(ZcashError.synchronizerDisconnected):
|
||||
return "Disconnected"
|
||||
case .error:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,21 +1,12 @@
|
|||
{
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "csqlite",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/stephencelis/CSQLite.git",
|
||||
"state" : {
|
||||
"revision" : "9106e983d5e3d5149ee35281ec089484b0def018",
|
||||
"version" : "0.0.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "grpc-swift",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/grpc/grpc-swift.git",
|
||||
"state" : {
|
||||
"revision" : "a20cac0cad4e0da457de687c45cb55aee9a45e19",
|
||||
"version" : "1.14.1"
|
||||
"revision" : "84bac657e9930d26e9124bac082f26586dc2d209",
|
||||
"version" : "1.19.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -32,8 +23,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-atomics.git",
|
||||
"state" : {
|
||||
"revision" : "ff3d2212b6b093db7f177d0855adbc4ef9c5f036",
|
||||
"version" : "1.0.3"
|
||||
"revision" : "6c89474e62719ddcc1e9614989fff2f68208fe10",
|
||||
"version" : "1.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -50,8 +41,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-log.git",
|
||||
"state" : {
|
||||
"revision" : "32e8d724467f8fe623624570367e3d50c5638e46",
|
||||
"version" : "1.5.2"
|
||||
"revision" : "532d8b529501fb73a2455b179e0bbb6d49b652ed",
|
||||
"version" : "1.5.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -59,8 +50,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio.git",
|
||||
"state" : {
|
||||
"revision" : "45167b8006448c79dda4b7bd604e07a034c15c49",
|
||||
"version" : "2.48.0"
|
||||
"revision" : "3db5c4aeee8100d2db6f1eaf3864afdad5dc68fd",
|
||||
"version" : "2.59.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -68,8 +59,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-extras.git",
|
||||
"state" : {
|
||||
"revision" : "0e0d0aab665ff1a0659ce75ac003081f2b1c8997",
|
||||
"version" : "1.19.0"
|
||||
"revision" : "fb70a0f5e984f23be48b11b4f1909f3bee016178",
|
||||
"version" : "1.19.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -77,8 +68,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-http2.git",
|
||||
"state" : {
|
||||
"revision" : "38feec96bcd929028939107684073554bf01abeb",
|
||||
"version" : "1.25.2"
|
||||
"revision" : "a8ccf13fa62775277a5d56844878c828bbb3be1a",
|
||||
"version" : "1.27.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -86,8 +77,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-ssl.git",
|
||||
"state" : {
|
||||
"revision" : "4fb7ead803e38949eb1d6fabb849206a72c580f3",
|
||||
"version" : "2.23.0"
|
||||
"revision" : "320bd978cceb8e88c125dcbb774943a92f6286e9",
|
||||
"version" : "2.25.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -95,8 +86,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-transport-services.git",
|
||||
"state" : {
|
||||
"revision" : "c0d9a144cfaec8d3d596aadde3039286a266c15c",
|
||||
"version" : "1.15.0"
|
||||
"revision" : "e7403c35ca6bb539a7ca353b91cc2d8ec0362d58",
|
||||
"version" : "1.19.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -104,8 +95,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-protobuf.git",
|
||||
"state" : {
|
||||
"revision" : "0af9125c4eae12a4973fb66574c53a54962a9e1e",
|
||||
"version" : "1.21.0"
|
||||
"revision" : "cf62cdaea48b77f1a631e5cb3aeda6047c2cba1d",
|
||||
"version" : "1.23.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -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" : "9bc5877ef6302e877922f79ebead52e50bce94fd",
|
||||
"version" : "0.4.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -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")
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
|
|
|
@ -11,12 +11,14 @@ final class ScanAction {
|
|||
let configProvider: CompactBlockProcessor.ConfigProvider
|
||||
let blockScanner: BlockScanner
|
||||
let rustBackend: ZcashRustBackendWelding
|
||||
let latestBlocksDataProvider: LatestBlocksDataProvider
|
||||
let logger: Logger
|
||||
|
||||
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
||||
self.configProvider = configProvider
|
||||
blockScanner = container.resolve(BlockScanner.self)
|
||||
rustBackend = container.resolve(ZcashRustBackendWelding.self)
|
||||
latestBlocksDataProvider = container.resolve(LatestBlocksDataProvider.self)
|
||||
logger = container.resolve(Logger.self)
|
||||
}
|
||||
|
||||
|
@ -54,7 +56,8 @@ extension ScanAction: Action {
|
|||
let processedHeight = await context.processedHeight
|
||||
let incrementedprocessedHeight = processedHeight + BlockHeight(increment)
|
||||
await context.update(processedHeight: incrementedprocessedHeight)
|
||||
|
||||
await self?.latestBlocksDataProvider.updateScannedData()
|
||||
|
||||
// report scan progress only if it's available
|
||||
if let scanProgress = try? await self?.rustBackend.getScanProgress() {
|
||||
let progress = try scanProgress.progress()
|
||||
|
|
|
@ -11,12 +11,14 @@ final class UpdateChainTipAction {
|
|||
let rustBackend: ZcashRustBackendWelding
|
||||
let downloader: BlockDownloader
|
||||
let service: LightWalletService
|
||||
let latestBlocksDataProvider: LatestBlocksDataProvider
|
||||
let logger: Logger
|
||||
|
||||
init(container: DIContainer) {
|
||||
service = container.resolve(LightWalletService.self)
|
||||
downloader = container.resolve(BlockDownloader.self)
|
||||
rustBackend = container.resolve(ZcashRustBackendWelding.self)
|
||||
latestBlocksDataProvider = container.resolve(LatestBlocksDataProvider.self)
|
||||
logger = container.resolve(Logger.self)
|
||||
}
|
||||
|
||||
|
@ -26,6 +28,7 @@ final class UpdateChainTipAction {
|
|||
logger.info("Latest block height is \(latestBlockHeight)")
|
||||
try await rustBackend.updateChainTip(height: Int32(latestBlockHeight))
|
||||
await context.update(lastChainTipUpdateTime: time)
|
||||
await latestBlocksDataProvider.update(latestBlockHeight)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,7 @@ extension BlockScannerImpl: BlockScanner {
|
|||
let previousScannedHeight = lastScannedHeight
|
||||
let startHeight = previousScannedHeight + 1
|
||||
|
||||
// TODO: [#576] remove this arbitrary batch size https://github.com/zcash/ZcashLightClientKit/issues/576
|
||||
let batchSize = scanBatchSize(startScanHeight: startHeight, network: config.networkType)
|
||||
let batchSize = UInt32(config.scanningBatchSize)
|
||||
|
||||
let scanStartTime = Date()
|
||||
do {
|
||||
|
@ -87,17 +86,4 @@ extension BlockScannerImpl: BlockScanner {
|
|||
|
||||
return lastScannedHeight
|
||||
}
|
||||
|
||||
private func scanBatchSize(startScanHeight height: BlockHeight, network: NetworkType) -> UInt32 {
|
||||
assert(config.scanningBatchSize > 0, "ZcashSDK.DefaultScanningBatch must be larger than 0!")
|
||||
guard network == .mainnet else { return UInt32(config.scanningBatchSize) }
|
||||
|
||||
if height > 1_650_000 {
|
||||
// librustzcash thread saturation at a number of blocks
|
||||
// that contains 100 * num_cores Sapling outputs.
|
||||
return UInt32(max(ProcessInfo().activeProcessorCount, 10))
|
||||
}
|
||||
|
||||
return UInt32(config.scanningBatchSize)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,22 @@
|
|||
import Foundation
|
||||
import SQLite
|
||||
|
||||
extension Connection {
|
||||
public func scalarLocked<V: Value>(_ query: ScalarQuery<V?>) throws -> V.ValueType? {
|
||||
globalDBLock.lock()
|
||||
defer { globalDBLock.unlock() }
|
||||
|
||||
return try scalar(query)
|
||||
}
|
||||
|
||||
public func scalarLocked<V: Value>(_ query: ScalarQuery<V>) throws -> V {
|
||||
globalDBLock.lock()
|
||||
defer { globalDBLock.unlock() }
|
||||
|
||||
return try scalar(query)
|
||||
}
|
||||
}
|
||||
|
||||
class TransactionSQLDAO: TransactionRepository {
|
||||
enum NotesTableStructure {
|
||||
static let transactionID = Expression<Int>("tx")
|
||||
|
@ -41,7 +57,7 @@ class TransactionSQLDAO: TransactionRepository {
|
|||
|
||||
func countAll() async throws -> Int {
|
||||
do {
|
||||
return try connection().scalar(transactionsView.count)
|
||||
return try connection().scalarLocked(transactionsView.count)
|
||||
} catch {
|
||||
throw ZcashError.transactionRepositoryCountAll(error)
|
||||
}
|
||||
|
@ -49,20 +65,12 @@ class TransactionSQLDAO: TransactionRepository {
|
|||
|
||||
func countUnmined() async throws -> Int {
|
||||
do {
|
||||
return try connection().scalar(transactionsView.filter(ZcashTransaction.Overview.Column.minedHeight == nil).count)
|
||||
return try connection().scalarLocked(transactionsView.filter(ZcashTransaction.Overview.Column.minedHeight == nil).count)
|
||||
} catch {
|
||||
throw ZcashError.transactionRepositoryCountUnmined(error)
|
||||
}
|
||||
}
|
||||
|
||||
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 +81,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 +90,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 +103,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 +125,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 +134,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 +143,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 +151,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 {
|
||||
|
@ -167,11 +176,14 @@ class TransactionSQLDAO: TransactionRepository {
|
|||
}
|
||||
|
||||
private func execute<Entity>(_ query: View, createEntity: (Row) throws -> Entity) throws -> [Entity] {
|
||||
globalDBLock.lock()
|
||||
defer { globalDBLock.unlock() }
|
||||
|
||||
do {
|
||||
let entities = try connection()
|
||||
.prepare(query)
|
||||
.map(createEntity)
|
||||
|
||||
|
||||
return entities
|
||||
} catch {
|
||||
if let error = error as? ZcashError {
|
||||
|
|
|
@ -109,6 +109,9 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
|
|||
)
|
||||
"""
|
||||
do {
|
||||
globalDBLock.lock()
|
||||
defer { globalDBLock.unlock() }
|
||||
|
||||
try dbProvider.connection().run(stringStatement)
|
||||
} catch {
|
||||
throw ZcashError.unspentTransactionOutputDAOCreateTable(error)
|
||||
|
@ -118,8 +121,11 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
|
|||
/// - Throws: `unspentTransactionOutputDAOStore` if sqlite query fails.
|
||||
func store(utxos: [UnspentTransactionOutputEntity]) async throws {
|
||||
do {
|
||||
globalDBLock.lock()
|
||||
defer { globalDBLock.unlock() }
|
||||
|
||||
let db = try dbProvider.connection()
|
||||
try dbProvider.connection().transaction {
|
||||
try db.transaction {
|
||||
for utxo in utxos.map({ $0 as? UTXO ?? $0.asUTXO() }) {
|
||||
try db.run(table.insert(utxo))
|
||||
}
|
||||
|
@ -132,6 +138,9 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
|
|||
/// - Throws: `unspentTransactionOutputDAOClearAll` if sqlite query fails.
|
||||
func clearAll(address: String?) async throws {
|
||||
do {
|
||||
globalDBLock.lock()
|
||||
defer { globalDBLock.unlock() }
|
||||
|
||||
if let tAddr = address {
|
||||
try dbProvider.connection().run(table.filter(TableColumns.address == tAddr).delete())
|
||||
} else {
|
||||
|
@ -178,16 +187,16 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
|
|||
/// - Throws: `unspentTransactionOutputDAOBalance` if sqlite query fails.
|
||||
func balance(address: String, latestHeight: BlockHeight) async throws -> WalletBalance {
|
||||
do {
|
||||
let verified = try dbProvider.connection().scalar(
|
||||
let verified = try dbProvider.connection().scalarLocked(
|
||||
table.select(TableColumns.valueZat.sum)
|
||||
.filter(TableColumns.address == address)
|
||||
.filter(TableColumns.height <= latestHeight - ZcashSDK.defaultStaleTolerance)
|
||||
) ?? 0
|
||||
let total = try dbProvider.connection().scalar(
|
||||
let total = try dbProvider.connection().scalarLocked(
|
||||
table.select(TableColumns.valueZat.sum)
|
||||
.filter(TableColumns.address == address)
|
||||
) ?? 0
|
||||
|
||||
|
||||
return WalletBalance(
|
||||
verified: Zatoshi(Int64(verified)),
|
||||
total: Zatoshi(Int64(total))
|
||||
|
|
|
@ -66,6 +66,9 @@ class AccountSQDAO: AccountRepository {
|
|||
/// - `accountDAOGetAll` if sqlite query fetching account data failed.
|
||||
func getAll() throws -> [AccountEntity] {
|
||||
do {
|
||||
globalDBLock.lock()
|
||||
defer { globalDBLock.unlock() }
|
||||
|
||||
return try dbProvider.connection()
|
||||
.prepare(table)
|
||||
.map { row -> DbAccount in
|
||||
|
@ -90,6 +93,9 @@ class AccountSQDAO: AccountRepository {
|
|||
func findBy(account: Int) throws -> AccountEntity? {
|
||||
let query = table.filter(TableColums.account == account).limit(1)
|
||||
do {
|
||||
globalDBLock.lock()
|
||||
defer { globalDBLock.unlock() }
|
||||
|
||||
return try dbProvider.connection()
|
||||
.prepare(query)
|
||||
.map {
|
||||
|
@ -119,6 +125,9 @@ class AccountSQDAO: AccountRepository {
|
|||
|
||||
let updatedRows: Int
|
||||
do {
|
||||
globalDBLock.lock()
|
||||
defer { globalDBLock.unlock() }
|
||||
|
||||
updatedRows = try dbProvider.connection().run(table.filter(TableColums.account == acc.account).update(acc))
|
||||
} catch {
|
||||
throw ZcashError.accountDAOUpdate(error)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -12,8 +12,11 @@ struct ScanProgress: Equatable {
|
|||
let denominator: UInt64
|
||||
|
||||
func progress() throws -> Float {
|
||||
// division by 0 is not a concern here because `ZcashRustBackend.getScanProgress() -> ScanProgress?`
|
||||
// handles the 0 and returns nil rather than returning nil progress or 0 value here
|
||||
guard denominator != 0 else {
|
||||
// this shouldn't happen but if it does, we need to get notified by clients and work on a fix
|
||||
throw ZcashError.rustScanProgressOutOfRange("\(numerator)/\(denominator)")
|
||||
}
|
||||
|
||||
let value = Float(numerator) / Float(denominator)
|
||||
|
||||
// this shouldn't happen but if it does, we need to get notified by clients and work on a fix
|
||||
|
|
|
@ -16,6 +16,7 @@ protocol LatestBlocksDataProvider {
|
|||
func updateScannedData() async
|
||||
func updateBlockData() async
|
||||
func updateWalletBirthday(_ walletBirthday: BlockHeight) async
|
||||
func update(_ latestBlockHeight: BlockHeight) async
|
||||
}
|
||||
|
||||
actor LatestBlocksDataProviderImpl: LatestBlocksDataProvider {
|
||||
|
@ -41,13 +42,18 @@ actor LatestBlocksDataProviderImpl: LatestBlocksDataProvider {
|
|||
}
|
||||
|
||||
func updateBlockData() async {
|
||||
if let newLatestBlockHeight = try? await service.latestBlockHeight(),
|
||||
latestBlockHeight < newLatestBlockHeight {
|
||||
latestBlockHeight = newLatestBlockHeight
|
||||
if let newLatestBlockHeight = try? await service.latestBlockHeight() {
|
||||
await update(newLatestBlockHeight)
|
||||
}
|
||||
}
|
||||
|
||||
func updateWalletBirthday(_ walletBirthday: BlockHeight) async {
|
||||
self.walletBirthday = walletBirthday
|
||||
}
|
||||
|
||||
func update(_ newLatestBlockHeight: BlockHeight) async {
|
||||
if latestBlockHeight < newLatestBlockHeight {
|
||||
latestBlockHeight = newLatestBlockHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
import Foundation
|
||||
import libzcashlc
|
||||
|
||||
let globalDBLock = NSLock()
|
||||
|
||||
actor ZcashRustBackend: ZcashRustBackendWelding {
|
||||
let minimumConfirmations: UInt32 = 10
|
||||
let useZIP317Fees = false
|
||||
|
@ -56,6 +58,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
|
||||
let treeStateBytes = try treeState.serializedData(partial: false).bytes
|
||||
|
||||
globalDBLock.lock()
|
||||
let ffiBinaryKeyPtr = zcashlc_create_account(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
|
@ -66,6 +69,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
rUntil,
|
||||
networkType.networkId
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard let ffiBinaryKeyPtr else {
|
||||
throw ZcashError.rustCreateAccount(lastErrorMessage(fallback: "`createAccount` failed with unknown error"))
|
||||
|
@ -84,6 +88,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
) async throws -> Data {
|
||||
var contiguousTxIdBytes = ContiguousArray<UInt8>([UInt8](repeating: 0x0, count: 32))
|
||||
|
||||
globalDBLock.lock()
|
||||
let success = contiguousTxIdBytes.withUnsafeMutableBufferPointer { txIdBytePtr in
|
||||
usk.bytes.withUnsafeBufferPointer { uskPtr in
|
||||
zcashlc_create_to_address(
|
||||
|
@ -105,6 +110,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
)
|
||||
}
|
||||
}
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard success else {
|
||||
throw ZcashError.rustCreateToAddress(lastErrorMessage(fallback: "`createToAddress` failed with unknown error"))
|
||||
|
@ -116,6 +122,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func decryptAndStoreTransaction(txBytes: [UInt8], minedHeight: Int32) async throws {
|
||||
globalDBLock.lock()
|
||||
let result = zcashlc_decrypt_and_store_transaction(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
|
@ -124,6 +131,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
UInt32(minedHeight),
|
||||
networkType.networkId
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard result != 0 else {
|
||||
throw ZcashError.rustDecryptAndStoreTransaction(lastErrorMessage(fallback: "`decryptAndStoreTransaction` failed with unknown error"))
|
||||
|
@ -131,7 +139,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func getBalance(account: Int32) async throws -> Int64 {
|
||||
globalDBLock.lock()
|
||||
let balance = zcashlc_get_balance(dbData.0, dbData.1, account, networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard balance >= 0 else {
|
||||
throw ZcashError.rustGetBalance(Int(account), lastErrorMessage(fallback: "Error getting total balance from account \(account)"))
|
||||
|
@ -141,12 +151,14 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func getCurrentAddress(account: Int32) async throws -> UnifiedAddress {
|
||||
globalDBLock.lock()
|
||||
let addressCStr = zcashlc_get_current_address(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
account,
|
||||
networkType.networkId
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard let addressCStr else {
|
||||
throw ZcashError.rustGetCurrentAddress(lastErrorMessage(fallback: "`getCurrentAddress` failed with unknown error"))
|
||||
|
@ -162,12 +174,14 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func getNearestRewindHeight(height: Int32) async throws -> Int32 {
|
||||
globalDBLock.lock()
|
||||
let result = zcashlc_get_nearest_rewind_height(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
height,
|
||||
networkType.networkId
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard result > 0 else {
|
||||
throw ZcashError.rustGetNearestRewindHeight(lastErrorMessage(fallback: "`getNearestRewindHeight` failed with unknown error"))
|
||||
|
@ -177,12 +191,14 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func getNextAvailableAddress(account: Int32) async throws -> UnifiedAddress {
|
||||
globalDBLock.lock()
|
||||
let addressCStr = zcashlc_get_next_available_address(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
account,
|
||||
networkType.networkId
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard let addressCStr else {
|
||||
throw ZcashError.rustGetNextAvailableAddress(lastErrorMessage(fallback: "`getNextAvailableAddress` failed with unknown error"))
|
||||
|
@ -205,9 +221,11 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
var contiguousMemoBytes = ContiguousArray<UInt8>(MemoBytes.empty().bytes)
|
||||
var success = false
|
||||
|
||||
globalDBLock.lock()
|
||||
contiguousMemoBytes.withUnsafeMutableBufferPointer { memoBytePtr in
|
||||
success = zcashlc_get_memo(dbData.0, dbData.1, txId.bytes, outputIndex, memoBytePtr.baseAddress, networkType.networkId)
|
||||
}
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard success else { return nil }
|
||||
|
||||
|
@ -219,12 +237,14 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
throw ZcashError.rustGetTransparentBalanceNegativeAccount(Int(account))
|
||||
}
|
||||
|
||||
globalDBLock.lock()
|
||||
let balance = zcashlc_get_total_transparent_balance_for_account(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
networkType.networkId,
|
||||
account
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard balance >= 0 else {
|
||||
throw ZcashError.rustGetTransparentBalance(
|
||||
|
@ -237,6 +257,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func getVerifiedBalance(account: Int32) async throws -> Int64 {
|
||||
globalDBLock.lock()
|
||||
let balance = zcashlc_get_verified_balance(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
|
@ -244,6 +265,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
networkType.networkId,
|
||||
minimumConfirmations
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard balance >= 0 else {
|
||||
throw ZcashError.rustGetVerifiedBalance(
|
||||
|
@ -260,6 +282,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
throw ZcashError.rustGetVerifiedTransparentBalanceNegativeAccount(Int(account))
|
||||
}
|
||||
|
||||
globalDBLock.lock()
|
||||
let balance = zcashlc_get_verified_transparent_balance_for_account(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
|
@ -267,6 +290,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
account,
|
||||
minimumConfirmations
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard balance >= 0 else {
|
||||
throw ZcashError.rustGetVerifiedTransparentBalance(
|
||||
|
@ -279,7 +303,11 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func initDataDb(seed: [UInt8]?) async throws -> DbInitResult {
|
||||
switch zcashlc_init_data_database(dbData.0, dbData.1, seed, UInt(seed?.count ?? 0), networkType.networkId) {
|
||||
globalDBLock.lock()
|
||||
let initResult = zcashlc_init_data_database(dbData.0, dbData.1, seed, UInt(seed?.count ?? 0), networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
switch initResult {
|
||||
case 0: // ok
|
||||
return DbInitResult.success
|
||||
case 1:
|
||||
|
@ -290,7 +318,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func initBlockMetadataDb() async throws {
|
||||
globalDBLock.lock()
|
||||
let result = zcashlc_init_block_metadata_db(fsBlockDbRoot.0, fsBlockDbRoot.1)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard result else {
|
||||
throw ZcashError.rustInitBlockMetadataDb(lastErrorMessage(fallback: "`initBlockMetadataDb` failed with unknown error"))
|
||||
|
@ -346,7 +376,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
|
||||
fsBlocks.initialize(to: meta)
|
||||
|
||||
globalDBLock.lock()
|
||||
let res = zcashlc_write_block_metadata(fsBlockDbRoot.0, fsBlockDbRoot.1, fsBlocks)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard res else {
|
||||
throw ZcashError.rustWriteBlocksMetadata(lastErrorMessage(fallback: "`writeBlocksMetadata` failed with unknown error"))
|
||||
|
@ -355,7 +387,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func latestCachedBlockHeight() async throws -> BlockHeight {
|
||||
globalDBLock.lock()
|
||||
let height = zcashlc_latest_cached_block_height(fsBlockDbRoot.0, fsBlockDbRoot.1)
|
||||
globalDBLock.unlock()
|
||||
|
||||
if height >= 0 {
|
||||
return BlockHeight(height)
|
||||
|
@ -367,12 +401,14 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func listTransparentReceivers(account: Int32) async throws -> [TransparentAddress] {
|
||||
globalDBLock.lock()
|
||||
let encodedKeysPtr = zcashlc_list_transparent_receivers(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
account,
|
||||
networkType.networkId
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard let encodedKeysPtr else {
|
||||
throw ZcashError.rustListTransparentReceivers(lastErrorMessage(fallback: "`listTransparentReceivers` failed with unknown error"))
|
||||
|
@ -404,6 +440,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
value: Int64,
|
||||
height: BlockHeight
|
||||
) async throws {
|
||||
globalDBLock.lock()
|
||||
let result = zcashlc_put_utxo(
|
||||
dbData.0,
|
||||
dbData.1,
|
||||
|
@ -416,6 +453,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
Int32(height),
|
||||
networkType.networkId
|
||||
)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard result else {
|
||||
throw ZcashError.rustPutUnspentTransparentOutput(lastErrorMessage(fallback: "`putUnspentTransparentOutput` failed with unknown error"))
|
||||
|
@ -423,7 +461,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func rewindToHeight(height: Int32) async throws {
|
||||
globalDBLock.lock()
|
||||
let result = zcashlc_rewind_to_height(dbData.0, dbData.1, height, networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard result else {
|
||||
throw ZcashError.rustRewindToHeight(height, lastErrorMessage(fallback: "`rewindToHeight` failed with unknown error"))
|
||||
|
@ -431,7 +471,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func rewindCacheToHeight(height: Int32) async throws {
|
||||
globalDBLock.lock()
|
||||
let result = zcashlc_rewind_fs_block_cache_to_height(fsBlockDbRoot.0, fsBlockDbRoot.1, height)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard result else {
|
||||
throw ZcashError.rustRewindCacheToHeight(lastErrorMessage(fallback: "`rewindCacheToHeight` failed with unknown error"))
|
||||
|
@ -474,7 +516,10 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
|
||||
let rootsPtr = UnsafeMutablePointer<FfiSubtreeRoots>.allocate(capacity: 1)
|
||||
|
||||
defer { ffiSubtreeRootsVec.deallocateElements() }
|
||||
defer {
|
||||
ffiSubtreeRootsVec.deallocateElements()
|
||||
rootsPtr.deallocate()
|
||||
}
|
||||
|
||||
try contiguousFfiRoots.withContiguousMutableStorageIfAvailable { ptr in
|
||||
var roots = FfiSubtreeRoots()
|
||||
|
@ -483,7 +528,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
|
||||
rootsPtr.initialize(to: roots)
|
||||
|
||||
globalDBLock.lock()
|
||||
let res = zcashlc_put_sapling_subtree_roots(dbData.0, dbData.1, startIndex, rootsPtr, networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard res else {
|
||||
throw ZcashError.rustPutSaplingSubtreeRoots(lastErrorMessage(fallback: "`putSaplingSubtreeRoots` failed with unknown error"))
|
||||
|
@ -492,7 +539,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func updateChainTip(height: Int32) async throws {
|
||||
globalDBLock.lock()
|
||||
let result = zcashlc_update_chain_tip(dbData.0, dbData.1, height, networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard result else {
|
||||
throw ZcashError.rustUpdateChainTip(lastErrorMessage(fallback: "`updateChainTip` failed with unknown error"))
|
||||
|
@ -500,7 +549,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func fullyScannedHeight() async throws -> BlockHeight? {
|
||||
globalDBLock.lock()
|
||||
let height = zcashlc_fully_scanned_height(dbData.0, dbData.1, networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
if height >= 0 {
|
||||
return BlockHeight(height)
|
||||
|
@ -512,7 +563,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func maxScannedHeight() async throws -> BlockHeight? {
|
||||
globalDBLock.lock()
|
||||
let height = zcashlc_max_scanned_height(dbData.0, dbData.1, networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
if height >= 0 {
|
||||
return BlockHeight(height)
|
||||
|
@ -524,7 +577,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func getScanProgress() async throws -> ScanProgress? {
|
||||
globalDBLock.lock()
|
||||
let result = zcashlc_get_scan_progress(dbData.0, dbData.1, networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
if result.denominator == 0 {
|
||||
switch result.numerator {
|
||||
|
@ -539,7 +594,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func suggestScanRanges() async throws -> [ScanRange] {
|
||||
globalDBLock.lock()
|
||||
let scanRangesPtr = zcashlc_suggest_scan_ranges(dbData.0, dbData.1, networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard let scanRangesPtr else {
|
||||
throw ZcashError.rustSuggestScanRanges(lastErrorMessage(fallback: "`suggestScanRanges` failed with unknown error"))
|
||||
|
@ -567,7 +624,9 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
func scanBlocks(fromHeight: Int32, limit: UInt32 = 0) async throws {
|
||||
globalDBLock.lock()
|
||||
let result = zcashlc_scan_blocks(fsBlockDbRoot.0, fsBlockDbRoot.1, dbData.0, dbData.1, fromHeight, limit, networkType.networkId)
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard result != 0 else {
|
||||
throw ZcashError.rustScanBlocks(lastErrorMessage(fallback: "`scanBlocks` failed with unknown error"))
|
||||
|
@ -581,6 +640,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
) async throws -> Data {
|
||||
var contiguousTxIdBytes = ContiguousArray<UInt8>([UInt8](repeating: 0x0, count: 32))
|
||||
|
||||
globalDBLock.lock()
|
||||
let success = contiguousTxIdBytes.withUnsafeMutableBufferPointer { txIdBytePtr in
|
||||
usk.bytes.withUnsafeBufferPointer { uskBuffer in
|
||||
zcashlc_shield_funds(
|
||||
|
@ -601,6 +661,7 @@ actor ZcashRustBackend: ZcashRustBackendWelding {
|
|||
)
|
||||
}
|
||||
}
|
||||
globalDBLock.unlock()
|
||||
|
||||
guard success else {
|
||||
throw ZcashError.rustShieldFunds(lastErrorMessage(fallback: "`shieldFunds` failed with unknown error"))
|
||||
|
|
|
@ -317,6 +317,9 @@ public enum SyncStatus: Equatable {
|
|||
/// When set, a UI element may want to turn green.
|
||||
case upToDate
|
||||
|
||||
/// Indicates that this Synchronizer was succesfully stopped via `stop()` method.
|
||||
case stopped
|
||||
|
||||
case error(_ error: Error)
|
||||
|
||||
public var isSyncing: Bool {
|
||||
|
@ -347,6 +350,7 @@ public enum SyncStatus: Equatable {
|
|||
switch self {
|
||||
case .unprepared: return "unprepared"
|
||||
case .syncing: return "syncing"
|
||||
case .stopped: return "stopped"
|
||||
case .upToDate: return "up to date"
|
||||
case .error: return "error"
|
||||
}
|
||||
|
@ -469,7 +473,7 @@ extension InternalSyncStatus {
|
|||
case .synced:
|
||||
return .upToDate
|
||||
case .stopped:
|
||||
return .upToDate
|
||||
return .stopped
|
||||
case .disconnected:
|
||||
return .error(ZcashError.synchronizerDisconnected)
|
||||
case .error(let error):
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 }))
|
||||
/*
|
||||
There’s a pending transaction that has expired
|
||||
*/
|
||||
|
|
|
@ -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)")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -13,7 +13,7 @@ final class ScanActionTests: ZcashTestCase {
|
|||
func testScanAction_NextAction() async throws {
|
||||
let blockScannerMock = BlockScannerMock()
|
||||
let loggerMock = LoggerMock()
|
||||
|
||||
|
||||
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
|
||||
|
||||
let scanAction = setupAction(blockScannerMock, loggerMock)
|
||||
|
@ -46,7 +46,7 @@ final class ScanActionTests: ZcashTestCase {
|
|||
func testScanAction_EarlyOutForNoDownloadAndScanRangeSet() async throws {
|
||||
let blockScannerMock = BlockScannerMock()
|
||||
let loggerMock = LoggerMock()
|
||||
|
||||
|
||||
let scanAction = setupAction(blockScannerMock, loggerMock)
|
||||
let syncContext = ActionContextMock.default()
|
||||
|
||||
|
@ -83,7 +83,7 @@ final class ScanActionTests: ZcashTestCase {
|
|||
func testScanAction_EndRangeProperlySetLowerThanBatchSize() async throws {
|
||||
let blockScannerMock = BlockScannerMock()
|
||||
let loggerMock = LoggerMock()
|
||||
|
||||
|
||||
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
|
||||
|
||||
let scanAction = setupAction(blockScannerMock, loggerMock)
|
||||
|
@ -107,7 +107,7 @@ final class ScanActionTests: ZcashTestCase {
|
|||
func testScanAction_EndRangeProperlySetBatchSize() async throws {
|
||||
let blockScannerMock = BlockScannerMock()
|
||||
let loggerMock = LoggerMock()
|
||||
|
||||
|
||||
loggerMock.debugFileFunctionLineClosure = { _, _, _, _ in }
|
||||
|
||||
let scanAction = setupAction(blockScannerMock, loggerMock)
|
||||
|
@ -130,7 +130,8 @@ final class ScanActionTests: ZcashTestCase {
|
|||
|
||||
private func setupAction(
|
||||
_ blockScannerMock: BlockScannerMock,
|
||||
_ loggerMock: LoggerMock
|
||||
_ loggerMock: LoggerMock,
|
||||
_ latestBlocksDataProvider: LatestBlocksDataProvider = LatestBlocksDataProviderMock()
|
||||
) -> ScanAction {
|
||||
let rustBackendMock = ZcashRustBackendWeldingMock(
|
||||
consensusBranchIdForHeightClosure: { height in
|
||||
|
@ -142,7 +143,8 @@ final class ScanActionTests: ZcashTestCase {
|
|||
mockContainer.mock(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in rustBackendMock }
|
||||
mockContainer.mock(type: BlockScanner.self, isSingleton: true) { _ in blockScannerMock }
|
||||
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }
|
||||
|
||||
mockContainer.mock(type: LatestBlocksDataProvider.self, isSingleton: true) { _ in latestBlocksDataProvider }
|
||||
|
||||
let config: CompactBlockProcessor.Configuration = .standard(
|
||||
for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: 0
|
||||
)
|
||||
|
|
|
@ -27,11 +27,13 @@ final class UpdateChainTipActionTests: ZcashTestCase {
|
|||
func testUpdateChainTipAction_UpdateChainTipTimeTriggered() async throws {
|
||||
let loggerMock = LoggerMock()
|
||||
let blockDownloaderMock = BlockDownloaderMock()
|
||||
let latestBlocksDataProvider = LatestBlocksDataProviderMock()
|
||||
|
||||
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
|
||||
blockDownloaderMock.stopDownloadClosure = { }
|
||||
|
||||
let updateChainTipAction = await setupAction(loggerMock, blockDownloaderMock)
|
||||
latestBlocksDataProvider.updateClosure = { _ in }
|
||||
|
||||
let updateChainTipAction = await setupAction(loggerMock, blockDownloaderMock, latestBlocksDataProvider)
|
||||
|
||||
do {
|
||||
let context = ActionContextMock.default()
|
||||
|
@ -53,11 +55,13 @@ final class UpdateChainTipActionTests: ZcashTestCase {
|
|||
func testUpdateChainTipAction_UpdateChainTipPrevActionTriggered() async throws {
|
||||
let loggerMock = LoggerMock()
|
||||
let blockDownloaderMock = BlockDownloaderMock()
|
||||
let latestBlocksDataProvider = LatestBlocksDataProviderMock()
|
||||
|
||||
loggerMock.infoFileFunctionLineClosure = { _, _, _, _ in }
|
||||
blockDownloaderMock.stopDownloadClosure = { }
|
||||
latestBlocksDataProvider.updateClosure = { _ in }
|
||||
|
||||
let updateChainTipAction = await setupAction(loggerMock, blockDownloaderMock)
|
||||
let updateChainTipAction = await setupAction(loggerMock, blockDownloaderMock, latestBlocksDataProvider)
|
||||
|
||||
do {
|
||||
let context = ActionContextMock.default()
|
||||
|
@ -104,7 +108,8 @@ final class UpdateChainTipActionTests: ZcashTestCase {
|
|||
|
||||
private func setupAction(
|
||||
_ loggerMock: LoggerMock = LoggerMock(),
|
||||
_ blockDownloaderMock: BlockDownloaderMock = BlockDownloaderMock()
|
||||
_ blockDownloaderMock: BlockDownloaderMock = BlockDownloaderMock(),
|
||||
_ latestBlocksDataProvider: LatestBlocksDataProvider = LatestBlocksDataProviderMock()
|
||||
) async -> UpdateChainTipAction {
|
||||
let config: CompactBlockProcessor.Configuration = .standard(
|
||||
for: ZcashNetworkBuilder.network(for: underlyingNetworkType), walletBirthday: 0
|
||||
|
@ -133,6 +138,7 @@ final class UpdateChainTipActionTests: ZcashTestCase {
|
|||
mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in serviceMock }
|
||||
mockContainer.mock(type: Logger.self, isSingleton: true) { _ in loggerMock }
|
||||
mockContainer.mock(type: BlockDownloader.self, isSingleton: true) { _ in blockDownloaderMock }
|
||||
mockContainer.mock(type: LatestBlocksDataProvider.self, isSingleton: true) { _ in latestBlocksDataProvider }
|
||||
|
||||
return UpdateChainTipAction(container: mockContainer)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,4 +157,14 @@ class ZcashRustBackendTests: XCTestCase {
|
|||
XCTAssertEqual(metadata?.networkType, .mainnet)
|
||||
XCTAssertEqual(metadata?.addressType, .sapling)
|
||||
}
|
||||
|
||||
func testScanProgressThrowsOnWrongValues() {
|
||||
// Assert that throws on Zero denominator
|
||||
XCTAssertThrowsError(try ScanProgress(numerator: 0, denominator: 0).progress())
|
||||
|
||||
// Assert that throws on numerator > denominator
|
||||
XCTAssertThrowsError(try ScanProgress(numerator: 23, denominator: 2).progress())
|
||||
|
||||
XCTAssertNoThrow(try ScanProgress(numerator: 3, denominator: 4).progress())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -712,6 +712,21 @@ class LatestBlocksDataProviderMock: LatestBlocksDataProvider {
|
|||
await updateWalletBirthdayClosure!(walletBirthday)
|
||||
}
|
||||
|
||||
// MARK: - update
|
||||
|
||||
var updateCallsCount = 0
|
||||
var updateCalled: Bool {
|
||||
return updateCallsCount > 0
|
||||
}
|
||||
var updateReceivedLatestBlockHeight: BlockHeight?
|
||||
var updateClosure: ((BlockHeight) async -> Void)?
|
||||
|
||||
func update(_ latestBlockHeight: BlockHeight) async {
|
||||
updateCallsCount += 1
|
||||
updateReceivedLatestBlockHeight = latestBlockHeight
|
||||
await updateClosure!(latestBlockHeight)
|
||||
}
|
||||
|
||||
}
|
||||
class LightWalletServiceMock: LightWalletService {
|
||||
|
||||
|
@ -1693,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 {
|
||||
|
@ -1914,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
|
||||
}
|
||||
|
@ -1938,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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue