Migrate to first pre-release of FFI 0.9.0
Includes: - Initialization changes to enable log filter customization. We now connect the Rust log level to the Swift log level, and always run other Rust initialization steps. - Fetching the ZEC-USD exchange rate over Tor.
This commit is contained in:
parent
4c92c2b4a6
commit
929f1983bd
|
@ -6,6 +6,11 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
# Unreleased
|
||||
|
||||
## Added
|
||||
- `Synchronizer.getExchangeRateUSD() -> NSDecimalNumber`, which fetches the latest USD/ZEC
|
||||
exchange rate. Prices are queried over Tor (to hide the wallet's IP address) on Binance,
|
||||
Coinbase, and Gemini.
|
||||
|
||||
# 2.1.9 - 2024-06-05
|
||||
|
||||
## Fixed
|
||||
|
|
|
@ -176,8 +176,7 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi",
|
||||
"state" : {
|
||||
"revision" : "9314c83d7a09d88e1c0bd3ff3738a50833325059",
|
||||
"version" : "0.8.0"
|
||||
"revision" : "5919afaa2c37fa11946d43b5c1e66b8463867f98"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -48,12 +48,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
fsBlockDbRoot: try! fsBlockDbRootURLHelper(),
|
||||
generalStorageURL: try! generalStorageURLHelper(),
|
||||
dataDbURL: try! dataDbURLHelper(),
|
||||
torDirURL: try! torDirURLHelper(),
|
||||
endpoint: DemoAppConfig.endpoint,
|
||||
network: kZcashNetwork,
|
||||
spendParamsURL: try! spendParamsURLHelper(),
|
||||
outputParamsURL: try! outputParamsURLHelper(),
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL.default,
|
||||
enableBackendTracing: true
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL.default
|
||||
)
|
||||
|
||||
self.wallet = wallet
|
||||
|
@ -199,6 +199,15 @@ func dataDbURLHelper() throws -> URL {
|
|||
)
|
||||
}
|
||||
|
||||
func torDirURLHelper() throws -> URL {
|
||||
try documentsDirectoryHelper()
|
||||
.appendingPathComponent(kZcashNetwork.networkType.chainName)
|
||||
.appendingPathComponent(
|
||||
ZcashSDK.defaultTorDirName,
|
||||
isDirectory: true
|
||||
)
|
||||
}
|
||||
|
||||
func spendParamsURLHelper() throws -> URL {
|
||||
try documentsDirectoryHelper().appendingPathComponent("sapling-spend.params")
|
||||
}
|
||||
|
|
|
@ -19,10 +19,14 @@ class GetBalanceViewController: UIViewController {
|
|||
self.title = "Account 0 Balance"
|
||||
|
||||
Task { @MainActor in
|
||||
let balanceText = (try? await synchronizer.getAccountBalance()?.saplingBalance.total().formattedString) ?? "0.0"
|
||||
let verifiedText = (try? await synchronizer.getAccountBalance()?.saplingBalance.spendableValue.formattedString) ?? "0.0"
|
||||
self.balance.text = "\(balanceText) ZEC"
|
||||
self.verified.text = "\(verifiedText) ZEC"
|
||||
let balance = try? await synchronizer.getAccountBalance()
|
||||
let balanceText = (balance?.saplingBalance.total().formattedString) ?? "0.0"
|
||||
let verifiedText = (balance?.saplingBalance.spendableValue.formattedString) ?? "0.0"
|
||||
let usdZecRate = try await synchronizer.getExchangeRateUSD()
|
||||
let usdBalance = (balance?.saplingBalance.total().decimalValue ?? 0).multiplying(by: usdZecRate)
|
||||
let usdVerified = (balance?.saplingBalance.spendableValue.decimalValue ?? 0).multiplying(by: usdZecRate)
|
||||
self.balance.text = "\(balanceText) ZEC\n\(usdBalance) USD\n\n(\(usdZecRate) USD/ZEC)"
|
||||
self.verified.text = "\(verifiedText) ZEC\n\(usdVerified) USD"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,14 +102,14 @@ class SyncBlocksListViewController: UIViewController {
|
|||
fsBlockDbRoot: try! fsBlockDbRootURLHelper(),
|
||||
generalStorageURL: try! generalStorageURLHelper(),
|
||||
dataDbURL: try! dataDbURLHelper(),
|
||||
torDirURL: try! torDirURLHelper(),
|
||||
endpoint: DemoAppConfig.endpoint,
|
||||
network: kZcashNetwork,
|
||||
spendParamsURL: try! spendParamsURLHelper(),
|
||||
outputParamsURL: try! outputParamsURLHelper(),
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL.default,
|
||||
alias: data.alias,
|
||||
loggingPolicy: .default(.debug),
|
||||
enableBackendTracing: true
|
||||
loggingPolicy: .default(.debug)
|
||||
)
|
||||
|
||||
return SDKSynchronizer(initializer: initializer)
|
||||
|
|
|
@ -122,8 +122,7 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi",
|
||||
"state" : {
|
||||
"revision" : "9314c83d7a09d88e1c0bd3ff3738a50833325059",
|
||||
"version" : "0.8.0"
|
||||
"revision" : "5919afaa2c37fa11946d43b5c1e66b8463867f98"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -16,7 +16,9 @@ let package = Package(
|
|||
dependencies: [
|
||||
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.19.1"),
|
||||
.package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1"),
|
||||
.package(url: "https://github.com/zcash-hackworks/zcash-light-client-ffi", exact: "0.8.0")
|
||||
//.package(url: "https://github.com/zcash-hackworks/zcash-light-client-ffi", exact: "0.8.0")
|
||||
// Compiled from 7c7b797211a7bd0b847df6315faa9ae13c32a0f6
|
||||
.package(url: "https://github.com/zcash-hackworks/zcash-light-client-ffi", revision: "5919afaa2c37fa11946d43b5c1e66b8463867f98")
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
|
|
|
@ -56,6 +56,7 @@ actor CompactBlockProcessor {
|
|||
let saplingParamsSourceURL: SaplingParamsSourceURL
|
||||
let fsBlockCacheRoot: URL
|
||||
let dataDb: URL
|
||||
let torDir: URL
|
||||
let spendParamsURL: URL
|
||||
let outputParamsURL: URL
|
||||
let enhanceBatchSize: Int
|
||||
|
@ -79,6 +80,7 @@ actor CompactBlockProcessor {
|
|||
cacheDbURL: URL? = nil,
|
||||
fsBlockCacheRoot: URL,
|
||||
dataDb: URL,
|
||||
torDir: URL,
|
||||
spendParamsURL: URL,
|
||||
outputParamsURL: URL,
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL,
|
||||
|
@ -94,6 +96,7 @@ actor CompactBlockProcessor {
|
|||
self.alias = alias
|
||||
self.fsBlockCacheRoot = fsBlockCacheRoot
|
||||
self.dataDb = dataDb
|
||||
self.torDir = torDir
|
||||
self.spendParamsURL = spendParamsURL
|
||||
self.outputParamsURL = outputParamsURL
|
||||
self.saplingParamsSourceURL = saplingParamsSourceURL
|
||||
|
@ -112,6 +115,7 @@ actor CompactBlockProcessor {
|
|||
alias: ZcashSynchronizerAlias,
|
||||
fsBlockCacheRoot: URL,
|
||||
dataDb: URL,
|
||||
torDir: URL,
|
||||
spendParamsURL: URL,
|
||||
outputParamsURL: URL,
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL,
|
||||
|
@ -126,6 +130,7 @@ actor CompactBlockProcessor {
|
|||
self.alias = alias
|
||||
self.fsBlockCacheRoot = fsBlockCacheRoot
|
||||
self.dataDb = dataDb
|
||||
self.torDir = torDir
|
||||
self.spendParamsURL = spendParamsURL
|
||||
self.outputParamsURL = outputParamsURL
|
||||
self.saplingParamsSourceURL = saplingParamsSourceURL
|
||||
|
@ -151,6 +156,7 @@ actor CompactBlockProcessor {
|
|||
alias: initializer.alias,
|
||||
fsBlockCacheRoot: initializer.fsBlockDbRoot,
|
||||
dataDb: initializer.dataDbURL,
|
||||
torDir: initializer.torDirURL,
|
||||
spendParamsURL: initializer.spendParamsURL,
|
||||
outputParamsURL: initializer.outputParamsURL,
|
||||
saplingParamsSourceURL: initializer.saplingParamsSourceURL,
|
||||
|
|
|
@ -128,7 +128,10 @@ public protocol ClosureSynchronizer {
|
|||
func refreshUTXOs(address: TransparentAddress, from height: BlockHeight, completion: @escaping (Result<RefreshedUTXOs, Error>) -> Void)
|
||||
|
||||
func getAccountBalance(accountIndex: Int, completion: @escaping (Result<AccountBalance?, Error>) -> Void)
|
||||
|
||||
|
||||
/// Fetches the latest ZEC-USD exchange rate.
|
||||
func getExchangeRateUSD(completion: @escaping (Result<NSDecimalNumber, Error>) -> Void)
|
||||
|
||||
/*
|
||||
It can be missleading that these two methods are returning Publisher even this protocol is closure based. Reason is that Synchronizer doesn't
|
||||
provide different implementations for these two methods. So Combine it is even here.
|
||||
|
|
|
@ -131,6 +131,9 @@ public protocol CombineSynchronizer {
|
|||
|
||||
func getAccountBalance(accountIndex: Int) -> SinglePublisher<AccountBalance?, Error>
|
||||
|
||||
/// Fetches the latest ZEC-USD exchange rate.
|
||||
func getExchangeRateUSD() -> SinglePublisher<NSDecimalNumber, Error>
|
||||
|
||||
func rewind(_ policy: RewindPolicy) -> CompletablePublisher<Error>
|
||||
func wipe() -> CompletablePublisher<Error>
|
||||
}
|
||||
|
|
|
@ -124,6 +124,9 @@ public enum ZcashSDK {
|
|||
/// Default Name for LibRustZcash data.db
|
||||
public static let defaultDataDbName = "data.db"
|
||||
|
||||
/// Default Name for Tor data directory
|
||||
public static let defaultTorDirName = "tor"
|
||||
|
||||
/// Default Name for Compact Block file system based db
|
||||
public static let defaultFsCacheName = "fs_cache"
|
||||
|
||||
|
@ -154,6 +157,9 @@ public protocol NetworkConstants {
|
|||
/// Default Name for LibRustZcash data.db
|
||||
static var defaultDataDbName: String { get }
|
||||
|
||||
/// Default Name for Tor data directory
|
||||
static var defaultTorDirName: String { get }
|
||||
|
||||
static var defaultFsBlockDbRootName: String { get }
|
||||
|
||||
/// Default Name for Compact Block caches db
|
||||
|
@ -181,6 +187,9 @@ public enum ZcashSDKMainnetConstants: NetworkConstants {
|
|||
/// Default Name for LibRustZcash data.db
|
||||
public static let defaultDataDbName = "data.db"
|
||||
|
||||
/// Default Name for Tor data directory
|
||||
public static let defaultTorDirName = "tor"
|
||||
|
||||
public static let defaultFsBlockDbRootName = "fs_cache"
|
||||
|
||||
/// Default Name for Compact Block caches db
|
||||
|
@ -197,6 +206,9 @@ public enum ZcashSDKTestnetConstants: NetworkConstants {
|
|||
/// Default Name for LibRustZcash data.db
|
||||
public static let defaultDataDbName = "data.db"
|
||||
|
||||
/// Default Name for Tor data directory
|
||||
public static let defaultTorDirName = "tor"
|
||||
|
||||
/// Default Name for Compact Block caches db
|
||||
public static let defaultCacheDbName = "caches.db"
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
scriptDir=${0:a:h}
|
||||
cd "${scriptDir}"
|
||||
|
||||
sourcery_version=2.1.7
|
||||
sourcery_version=2.2.4
|
||||
|
||||
if which sourcery >/dev/null; then
|
||||
if [[ $(sourcery --version) != $sourcery_version ]]; then
|
||||
echo "warning: Compatible sourcer version not installed. Install sourcer $sourcery_version. Currently installed version is $(sourcer --version)"
|
||||
echo "warning: Compatible sourcer version not installed. Install sourcer $sourcery_version. Currently installed version is $(sourcery --version)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery
|
||||
// Generated using Sourcery 2.2.4 — https://github.com/krzysztofzablocki/Sourcery
|
||||
// DO NOT EDIT
|
||||
|
||||
/*
|
||||
|
@ -342,6 +342,16 @@ public enum ZcashError: Equatable, Error {
|
|||
/// sourcery: code="ZRUST0061"
|
||||
/// ZRUST0061
|
||||
case rustPutOrchardSubtreeRoots(_ rustError: String)
|
||||
/// Error from rust layer when calling TorClient.init
|
||||
/// - `rustError` contains error generated by the rust layer.
|
||||
/// sourcery: code="ZRUST0062"
|
||||
/// ZRUST0062
|
||||
case rustTorClientInit(_ rustError: String)
|
||||
/// Error from rust layer when calling TorClient.get
|
||||
/// - `rustError` contains error generated by the rust layer.
|
||||
/// sourcery: code="ZRUST0063"
|
||||
/// ZRUST0063
|
||||
case rustTorClientGet(_ rustError: String)
|
||||
/// SQLite query failed when fetching all accounts from the database.
|
||||
/// - `sqliteError` is error produced by SQLite library.
|
||||
/// ZADAO0001
|
||||
|
@ -705,6 +715,8 @@ public enum ZcashError: Equatable, Error {
|
|||
case .rustIsSeedRelevantToAnyDerivedAccount: return "Error from rust layer when calling ZcashRustBackend.rustIsSeedRelevantToAnyDerivedAccount"
|
||||
case .rustPutOrchardSubtreeRootsAllocationProblem: return "Unable to allocate memory required to write blocks when calling ZcashRustBackend.putOrchardSubtreeRoots"
|
||||
case .rustPutOrchardSubtreeRoots: return "Error from rust layer when calling ZcashRustBackend.putOrchardSubtreeRoots"
|
||||
case .rustTorClientInit: return "Error from rust layer when calling TorClient.init"
|
||||
case .rustTorClientGet: return "Error from rust layer when calling TorClient.get"
|
||||
case .accountDAOGetAll: return "SQLite query failed when fetching all accounts from the database."
|
||||
case .accountDAOGetAllCantDecode: return "Fetched accounts from SQLite but can't decode them."
|
||||
case .accountDAOFindBy: return "SQLite query failed when seaching for accounts in the database."
|
||||
|
@ -885,6 +897,8 @@ public enum ZcashError: Equatable, Error {
|
|||
case .rustIsSeedRelevantToAnyDerivedAccount: return .rustIsSeedRelevantToAnyDerivedAccount
|
||||
case .rustPutOrchardSubtreeRootsAllocationProblem: return .rustPutOrchardSubtreeRootsAllocationProblem
|
||||
case .rustPutOrchardSubtreeRoots: return .rustPutOrchardSubtreeRoots
|
||||
case .rustTorClientInit: return .rustTorClientInit
|
||||
case .rustTorClientGet: return .rustTorClientGet
|
||||
case .accountDAOGetAll: return .accountDAOGetAll
|
||||
case .accountDAOGetAllCantDecode: return .accountDAOGetAllCantDecode
|
||||
case .accountDAOFindBy: return .accountDAOFindBy
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery
|
||||
// Generated using Sourcery 2.2.4 — https://github.com/krzysztofzablocki/Sourcery
|
||||
// DO NOT EDIT
|
||||
|
||||
/*
|
||||
|
@ -185,6 +185,10 @@ public enum ZcashErrorCode: String {
|
|||
case rustPutOrchardSubtreeRootsAllocationProblem = "ZRUST0060"
|
||||
/// Error from rust layer when calling ZcashRustBackend.putOrchardSubtreeRoots
|
||||
case rustPutOrchardSubtreeRoots = "ZRUST0061"
|
||||
/// Error from rust layer when calling TorClient.init
|
||||
case rustTorClientInit = "ZRUST0062"
|
||||
/// Error from rust layer when calling TorClient.get
|
||||
case rustTorClientGet = "ZRUST0063"
|
||||
/// SQLite query failed when fetching all accounts from the database.
|
||||
case accountDAOGetAll = "ZADAO0001"
|
||||
/// Fetched accounts from SQLite but can't decode them.
|
||||
|
|
|
@ -367,6 +367,14 @@ enum ZcashErrorDefinition {
|
|||
/// - `rustError` contains error generated by the rust layer.
|
||||
/// sourcery: code="ZRUST0061"
|
||||
case rustPutOrchardSubtreeRoots(_ rustError: String)
|
||||
/// Error from rust layer when calling TorClient.init
|
||||
/// - `rustError` contains error generated by the rust layer.
|
||||
/// sourcery: code="ZRUST0062"
|
||||
case rustTorClientInit(_ rustError: String)
|
||||
/// Error from rust layer when calling TorClient.get
|
||||
/// - `rustError` contains error generated by the rust layer.
|
||||
/// sourcery: code="ZRUST0063"
|
||||
case rustTorClientGet(_ rustError: String)
|
||||
|
||||
// MARK: - Account DAO
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ public class Initializer {
|
|||
struct URLs {
|
||||
let fsBlockDbRoot: URL
|
||||
let dataDbURL: URL
|
||||
let torDirURL: URL
|
||||
let generalStorageURL: URL
|
||||
let spendParamsURL: URL
|
||||
let outputParamsURL: URL
|
||||
|
@ -115,6 +116,7 @@ public class Initializer {
|
|||
let fsBlockDbRoot: URL
|
||||
let generalStorageURL: URL
|
||||
let dataDbURL: URL
|
||||
let torDirURL: URL
|
||||
let spendParamsURL: URL
|
||||
let outputParamsURL: URL
|
||||
let saplingParamsSourceURL: SaplingParamsSourceURL
|
||||
|
@ -158,14 +160,14 @@ public class Initializer {
|
|||
fsBlockDbRoot: URL,
|
||||
generalStorageURL: URL,
|
||||
dataDbURL: URL,
|
||||
torDirURL: URL,
|
||||
endpoint: LightWalletEndpoint,
|
||||
network: ZcashNetwork,
|
||||
spendParamsURL: URL,
|
||||
outputParamsURL: URL,
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL,
|
||||
alias: ZcashSynchronizerAlias = .default,
|
||||
loggingPolicy: LoggingPolicy = .default(.debug),
|
||||
enableBackendTracing: Bool = false
|
||||
loggingPolicy: LoggingPolicy = .default(.debug)
|
||||
) {
|
||||
let container = DIContainer()
|
||||
|
||||
|
@ -177,14 +179,14 @@ public class Initializer {
|
|||
fsBlockDbRoot: fsBlockDbRoot,
|
||||
generalStorageURL: generalStorageURL,
|
||||
dataDbURL: dataDbURL,
|
||||
torDirURL: torDirURL,
|
||||
endpoint: endpoint,
|
||||
network: network,
|
||||
spendParamsURL: spendParamsURL,
|
||||
outputParamsURL: outputParamsURL,
|
||||
saplingParamsSourceURL: saplingParamsSourceURL,
|
||||
alias: alias,
|
||||
loggingPolicy: loggingPolicy,
|
||||
enableBackendTracing: enableBackendTracing
|
||||
loggingPolicy: loggingPolicy
|
||||
)
|
||||
|
||||
self.init(
|
||||
|
@ -207,14 +209,14 @@ public class Initializer {
|
|||
fsBlockDbRoot: URL,
|
||||
generalStorageURL: URL,
|
||||
dataDbURL: URL,
|
||||
torDirURL: URL,
|
||||
endpoint: LightWalletEndpoint,
|
||||
network: ZcashNetwork,
|
||||
spendParamsURL: URL,
|
||||
outputParamsURL: URL,
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL,
|
||||
alias: ZcashSynchronizerAlias = .default,
|
||||
loggingPolicy: LoggingPolicy = .default(.debug),
|
||||
enableBackendTracing: Bool = false
|
||||
loggingPolicy: LoggingPolicy = .default(.debug)
|
||||
) {
|
||||
// It's not possible to fail from constructor. Technically it's possible but it can be pain for the client apps to handle errors thrown
|
||||
// from constructor. So `parsingError` is just stored in initializer and `SDKSynchronizer.prepare()` throw this error if it exists.
|
||||
|
@ -224,14 +226,14 @@ public class Initializer {
|
|||
fsBlockDbRoot: fsBlockDbRoot,
|
||||
generalStorageURL: generalStorageURL,
|
||||
dataDbURL: dataDbURL,
|
||||
torDirURL: torDirURL,
|
||||
endpoint: endpoint,
|
||||
network: network,
|
||||
spendParamsURL: spendParamsURL,
|
||||
outputParamsURL: outputParamsURL,
|
||||
saplingParamsSourceURL: saplingParamsSourceURL,
|
||||
alias: alias,
|
||||
loggingPolicy: loggingPolicy,
|
||||
enableBackendTracing: enableBackendTracing
|
||||
loggingPolicy: loggingPolicy
|
||||
)
|
||||
|
||||
self.init(
|
||||
|
@ -264,6 +266,7 @@ public class Initializer {
|
|||
self.fsBlockDbRoot = urls.fsBlockDbRoot
|
||||
self.generalStorageURL = urls.generalStorageURL
|
||||
self.dataDbURL = urls.dataDbURL
|
||||
self.torDirURL = urls.torDirURL
|
||||
self.endpoint = endpoint
|
||||
self.spendParamsURL = urls.spendParamsURL
|
||||
self.outputParamsURL = urls.outputParamsURL
|
||||
|
@ -286,18 +289,19 @@ public class Initializer {
|
|||
fsBlockDbRoot: URL,
|
||||
generalStorageURL: URL,
|
||||
dataDbURL: URL,
|
||||
torDirURL: URL,
|
||||
endpoint: LightWalletEndpoint,
|
||||
network: ZcashNetwork,
|
||||
spendParamsURL: URL,
|
||||
outputParamsURL: URL,
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL,
|
||||
alias: ZcashSynchronizerAlias,
|
||||
loggingPolicy: LoggingPolicy = .default(.debug),
|
||||
enableBackendTracing: Bool = false
|
||||
loggingPolicy: LoggingPolicy = .default(.debug)
|
||||
) -> (URLs, ZcashError?) {
|
||||
let urls = URLs(
|
||||
fsBlockDbRoot: fsBlockDbRoot,
|
||||
dataDbURL: dataDbURL,
|
||||
torDirURL: torDirURL,
|
||||
generalStorageURL: generalStorageURL,
|
||||
spendParamsURL: spendParamsURL,
|
||||
outputParamsURL: outputParamsURL
|
||||
|
@ -313,8 +317,7 @@ public class Initializer {
|
|||
alias: alias,
|
||||
networkType: network.networkType,
|
||||
endpoint: endpoint,
|
||||
loggingPolicy: loggingPolicy,
|
||||
enableBackendTracing: enableBackendTracing
|
||||
loggingPolicy: loggingPolicy
|
||||
)
|
||||
|
||||
return (updatedURLs, parsingError)
|
||||
|
@ -362,6 +365,10 @@ public class Initializer {
|
|||
return .failure(.initializerCantUpdateURLWithAlias(urls.dataDbURL))
|
||||
}
|
||||
|
||||
guard let updatedTorDirURL = urls.torDirURL.updateLastPathComponent(with: alias) else {
|
||||
return .failure(.initializerCantUpdateURLWithAlias(urls.torDirURL))
|
||||
}
|
||||
|
||||
guard let updatedSpendParamsURL = urls.spendParamsURL.updateLastPathComponent(with: alias) else {
|
||||
return .failure(.initializerCantUpdateURLWithAlias(urls.spendParamsURL))
|
||||
}
|
||||
|
@ -378,6 +385,7 @@ public class Initializer {
|
|||
URLs(
|
||||
fsBlockDbRoot: updatedFsBlockDbRoot,
|
||||
dataDbURL: updatedDataDbURL,
|
||||
torDirURL: updatedTorDirURL,
|
||||
generalStorageURL: updatedGeneralStorageURL,
|
||||
spendParamsURL: updatedSpendParamsURL,
|
||||
outputParamsURL: updateOutputParamsURL
|
||||
|
|
|
@ -31,6 +31,16 @@ public struct DefaultResourceProvider: ResourceProvider {
|
|||
}
|
||||
}
|
||||
|
||||
public var torDirURL: URL {
|
||||
let constants = network.constants
|
||||
do {
|
||||
let url = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
|
||||
return url.appendingPathComponent(constants.defaultTorDirName)
|
||||
} catch {
|
||||
return URL(fileURLWithPath: "file://\(constants.defaultTorDirName)")
|
||||
}
|
||||
}
|
||||
|
||||
public var fsCacheURL: URL {
|
||||
let constants = network.constants
|
||||
do {
|
||||
|
|
|
@ -9,6 +9,21 @@
|
|||
import Foundation
|
||||
import libzcashlc
|
||||
|
||||
enum RustLogging: String {
|
||||
/// The logs are completely disabled.
|
||||
case off
|
||||
/// Logs very serious errors.
|
||||
case error
|
||||
/// Logs hazardous situations.
|
||||
case warn
|
||||
/// Logs useful information.
|
||||
case info
|
||||
/// Logs lower priority information.
|
||||
case debug
|
||||
/// Logs very low priority, often extremely verbose, information.
|
||||
case trace
|
||||
}
|
||||
|
||||
struct ZcashRustBackend: ZcashRustBackendWelding {
|
||||
let minimumConfirmations: UInt32 = 10
|
||||
let minimumShieldingConfirmations: UInt32 = 1
|
||||
|
@ -22,7 +37,8 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
|
|||
|
||||
let networkType: NetworkType
|
||||
|
||||
static var tracingEnabled = false
|
||||
static var rustInitialized = false
|
||||
|
||||
/// Creates instance of `ZcashRustBackend`.
|
||||
/// - Parameters:
|
||||
/// - dbData: `URL` pointing to file where data database will be.
|
||||
|
@ -32,9 +48,17 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
|
|||
/// - spendParamsPath: `URL` pointing to spend parameters file.
|
||||
/// - outputParamsPath: `URL` pointing to output parameters file.
|
||||
/// - networkType: Network type to use.
|
||||
/// - enableTracing: this sets up whether the tracing system will dump logs onto the OSLogger system or not.
|
||||
/// **Important note:** this will enable the tracing **for all instances** of ZcashRustBackend, not only for this one.
|
||||
init(dbData: URL, fsBlockDbRoot: URL, spendParamsPath: URL, outputParamsPath: URL, networkType: NetworkType, enableTracing: Bool = false) {
|
||||
/// - logLevel: this sets up whether the tracing system will dump logs onto the OSLogger system or not.
|
||||
/// **Important note:** this will enable the tracing **for all instances** of ZcashRustBackend, not only for this one.
|
||||
/// This is ignored after the first ZcashRustBackend instance is created.
|
||||
init(
|
||||
dbData: URL,
|
||||
fsBlockDbRoot: URL,
|
||||
spendParamsPath: URL,
|
||||
outputParamsPath: URL,
|
||||
networkType: NetworkType,
|
||||
logLevel: RustLogging = RustLogging.off
|
||||
) {
|
||||
self.dbData = dbData.osStr()
|
||||
self.fsBlockDbRoot = fsBlockDbRoot.osPathStr()
|
||||
self.spendParamsPath = spendParamsPath.osPathStr()
|
||||
|
@ -42,9 +66,9 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
|
|||
self.networkType = networkType
|
||||
self.keyDeriving = ZcashKeyDerivationBackend(networkType: networkType)
|
||||
|
||||
if enableTracing && !Self.tracingEnabled {
|
||||
Self.tracingEnabled = true
|
||||
Self.enableTracing()
|
||||
if !Self.rustInitialized {
|
||||
Self.rustInitialized = true
|
||||
Self.initializeRust(logLevel: logLevel)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -823,33 +847,33 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
|
|||
}
|
||||
|
||||
private extension ZcashRustBackend {
|
||||
static func enableTracing() {
|
||||
zcashlc_init_on_load(false)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ZcashRustBackend {
|
||||
nonisolated func lastErrorMessage(fallback: String) -> String {
|
||||
let errorLen = zcashlc_last_error_length()
|
||||
defer { zcashlc_clear_last_error() }
|
||||
|
||||
if errorLen > 0 {
|
||||
let error = UnsafeMutablePointer<Int8>.allocate(capacity: Int(errorLen))
|
||||
defer { error.deallocate() }
|
||||
|
||||
zcashlc_error_message_utf8(error, errorLen)
|
||||
if let errorMessage = String(validatingUTF8: error) {
|
||||
return errorMessage
|
||||
} else {
|
||||
return fallback
|
||||
}
|
||||
} else {
|
||||
return fallback
|
||||
static func initializeRust(logLevel: RustLogging) {
|
||||
logLevel.rawValue.utf8CString.withUnsafeBufferPointer { levelPtr in
|
||||
zcashlc_init_on_load(levelPtr.baseAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension URL {
|
||||
nonisolated func lastErrorMessage(fallback: String) -> String {
|
||||
let errorLen = zcashlc_last_error_length()
|
||||
defer { zcashlc_clear_last_error() }
|
||||
|
||||
if errorLen > 0 {
|
||||
let error = UnsafeMutablePointer<Int8>.allocate(capacity: Int(errorLen))
|
||||
defer { error.deallocate() }
|
||||
|
||||
zcashlc_error_message_utf8(error, errorLen)
|
||||
if let errorMessage = String(validatingUTF8: error) {
|
||||
return errorMessage
|
||||
} else {
|
||||
return fallback
|
||||
}
|
||||
} else {
|
||||
return fallback
|
||||
}
|
||||
}
|
||||
|
||||
extension URL {
|
||||
func osStr() -> (String, UInt) {
|
||||
let path = self.absoluteString
|
||||
return (path, UInt(path.lengthOfBytes(using: .utf8)))
|
||||
|
|
|
@ -309,6 +309,9 @@ public protocol Synchronizer: AnyObject {
|
|||
/// - Returns: `AccountBalance`, struct that holds sapling and unshielded balances or `nil` when no account is associated with `accountIndex`
|
||||
func getAccountBalance(accountIndex: Int) async throws -> AccountBalance?
|
||||
|
||||
/// Fetches the latest ZEC-USD exchange rate.
|
||||
func getExchangeRateUSD() async throws -> NSDecimalNumber
|
||||
|
||||
/// Rescans the known blocks with the current keys.
|
||||
///
|
||||
/// `rewind(policy:)` can be called anytime. If the sync process is in progress then it is stopped first. In this case, it make some significant
|
||||
|
|
|
@ -194,6 +194,12 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
|
|||
}
|
||||
}
|
||||
|
||||
public func getExchangeRateUSD(completion: @escaping (Result<NSDecimalNumber, Error>) -> Void) {
|
||||
AsyncToClosureGateway.executeThrowingAction(completion) {
|
||||
try await self.synchronizer.getExchangeRateUSD()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
It can be missleading that these two methods are returning Publisher even this protocol is closure based. Reason is that Synchronizer doesn't
|
||||
provide different implementations for these two methods. So Combine it is even here.
|
||||
|
|
|
@ -196,6 +196,12 @@ extension CombineSDKSynchronizer: CombineSynchronizer {
|
|||
}
|
||||
}
|
||||
|
||||
public func getExchangeRateUSD() -> SinglePublisher<NSDecimalNumber, Error> {
|
||||
AsyncToCombineGateway.executeThrowingAction() {
|
||||
try await self.synchronizer.getExchangeRateUSD()
|
||||
}
|
||||
}
|
||||
|
||||
public func rewind(_ policy: RewindPolicy) -> CompletablePublisher<Error> { synchronizer.rewind(policy) }
|
||||
public func wipe() -> CompletablePublisher<Error> { synchronizer.wipe() }
|
||||
}
|
||||
|
|
|
@ -14,8 +14,7 @@ enum Dependencies {
|
|||
alias: ZcashSynchronizerAlias,
|
||||
networkType: NetworkType,
|
||||
endpoint: LightWalletEndpoint,
|
||||
loggingPolicy: Initializer.LoggingPolicy = .default(.debug),
|
||||
enableBackendTracing: Bool = false
|
||||
loggingPolicy: Initializer.LoggingPolicy = .default(.debug)
|
||||
) {
|
||||
container.register(type: CheckpointSource.self, isSingleton: true) { _ in
|
||||
CheckpointSourceFactory.fromBundle(for: networkType)
|
||||
|
@ -35,6 +34,36 @@ enum Dependencies {
|
|||
return logger
|
||||
}
|
||||
|
||||
let rustLogging: RustLogging
|
||||
switch loggingPolicy {
|
||||
case .default(let logLevel):
|
||||
switch logLevel {
|
||||
case .debug:
|
||||
rustLogging = RustLogging.debug
|
||||
case .info, .event:
|
||||
rustLogging = RustLogging.info
|
||||
case .warning:
|
||||
rustLogging = RustLogging.warn
|
||||
case .error:
|
||||
rustLogging = RustLogging.error
|
||||
}
|
||||
case .custom(let logger):
|
||||
switch logger.maxLogLevel() {
|
||||
case .debug:
|
||||
rustLogging = RustLogging.debug
|
||||
case .info, .event:
|
||||
rustLogging = RustLogging.info
|
||||
case .warning:
|
||||
rustLogging = RustLogging.warn
|
||||
case .error:
|
||||
rustLogging = RustLogging.error
|
||||
case .none:
|
||||
rustLogging = RustLogging.off
|
||||
}
|
||||
case .noLogging:
|
||||
rustLogging = RustLogging.off
|
||||
}
|
||||
|
||||
container.register(type: ZcashRustBackendWelding.self, isSingleton: true) { _ in
|
||||
ZcashRustBackend(
|
||||
dbData: urls.dataDbURL,
|
||||
|
@ -42,7 +71,7 @@ enum Dependencies {
|
|||
spendParamsPath: urls.spendParamsURL,
|
||||
outputParamsPath: urls.outputParamsURL,
|
||||
networkType: networkType,
|
||||
enableTracing: enableBackendTracing
|
||||
logLevel: rustLogging
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -508,6 +508,24 @@ public class SDKSynchronizer: Synchronizer {
|
|||
try await initializer.rustBackend.getWalletSummary()?.accountBalances[UInt32(accountIndex)]
|
||||
}
|
||||
|
||||
public func getExchangeRateUSD() async throws -> NSDecimalNumber {
|
||||
logger.info("Bootstrapping Tor client for fetching exchange rates")
|
||||
let tor: TorClient
|
||||
do {
|
||||
tor = try await TorClient(torDir: initializer.torDirURL)
|
||||
} catch {
|
||||
logger.error("failed to bootstrap Tor client: \(error)")
|
||||
throw error
|
||||
}
|
||||
|
||||
do {
|
||||
return try await tor.getExchangeRateUSD()
|
||||
} catch {
|
||||
logger.error("Failed to fetch exchange rate through Tor: \(error)")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
public func getUnifiedAddress(accountIndex: Int) async throws -> UnifiedAddress {
|
||||
try await blockProcessor.getUnifiedAddress(accountIndex: accountIndex)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// TorRuntime.swift
|
||||
//
|
||||
//
|
||||
// Created by Jack Grigg on 04/06/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import libzcashlc
|
||||
|
||||
public class TorClient {
|
||||
private let runtime: OpaquePointer
|
||||
|
||||
init(torDir: URL) async throws {
|
||||
// Ensure that the directory exists.
|
||||
let fileManager = FileManager()
|
||||
if !fileManager.fileExists(atPath: torDir.path) {
|
||||
do {
|
||||
try fileManager.createDirectory(at: torDir, withIntermediateDirectories: true)
|
||||
} catch {
|
||||
throw ZcashError.blockRepositoryCreateBlocksCacheDirectory(torDir, error)
|
||||
}
|
||||
}
|
||||
|
||||
let rawDir = torDir.osPathStr()
|
||||
let runtimePtr = zcashlc_create_tor_runtime(rawDir.0, rawDir.1)
|
||||
|
||||
guard let runtimePtr else {
|
||||
throw ZcashError.rustTorClientInit(lastErrorMessage(fallback: "`TorClient` init failed with unknown error"))
|
||||
}
|
||||
|
||||
runtime = runtimePtr
|
||||
}
|
||||
|
||||
deinit {
|
||||
zcashlc_free_tor_runtime(runtime)
|
||||
}
|
||||
|
||||
public func getExchangeRateUSD() async throws -> NSDecimalNumber {
|
||||
let rate = zcashlc_get_exchange_rate_usd(runtime)
|
||||
|
||||
if rate.is_sign_negative {
|
||||
throw ZcashError.rustTorClientGet(lastErrorMessage(fallback: "`TorClient.get` failed with unknown error"))
|
||||
}
|
||||
|
||||
return NSDecimalNumber(mantissa: rate.mantissa, exponent: rate.exponent, isNegative: rate.is_sign_negative)
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import Foundation
|
|||
Represents what's expected from a logging entity
|
||||
*/
|
||||
public protocol Logger {
|
||||
func maxLogLevel() -> OSLogger.LogLevel?
|
||||
func debug(_ message: String, file: StaticString, function: StaticString, line: Int)
|
||||
func info(_ message: String, file: StaticString, function: StaticString, line: Int)
|
||||
func event(_ message: String, file: StaticString, function: StaticString, line: Int)
|
||||
|
@ -44,6 +45,9 @@ extension Logger {
|
|||
A concrete logger implementation that logs nothing at all
|
||||
*/
|
||||
struct NullLogger: Logger {
|
||||
func maxLogLevel() -> OSLogger.LogLevel? {
|
||||
nil
|
||||
}
|
||||
func debug(_ message: String, file: StaticString, function: StaticString, line: Int) {}
|
||||
func info(_ message: String, file: StaticString, function: StaticString, line: Int) {}
|
||||
func event(_ message: String, file: StaticString, function: StaticString, line: Int) {}
|
||||
|
|
|
@ -39,6 +39,10 @@ public class OSLogger: Logger {
|
|||
}
|
||||
}
|
||||
|
||||
public func maxLogLevel() -> LogLevel? {
|
||||
self.level
|
||||
}
|
||||
|
||||
public func debug(
|
||||
_ message: String,
|
||||
file: StaticString = #file,
|
||||
|
|
|
@ -60,6 +60,7 @@ class TransactionEnhancementTests: ZcashTestCase {
|
|||
alias: .default,
|
||||
fsBlockCacheRoot: testTempDirectory,
|
||||
dataDb: pathProvider.dataDbURL,
|
||||
torDir: pathProvider.torDirURL,
|
||||
spendParamsURL: pathProvider.spendParamsURL,
|
||||
outputParamsURL: pathProvider.outputParamsURL,
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL.tests,
|
||||
|
@ -117,6 +118,7 @@ class TransactionEnhancementTests: ZcashTestCase {
|
|||
urls: Initializer.URLs(
|
||||
fsBlockDbRoot: testTempDirectory,
|
||||
dataDbURL: pathProvider.dataDbURL,
|
||||
torDirURL: pathProvider.torDirURL,
|
||||
generalStorageURL: testGeneralStorageDirectory,
|
||||
spendParamsURL: pathProvider.spendParamsURL,
|
||||
outputParamsURL: pathProvider.outputParamsURL
|
||||
|
|
|
@ -31,6 +31,7 @@ class BlockStreamingTest: ZcashTestCase {
|
|||
urls: Initializer.URLs(
|
||||
fsBlockDbRoot: testTempDirectory,
|
||||
dataDbURL: try! __dataDbURL(),
|
||||
torDirURL: try! __torDirURL(),
|
||||
generalStorageURL: testGeneralStorageDirectory,
|
||||
spendParamsURL: try! __spendParamsURL(),
|
||||
outputParamsURL: try! __outputParamsURL()
|
||||
|
|
|
@ -35,6 +35,7 @@ class CompactBlockProcessorTests: ZcashTestCase {
|
|||
alias: .default,
|
||||
fsBlockCacheRoot: testTempDirectory,
|
||||
dataDb: pathProvider.dataDbURL,
|
||||
torDir: pathProvider.torDirURL,
|
||||
spendParamsURL: pathProvider.spendParamsURL,
|
||||
outputParamsURL: pathProvider.outputParamsURL,
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL.tests,
|
||||
|
@ -71,6 +72,7 @@ class CompactBlockProcessorTests: ZcashTestCase {
|
|||
urls: Initializer.URLs(
|
||||
fsBlockDbRoot: testTempDirectory,
|
||||
dataDbURL: processorConfig.dataDb,
|
||||
torDirURL: processorConfig.torDir,
|
||||
generalStorageURL: testGeneralStorageDirectory,
|
||||
spendParamsURL: processorConfig.spendParamsURL,
|
||||
outputParamsURL: processorConfig.outputParamsURL
|
||||
|
|
|
@ -36,6 +36,7 @@ class CompactBlockReorgTests: ZcashTestCase {
|
|||
alias: .default,
|
||||
fsBlockCacheRoot: testTempDirectory,
|
||||
dataDb: pathProvider.dataDbURL,
|
||||
torDir: pathProvider.torDirURL,
|
||||
spendParamsURL: pathProvider.spendParamsURL,
|
||||
outputParamsURL: pathProvider.outputParamsURL,
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL.tests,
|
||||
|
@ -94,6 +95,7 @@ class CompactBlockReorgTests: ZcashTestCase {
|
|||
urls: Initializer.URLs(
|
||||
fsBlockDbRoot: testTempDirectory,
|
||||
dataDbURL: processorConfig.dataDb,
|
||||
torDirURL: processorConfig.torDir,
|
||||
generalStorageURL: testGeneralStorageDirectory,
|
||||
spendParamsURL: processorConfig.spendParamsURL,
|
||||
outputParamsURL: processorConfig.outputParamsURL
|
||||
|
|
|
@ -23,6 +23,7 @@ class DownloadTests: ZcashTestCase {
|
|||
urls: Initializer.URLs(
|
||||
fsBlockDbRoot: testTempDirectory,
|
||||
dataDbURL: try! __dataDbURL(),
|
||||
torDirURL: try! __torDirURL(),
|
||||
generalStorageURL: testGeneralStorageDirectory,
|
||||
spendParamsURL: try! __spendParamsURL(),
|
||||
outputParamsURL: try! __outputParamsURL()
|
||||
|
|
|
@ -235,6 +235,7 @@ final class MigrateLegacyCacheDBActionTests: ZcashTestCase {
|
|||
cacheDbURL: underlyingCacheDbURL ?? defaultConfig.cacheDbURL,
|
||||
fsBlockCacheRoot: underlyingFsBlockCacheRoot ?? defaultConfig.fsBlockCacheRoot,
|
||||
dataDb: defaultConfig.dataDb,
|
||||
torDir: defaultConfig.torDir,
|
||||
spendParamsURL: defaultConfig.spendParamsURL,
|
||||
outputParamsURL: defaultConfig.outputParamsURL,
|
||||
saplingParamsSourceURL: defaultConfig.saplingParamsSourceURL,
|
||||
|
|
|
@ -20,6 +20,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
private func makeInitializer(
|
||||
fsBlockDbRoot: URL,
|
||||
dataDbURL: URL,
|
||||
torDirURL: URL,
|
||||
generalStorageURL: URL,
|
||||
spendParamsURL: URL,
|
||||
outputParamsURL: URL,
|
||||
|
@ -30,6 +31,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
fsBlockDbRoot: fsBlockDbRoot,
|
||||
generalStorageURL: generalStorageURL,
|
||||
dataDbURL: dataDbURL,
|
||||
torDirURL: torDirURL,
|
||||
endpoint: LightWalletEndpointBuilder.default,
|
||||
network: ZcashNetworkBuilder.network(for: .testnet),
|
||||
spendParamsURL: spendParamsURL,
|
||||
|
@ -54,6 +56,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
private func genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: URL,
|
||||
dataDbURL: URL,
|
||||
torDirURL: URL,
|
||||
generalStorageURL: URL,
|
||||
spendParamsURL: URL,
|
||||
outputParamsURL: URL,
|
||||
|
@ -63,6 +66,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
let initializer = makeInitializer(
|
||||
fsBlockDbRoot: fsBlockDbRoot,
|
||||
dataDbURL: dataDbURL,
|
||||
torDirURL: torDirURL,
|
||||
generalStorageURL: generalStorageURL,
|
||||
spendParamsURL: spendParamsURL,
|
||||
outputParamsURL: outputParamsURL,
|
||||
|
@ -85,6 +89,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
let initializer = makeInitializer(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
@ -102,6 +107,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: invalidPathURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
@ -113,6 +119,19 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: invalidPathURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
alias: .default
|
||||
)
|
||||
}
|
||||
|
||||
func test__defaultAlias__invalidTorDirURL__errorIsGenerated() {
|
||||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: invalidPathURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
@ -124,6 +143,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: invalidPathURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
@ -135,6 +155,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: invalidPathURL,
|
||||
|
@ -146,6 +167,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: invalidPathURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
@ -158,6 +180,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
let initializer = makeInitializer(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
@ -175,6 +198,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: invalidPathURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
@ -186,6 +210,19 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: invalidPathURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
alias: .custom("alias")
|
||||
)
|
||||
}
|
||||
|
||||
func test__customAlias__invalidTorDirURL__errorIsGenerated() {
|
||||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: invalidPathURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
@ -197,6 +234,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: invalidPathURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
@ -208,6 +246,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: invalidPathURL,
|
||||
|
@ -219,6 +258,7 @@ class InitializerOfflineTests: XCTestCase {
|
|||
genericTestForURLsParsingFailures(
|
||||
fsBlockDbRoot: validDirectoryURL,
|
||||
dataDbURL: validFileURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
generalStorageURL: invalidPathURL,
|
||||
spendParamsURL: validFileURL,
|
||||
outputParamsURL: validFileURL,
|
||||
|
|
|
@ -314,6 +314,7 @@ class SynchronizerOfflineTests: ZcashTestCase {
|
|||
fsBlockDbRoot: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
dataDbURL: invalidPathURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
endpoint: LightWalletEndpointBuilder.default,
|
||||
network: ZcashNetworkBuilder.network(for: .testnet),
|
||||
spendParamsURL: validFileURL,
|
||||
|
@ -349,6 +350,7 @@ class SynchronizerOfflineTests: ZcashTestCase {
|
|||
fsBlockDbRoot: validDirectoryURL,
|
||||
generalStorageURL: validDirectoryURL,
|
||||
dataDbURL: invalidPathURL,
|
||||
torDirURL: validDirectoryURL,
|
||||
endpoint: LightWalletEndpointBuilder.default,
|
||||
network: ZcashNetworkBuilder.network(for: .testnet),
|
||||
spendParamsURL: validFileURL,
|
||||
|
|
|
@ -45,6 +45,7 @@ class WalletTests: ZcashTestCase {
|
|||
fsBlockDbRoot: testTempDirectory,
|
||||
generalStorageURL: testGeneralStorageDirectory,
|
||||
dataDbURL: try __dataDbURL(),
|
||||
torDirURL: try __torDirURL(),
|
||||
endpoint: LightWalletEndpointBuilder.default,
|
||||
network: network,
|
||||
spendParamsURL: try __spendParamsURL(),
|
||||
|
|
|
@ -64,6 +64,7 @@ class SynchronizerTests: ZcashTestCase {
|
|||
fsBlockDbRoot: databases.fsCacheDbRoot,
|
||||
generalStorageURL: testGeneralStorageDirectory,
|
||||
dataDbURL: databases.dataDB,
|
||||
torDirURL: databases.torDir,
|
||||
endpoint: endpoint,
|
||||
network: network,
|
||||
spendParamsURL: try __spendParamsURL(),
|
||||
|
|
|
@ -206,7 +206,11 @@ enum DarksideWalletDConstants: NetworkConstants {
|
|||
static var defaultDataDbName: String {
|
||||
ZcashSDKMainnetConstants.defaultDataDbName
|
||||
}
|
||||
|
||||
|
||||
static var defaultTorDirName: String {
|
||||
ZcashSDKMainnetConstants.defaultTorDirName
|
||||
}
|
||||
|
||||
static var defaultCacheDbName: String {
|
||||
ZcashSDKMainnetConstants.defaultCacheDbName
|
||||
}
|
||||
|
|
|
@ -1072,6 +1072,24 @@ class LoggerMock: Logger {
|
|||
) {
|
||||
}
|
||||
|
||||
// MARK: - maxLogLevel
|
||||
|
||||
var maxLogLevelCallsCount = 0
|
||||
var maxLogLevelCalled: Bool {
|
||||
return maxLogLevelCallsCount > 0
|
||||
}
|
||||
var maxLogLevelReturnValue: OSLogger.LogLevel?
|
||||
var maxLogLevelClosure: (() -> OSLogger.LogLevel?)?
|
||||
|
||||
func maxLogLevel() -> OSLogger.LogLevel? {
|
||||
maxLogLevelCallsCount += 1
|
||||
if let closure = maxLogLevelClosure {
|
||||
return closure()
|
||||
} else {
|
||||
return maxLogLevelReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - debug
|
||||
|
||||
var debugFileFunctionLineCallsCount = 0
|
||||
|
@ -1780,6 +1798,28 @@ class SynchronizerMock: Synchronizer {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - getExchangeRateUSD
|
||||
|
||||
var getExchangeRateUSDThrowableError: Error?
|
||||
var getExchangeRateUSDCallsCount = 0
|
||||
var getExchangeRateUSDCalled: Bool {
|
||||
return getExchangeRateUSDCallsCount > 0
|
||||
}
|
||||
var getExchangeRateUSDReturnValue: Float64!
|
||||
var getExchangeRateUSDClosure: (() async throws -> Float64)?
|
||||
|
||||
func getExchangeRateUSD() async throws -> Float64 {
|
||||
if let error = getExchangeRateUSDThrowableError {
|
||||
throw error
|
||||
}
|
||||
getExchangeRateUSDCallsCount += 1
|
||||
if let closure = getExchangeRateUSDClosure {
|
||||
return try await closure()
|
||||
} else {
|
||||
return getExchangeRateUSDReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - rewind
|
||||
|
||||
var rewindCallsCount = 0
|
||||
|
|
|
@ -132,6 +132,7 @@ extension CompactBlockProcessor.Configuration {
|
|||
alias: alias,
|
||||
fsBlockCacheRoot: pathProvider.fsCacheURL,
|
||||
dataDb: pathProvider.dataDbURL,
|
||||
torDir: pathProvider.torDirURL,
|
||||
spendParamsURL: pathProvider.spendParamsURL,
|
||||
outputParamsURL: pathProvider.outputParamsURL,
|
||||
saplingParamsSourceURL: SaplingParamsSourceURL.tests,
|
||||
|
|
|
@ -72,6 +72,7 @@ class TestCoordinator {
|
|||
fsBlockDbRoot: databases.fsCacheDbRoot,
|
||||
generalStorageURL: databases.generalStorageURL,
|
||||
dataDbURL: databases.dataDB,
|
||||
torDirURL: databases.torDir,
|
||||
endpoint: endpoint,
|
||||
network: network,
|
||||
spendParamsURL: try __spendParamsURL(),
|
||||
|
@ -216,6 +217,7 @@ extension TestCoordinator {
|
|||
alias: config.alias,
|
||||
fsBlockCacheRoot: config.fsBlockCacheRoot,
|
||||
dataDb: config.dataDb,
|
||||
torDir: config.torDir,
|
||||
spendParamsURL: config.spendParamsURL,
|
||||
outputParamsURL: config.outputParamsURL,
|
||||
saplingParamsSourceURL: config.saplingParamsSourceURL,
|
||||
|
@ -246,6 +248,7 @@ extension TestCoordinator {
|
|||
struct TemporaryTestDatabases {
|
||||
var fsCacheDbRoot: URL
|
||||
let generalStorageURL: URL
|
||||
var torDir: URL
|
||||
var dataDB: URL
|
||||
}
|
||||
|
||||
|
@ -257,6 +260,7 @@ enum TemporaryDbBuilder {
|
|||
return TemporaryTestDatabases(
|
||||
fsCacheDbRoot: tempUrl.appendingPathComponent("fs_cache_\(timestamp)"),
|
||||
generalStorageURL: tempUrl.appendingPathComponent("general_storage_\(timestamp)"),
|
||||
torDir: tempUrl.appendingPathComponent("tor_\(timestamp)"),
|
||||
dataDB: tempUrl.appendingPathComponent("data_db_\(timestamp).db")
|
||||
)
|
||||
}
|
||||
|
|
|
@ -96,6 +96,10 @@ func __dataDbURL() throws -> URL {
|
|||
try __documentsDirectory().appendingPathComponent("data.db", isDirectory: false)
|
||||
}
|
||||
|
||||
func __torDirURL() throws -> URL {
|
||||
try __documentsDirectory().appendingPathComponent("tor", isDirectory: true)
|
||||
}
|
||||
|
||||
func __spendParamsURL() throws -> URL {
|
||||
try __documentsDirectory().appendingPathComponent("sapling-spend.params")
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ class TestsData {
|
|||
fsBlockDbRoot: URL(fileURLWithPath: "/"),
|
||||
generalStorageURL: URL(fileURLWithPath: "/"),
|
||||
dataDbURL: URL(fileURLWithPath: "/"),
|
||||
torDirURL: URL(fileURLWithPath: "/"),
|
||||
endpoint: LightWalletEndpointBuilder.default,
|
||||
network: ZcashNetworkBuilder.network(for: networkType),
|
||||
spendParamsURL: URL(fileURLWithPath: "/"),
|
||||
|
|
Loading…
Reference in New Issue