create + prepare API
This commit is contained in:
parent
5aa8afd2aa
commit
39837009a4
|
@ -66,6 +66,7 @@ public class Initializer {
|
||||||
private(set) var transactionRepository: TransactionRepository
|
private(set) var transactionRepository: TransactionRepository
|
||||||
private(set) var accountRepository: AccountRepository
|
private(set) var accountRepository: AccountRepository
|
||||||
private(set) var downloader: CompactBlockDownloader
|
private(set) var downloader: CompactBlockDownloader
|
||||||
|
private(set) public var viewingKeys: [UnifiedViewingKey]
|
||||||
private(set) public var walletBirthday: WalletBirthday
|
private(set) public var walletBirthday: WalletBirthday
|
||||||
/**
|
/**
|
||||||
Constructs the Initializer
|
Constructs the Initializer
|
||||||
|
@ -83,6 +84,7 @@ public class Initializer {
|
||||||
endpoint: LightWalletEndpoint,
|
endpoint: LightWalletEndpoint,
|
||||||
spendParamsURL: URL,
|
spendParamsURL: URL,
|
||||||
outputParamsURL: URL,
|
outputParamsURL: URL,
|
||||||
|
viewingKeys: [UnifiedViewingKey],
|
||||||
walletBirthday: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT,
|
walletBirthday: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT,
|
||||||
alias: String = "",
|
alias: String = "",
|
||||||
loggerProxy: Logger? = nil) {
|
loggerProxy: Logger? = nil) {
|
||||||
|
@ -104,6 +106,7 @@ public class Initializer {
|
||||||
downloader: CompactBlockDownloader(service: lwdService, storage: storage),
|
downloader: CompactBlockDownloader(service: lwdService, storage: storage),
|
||||||
spendParamsURL: spendParamsURL,
|
spendParamsURL: spendParamsURL,
|
||||||
outputParamsURL: outputParamsURL,
|
outputParamsURL: outputParamsURL,
|
||||||
|
viewingKeys: viewingKeys,
|
||||||
walletBirthday: walletBirthday,
|
walletBirthday: walletBirthday,
|
||||||
alias: alias,
|
alias: alias,
|
||||||
loggerProxy: loggerProxy
|
loggerProxy: loggerProxy
|
||||||
|
@ -125,6 +128,7 @@ public class Initializer {
|
||||||
downloader: CompactBlockDownloader,
|
downloader: CompactBlockDownloader,
|
||||||
spendParamsURL: URL,
|
spendParamsURL: URL,
|
||||||
outputParamsURL: URL,
|
outputParamsURL: URL,
|
||||||
|
viewingKeys: [UnifiedViewingKey],
|
||||||
walletBirthday: BlockHeight,
|
walletBirthday: BlockHeight,
|
||||||
alias: String = "",
|
alias: String = "",
|
||||||
loggerProxy: Logger? = nil
|
loggerProxy: Logger? = nil
|
||||||
|
@ -144,69 +148,13 @@ public class Initializer {
|
||||||
self.transactionRepository = repository
|
self.transactionRepository = repository
|
||||||
self.accountRepository = accountRepository
|
self.accountRepository = accountRepository
|
||||||
self.downloader = downloader
|
self.downloader = downloader
|
||||||
|
self.viewingKeys = viewingKeys
|
||||||
self.walletBirthday = WalletBirthday.birthday(with: walletBirthday)
|
self.walletBirthday = WalletBirthday.birthday(with: walletBirthday)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Initialize the wallet with the given seed and return the related private keys for each
|
|
||||||
account specified or null if the wallet was previously initialized and block data exists on
|
|
||||||
disk. When this method returns null, that signals that the wallet will need to retrieve the
|
|
||||||
private keys from its own secure storage. In other words, the private keys are only given out
|
|
||||||
once for each set of database files. Subsequent calls to [initialize] will only load the Rust
|
|
||||||
library and return null.
|
|
||||||
|
|
||||||
'compactBlockCache.db' and 'transactionData.db' files are created by this function (if they
|
|
||||||
do not already exist). These files can be given a prefix for scenarios where multiple wallets
|
|
||||||
operate in one app--for instance, when sweeping funds from another wallet seed.
|
|
||||||
- Parameters:
|
|
||||||
- seedProvider: the seed to use for initializing this wallet.
|
|
||||||
- walletBirthdayHeight: the height corresponding to when the wallet seed was created. If null, this signals that the wallet is being born.
|
|
||||||
- numberOfAccounts: the number of accounts to create from this seed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public func initialize(seedBytes: [UInt8], numberOfAccounts: Int = 1) throws -> [String]? {
|
|
||||||
|
|
||||||
do {
|
|
||||||
try rustBackend.initDataDb(dbData: dataDbURL)
|
|
||||||
} catch RustWeldingError.dataDbNotEmpty {
|
|
||||||
// this is fine
|
|
||||||
} catch {
|
|
||||||
throw InitializerError.dataDbInitFailed
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
try rustBackend.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthday.height), hash: walletBirthday.hash, time: walletBirthday.time, saplingTree: walletBirthday.tree)
|
|
||||||
} catch RustWeldingError.dataDbNotEmpty {
|
|
||||||
// this is fine
|
|
||||||
} catch {
|
|
||||||
throw InitializerError.dataDbInitFailed
|
|
||||||
}
|
|
||||||
|
|
||||||
let lastDownloaded = (try? downloader.storage.latestHeight()) ?? self.walletBirthday.height
|
|
||||||
// resume from last downloaded block
|
|
||||||
lowerBoundHeight = max(walletBirthday.height, lastDownloaded)
|
|
||||||
|
|
||||||
var accounts: [String]? = nil
|
|
||||||
do {
|
|
||||||
guard let a = rustBackend.initAccountsTable(dbData: dataDbURL, seed: seedBytes, accounts: Int32(numberOfAccounts)) else {
|
|
||||||
throw rustBackend.lastError() ?? InitializerError.accountInitFailed
|
|
||||||
}
|
|
||||||
accounts = a
|
|
||||||
} catch RustWeldingError.dataDbNotEmpty {
|
|
||||||
// this is fine
|
|
||||||
} catch {
|
|
||||||
throw InitializerError.dataDbInitFailed
|
|
||||||
}
|
|
||||||
let migrationManager = MigrationManager(cacheDbConnection: SimpleConnectionProvider(path: cacheDbURL.path),
|
|
||||||
dataDbConnection: SimpleConnectionProvider(path: dataDbURL.path), pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path))
|
|
||||||
|
|
||||||
try migrationManager.performMigration(seedBytes: seedBytes)
|
|
||||||
return accounts
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
__TEMPORARILY UNAVAILABLE__
|
|
||||||
Initialize the wallet with the given seed and return the related private keys for each
|
Initialize the wallet with the given seed and return the related private keys for each
|
||||||
account specified or null if the wallet was previously initialized and block data exists on
|
account specified or null if the wallet was previously initialized and block data exists on
|
||||||
disk. When this method returns null, that signals that the wallet will need to retrieve the
|
disk. When this method returns null, that signals that the wallet will need to retrieve the
|
||||||
|
@ -221,7 +169,7 @@ public class Initializer {
|
||||||
- viewingKeys: Extended Full Viewing Keys to initialize the DBs with
|
- viewingKeys: Extended Full Viewing Keys to initialize the DBs with
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public func initialize(unifiedViewingKeys: [UnifiedViewingKey], walletBirthday: BlockHeight) throws {
|
public func initialize() throws {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try rustBackend.initDataDb(dbData: dataDbURL)
|
try rustBackend.initDataDb(dbData: dataDbURL)
|
||||||
|
@ -230,23 +178,21 @@ public class Initializer {
|
||||||
} catch {
|
} catch {
|
||||||
throw InitializerError.dataDbInitFailed
|
throw InitializerError.dataDbInitFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
let birthday = WalletBirthday.birthday(with: walletBirthday)
|
|
||||||
self.walletBirthday = birthday
|
|
||||||
do {
|
do {
|
||||||
try rustBackend.initBlocksTable(dbData: dataDbURL, height: Int32(birthday.height), hash: birthday.hash, time: birthday.time, saplingTree: birthday.tree)
|
try rustBackend.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthday.height), hash: walletBirthday.hash, time: walletBirthday.time, saplingTree: walletBirthday.tree)
|
||||||
} catch RustWeldingError.dataDbNotEmpty {
|
} catch RustWeldingError.dataDbNotEmpty {
|
||||||
// this is fine
|
// this is fine
|
||||||
} catch {
|
} catch {
|
||||||
throw InitializerError.dataDbInitFailed
|
throw InitializerError.dataDbInitFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastDownloaded = (try? downloader.storage.latestHeight()) ?? birthday.height
|
let lastDownloaded = (try? downloader.storage.latestHeight()) ?? walletBirthday.height
|
||||||
// resume from last downloaded block
|
// resume from last downloaded block
|
||||||
lowerBoundHeight = max(birthday.height, lastDownloaded)
|
lowerBoundHeight = max(walletBirthday.height, lastDownloaded)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
guard try rustBackend.initAccountsTable(dbData: dataDbURL, uvks: unifiedViewingKeys) else {
|
guard try rustBackend.initAccountsTable(dbData: dataDbURL, uvks: viewingKeys) else {
|
||||||
throw rustBackend.lastError() ?? InitializerError.accountInitFailed
|
throw rustBackend.lastError() ?? InitializerError.accountInitFailed
|
||||||
}
|
}
|
||||||
} catch RustWeldingError.dataDbNotEmpty {
|
} catch RustWeldingError.dataDbNotEmpty {
|
||||||
|
@ -258,7 +204,7 @@ public class Initializer {
|
||||||
let migrationManager = MigrationManager(cacheDbConnection: SimpleConnectionProvider(path: cacheDbURL.path),
|
let migrationManager = MigrationManager(cacheDbConnection: SimpleConnectionProvider(path: cacheDbURL.path),
|
||||||
dataDbConnection: SimpleConnectionProvider(path: dataDbURL.path), pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path))
|
dataDbConnection: SimpleConnectionProvider(path: dataDbURL.path), pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path))
|
||||||
|
|
||||||
try migrationManager.performMigration(uvks: unifiedViewingKeys)
|
try migrationManager.performMigration(uvks: viewingKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,6 +13,7 @@ Represents errors thrown by a Synchronizer
|
||||||
*/
|
*/
|
||||||
public enum SynchronizerError: Error {
|
public enum SynchronizerError: Error {
|
||||||
case initFailed(message: String)
|
case initFailed(message: String)
|
||||||
|
case notPrepared
|
||||||
case syncFailed
|
case syncFailed
|
||||||
case connectionFailed(message: Error)
|
case connectionFailed(message: Error)
|
||||||
case generalError(message: String)
|
case generalError(message: String)
|
||||||
|
@ -68,14 +69,9 @@ public protocol Synchronizer {
|
||||||
var progress: Float { get }
|
var progress: Float { get }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize the internal state with the given Extended Viewing Keys and a wallet birthday
|
prepares this initializer to operate. Initializes the internal state with the given Extended Viewing Keys and a wallet birthday found in the initializer object
|
||||||
- Parameter viewingKeys: an array containing the viewing keys to initialize the internal state
|
|
||||||
- Parameter walletBirthday: the eldest when the different keys differ in birthday
|
|
||||||
- Throws: Initializer Errors and RustWeldingError if fails
|
|
||||||
- Note: The subsequent initializations don't have any effect or failure
|
|
||||||
*/
|
*/
|
||||||
func initialize(unifiedViewingKeys: [UnifiedViewingKey], walletBirthday: BlockHeight) throws
|
func prepare() throws
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Starts this synchronizer within the given scope.
|
Starts this synchronizer within the given scope.
|
||||||
|
|
||||||
|
@ -222,6 +218,10 @@ public protocol Synchronizer {
|
||||||
The Status of the synchronizer
|
The Status of the synchronizer
|
||||||
*/
|
*/
|
||||||
public enum Status {
|
public enum Status {
|
||||||
|
/**
|
||||||
|
This synchronizer is not ready to start
|
||||||
|
*/
|
||||||
|
case unprepared
|
||||||
/**
|
/**
|
||||||
Indicates that [stop] has been called on this Synchronizer and it will no longer be used.
|
Indicates that [stop] has been called on this Synchronizer and it will no longer be used.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class SDKSynchronizer: Synchronizer {
|
||||||
*/
|
*/
|
||||||
public convenience init(initializer: Initializer) throws {
|
public convenience init(initializer: Initializer) throws {
|
||||||
|
|
||||||
try self.init(status: .disconnected,
|
try self.init(status: .unprepared,
|
||||||
initializer: initializer,
|
initializer: initializer,
|
||||||
transactionManager: try OutboundTransactionManagerBuilder.build(initializer: initializer),
|
transactionManager: try OutboundTransactionManagerBuilder.build(initializer: initializer),
|
||||||
transactionRepository: initializer.transactionRepository,
|
transactionRepository: initializer.transactionRepository,
|
||||||
|
@ -128,26 +128,36 @@ public class SDKSynchronizer: Synchronizer {
|
||||||
self.blockProcessor.stop()
|
self.blockProcessor.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func initialize(unifiedViewingKeys: [UnifiedViewingKey], walletBirthday: BlockHeight) throws {
|
public func initialize() throws {
|
||||||
try self.initializer.initialize(unifiedViewingKeys: unifiedViewingKeys, walletBirthday: walletBirthday)
|
try self.initializer.initialize()
|
||||||
try self.blockProcessor.setStartHeight(WalletBirthday.birthday(with: walletBirthday).height)
|
try self.blockProcessor.setStartHeight(initializer.walletBirthday.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func prepare() throws {
|
||||||
|
try self.initializer.initialize()
|
||||||
|
try self.blockProcessor.setStartHeight(initializer.walletBirthday.height)
|
||||||
|
self.status = .disconnected
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
Starts the synchronizer
|
Starts the synchronizer
|
||||||
- Throws: CompactBlockProcessorError when failures occur
|
- Throws: CompactBlockProcessorError when failures occur
|
||||||
*/
|
*/
|
||||||
public func start(retry: Bool = false) throws {
|
public func start(retry: Bool = false) throws {
|
||||||
|
|
||||||
guard status == .stopped || status == .disconnected || status == .synced else {
|
|
||||||
assert(true,"warning: synchronizer started when already started") // TODO: remove this assertion sometime in the near future
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
switch status {
|
||||||
try blockProcessor.start(retry: retry)
|
case .unprepared:
|
||||||
} catch {
|
throw SynchronizerError.notPrepared
|
||||||
throw mapError(error)
|
case .syncing:
|
||||||
|
assert(true,"warning: synchronizer started when already started") // TODO: remove this assertion sometime in the near future
|
||||||
|
LoggerProxy.debug("warning: synchronizer started when already started")
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
do {
|
||||||
|
try blockProcessor.start(retry: retry)
|
||||||
|
} catch {
|
||||||
|
throw mapError(error)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +166,10 @@ public class SDKSynchronizer: Synchronizer {
|
||||||
*/
|
*/
|
||||||
public func stop() {
|
public func stop() {
|
||||||
|
|
||||||
guard status != .stopped, status != .disconnected else { return }
|
guard status != .stopped, status != .disconnected else {
|
||||||
|
LoggerProxy.info("attempted to stop when status was: \(status)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
blockProcessor.stop(cancelTasks: true)
|
blockProcessor.stop(cancelTasks: true)
|
||||||
}
|
}
|
||||||
|
@ -562,7 +575,8 @@ public class SDKSynchronizer: Synchronizer {
|
||||||
NotificationCenter.default.post(name: Notification.Name.synchronizerSynced, object: self)
|
NotificationCenter.default.post(name: Notification.Name.synchronizerSynced, object: self)
|
||||||
case .syncing:
|
case .syncing:
|
||||||
NotificationCenter.default.post(name: Notification.Name.synchronizerSyncing, object: self)
|
NotificationCenter.default.post(name: Notification.Name.synchronizerSyncing, object: self)
|
||||||
|
case .unprepared:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// MARK: book keeping
|
// MARK: book keeping
|
||||||
|
|
Loading…
Reference in New Issue