Zip32AccountIndex UInt32 refactor

- Zip32Account(Int32) has been refactored to Zip32AccountIndex(UIn32)
This commit is contained in:
Lukas Korba 2024-11-25 11:32:55 +01:00
parent b31e1c91d7
commit 97137510b2
34 changed files with 485 additions and 520 deletions

View File

@ -21,6 +21,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
private var wallet: Initializer? private var wallet: Initializer?
private var synchronizer: SDKSynchronizer? private var synchronizer: SDKSynchronizer?
let accountIndex = Zip32AccountIndex(0)
var sharedSynchronizer: SDKSynchronizer { var sharedSynchronizer: SDKSynchronizer {
if let sync = synchronizer { if let sync = synchronizer {
return sync return sync
@ -34,7 +36,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var sharedViewingKey: UnifiedFullViewingKey { var sharedViewingKey: UnifiedFullViewingKey {
let derivationTool = DerivationTool(networkType: kZcashNetwork.networkType) let derivationTool = DerivationTool(networkType: kZcashNetwork.networkType)
let spendingKey = try! derivationTool let spendingKey = try! derivationTool
.deriveUnifiedSpendingKey(seed: DemoAppConfig.defaultSeed, accountIndex: 0) .deriveUnifiedSpendingKey(seed: DemoAppConfig.defaultSeed, accountIndex: accountIndex)
return try! derivationTool.deriveUnifiedFullViewingKey(from: spendingKey) return try! derivationTool.deriveUnifiedFullViewingKey(from: spendingKey)
} }

View File

@ -19,7 +19,7 @@ class GetAddressViewController: UIViewController {
let synchronizer = SDKSynchronizer.shared let synchronizer = SDKSynchronizer.shared
Task { @MainActor in Task { @MainActor in
guard let uAddress = try? await synchronizer.getUnifiedAddress(account: Zip32Account(0)) else { guard let uAddress = try? await synchronizer.getUnifiedAddress(accountIndex: Zip32AccountIndex(0)) else {
unifiedAddressLabel.text = "could not derive UA" unifiedAddressLabel.text = "could not derive UA"
tAddressLabel.text = "could not derive tAddress" tAddressLabel.text = "could not derive tAddress"
saplingAddress.text = "could not derive zAddress" saplingAddress.text = "could not derive zAddress"

View File

@ -19,13 +19,15 @@ class GetBalanceViewController: UIViewController {
var accountBalance: AccountBalance? var accountBalance: AccountBalance?
var rate: FiatCurrencyResult? var rate: FiatCurrencyResult?
let accountIndex = Zip32AccountIndex(0)
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
let synchronizer = AppDelegate.shared.sharedSynchronizer let synchronizer = AppDelegate.shared.sharedSynchronizer
self.title = "Account 0 Balance" self.title = "Account 0 Balance"
Task { @MainActor [weak self] in Task { @MainActor [weak self] in
self?.accountBalance = try? await synchronizer.getAccountBalance() self?.accountBalance = try? await synchronizer.getAccountBalance(accountIndex: accountIndex)
self?.updateLabels() self?.updateLabels()
} }

View File

@ -15,7 +15,9 @@ class GetUTXOsViewController: UIViewController {
@IBOutlet weak var totalBalanceLabel: UILabel! @IBOutlet weak var totalBalanceLabel: UILabel!
@IBOutlet weak var messageLabel: UILabel! @IBOutlet weak var messageLabel: UILabel!
@IBOutlet weak var shieldFundsButton: UIButton! @IBOutlet weak var shieldFundsButton: UIButton!
let accountIndex = Zip32AccountIndex(0)
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -26,13 +28,12 @@ class GetUTXOsViewController: UIViewController {
let synchronizer = SDKSynchronizer.shared let synchronizer = SDKSynchronizer.shared
Task { @MainActor in Task { @MainActor in
let account = Zip32Account(0) let tAddress = (try? await synchronizer.getTransparentAddress(accountIndex: accountIndex))?.stringEncoded ?? "no t-address found"
let tAddress = (try? await synchronizer.getTransparentAddress(account: account))?.stringEncoded ?? "no t-address found"
self.transparentAddressLabel.text = tAddress self.transparentAddressLabel.text = tAddress
// swiftlint:disable:next force_try // swiftlint:disable:next force_try
let balance = try! await AppDelegate.shared.sharedSynchronizer.getAccountBalance(account: account)?.unshielded ?? .zero let balance = try! await AppDelegate.shared.sharedSynchronizer.getAccountBalance(accountIndex: accountIndex)?.unshielded ?? .zero
self.totalBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.amount)) self.totalBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.amount))
self.verifiedBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.amount)) self.verifiedBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.amount))
@ -43,7 +44,7 @@ class GetUTXOsViewController: UIViewController {
do { do {
let derivationTool = DerivationTool(networkType: kZcashNetwork.networkType) let derivationTool = DerivationTool(networkType: kZcashNetwork.networkType)
let usk = try derivationTool.deriveUnifiedSpendingKey(seed: DemoAppConfig.defaultSeed, accountIndex: 0) let usk = try derivationTool.deriveUnifiedSpendingKey(seed: DemoAppConfig.defaultSeed, accountIndex: accountIndex)
KRProgressHUD.showMessage("🛡 Shielding 🛡") KRProgressHUD.showMessage("🛡 Shielding 🛡")

View File

@ -25,6 +25,7 @@ class SendViewController: UIViewController {
@IBOutlet weak var charactersLeftLabel: UILabel! @IBOutlet weak var charactersLeftLabel: UILabel!
let characterLimit: Int = 512 let characterLimit: Int = 512
let accountIndex = Zip32AccountIndex(0)
var wallet = Initializer.shared var wallet = Initializer.shared
@ -103,13 +104,11 @@ class SendViewController: UIViewController {
} }
func updateBalance() async { func updateBalance() async {
let account = Zip32Account(0)
balanceLabel.text = format( balanceLabel.text = format(
balance: (try? await synchronizer.getAccountBalance(account: account))?.saplingBalance.total() ?? .zero balance: (try? await synchronizer.getAccountBalance(accountIndex: accountIndex))?.saplingBalance.total() ?? .zero
) )
verifiedBalanceLabel.text = format( verifiedBalanceLabel.text = format(
balance: (try? await synchronizer.getAccountBalance(account: account))?.saplingBalance.spendableValue ?? .zero balance: (try? await synchronizer.getAccountBalance(accountIndex: accountIndex))?.saplingBalance.spendableValue ?? .zero
) )
} }
@ -124,7 +123,7 @@ class SendViewController: UIViewController {
func maxFundsOn() { func maxFundsOn() {
Task { @MainActor in Task { @MainActor in
let fee = Zatoshi(10000) let fee = Zatoshi(10000)
let max: Zatoshi = ((try? await synchronizer.getAccountBalance(account: Zip32Account(0)))?.saplingBalance.spendableValue ?? .zero) - fee let max: Zatoshi = ((try? await synchronizer.getAccountBalance(accountIndex: accountIndex))?.saplingBalance.spendableValue ?? .zero) - fee
amountTextField.text = format(balance: max) amountTextField.text = format(balance: max)
amountTextField.isEnabled = false amountTextField.isEnabled = false
} }
@ -146,12 +145,12 @@ class SendViewController: UIViewController {
} }
func isBalanceValid() async -> Bool { func isBalanceValid() async -> Bool {
let balance = (try? await synchronizer.getAccountBalance(account: Zip32Account(0)))?.saplingBalance.spendableValue ?? .zero let balance = (try? await synchronizer.getAccountBalance(accountIndex: accountIndex))?.saplingBalance.spendableValue ?? .zero
return balance > .zero return balance > .zero
} }
func isAmountValid() async -> Bool { func isAmountValid() async -> Bool {
let balance = (try? await synchronizer.getAccountBalance(account: Zip32Account(0)))?.saplingBalance.spendableValue ?? .zero let balance = (try? await synchronizer.getAccountBalance(accountIndex: accountIndex))?.saplingBalance.spendableValue ?? .zero
guard guard
let value = amountTextField.text, let value = amountTextField.text,
let amount = NumberFormatter.zcashNumberFormatter.number(from: value).flatMap({ Zatoshi($0.int64Value) }), let amount = NumberFormatter.zcashNumberFormatter.number(from: value).flatMap({ Zatoshi($0.int64Value) }),
@ -230,7 +229,7 @@ class SendViewController: UIViewController {
} }
let derivationTool = DerivationTool(networkType: kZcashNetwork.networkType) let derivationTool = DerivationTool(networkType: kZcashNetwork.networkType)
guard let spendingKey = try? derivationTool.deriveUnifiedSpendingKey(seed: DemoAppConfig.defaultSeed, accountIndex: 0) else { guard let spendingKey = try? derivationTool.deriveUnifiedSpendingKey(seed: DemoAppConfig.defaultSeed, accountIndex: accountIndex) else {
loggerProxy.error("NO SPENDING KEY") loggerProxy.error("NO SPENDING KEY")
return return
} }

View File

@ -6,12 +6,16 @@
// //
/// A [ZIP 32](https://zips.z.cash/zip-0032) account index. /// A [ZIP 32](https://zips.z.cash/zip-0032) account index.
public struct Zip32Account: Equatable, Codable, Hashable { ///
public let index: Int32 /// This index must be paired with a seed, or other context that determines a seed,
/// in order to identify a ZIP 32 *account*.
public struct Zip32AccountIndex: Equatable, Codable, Hashable {
public let index: UInt32
public init(_ index: Int32) { /// - Parameter index: the ZIP 32 account index, which must be less than ``1<<31``.
guard index >= 0 else { public init(_ index: UInt32) {
fatalError("Account index must be >= 0. Input value is \(index).") guard index < (1<<31) else {
fatalError("Account index must be less than 1<<31. Input value is \(index).")
} }
self.index = index self.index = index
@ -19,13 +23,14 @@ public struct Zip32Account: Equatable, Codable, Hashable {
} }
public struct AccountId: Equatable, Codable, Hashable { public struct AccountId: Equatable, Codable, Hashable {
public let index: Int public let id: Int
public init(_ index: Int) { /// - Parameter id: the local account id, which must be nonnegative.
guard index >= 0 else { public init(_ id: Int) {
fatalError("Account index must be >= 0. Input value is \(index).") guard id >= 0 else {
fatalError("Account id must be >= 0. Input value is \(id).")
} }
self.index = index self.id = id
} }
} }

View File

@ -22,8 +22,9 @@ extension SaplingParamsAction: Action {
func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext { func run(with context: ActionContext, didUpdate: @escaping (CompactBlockProcessor.Event) async -> Void) async throws -> ActionContext {
logger.debug("Fetching sapling parameters") logger.debug("Fetching sapling parameters")
// TODO: This is hardcoded Zip32Account for index 0, must be updated // TODO: [#1512] This is hardcoded Zip32AccountIndex for index 0, must be updated
try await saplingParametersHandler.handleIfNeeded(account: Zip32Account(0)) // https://github.com/Electric-Coin-Company/zcash-swift-wallet-sdk/issues/1512
try await saplingParametersHandler.handleIfNeeded(accountIndex: Zip32AccountIndex(0))
await context.update(state: .updateSubtreeRoots) await context.update(state: .updateSubtreeRoots)

View File

@ -837,16 +837,16 @@ extension CompactBlockProcessor {
} }
extension CompactBlockProcessor { extension CompactBlockProcessor {
func getUnifiedAddress(account: Zip32Account) async throws -> UnifiedAddress { func getUnifiedAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress {
try await rustBackend.getCurrentAddress(account: account) try await rustBackend.getCurrentAddress(accountIndex: accountIndex)
} }
func getSaplingAddress(account: Zip32Account) async throws -> SaplingAddress { func getSaplingAddress(accountIndex: Zip32AccountIndex) async throws -> SaplingAddress {
try await getUnifiedAddress(account: account).saplingReceiver() try await getUnifiedAddress(accountIndex: accountIndex).saplingReceiver()
} }
func getTransparentAddress(account: Zip32Account) async throws -> TransparentAddress { func getTransparentAddress(accountIndex: Zip32AccountIndex) async throws -> TransparentAddress {
try await getUnifiedAddress(account: account).transparentReceiver() try await getUnifiedAddress(accountIndex: accountIndex).transparentReceiver()
} }
} }

View File

@ -39,8 +39,8 @@ extension UTXOFetcherImpl: UTXOFetcher {
let accounts = try await rustBackend.listAccounts() let accounts = try await rustBackend.listAccounts()
var tAddresses: [TransparentAddress] = [] var tAddresses: [TransparentAddress] = []
for account in accounts { for accountIndex in accounts {
tAddresses += try await rustBackend.listTransparentReceivers(account: account) tAddresses += try await rustBackend.listTransparentReceivers(accountIndex: accountIndex)
} }
var utxos: [UnspentTransactionOutputEntity] = [] var utxos: [UnspentTransactionOutputEntity] = []

View File

@ -14,7 +14,7 @@ struct SaplingParametersHandlerConfig {
} }
protocol SaplingParametersHandler { protocol SaplingParametersHandler {
func handleIfNeeded(account: Zip32Account) async throws func handleIfNeeded(accountIndex: Zip32AccountIndex) async throws
} }
struct SaplingParametersHandlerImpl { struct SaplingParametersHandlerImpl {
@ -24,14 +24,14 @@ struct SaplingParametersHandlerImpl {
} }
extension SaplingParametersHandlerImpl: SaplingParametersHandler { extension SaplingParametersHandlerImpl: SaplingParametersHandler {
func handleIfNeeded(account: Zip32Account) async throws { func handleIfNeeded(accountIndex: Zip32AccountIndex) async throws {
try Task.checkCancellation() try Task.checkCancellation()
do { do {
let totalSaplingBalance = let totalSaplingBalance =
try await rustBackend.getWalletSummary()?.accountBalances[0]?.saplingBalance.total().amount try await rustBackend.getWalletSummary()?.accountBalances[0]?.saplingBalance.total().amount
?? 0 ?? 0
let totalTransparentBalance = try await rustBackend.getTransparentBalance(account: account) let totalTransparentBalance = try await rustBackend.getTransparentBalance(accountIndex: accountIndex)
// Download Sapling parameters only if sapling funds are detected. // Download Sapling parameters only if sapling funds are detected.
guard totalSaplingBalance > 0 || totalTransparentBalance > 0 else { return } guard totalSaplingBalance > 0 || totalTransparentBalance > 0 else { return }

View File

@ -32,13 +32,13 @@ public protocol ClosureSynchronizer {
func start(retry: Bool, completion: @escaping (Error?) -> Void) func start(retry: Bool, completion: @escaping (Error?) -> Void)
func stop() func stop()
func getSaplingAddress(account: Zip32Account, completion: @escaping (Result<SaplingAddress, Error>) -> Void) func getSaplingAddress(accountIndex: Zip32AccountIndex, completion: @escaping (Result<SaplingAddress, Error>) -> Void)
func getUnifiedAddress(account: Zip32Account, completion: @escaping (Result<UnifiedAddress, Error>) -> Void) func getUnifiedAddress(accountIndex: Zip32AccountIndex, completion: @escaping (Result<UnifiedAddress, Error>) -> Void)
func getTransparentAddress(account: Zip32Account, completion: @escaping (Result<TransparentAddress, Error>) -> Void) func getTransparentAddress(accountIndex: Zip32AccountIndex, completion: @escaping (Result<TransparentAddress, Error>) -> Void)
/// Creates a proposal for transferring funds to the given recipient. /// Creates a proposal for transferring funds to the given recipient.
/// ///
/// - Parameter account: the account from which to transfer funds. /// - Parameter accountIndex: the ZIP 32 index of the account from which to transfer funds.
/// - Parameter recipient: the recipient's address. /// - Parameter recipient: the recipient's address.
/// - Parameter amount: the amount to send in Zatoshi. /// - Parameter amount: the amount to send in Zatoshi.
/// - Parameter memo: an optional memo to include as part of the proposal's transactions. Use `nil` when sending to transparent receivers otherwise the function will throw an error. /// - Parameter memo: an optional memo to include as part of the proposal's transactions. Use `nil` when sending to transparent receivers otherwise the function will throw an error.
@ -46,7 +46,7 @@ public protocol ClosureSynchronizer {
/// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws /// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws
/// `SynchronizerErrors.notPrepared`. /// `SynchronizerErrors.notPrepared`.
func proposeTransfer( func proposeTransfer(
account: Zip32Account, accountIndex: Zip32AccountIndex,
recipient: Recipient, recipient: Recipient,
amount: Zatoshi, amount: Zatoshi,
memo: Memo?, memo: Memo?,
@ -55,7 +55,7 @@ public protocol ClosureSynchronizer {
/// Creates a proposal for shielding any transparent funds received by the given account. /// Creates a proposal for shielding any transparent funds received by the given account.
/// ///
/// - Parameter account: the account for which to shield funds. /// - Parameter accountIndex: the ZIP 32 index of the account from which to shield funds.
/// - Parameter shieldingThreshold: the minimum transparent balance required before a proposal will be created. /// - Parameter shieldingThreshold: the minimum transparent balance required before a proposal will be created.
/// - Parameter memo: an optional memo to include as part of the proposal's transactions. /// - Parameter memo: an optional memo to include as part of the proposal's transactions.
/// - Parameter transparentReceiver: a specific transparent receiver within the account /// - Parameter transparentReceiver: a specific transparent receiver within the account
@ -69,7 +69,7 @@ public protocol ClosureSynchronizer {
/// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws /// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws
/// `SynchronizerErrors.notPrepared`. /// `SynchronizerErrors.notPrepared`.
func proposeShielding( func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
memo: Memo, memo: Memo,
transparentReceiver: TransparentAddress?, transparentReceiver: TransparentAddress?,
@ -127,7 +127,7 @@ public protocol ClosureSynchronizer {
func refreshUTXOs(address: TransparentAddress, from height: BlockHeight, completion: @escaping (Result<RefreshedUTXOs, Error>) -> Void) func refreshUTXOs(address: TransparentAddress, from height: BlockHeight, completion: @escaping (Result<RefreshedUTXOs, Error>) -> Void)
func getAccountBalance(account: Zip32Account, completion: @escaping (Result<AccountBalance?, Error>) -> Void) func getAccountBalance(accountIndex: Zip32AccountIndex, completion: @escaping (Result<AccountBalance?, Error>) -> Void)
func refreshExchangeRateUSD() func refreshExchangeRateUSD()

View File

@ -31,13 +31,13 @@ public protocol CombineSynchronizer {
func start(retry: Bool) -> CompletablePublisher<Error> func start(retry: Bool) -> CompletablePublisher<Error>
func stop() func stop()
func getSaplingAddress(account: Zip32Account) -> SinglePublisher<SaplingAddress, Error> func getSaplingAddress(accountIndex: Zip32AccountIndex) -> SinglePublisher<SaplingAddress, Error>
func getUnifiedAddress(account: Zip32Account) -> SinglePublisher<UnifiedAddress, Error> func getUnifiedAddress(accountIndex: Zip32AccountIndex) -> SinglePublisher<UnifiedAddress, Error>
func getTransparentAddress(account: Zip32Account) -> SinglePublisher<TransparentAddress, Error> func getTransparentAddress(accountIndex: Zip32AccountIndex) -> SinglePublisher<TransparentAddress, Error>
/// Creates a proposal for transferring funds to the given recipient. /// Creates a proposal for transferring funds to the given recipient.
/// ///
/// - Parameter account: the account from which to transfer funds. /// - Parameter accountIndex: the ZIP 32 index of the account from which to transfer funds.
/// - Parameter recipient: the recipient's address. /// - Parameter recipient: the recipient's address.
/// - Parameter amount: the amount to send in Zatoshi. /// - Parameter amount: the amount to send in Zatoshi.
/// - Parameter memo: an optional memo to include as part of the proposal's transactions. Use `nil` when sending to transparent receivers otherwise the function will throw an error. /// - Parameter memo: an optional memo to include as part of the proposal's transactions. Use `nil` when sending to transparent receivers otherwise the function will throw an error.
@ -45,7 +45,7 @@ public protocol CombineSynchronizer {
/// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws /// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws
/// `SynchronizerErrors.notPrepared`. /// `SynchronizerErrors.notPrepared`.
func proposeTransfer( func proposeTransfer(
account: Zip32Account, accountIndex: Zip32AccountIndex,
recipient: Recipient, recipient: Recipient,
amount: Zatoshi, amount: Zatoshi,
memo: Memo? memo: Memo?
@ -53,7 +53,7 @@ public protocol CombineSynchronizer {
/// Creates a proposal for shielding any transparent funds received by the given account. /// Creates a proposal for shielding any transparent funds received by the given account.
/// ///
/// - Parameter account: the account for which to shield funds. /// - Parameter accountIndex: the ZIP 32 index of the account from which to shield funds.
/// - Parameter shieldingThreshold: the minimum transparent balance required before a proposal will be created. /// - Parameter shieldingThreshold: the minimum transparent balance required before a proposal will be created.
/// - Parameter memo: an optional memo to include as part of the proposal's transactions. /// - Parameter memo: an optional memo to include as part of the proposal's transactions.
/// - Parameter transparentReceiver: a specific transparent receiver within the account /// - Parameter transparentReceiver: a specific transparent receiver within the account
@ -67,7 +67,7 @@ public protocol CombineSynchronizer {
/// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws /// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws
/// `SynchronizerErrors.notPrepared`. /// `SynchronizerErrors.notPrepared`.
func proposeShielding( func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
memo: Memo, memo: Memo,
transparentReceiver: TransparentAddress? transparentReceiver: TransparentAddress?
@ -110,7 +110,7 @@ public protocol CombineSynchronizer {
func proposefulfillingPaymentURI( func proposefulfillingPaymentURI(
_ uri: String, _ uri: String,
account: Zip32Account accountIndex: Zip32AccountIndex
) -> SinglePublisher<Proposal, Error> ) -> SinglePublisher<Proposal, Error>
var allTransactions: SinglePublisher<[ZcashTransaction.Overview], Never> { get } var allTransactions: SinglePublisher<[ZcashTransaction.Overview], Never> { get }

View File

@ -9,24 +9,24 @@ import Foundation
import SQLite import SQLite
protocol AccountEntity { protocol AccountEntity {
var account: Zip32Account { get } var accountIndex: Zip32AccountIndex { get }
var ufvk: String { get } var ufvk: String { get }
} }
struct DbAccount: AccountEntity, Encodable, Decodable { struct DbAccount: AccountEntity, Encodable, Decodable {
let account: Zip32Account let accountIndex: Zip32AccountIndex
let ufvk: String let ufvk: String
} }
extension DbAccount: Hashable { extension DbAccount: Hashable {
func hash(into hasher: inout Hasher) { func hash(into hasher: inout Hasher) {
hasher.combine(account.index) hasher.combine(accountIndex.index)
hasher.combine(ufvk) hasher.combine(ufvk)
} }
static func == (lhs: Self, rhs: Self) -> Bool { static func == (lhs: Self, rhs: Self) -> Bool {
guard guard
lhs.account == rhs.account, lhs.accountIndex == rhs.accountIndex,
lhs.ufvk == rhs.ufvk lhs.ufvk == rhs.ufvk
else { return false } else { return false }

View File

@ -147,10 +147,6 @@ public enum ZcashError: Equatable, Error {
/// Unified address generated by rust layer is invalid when calling ZcashRustBackend.getNextAvailableAddress /// Unified address generated by rust layer is invalid when calling ZcashRustBackend.getNextAvailableAddress
/// ZRUST0009 /// ZRUST0009
case rustGetNextAvailableAddressInvalidAddress case rustGetNextAvailableAddressInvalidAddress
/// account parameter is lower than 0 when calling ZcashRustBackend.getTransparentBalance
/// - `account` is account passed to ZcashRustBackend.getTransparentBalance.
/// ZRUST0010
case rustGetTransparentBalanceNegativeAccount(_ account: Int)
/// Error from rust layer when calling ZcashRustBackend.getTransparentBalance /// Error from rust layer when calling ZcashRustBackend.getTransparentBalance
/// - `account` is account passed to ZcashRustBackend.getTransparentBalance. /// - `account` is account passed to ZcashRustBackend.getTransparentBalance.
/// - `rustError` contains error generated by the rust layer. /// - `rustError` contains error generated by the rust layer.
@ -487,9 +483,6 @@ public enum ZcashError: Equatable, Error {
/// Failed to decode `Checkpoint` object. /// Failed to decode `Checkpoint` object.
/// ZCHKP0002 /// ZCHKP0002
case checkpointDecode(_ error: Error) case checkpointDecode(_ error: Error)
/// Invalid account when trying to derive a key
/// ZDRVT0001
case derivationToolInvalidAccount
/// Creation of the table for unspent transaction output failed. /// Creation of the table for unspent transaction output failed.
/// - `sqliteError` is error produced by SQLite library. /// - `sqliteError` is error produced by SQLite library.
/// ZUTOD0001 /// ZUTOD0001
@ -684,7 +677,6 @@ public enum ZcashError: Equatable, Error {
case .rustGetNearestRewindHeight: return "Error from rust layer when calling ZcashRustBackend.getNearestRewindHeight" case .rustGetNearestRewindHeight: return "Error from rust layer when calling ZcashRustBackend.getNearestRewindHeight"
case .rustGetNextAvailableAddress: return "Error from rust layer when calling ZcashRustBackend.getNextAvailableAddress" case .rustGetNextAvailableAddress: return "Error from rust layer when calling ZcashRustBackend.getNextAvailableAddress"
case .rustGetNextAvailableAddressInvalidAddress: return "Unified address generated by rust layer is invalid when calling ZcashRustBackend.getNextAvailableAddress" case .rustGetNextAvailableAddressInvalidAddress: return "Unified address generated by rust layer is invalid when calling ZcashRustBackend.getNextAvailableAddress"
case .rustGetTransparentBalanceNegativeAccount: return "account parameter is lower than 0 when calling ZcashRustBackend.getTransparentBalance"
case .rustGetTransparentBalance: return "Error from rust layer when calling ZcashRustBackend.getTransparentBalance" case .rustGetTransparentBalance: return "Error from rust layer when calling ZcashRustBackend.getTransparentBalance"
case .rustGetVerifiedBalance: return "Error from rust layer when calling ZcashRustBackend.getVerifiedBalance" case .rustGetVerifiedBalance: return "Error from rust layer when calling ZcashRustBackend.getVerifiedBalance"
case .rustGetVerifiedTransparentBalanceNegativeAccount: return "account parameter is lower than 0 when calling ZcashRustBackend.getVerifiedTransparentBalance" case .rustGetVerifiedTransparentBalanceNegativeAccount: return "account parameter is lower than 0 when calling ZcashRustBackend.getVerifiedTransparentBalance"
@ -778,7 +770,6 @@ public enum ZcashError: Equatable, Error {
case .memoBytesInvalidUTF8: return "Invalid UTF-8 Bytes where detected when attempting to convert MemoBytes to Memo." case .memoBytesInvalidUTF8: return "Invalid UTF-8 Bytes where detected when attempting to convert MemoBytes to Memo."
case .checkpointCantLoadFromDisk: return "Failed to load JSON with checkpoint from disk." case .checkpointCantLoadFromDisk: return "Failed to load JSON with checkpoint from disk."
case .checkpointDecode: return "Failed to decode `Checkpoint` object." case .checkpointDecode: return "Failed to decode `Checkpoint` object."
case .derivationToolInvalidAccount: return "Invalid account when trying to derive a key"
case .unspentTransactionOutputDAOCreateTable: return "Creation of the table for unspent transaction output failed." case .unspentTransactionOutputDAOCreateTable: return "Creation of the table for unspent transaction output failed."
case .unspentTransactionOutputDAOStore: return "SQLite query failed when storing unspent transaction output." case .unspentTransactionOutputDAOStore: return "SQLite query failed when storing unspent transaction output."
case .unspentTransactionOutputDAOClearAll: return "SQLite query failed when removing all the unspent transation outputs." case .unspentTransactionOutputDAOClearAll: return "SQLite query failed when removing all the unspent transation outputs."
@ -871,7 +862,6 @@ public enum ZcashError: Equatable, Error {
case .rustGetNearestRewindHeight: return .rustGetNearestRewindHeight case .rustGetNearestRewindHeight: return .rustGetNearestRewindHeight
case .rustGetNextAvailableAddress: return .rustGetNextAvailableAddress case .rustGetNextAvailableAddress: return .rustGetNextAvailableAddress
case .rustGetNextAvailableAddressInvalidAddress: return .rustGetNextAvailableAddressInvalidAddress case .rustGetNextAvailableAddressInvalidAddress: return .rustGetNextAvailableAddressInvalidAddress
case .rustGetTransparentBalanceNegativeAccount: return .rustGetTransparentBalanceNegativeAccount
case .rustGetTransparentBalance: return .rustGetTransparentBalance case .rustGetTransparentBalance: return .rustGetTransparentBalance
case .rustGetVerifiedBalance: return .rustGetVerifiedBalance case .rustGetVerifiedBalance: return .rustGetVerifiedBalance
case .rustGetVerifiedTransparentBalanceNegativeAccount: return .rustGetVerifiedTransparentBalanceNegativeAccount case .rustGetVerifiedTransparentBalanceNegativeAccount: return .rustGetVerifiedTransparentBalanceNegativeAccount
@ -965,7 +955,6 @@ public enum ZcashError: Equatable, Error {
case .memoBytesInvalidUTF8: return .memoBytesInvalidUTF8 case .memoBytesInvalidUTF8: return .memoBytesInvalidUTF8
case .checkpointCantLoadFromDisk: return .checkpointCantLoadFromDisk case .checkpointCantLoadFromDisk: return .checkpointCantLoadFromDisk
case .checkpointDecode: return .checkpointDecode case .checkpointDecode: return .checkpointDecode
case .derivationToolInvalidAccount: return .derivationToolInvalidAccount
case .unspentTransactionOutputDAOCreateTable: return .unspentTransactionOutputDAOCreateTable case .unspentTransactionOutputDAOCreateTable: return .unspentTransactionOutputDAOCreateTable
case .unspentTransactionOutputDAOStore: return .unspentTransactionOutputDAOStore case .unspentTransactionOutputDAOStore: return .unspentTransactionOutputDAOStore
case .unspentTransactionOutputDAOClearAll: return .unspentTransactionOutputDAOClearAll case .unspentTransactionOutputDAOClearAll: return .unspentTransactionOutputDAOClearAll

View File

@ -85,8 +85,6 @@ public enum ZcashErrorCode: String {
case rustGetNextAvailableAddress = "ZRUST0008" case rustGetNextAvailableAddress = "ZRUST0008"
/// Unified address generated by rust layer is invalid when calling ZcashRustBackend.getNextAvailableAddress /// Unified address generated by rust layer is invalid when calling ZcashRustBackend.getNextAvailableAddress
case rustGetNextAvailableAddressInvalidAddress = "ZRUST0009" case rustGetNextAvailableAddressInvalidAddress = "ZRUST0009"
/// account parameter is lower than 0 when calling ZcashRustBackend.getTransparentBalance
case rustGetTransparentBalanceNegativeAccount = "ZRUST0010"
/// Error from rust layer when calling ZcashRustBackend.getTransparentBalance /// Error from rust layer when calling ZcashRustBackend.getTransparentBalance
case rustGetTransparentBalance = "ZRUST0011" case rustGetTransparentBalance = "ZRUST0011"
/// Error from rust layer when calling ZcashRustBackend.getVerifiedBalance /// Error from rust layer when calling ZcashRustBackend.getVerifiedBalance
@ -273,8 +271,6 @@ public enum ZcashErrorCode: String {
case checkpointCantLoadFromDisk = "ZCHKP0001" case checkpointCantLoadFromDisk = "ZCHKP0001"
/// Failed to decode `Checkpoint` object. /// Failed to decode `Checkpoint` object.
case checkpointDecode = "ZCHKP0002" case checkpointDecode = "ZCHKP0002"
/// Invalid account when trying to derive a key
case derivationToolInvalidAccount = "ZDRVT0001"
/// Creation of the table for unspent transaction output failed. /// Creation of the table for unspent transaction output failed.
case unspentTransactionOutputDAOCreateTable = "ZUTOD0001" case unspentTransactionOutputDAOCreateTable = "ZUTOD0001"
/// SQLite query failed when storing unspent transaction output. /// SQLite query failed when storing unspent transaction output.

View File

@ -178,10 +178,6 @@ enum ZcashErrorDefinition {
/// Unified address generated by rust layer is invalid when calling ZcashRustBackend.getNextAvailableAddress /// Unified address generated by rust layer is invalid when calling ZcashRustBackend.getNextAvailableAddress
// sourcery: code="ZRUST0009" // sourcery: code="ZRUST0009"
case rustGetNextAvailableAddressInvalidAddress case rustGetNextAvailableAddressInvalidAddress
/// account parameter is lower than 0 when calling ZcashRustBackend.getTransparentBalance
/// - `account` is account passed to ZcashRustBackend.getTransparentBalance.
// sourcery: code="ZRUST0010"
case rustGetTransparentBalanceNegativeAccount(_ account: Int)
/// Error from rust layer when calling ZcashRustBackend.getTransparentBalance /// Error from rust layer when calling ZcashRustBackend.getTransparentBalance
/// - `account` is account passed to ZcashRustBackend.getTransparentBalance. /// - `account` is account passed to ZcashRustBackend.getTransparentBalance.
/// - `rustError` contains error generated by the rust layer. /// - `rustError` contains error generated by the rust layer.
@ -538,12 +534,6 @@ enum ZcashErrorDefinition {
// sourcery: code="ZCHKP0002" // sourcery: code="ZCHKP0002"
case checkpointDecode(_ error: Error) case checkpointDecode(_ error: Error)
// MARK: - DerivationTool
/// Invalid account when trying to derive a key
// sourcery: code="ZDRVT0001"
case derivationToolInvalidAccount
// MARK: - UnspentTransactionOutputDAO // MARK: - UnspentTransactionOutputDAO
/// Creation of the table for unspent transaction output failed. /// Creation of the table for unspent transaction output failed.

View File

@ -13,7 +13,7 @@ public protocol StringEncoded {
public struct UnifiedSpendingKey: Equatable, Undescribable { public struct UnifiedSpendingKey: Equatable, Undescribable {
let network: NetworkType let network: NetworkType
let bytes: [UInt8] let bytes: [UInt8]
public let account: UInt32 public let accountIndex: Zip32AccountIndex
} }
/// Sapling Extended Spending Key /// Sapling Extended Spending Key
@ -45,23 +45,23 @@ public struct TransparentAccountPrivKey: Equatable, Undescribable {
/// A ZIP 316 Unified Full Viewing Key. /// A ZIP 316 Unified Full Viewing Key.
public struct UnifiedFullViewingKey: Equatable, StringEncoded, Undescribable { public struct UnifiedFullViewingKey: Equatable, StringEncoded, Undescribable {
let encoding: String let encoding: String
public let account: UInt32 public let accountIndex: Zip32AccountIndex
public var stringEncoded: String { encoding } public var stringEncoded: String { encoding }
/// Initializes a new UnifiedFullViewingKey (UFVK) from the provided string encoding /// Initializes a new UnifiedFullViewingKey (UFVK) from the provided string encoding
/// - Parameters: /// - Parameters:
/// - parameter encoding: String encoding of unified full viewing key /// - parameter encoding: String encoding of unified full viewing key
/// - parameter account: account number of the given UFVK /// - parameter accountIndex: the ZIP32 account Index of the given UFVK
/// - parameter network: `NetworkType` corresponding to the encoding (Mainnet or Testnet) /// - parameter network: `NetworkType` corresponding to the encoding (Mainnet or Testnet)
/// - Throws: `unifiedFullViewingKeyInvalidInput`when the provided encoding is found to be invalid /// - Throws: `unifiedFullViewingKeyInvalidInput`when the provided encoding is found to be invalid
public init(encoding: String, account: UInt32, network: NetworkType) throws { public init(encoding: String, accountIndex: Zip32AccountIndex, network: NetworkType) throws {
guard DerivationTool(networkType: network).isValidUnifiedFullViewingKey(encoding) else { guard DerivationTool(networkType: network).isValidUnifiedFullViewingKey(encoding) else {
throw ZcashError.unifiedFullViewingKeyInvalidInput throw ZcashError.unifiedFullViewingKeyInvalidInput
} }
self.encoding = encoding self.encoding = encoding
self.account = account self.accountIndex = accountIndex
} }
} }

View File

@ -95,13 +95,13 @@ struct ZcashKeyDerivationBackend: ZcashKeyDerivationBackendWelding {
func deriveUnifiedSpendingKey( func deriveUnifiedSpendingKey(
from seed: [UInt8], from seed: [UInt8],
accountIndex: Int32 accountIndex: Zip32AccountIndex
) throws -> UnifiedSpendingKey { ) throws -> UnifiedSpendingKey {
let binaryKeyPtr = seed.withUnsafeBufferPointer { seedBufferPtr in let binaryKeyPtr = seed.withUnsafeBufferPointer { seedBufferPtr in
return zcashlc_derive_spending_key( return zcashlc_derive_spending_key(
seedBufferPtr.baseAddress, seedBufferPtr.baseAddress,
UInt(seed.count), UInt(seed.count),
accountIndex, Int32(accountIndex.index),
networkType.networkId networkType.networkId
) )
} }
@ -137,7 +137,7 @@ struct ZcashKeyDerivationBackend: ZcashKeyDerivationBackendWelding {
throw ZcashError.rustDeriveUnifiedFullViewingKeyInvalidDerivedKey throw ZcashError.rustDeriveUnifiedFullViewingKeyInvalidDerivedKey
} }
return UnifiedFullViewingKey(validatedEncoding: derived, account: spendingKey.account) return UnifiedFullViewingKey(validatedEncoding: derived, accountIndex: spendingKey.accountIndex)
} }
func getSaplingReceiver(for uAddr: UnifiedAddress) throws -> SaplingAddress { func getSaplingReceiver(for uAddr: UnifiedAddress) throws -> SaplingAddress {
@ -202,7 +202,7 @@ struct ZcashKeyDerivationBackend: ZcashKeyDerivationBackendWelding {
func deriveArbitraryAccountKey( func deriveArbitraryAccountKey(
contextString: [UInt8], contextString: [UInt8],
from seed: [UInt8], from seed: [UInt8],
accountIndex: Int32 accountIndex: Zip32AccountIndex
) throws -> [UInt8] { ) throws -> [UInt8] {
let boxedSlicePtr = contextString.withUnsafeBufferPointer { contextStringBufferPtr in let boxedSlicePtr = contextString.withUnsafeBufferPointer { contextStringBufferPtr in
seed.withUnsafeBufferPointer { seedBufferPtr in seed.withUnsafeBufferPointer { seedBufferPtr in
@ -211,7 +211,7 @@ struct ZcashKeyDerivationBackend: ZcashKeyDerivationBackendWelding {
UInt(contextString.count), UInt(contextString.count),
seedBufferPtr.baseAddress, seedBufferPtr.baseAddress,
UInt(seed.count), UInt(seed.count),
accountIndex, Int32(accountIndex.index),
networkType.networkId networkType.networkId
) )
} }

View File

@ -40,12 +40,12 @@ protocol ZcashKeyDerivationBackendWelding {
/// - Returns: true when the encoded string is a valid UFVK. false in any other case /// - Returns: true when the encoded string is a valid UFVK. false in any other case
func isValidUnifiedFullViewingKey(_ ufvk: String) -> Bool func isValidUnifiedFullViewingKey(_ ufvk: String) -> Bool
/// Derives and returns a unified spending key from the given seed for the given account ID. /// Derives and returns a unified spending key from the given seed and ZIP 32 account index.
/// Returns the binary encoding of the spending key. The caller should manage the memory of (and store, if necessary) the returned spending key in a secure fashion. /// Returns the binary encoding of the spending key. The caller should manage the memory of (and store, if necessary) the returned spending key in a secure fashion.
/// - Parameter seed: a Byte Array with the seed /// - Parameter seed: a Byte Array with the seed
/// - Parameter accountIndex:account that the key can spend from /// - Parameter accountIndex: the ZIP 32 index of the account from which the key can spend
/// - Throws: `rustDeriveUnifiedSpendingKey` if rust layer returns error. /// - Throws: `rustDeriveUnifiedSpendingKey` if rust layer returns error.
func deriveUnifiedSpendingKey(from seed: [UInt8], accountIndex: Int32) throws -> UnifiedSpendingKey func deriveUnifiedSpendingKey(from seed: [UInt8], accountIndex: Zip32AccountIndex) throws -> UnifiedSpendingKey
/// Derives a `UnifiedFullViewingKey` from a `UnifiedSpendingKey` /// Derives a `UnifiedFullViewingKey` from a `UnifiedSpendingKey`
/// - Parameter spendingKey: the `UnifiedSpendingKey` to derive from /// - Parameter spendingKey: the `UnifiedSpendingKey` to derive from
@ -81,7 +81,6 @@ protocol ZcashKeyDerivationBackendWelding {
/// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context. /// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context.
/// - Parameter seed: `[Uint8]` seed bytes /// - Parameter seed: `[Uint8]` seed bytes
/// - Throws: /// - Throws:
/// - `derivationToolInvalidAccount` if the `account.index` is invalid.
/// - some `ZcashError.rust*` error if the derivation fails. /// - some `ZcashError.rust*` error if the derivation fails.
/// - Returns a `[Uint8]` /// - Returns a `[Uint8]`
static func deriveArbitraryWalletKey( static func deriveArbitraryWalletKey(
@ -93,14 +92,13 @@ protocol ZcashKeyDerivationBackendWelding {
/// ///
/// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context. /// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context.
/// - Parameter seed: `[Uint8]` seed bytes /// - Parameter seed: `[Uint8]` seed bytes
/// - Parameter accountIndex: `Int32` with the account number /// - Parameter accountIndex: the ZIP 32 index of the account
/// - Throws: /// - Throws:
/// - `derivationToolInvalidAccount` if the `account.index` is invalid.
/// - some `ZcashError.rust*` error if the derivation fails. /// - some `ZcashError.rust*` error if the derivation fails.
/// - Returns a `[Uint8]` /// - Returns a `[Uint8]`
func deriveArbitraryAccountKey( func deriveArbitraryAccountKey(
contextString: [UInt8], contextString: [UInt8],
from seed: [UInt8], from seed: [UInt8],
accountIndex: Int32 accountIndex: Zip32AccountIndex
) throws -> [UInt8] ) throws -> [UInt8]
} }

View File

@ -9,6 +9,8 @@
import Foundation import Foundation
import libzcashlc import libzcashlc
typealias LCZip32Index = Int32
enum RustLogging: String { enum RustLogging: String {
/// The logs are completely disabled. /// The logs are completely disabled.
case off case off
@ -72,7 +74,7 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
} }
@DBActor @DBActor
func listAccounts() async throws -> [Zip32Account] { func listAccounts() async throws -> [Zip32AccountIndex] {
let accountsPtr = zcashlc_list_accounts( let accountsPtr = zcashlc_list_accounts(
dbData.0, dbData.0,
dbData.1, dbData.1,
@ -85,11 +87,11 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
defer { zcashlc_free_accounts(accountsPtr) } defer { zcashlc_free_accounts(accountsPtr) }
var accounts: [Zip32Account] = [] var accounts: [Zip32AccountIndex] = []
for i in (0 ..< Int(accountsPtr.pointee.len)) { for i in (0 ..< Int(accountsPtr.pointee.len)) {
let account = accountsPtr.pointee.ptr.advanced(by: i).pointee let account = accountsPtr.pointee.ptr.advanced(by: i).pointee
accounts.append(Zip32Account(Int32(account.account_index))) accounts.append(Zip32AccountIndex(account.account_index))
} }
return accounts return accounts
@ -148,7 +150,7 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
@DBActor @DBActor
func proposeTransfer( func proposeTransfer(
account: Zip32Account, accountIndex: Zip32AccountIndex,
to address: String, to address: String,
value: Int64, value: Int64,
memo: MemoBytes? memo: MemoBytes?
@ -156,7 +158,7 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
let proposal = zcashlc_propose_transfer( let proposal = zcashlc_propose_transfer(
dbData.0, dbData.0,
dbData.1, dbData.1,
account.index, LCZip32Index(accountIndex.index),
[CChar](address.utf8CString), [CChar](address.utf8CString),
value, value,
memo?.bytes, memo?.bytes,
@ -179,12 +181,12 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
@DBActor @DBActor
func proposeTransferFromURI( func proposeTransferFromURI(
_ uri: String, _ uri: String,
account: Zip32Account accountIndex: Zip32AccountIndex
) async throws -> FfiProposal { ) async throws -> FfiProposal {
let proposal = zcashlc_propose_transfer_from_uri( let proposal = zcashlc_propose_transfer_from_uri(
dbData.0, dbData.0,
dbData.1, dbData.1,
account.index, LCZip32Index(accountIndex.index),
[CChar](uri.utf8CString), [CChar](uri.utf8CString),
networkType.networkId, networkType.networkId,
minimumConfirmations minimumConfirmations
@ -219,11 +221,11 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
} }
@DBActor @DBActor
func getCurrentAddress(account: Zip32Account) async throws -> UnifiedAddress { func getCurrentAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress {
let addressCStr = zcashlc_get_current_address( let addressCStr = zcashlc_get_current_address(
dbData.0, dbData.0,
dbData.1, dbData.1,
account.index, LCZip32Index(accountIndex.index),
networkType.networkId networkType.networkId
) )
@ -241,11 +243,11 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
} }
@DBActor @DBActor
func getNextAvailableAddress(account: Zip32Account) async throws -> UnifiedAddress { func getNextAvailableAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress {
let addressCStr = zcashlc_get_next_available_address( let addressCStr = zcashlc_get_next_available_address(
dbData.0, dbData.0,
dbData.1, dbData.1,
account.index, LCZip32Index(accountIndex.index),
networkType.networkId networkType.networkId
) )
@ -281,22 +283,18 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
} }
@DBActor @DBActor
func getTransparentBalance(account: Zip32Account) async throws -> Int64 { func getTransparentBalance(accountIndex: Zip32AccountIndex) async throws -> Int64 {
guard account.index >= 0 else {
throw ZcashError.rustGetTransparentBalanceNegativeAccount(Int(account.index))
}
let balance = zcashlc_get_total_transparent_balance_for_account( let balance = zcashlc_get_total_transparent_balance_for_account(
dbData.0, dbData.0,
dbData.1, dbData.1,
networkType.networkId, networkType.networkId,
account.index LCZip32Index(accountIndex.index)
) )
guard balance >= 0 else { guard balance >= 0 else {
throw ZcashError.rustGetTransparentBalance( throw ZcashError.rustGetTransparentBalance(
Int(account.index), Int(accountIndex.index),
lastErrorMessage(fallback: "Error getting Total Transparent balance from account \(account.index)") lastErrorMessage(fallback: "Error getting Total Transparent balance from accountIndex \(accountIndex.index)")
) )
} }
@ -304,23 +302,19 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
} }
@DBActor @DBActor
func getVerifiedTransparentBalance(account: Zip32Account) async throws -> Int64 { func getVerifiedTransparentBalance(accountIndex: Zip32AccountIndex) async throws -> Int64 {
guard account.index >= 0 else {
throw ZcashError.rustGetVerifiedTransparentBalanceNegativeAccount(Int(account.index))
}
let balance = zcashlc_get_verified_transparent_balance_for_account( let balance = zcashlc_get_verified_transparent_balance_for_account(
dbData.0, dbData.0,
dbData.1, dbData.1,
networkType.networkId, networkType.networkId,
account.index, LCZip32Index(accountIndex.index),
minimumShieldingConfirmations minimumShieldingConfirmations
) )
guard balance >= 0 else { guard balance >= 0 else {
throw ZcashError.rustGetVerifiedTransparentBalance( throw ZcashError.rustGetVerifiedTransparentBalance(
Int(account.index), Int(accountIndex.index),
lastErrorMessage(fallback: "Error getting verified transparent balance from account \(account.index)") lastErrorMessage(fallback: "Error getting verified transparent balance from accountIndex \(accountIndex.index)")
) )
} }
@ -424,11 +418,11 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
} }
@DBActor @DBActor
func listTransparentReceivers(account: Zip32Account) async throws -> [TransparentAddress] { func listTransparentReceivers(accountIndex: Zip32AccountIndex) async throws -> [TransparentAddress] {
let encodedKeysPtr = zcashlc_list_transparent_receivers( let encodedKeysPtr = zcashlc_list_transparent_receivers(
dbData.0, dbData.0,
dbData.1, dbData.1,
account.index, LCZip32Index(accountIndex.index),
networkType.networkId networkType.networkId
) )
@ -747,7 +741,7 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
@DBActor @DBActor
func proposeShielding( func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
memo: MemoBytes?, memo: MemoBytes?,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
transparentReceiver: String? transparentReceiver: String?
@ -755,7 +749,7 @@ struct ZcashRustBackend: ZcashRustBackendWelding {
let proposal = zcashlc_propose_shielding( let proposal = zcashlc_propose_shielding(
dbData.0, dbData.0,
dbData.1, dbData.1,
account.index, LCZip32Index(accountIndex.index),
memo?.bytes, memo?.bytes,
UInt64(shieldingThreshold.amount), UInt64(shieldingThreshold.amount),
transparentReceiver.map { [CChar]($0.utf8CString) }, transparentReceiver.map { [CChar]($0.utf8CString) },
@ -963,7 +957,7 @@ extension FFIBinaryKey {
bytes: self.encoding.toByteArray( bytes: self.encoding.toByteArray(
length: Int(self.encoding_len) length: Int(self.encoding_len)
), ),
account: self.account_id accountIndex: Zip32AccountIndex(self.account_id)
) )
} }
} }

View File

@ -33,8 +33,8 @@ public enum RewindResult {
} }
protocol ZcashRustBackendWelding { protocol ZcashRustBackendWelding {
/// Returns a list of the accounts in the wallet. /// Returns a list of the ZIP 32 indices of accounts in the wallet.
func listAccounts() async throws -> [Zip32Account] func listAccounts() async throws -> [Zip32AccountIndex]
/// Adds the next available account-level spend authority, given the current set of [ZIP 316] /// Adds the next available account-level spend authority, given the current set of [ZIP 316]
/// account identifiers known, to the wallet database. /// account identifiers known, to the wallet database.
@ -73,14 +73,14 @@ protocol ZcashRustBackendWelding {
/// - Throws: /// - Throws:
/// - `rustGetCurrentAddress` if rust layer returns error. /// - `rustGetCurrentAddress` if rust layer returns error.
/// - `rustGetCurrentAddressInvalidAddress` if generated unified address isn't valid. /// - `rustGetCurrentAddressInvalidAddress` if generated unified address isn't valid.
func getCurrentAddress(account: Zip32Account) async throws -> UnifiedAddress func getCurrentAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress
/// Returns a newly-generated unified payment address for the specified account, with the next available diversifier. /// Returns a newly-generated unified payment address for the specified account, with the next available diversifier.
/// - parameter account: index of the given account /// - parameter account: index of the given account
/// - Throws: /// - Throws:
/// - `rustGetNextAvailableAddress` if rust layer returns error. /// - `rustGetNextAvailableAddress` if rust layer returns error.
/// - `rustGetNextAvailableAddressInvalidAddress` if generated unified address isn't valid. /// - `rustGetNextAvailableAddressInvalidAddress` if generated unified address isn't valid.
func getNextAvailableAddress(account: Zip32Account) async throws -> UnifiedAddress func getNextAvailableAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress
/// Get memo from note. /// Get memo from note.
/// - parameter txId: ID of transaction containing the note /// - parameter txId: ID of transaction containing the note
@ -93,7 +93,7 @@ protocol ZcashRustBackendWelding {
/// - Throws: /// - Throws:
/// - `rustGetTransparentBalanceNegativeAccount` if `account` is < 0. /// - `rustGetTransparentBalanceNegativeAccount` if `account` is < 0.
/// - `rustGetTransparentBalance` if rust layer returns error. /// - `rustGetTransparentBalance` if rust layer returns error.
func getTransparentBalance(account: Zip32Account) async throws -> Int64 func getTransparentBalance(accountIndex: Zip32AccountIndex) async throws -> Int64
/// Initializes the data db. This will performs any migrations needed on the sqlite file /// Initializes the data db. This will performs any migrations needed on the sqlite file
/// provided. Some migrations might need that callers provide the seed bytes. /// provided. Some migrations might need that callers provide the seed bytes.
@ -110,14 +110,14 @@ protocol ZcashRustBackendWelding {
/// - Throws: /// - Throws:
/// - `rustListTransparentReceivers` if rust layer returns error. /// - `rustListTransparentReceivers` if rust layer returns error.
/// - `rustListTransparentReceiversInvalidAddress` if transarent received generated by rust is invalid. /// - `rustListTransparentReceiversInvalidAddress` if transarent received generated by rust is invalid.
func listTransparentReceivers(account: Zip32Account) async throws -> [TransparentAddress] func listTransparentReceivers(accountIndex: Zip32AccountIndex) async throws -> [TransparentAddress]
/// Get the verified cached transparent balance for the given account /// Get the verified cached transparent balance for the given account
/// - parameter account: account index to query the balance for. /// - parameter account: account index to query the balance for.
/// - Throws: /// - Throws:
/// - `rustGetVerifiedTransparentBalanceNegativeAccount` if `account` is < 0. /// - `rustGetVerifiedTransparentBalanceNegativeAccount` if `account` is < 0.
/// - `rustGetVerifiedTransparentBalance` if rust layer returns error. /// - `rustGetVerifiedTransparentBalance` if rust layer returns error.
func getVerifiedTransparentBalance(account: Zip32Account) async throws -> Int64 func getVerifiedTransparentBalance(accountIndex: Zip32AccountIndex) async throws -> Int64
/// Resets the state of the database to only contain block and transaction information up to the given height. clears up all derived data as well /// Resets the state of the database to only contain block and transaction information up to the given height. clears up all derived data as well
/// - parameter height: height to rewind to. /// - parameter height: height to rewind to.
@ -215,7 +215,7 @@ protocol ZcashRustBackendWelding {
/// - Parameter memo: the `MemoBytes` for this transaction. pass `nil` when sending to transparent receivers /// - Parameter memo: the `MemoBytes` for this transaction. pass `nil` when sending to transparent receivers
/// - Throws: `rustCreateToAddress`. /// - Throws: `rustCreateToAddress`.
func proposeTransfer( func proposeTransfer(
account: Zip32Account, accountIndex: Zip32AccountIndex,
to address: String, to address: String,
value: Int64, value: Int64,
memo: MemoBytes? memo: MemoBytes?
@ -233,7 +233,7 @@ protocol ZcashRustBackendWelding {
/// - Throws: `rustCreateToAddress`. /// - Throws: `rustCreateToAddress`.
func proposeTransferFromURI( func proposeTransferFromURI(
_ uri: String, _ uri: String,
account: Zip32Account accountIndex: Zip32AccountIndex
) async throws -> FfiProposal ) async throws -> FfiProposal
/// Constructs a transaction proposal to shield all found UTXOs in data db for the given account, /// Constructs a transaction proposal to shield all found UTXOs in data db for the given account,
@ -251,7 +251,7 @@ protocol ZcashRustBackendWelding {
/// to shield. /// to shield.
/// - Throws: `rustShieldFunds` if rust layer returns error. /// - Throws: `rustShieldFunds` if rust layer returns error.
func proposeShielding( func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
memo: MemoBytes?, memo: MemoBytes?,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
transparentReceiver: String? transparentReceiver: String?

View File

@ -144,23 +144,23 @@ public protocol Synchronizer: AnyObject {
func stop() func stop()
/// Gets the sapling shielded address for the given account. /// Gets the sapling shielded address for the given account.
/// - Parameter account: the account whose address is of interest. By default, the first account is used. /// - Parameter accountIndex: the ZIP 32 index of the account whose address is of interest.
/// - Returns the address or nil if account index is incorrect /// - Returns the address or nil if account index is incorrect
func getSaplingAddress(account: Zip32Account) async throws -> SaplingAddress func getSaplingAddress(accountIndex: Zip32AccountIndex) async throws -> SaplingAddress
/// Gets the unified address for the given account. /// Gets the unified address for the given account.
/// - Parameter account: the account whose address is of interest. By default, the first account is used. /// - Parameter accountIndex: the ZIP 32 index of the account whose address is of interest.
/// - Returns the address or nil if account index is incorrect /// - Returns the address or nil if account index is incorrect
func getUnifiedAddress(account: Zip32Account) async throws -> UnifiedAddress func getUnifiedAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress
/// Gets the transparent address for the given account. /// Gets the transparent address for the given account.
/// - Parameter account: the account whose address is of interest. By default, the first account is used. /// - Parameter accountIndex: the ZIP 32 index of the account whose address is of interest. By default, the first account is used.
/// - Returns the address or nil if account index is incorrect /// - Returns the address or nil if account index is incorrect
func getTransparentAddress(account: Zip32Account) async throws -> TransparentAddress func getTransparentAddress(accountIndex: Zip32AccountIndex) async throws -> TransparentAddress
/// Creates a proposal for transferring funds to the given recipient. /// Creates a proposal for transferring funds to the given recipient.
/// ///
/// - Parameter account: the account from which to transfer funds. /// - Parameter accountIndex: the ZIP 32 index of the account from which to transfer funds.
/// - Parameter recipient: the recipient's address. /// - Parameter recipient: the recipient's address.
/// - Parameter amount: the amount to send in Zatoshi. /// - Parameter amount: the amount to send in Zatoshi.
/// - Parameter memo: an optional memo to include as part of the proposal's transactions. Use `nil` when sending to transparent receivers otherwise the function will throw an error. /// - Parameter memo: an optional memo to include as part of the proposal's transactions. Use `nil` when sending to transparent receivers otherwise the function will throw an error.
@ -168,7 +168,7 @@ public protocol Synchronizer: AnyObject {
/// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws /// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws
/// `SynchronizerErrors.notPrepared`. /// `SynchronizerErrors.notPrepared`.
func proposeTransfer( func proposeTransfer(
account: Zip32Account, accountIndex: Zip32AccountIndex,
recipient: Recipient, recipient: Recipient,
amount: Zatoshi, amount: Zatoshi,
memo: Memo? memo: Memo?
@ -176,7 +176,7 @@ public protocol Synchronizer: AnyObject {
/// Creates a proposal for shielding any transparent funds received by the given account. /// Creates a proposal for shielding any transparent funds received by the given account.
/// ///
/// - Parameter account: the account for which to shield funds. /// - Parameter accountIndex: the ZIP 32 index of the account for which to shield funds.
/// - Parameter shieldingThreshold: the minimum transparent balance required before a proposal will be created. /// - Parameter shieldingThreshold: the minimum transparent balance required before a proposal will be created.
/// - Parameter memo: an optional memo to include as part of the proposal's transactions. /// - Parameter memo: an optional memo to include as part of the proposal's transactions.
/// - Parameter transparentReceiver: a specific transparent receiver within the account /// - Parameter transparentReceiver: a specific transparent receiver within the account
@ -190,7 +190,7 @@ public protocol Synchronizer: AnyObject {
/// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws /// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws
/// `SynchronizerErrors.notPrepared`. /// `SynchronizerErrors.notPrepared`.
func proposeShielding( func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
memo: Memo, memo: Memo,
transparentReceiver: TransparentAddress? transparentReceiver: TransparentAddress?
@ -228,15 +228,15 @@ public protocol Synchronizer: AnyObject {
memo: Memo? memo: Memo?
) async throws -> ZcashTransaction.Overview ) async throws -> ZcashTransaction.Overview
/// Attempts to propose fulfilling a [ZIP-321](https://zips.z.cash/zip-0321) payment URI using the given `account.index` /// Attempts to propose fulfilling a [ZIP-321](https://zips.z.cash/zip-0321) payment URI by spending from the ZIP 32 account with the given index.
/// - Parameter uri: a valid ZIP-321 payment URI /// - Parameter uri: a valid ZIP-321 payment URI
/// - Parameter account: the account index that allows spends to occur. /// - Parameter accountIndex: the ZIP 32 index of the account providing spend authority.
/// ///
/// - NOTE: If `prepare()` hasn't already been called since creating of synchronizer instance or since the last wipe then this method throws /// - NOTE: If `prepare()` hasn't already been called since creating of synchronizer instance or since the last wipe then this method throws
/// `SynchronizerErrors.notPrepared`. /// `SynchronizerErrors.notPrepared`.
func proposefulfillingPaymentURI( func proposefulfillingPaymentURI(
_ uri: String, _ uri: String,
account: Zip32Account accountIndex: Zip32AccountIndex
) async throws -> Proposal ) async throws -> Proposal
/// Shields transparent funds from the given private key into the best shielded pool of the account associated to the given `UnifiedSpendingKey`. /// Shields transparent funds from the given private key into the best shielded pool of the account associated to the given `UnifiedSpendingKey`.
@ -310,7 +310,7 @@ public protocol Synchronizer: AnyObject {
/// Account balances from the given account index /// Account balances from the given account index
/// - Parameter account: the index of the account /// - Parameter account: the index of the account
/// - Returns: `AccountBalance`, struct that holds sapling and unshielded balances or `nil` when no account is associated with `account.index` /// - Returns: `AccountBalance`, struct that holds sapling and unshielded balances or `nil` when no account is associated with `account.index`
func getAccountBalance(account: Zip32Account) async throws -> AccountBalance? func getAccountBalance(accountIndex: Zip32AccountIndex) async throws -> AccountBalance?
/// Fetches the latest ZEC-USD exchange rate and updates `exchangeRateUSDSubject`. /// Fetches the latest ZEC-USD exchange rate and updates `exchangeRateUSDSubject`.
func refreshExchangeRateUSD() func refreshExchangeRateUSD()

View File

@ -52,38 +52,38 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
synchronizer.stop() synchronizer.stop()
} }
public func getSaplingAddress(account: Zip32Account, completion: @escaping (Result<SaplingAddress, Error>) -> Void) { public func getSaplingAddress(accountIndex: Zip32AccountIndex, completion: @escaping (Result<SaplingAddress, Error>) -> Void) {
AsyncToClosureGateway.executeThrowingAction(completion) { AsyncToClosureGateway.executeThrowingAction(completion) {
try await self.synchronizer.getSaplingAddress(account: account) try await self.synchronizer.getSaplingAddress(accountIndex: accountIndex)
} }
} }
public func getUnifiedAddress(account: Zip32Account, completion: @escaping (Result<UnifiedAddress, Error>) -> Void) { public func getUnifiedAddress(accountIndex: Zip32AccountIndex, completion: @escaping (Result<UnifiedAddress, Error>) -> Void) {
AsyncToClosureGateway.executeThrowingAction(completion) { AsyncToClosureGateway.executeThrowingAction(completion) {
try await self.synchronizer.getUnifiedAddress(account: account) try await self.synchronizer.getUnifiedAddress(accountIndex: accountIndex)
} }
} }
public func getTransparentAddress(account: Zip32Account, completion: @escaping (Result<TransparentAddress, Error>) -> Void) { public func getTransparentAddress(accountIndex: Zip32AccountIndex, completion: @escaping (Result<TransparentAddress, Error>) -> Void) {
AsyncToClosureGateway.executeThrowingAction(completion) { AsyncToClosureGateway.executeThrowingAction(completion) {
try await self.synchronizer.getTransparentAddress(account: account) try await self.synchronizer.getTransparentAddress(accountIndex: accountIndex)
} }
} }
public func proposeTransfer( public func proposeTransfer(
account: Zip32Account, accountIndex: Zip32AccountIndex,
recipient: Recipient, recipient: Recipient,
amount: Zatoshi, amount: Zatoshi,
memo: Memo?, memo: Memo?,
completion: @escaping (Result<Proposal, Error>) -> Void completion: @escaping (Result<Proposal, Error>) -> Void
) { ) {
AsyncToClosureGateway.executeThrowingAction(completion) { AsyncToClosureGateway.executeThrowingAction(completion) {
try await self.synchronizer.proposeTransfer(account: account, recipient: recipient, amount: amount, memo: memo) try await self.synchronizer.proposeTransfer(accountIndex: accountIndex, recipient: recipient, amount: amount, memo: memo)
} }
} }
public func proposeShielding( public func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
memo: Memo, memo: Memo,
transparentReceiver: TransparentAddress? = nil, transparentReceiver: TransparentAddress? = nil,
@ -91,7 +91,7 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
) { ) {
AsyncToClosureGateway.executeThrowingAction(completion) { AsyncToClosureGateway.executeThrowingAction(completion) {
try await self.synchronizer.proposeShielding( try await self.synchronizer.proposeShielding(
account: account, accountIndex: accountIndex,
shieldingThreshold: shieldingThreshold, shieldingThreshold: shieldingThreshold,
memo: memo, memo: memo,
transparentReceiver: transparentReceiver transparentReceiver: transparentReceiver
@ -188,9 +188,9 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
} }
} }
public func getAccountBalance(account: Zip32Account, completion: @escaping (Result<AccountBalance?, Error>) -> Void) { public func getAccountBalance(accountIndex: Zip32AccountIndex, completion: @escaping (Result<AccountBalance?, Error>) -> Void) {
AsyncToClosureGateway.executeThrowingAction(completion) { AsyncToClosureGateway.executeThrowingAction(completion) {
try await self.synchronizer.getAccountBalance(account: account) try await self.synchronizer.getAccountBalance(accountIndex: accountIndex)
} }
} }

View File

@ -51,56 +51,56 @@ extension CombineSDKSynchronizer: CombineSynchronizer {
synchronizer.stop() synchronizer.stop()
} }
public func getSaplingAddress(account: Zip32Account) -> SinglePublisher<SaplingAddress, Error> { public func getSaplingAddress(accountIndex: Zip32AccountIndex) -> SinglePublisher<SaplingAddress, Error> {
AsyncToCombineGateway.executeThrowingAction() { AsyncToCombineGateway.executeThrowingAction() {
try await self.synchronizer.getSaplingAddress(account: account) try await self.synchronizer.getSaplingAddress(accountIndex: accountIndex)
} }
} }
public func getUnifiedAddress(account: Zip32Account) -> SinglePublisher<UnifiedAddress, Error> { public func getUnifiedAddress(accountIndex: Zip32AccountIndex) -> SinglePublisher<UnifiedAddress, Error> {
AsyncToCombineGateway.executeThrowingAction() { AsyncToCombineGateway.executeThrowingAction() {
try await self.synchronizer.getUnifiedAddress(account: account) try await self.synchronizer.getUnifiedAddress(accountIndex: accountIndex)
} }
} }
public func getTransparentAddress(account: Zip32Account) -> SinglePublisher<TransparentAddress, Error> { public func getTransparentAddress(accountIndex: Zip32AccountIndex) -> SinglePublisher<TransparentAddress, Error> {
AsyncToCombineGateway.executeThrowingAction() { AsyncToCombineGateway.executeThrowingAction() {
try await self.synchronizer.getTransparentAddress(account: account) try await self.synchronizer.getTransparentAddress(accountIndex: accountIndex)
} }
} }
public func proposeTransfer( public func proposeTransfer(
account: Zip32Account, accountIndex: Zip32AccountIndex,
recipient: Recipient, recipient: Recipient,
amount: Zatoshi, amount: Zatoshi,
memo: Memo? memo: Memo?
) -> SinglePublisher<Proposal, Error> { ) -> SinglePublisher<Proposal, Error> {
AsyncToCombineGateway.executeThrowingAction() { AsyncToCombineGateway.executeThrowingAction() {
try await self.synchronizer.proposeTransfer(account: account, recipient: recipient, amount: amount, memo: memo) try await self.synchronizer.proposeTransfer(accountIndex: accountIndex, recipient: recipient, amount: amount, memo: memo)
} }
} }
public func proposefulfillingPaymentURI( public func proposefulfillingPaymentURI(
_ uri: String, _ uri: String,
account: Zip32Account accountIndex: Zip32AccountIndex
) -> SinglePublisher<Proposal, Error> { ) -> SinglePublisher<Proposal, Error> {
AsyncToCombineGateway.executeThrowingAction() { AsyncToCombineGateway.executeThrowingAction() {
try await self.synchronizer.proposefulfillingPaymentURI( try await self.synchronizer.proposefulfillingPaymentURI(
uri, uri,
account: account accountIndex: accountIndex
) )
} }
} }
public func proposeShielding( public func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
memo: Memo, memo: Memo,
transparentReceiver: TransparentAddress? = nil transparentReceiver: TransparentAddress? = nil
) -> SinglePublisher<Proposal?, Error> { ) -> SinglePublisher<Proposal?, Error> {
AsyncToCombineGateway.executeThrowingAction() { AsyncToCombineGateway.executeThrowingAction() {
try await self.synchronizer.proposeShielding( try await self.synchronizer.proposeShielding(
account: account, accountIndex: accountIndex,
shieldingThreshold: shieldingThreshold, shieldingThreshold: shieldingThreshold,
memo: memo, memo: memo,
transparentReceiver: transparentReceiver transparentReceiver: transparentReceiver
@ -190,9 +190,9 @@ extension CombineSDKSynchronizer: CombineSynchronizer {
} }
} }
public func getAccountBalance(account: Zip32Account) -> SinglePublisher<AccountBalance?, Error> { public func getAccountBalance(accountIndex: Zip32AccountIndex) -> SinglePublisher<AccountBalance?, Error> {
AsyncToCombineGateway.executeThrowingAction() { AsyncToCombineGateway.executeThrowingAction() {
try await self.synchronizer.getAccountBalance(account: account) try await self.synchronizer.getAccountBalance(accountIndex: accountIndex)
} }
} }

View File

@ -28,6 +28,9 @@ public class SDKSynchronizer: Synchronizer {
let metrics: SDKMetrics let metrics: SDKMetrics
public let logger: Logger public let logger: Logger
var tor: TorClient? var tor: TorClient?
// TODO: [#1512] Only one instance of hardcoded account index has been removed in deeper levels and moved here, needs to be resolved i 1512
// https://github.com/Electric-Coin-Company/zcash-swift-wallet-sdk/issues/1512
private var accountIndex = Zip32AccountIndex(0)
// Don't read this variable directly. Use `status` instead. And don't update this variable directly use `updateStatus()` methods instead. // Don't read this variable directly. Use `status` instead. And don't update this variable directly use `updateStatus()` methods instead.
private var underlyingStatus: GenericActor<InternalSyncStatus> private var underlyingStatus: GenericActor<InternalSyncStatus>
@ -265,7 +268,7 @@ public class SDKSynchronizer: Synchronizer {
// MARK: Synchronizer methods // MARK: Synchronizer methods
public func proposeTransfer(account: Zip32Account, recipient: Recipient, amount: Zatoshi, memo: Memo?) async throws -> Proposal { public func proposeTransfer(accountIndex: Zip32AccountIndex, recipient: Recipient, amount: Zatoshi, memo: Memo?) async throws -> Proposal {
try throwIfUnprepared() try throwIfUnprepared()
if case Recipient.transparent = recipient, memo != nil { if case Recipient.transparent = recipient, memo != nil {
@ -273,7 +276,7 @@ public class SDKSynchronizer: Synchronizer {
} }
let proposal = try await transactionEncoder.proposeTransfer( let proposal = try await transactionEncoder.proposeTransfer(
account: account, accountIndex: accountIndex,
recipient: recipient.stringEncoded, recipient: recipient.stringEncoded,
amount: amount, amount: amount,
memoBytes: memo?.asMemoBytes() memoBytes: memo?.asMemoBytes()
@ -283,7 +286,7 @@ public class SDKSynchronizer: Synchronizer {
} }
public func proposeShielding( public func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
memo: Memo, memo: Memo,
transparentReceiver: TransparentAddress? = nil transparentReceiver: TransparentAddress? = nil
@ -291,7 +294,7 @@ public class SDKSynchronizer: Synchronizer {
try throwIfUnprepared() try throwIfUnprepared()
return try await transactionEncoder.proposeShielding( return try await transactionEncoder.proposeShielding(
account: account, accountIndex: accountIndex,
shieldingThreshold: shieldingThreshold, shieldingThreshold: shieldingThreshold,
memoBytes: memo.asMemoBytes(), memoBytes: memo.asMemoBytes(),
transparentReceiver: transparentReceiver?.stringEncoded transparentReceiver: transparentReceiver?.stringEncoded
@ -300,13 +303,13 @@ public class SDKSynchronizer: Synchronizer {
public func proposefulfillingPaymentURI( public func proposefulfillingPaymentURI(
_ uri: String, _ uri: String,
account: Zip32Account accountIndex: Zip32AccountIndex
) async throws -> Proposal { ) async throws -> Proposal {
do { do {
try throwIfUnprepared() try throwIfUnprepared()
return try await transactionEncoder.proposeFulfillingPaymentFromURI( return try await transactionEncoder.proposeFulfillingPaymentFromURI(
uri, uri,
account: account accountIndex: accountIndex
) )
} catch ZcashError.rustCreateToAddress(let error) { } catch ZcashError.rustCreateToAddress(let error) {
throw ZcashError.rustProposeTransferFromURI(error) throw ZcashError.rustProposeTransferFromURI(error)
@ -394,9 +397,7 @@ public class SDKSynchronizer: Synchronizer {
try throwIfUnprepared() try throwIfUnprepared()
// let's see if there are funds to shield // let's see if there are funds to shield
let account = Zip32Account(Int32(spendingKey.account)) guard let tBalance = try await self.getAccountBalance(accountIndex: spendingKey.accountIndex)?.unshielded else {
guard let tBalance = try await self.getAccountBalance(account: account)?.unshielded else {
throw ZcashError.synchronizerSpendingKeyDoesNotBelongToTheWallet throw ZcashError.synchronizerSpendingKeyDoesNotBelongToTheWallet
} }
@ -406,7 +407,7 @@ public class SDKSynchronizer: Synchronizer {
} }
guard let proposal = try await transactionEncoder.proposeShielding( guard let proposal = try await transactionEncoder.proposeShielding(
account: account, accountIndex: spendingKey.accountIndex,
shieldingThreshold: shieldingThreshold, shieldingThreshold: shieldingThreshold,
memoBytes: memo.asMemoBytes(), memoBytes: memo.asMemoBytes(),
transparentReceiver: nil transparentReceiver: nil
@ -441,7 +442,7 @@ public class SDKSynchronizer: Synchronizer {
} }
let proposal = try await transactionEncoder.proposeTransfer( let proposal = try await transactionEncoder.proposeTransfer(
account: Zip32Account(Int32(spendingKey.account)), accountIndex: spendingKey.accountIndex,
recipient: recipient.stringEncoded, recipient: recipient.stringEncoded,
amount: zatoshi, amount: zatoshi,
memoBytes: memo?.asMemoBytes() memoBytes: memo?.asMemoBytes()
@ -510,9 +511,8 @@ public class SDKSynchronizer: Synchronizer {
return try await blockProcessor.refreshUTXOs(tAddress: address, startHeight: height) return try await blockProcessor.refreshUTXOs(tAddress: address, startHeight: height)
} }
// TODO: This is hardcoded Zip32Account for index 0, must be updated public func getAccountBalance(accountIndex: Zip32AccountIndex) async throws -> AccountBalance? {
public func getAccountBalance(account: Zip32Account = Zip32Account(0)) async throws -> AccountBalance? { try await initializer.rustBackend.getWalletSummary()?.accountBalances[accountIndex.index]
try await initializer.rustBackend.getWalletSummary()?.accountBalances[UInt32(account.index)]
} }
/// Fetches the latest ZEC-USD exchange rate. /// Fetches the latest ZEC-USD exchange rate.
@ -550,16 +550,16 @@ public class SDKSynchronizer: Synchronizer {
} }
} }
public func getUnifiedAddress(account: Zip32Account) async throws -> UnifiedAddress { public func getUnifiedAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress {
try await blockProcessor.getUnifiedAddress(account: account) try await blockProcessor.getUnifiedAddress(accountIndex: accountIndex)
} }
public func getSaplingAddress(account: Zip32Account) async throws -> SaplingAddress { public func getSaplingAddress(accountIndex: Zip32AccountIndex) async throws -> SaplingAddress {
try await blockProcessor.getSaplingAddress(account: account) try await blockProcessor.getSaplingAddress(accountIndex: accountIndex)
} }
public func getTransparentAddress(account: Zip32Account) async throws -> TransparentAddress { public func getTransparentAddress(accountIndex: Zip32AccountIndex) async throws -> TransparentAddress {
try await blockProcessor.getTransparentAddress(account: account) try await blockProcessor.getTransparentAddress(accountIndex: accountIndex)
} }
// MARK: Rewind // MARK: Rewind
@ -923,10 +923,10 @@ public class SDKSynchronizer: Synchronizer {
// MARK: notify state // MARK: notify state
private func snapshotState(status: InternalSyncStatus) async -> SynchronizerState { private func snapshotState(status: InternalSyncStatus, accountIndex: Zip32AccountIndex) async -> SynchronizerState {
await SynchronizerState( await SynchronizerState(
syncSessionID: syncSession.value, syncSessionID: syncSession.value,
accountBalance: try? await getAccountBalance(), accountBalance: try? await getAccountBalance(accountIndex: accountIndex),
internalSyncStatus: status, internalSyncStatus: status,
latestBlockHeight: latestBlocksDataProvider.latestBlockHeight latestBlockHeight: latestBlocksDataProvider.latestBlockHeight
) )
@ -951,7 +951,7 @@ public class SDKSynchronizer: Synchronizer {
if SessionTicker.live.isNewSyncSession(oldStatus, newStatus) { if SessionTicker.live.isNewSyncSession(oldStatus, newStatus) {
await self.syncSession.newSession(with: self.syncSessionIDGenerator) await self.syncSession.newSession(with: self.syncSessionIDGenerator)
} }
newState = await snapshotState(status: newStatus) newState = await snapshotState(status: newStatus, accountIndex: accountIndex)
} }
latestState = newState latestState = newState

View File

@ -17,14 +17,13 @@ public protocol KeyValidation {
} }
public protocol KeyDeriving { public protocol KeyDeriving {
/// Given the seed bytes tand the account index, return the UnifiedSpendingKey /// Given the seed bytes and ZIP 32 account index, return the corresponding UnifiedSpendingKey.
/// - Parameter seed: `[Uint8]` seed bytes /// - Parameter seed: `[Uint8]` seed bytes
/// - Parameter accountIndex: `Int32` with the account number /// - Parameter accountIndex: the ZIP 32 index of the account
/// - Throws: /// - Throws:
/// - `derivationToolInvalidAccount` if the `accountIndex` is invalid.
/// - some `ZcashError.rust*` error if the derivation fails. /// - some `ZcashError.rust*` error if the derivation fails.
/// - Returns a `UnifiedSpendingKey` /// - Returns a `UnifiedSpendingKey`
func deriveUnifiedSpendingKey(seed: [UInt8], accountIndex: Int32) throws -> UnifiedSpendingKey func deriveUnifiedSpendingKey(seed: [UInt8], accountIndex: Zip32AccountIndex) throws -> UnifiedSpendingKey
/// Given a spending key, return the associated viewing key. /// Given a spending key, return the associated viewing key.
/// - Parameter spendingKey: the `UnifiedSpendingKey` from which to derive the `UnifiedFullViewingKey` from. /// - Parameter spendingKey: the `UnifiedSpendingKey` from which to derive the `UnifiedFullViewingKey` from.
@ -59,7 +58,6 @@ public protocol KeyDeriving {
/// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context. /// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context.
/// - Parameter seed: `[Uint8]` seed bytes /// - Parameter seed: `[Uint8]` seed bytes
/// - Throws: /// - Throws:
/// - `derivationToolInvalidAccount` if the `accountIndex` is invalid.
/// - some `ZcashError.rust*` error if the derivation fails. /// - some `ZcashError.rust*` error if the derivation fails.
/// - Returns a `[Uint8]` /// - Returns a `[Uint8]`
static func deriveArbitraryWalletKey(contextString: [UInt8], seed: [UInt8]) throws -> [UInt8] static func deriveArbitraryWalletKey(contextString: [UInt8], seed: [UInt8]) throws -> [UInt8]
@ -68,12 +66,11 @@ public protocol KeyDeriving {
/// ///
/// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context. /// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context.
/// - Parameter seed: `[Uint8]` seed bytes /// - Parameter seed: `[Uint8]` seed bytes
/// - Parameter accountIndex: `Int32` with the account number /// - Parameter accountIndex: the ZIP 32 index of the account
/// - Throws: /// - Throws:
/// - `derivationToolInvalidAccount` if the `accountIndex` is invalid.
/// - some `ZcashError.rust*` error if the derivation fails. /// - some `ZcashError.rust*` error if the derivation fails.
/// - Returns a `[Uint8]` /// - Returns a `[Uint8]`
func deriveArbitraryAccountKey(contextString: [UInt8], seed: [UInt8], accountIndex: Int32) throws -> [UInt8] func deriveArbitraryAccountKey(contextString: [UInt8], seed: [UInt8], accountIndex: Zip32AccountIndex) throws -> [UInt8]
} }
public class DerivationTool: KeyDeriving { public class DerivationTool: KeyDeriving {
@ -104,19 +101,14 @@ public class DerivationTool: KeyDeriving {
/// Given a seed and a number of accounts, return the associated spending keys. /// Given a seed and a number of accounts, return the associated spending keys.
/// - Parameter seed: the seed from which to derive spending keys. /// - Parameter seed: the seed from which to derive spending keys.
/// - Parameter numberOfAccounts: the number of accounts to use. Multiple accounts are not fully /// - Parameter accountIndex: the ZIP 32 index of the account
/// supported so the default value of 1 is recommended.
/// - Returns: the spending keys that correspond to the seed, formatted as Strings. /// - Returns: the spending keys that correspond to the seed, formatted as Strings.
public func deriveUnifiedSpendingKey(seed: [UInt8], accountIndex: Int32) throws -> UnifiedSpendingKey { public func deriveUnifiedSpendingKey(seed: [UInt8], accountIndex: Zip32AccountIndex) throws -> UnifiedSpendingKey {
guard accountIndex >= 0 else { try backend.deriveUnifiedSpendingKey(from: seed, accountIndex: accountIndex)
throw ZcashError.derivationToolInvalidAccount
}
return try backend.deriveUnifiedSpendingKey(from: seed, accountIndex: accountIndex)
} }
public func receiverTypecodesFromUnifiedAddress(_ address: UnifiedAddress) throws -> [UnifiedAddress.ReceiverTypecodes] { public func receiverTypecodesFromUnifiedAddress(_ address: UnifiedAddress) throws -> [UnifiedAddress.ReceiverTypecodes] {
return try backend.receiverTypecodesOnUnifiedAddress(address.stringEncoded) try backend.receiverTypecodesOnUnifiedAddress(address.stringEncoded)
.map { UnifiedAddress.ReceiverTypecodes(typecode: $0) } .map { UnifiedAddress.ReceiverTypecodes(typecode: $0) }
} }
@ -130,28 +122,22 @@ public class DerivationTool: KeyDeriving {
/// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context. /// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context.
/// - Parameter seed: `[Uint8]` seed bytes /// - Parameter seed: `[Uint8]` seed bytes
/// - Throws: /// - Throws:
/// - `derivationToolInvalidAccount` if the `account` is invalid.
/// - some `ZcashError.rust*` error if the derivation fails. /// - some `ZcashError.rust*` error if the derivation fails.
/// - Returns a `[Uint8]` /// - Returns a `[Uint8]`
public static func deriveArbitraryWalletKey(contextString: [UInt8], seed: [UInt8]) throws -> [UInt8] { public static func deriveArbitraryWalletKey(contextString: [UInt8], seed: [UInt8]) throws -> [UInt8] {
return try ZcashKeyDerivationBackend.deriveArbitraryWalletKey(contextString: contextString, from: seed) try ZcashKeyDerivationBackend.deriveArbitraryWalletKey(contextString: contextString, from: seed)
} }
/// Derives and returns a ZIP 32 Arbitrary Key from the given seed at the account level. /// Derives and returns a ZIP 32 Arbitrary Key from the given seed at the account level.
/// ///
/// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context. /// - Parameter contextString: a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context.
/// - Parameter seed: `[Uint8]` seed bytes /// - Parameter seed: `[Uint8]` seed bytes
/// - Parameter accountIndex: `Int32` with the account number /// - Parameter accountIndex: the ZIP 32 index of the account
/// - Throws: /// - Throws:
/// - `derivationToolInvalidAccount` if the `account` is invalid.
/// - some `ZcashError.rust*` error if the derivation fails. /// - some `ZcashError.rust*` error if the derivation fails.
/// - Returns a `[Uint8]` /// - Returns a `[Uint8]`
public func deriveArbitraryAccountKey(contextString: [UInt8], seed: [UInt8], accountIndex: Int32) throws -> [UInt8] { public func deriveArbitraryAccountKey(contextString: [UInt8], seed: [UInt8], accountIndex: Zip32AccountIndex) throws -> [UInt8] {
guard accountIndex >= 0 else { try backend.deriveArbitraryAccountKey(contextString: contextString, from: seed, accountIndex: accountIndex)
throw ZcashError.derivationToolInvalidAccount
}
return try backend.deriveArbitraryAccountKey(contextString: contextString, from: seed, accountIndex: accountIndex)
} }
} }
@ -247,9 +233,9 @@ extension UnifiedFullViewingKey {
/// already validated by another function. only for internal use. Unless you are /// already validated by another function. only for internal use. Unless you are
/// constructing an address from a primitive function of the FFI, you probably /// constructing an address from a primitive function of the FFI, you probably
/// shouldn't be using this. /// shouldn't be using this.
init(validatedEncoding: String, account: UInt32) { init(validatedEncoding: String, accountIndex: Zip32AccountIndex) {
self.encoding = validatedEncoding self.encoding = validatedEncoding
self.account = account self.accountIndex = accountIndex
} }
} }

View File

@ -21,7 +21,7 @@ public enum TransactionEncoderError: Error {
protocol TransactionEncoder { protocol TransactionEncoder {
/// Creates a proposal for transferring funds to the given recipient. /// Creates a proposal for transferring funds to the given recipient.
/// ///
/// - Parameter account: the account from which to transfer funds. /// - Parameter accountIndex: the ZIP 32 index of the account from which to transfer funds.
/// - Parameter recipient: string containing the recipient's address. /// - Parameter recipient: string containing the recipient's address.
/// - Parameter amount: the amount to send in Zatoshi. /// - Parameter amount: the amount to send in Zatoshi.
/// - Parameter memoBytes: an optional memo to include as part of the proposal's transactions. Use `nil` when sending to transparent receivers otherwise the function will throw an error. /// - Parameter memoBytes: an optional memo to include as part of the proposal's transactions. Use `nil` when sending to transparent receivers otherwise the function will throw an error.
@ -29,7 +29,7 @@ protocol TransactionEncoder {
/// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws /// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws
/// `SynchronizerErrors.notPrepared`. /// `SynchronizerErrors.notPrepared`.
func proposeTransfer( func proposeTransfer(
account: Zip32Account, accountIndex: Zip32AccountIndex,
recipient: String, recipient: String,
amount: Zatoshi, amount: Zatoshi,
memoBytes: MemoBytes? memoBytes: MemoBytes?
@ -37,7 +37,7 @@ protocol TransactionEncoder {
/// Creates a proposal for shielding any transparent funds received by the given account. /// Creates a proposal for shielding any transparent funds received by the given account.
/// ///
/// - Parameter account: the account for which to shield funds. /// - Parameter accountIndex: the ZIP 32 index of the account from which to shield funds.
/// - Parameter shieldingThreshold: the minimum transparent balance required before a proposal will be created. /// - Parameter shieldingThreshold: the minimum transparent balance required before a proposal will be created.
/// - Parameter memoBytes: an optional memo to include as part of the proposal's transactions. /// - Parameter memoBytes: an optional memo to include as part of the proposal's transactions.
/// - Parameter transparentReceiver: a specific transparent receiver within the account /// - Parameter transparentReceiver: a specific transparent receiver within the account
@ -51,7 +51,7 @@ protocol TransactionEncoder {
/// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws /// If `prepare()` hasn't already been called since creation of the synchronizer instance or since the last wipe then this method throws
/// `SynchronizerErrors.notPrepared`. /// `SynchronizerErrors.notPrepared`.
func proposeShielding( func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
memoBytes: MemoBytes?, memoBytes: MemoBytes?,
transparentReceiver: String? transparentReceiver: String?
@ -84,7 +84,7 @@ protocol TransactionEncoder {
/// - Some `ZcashError.rust*` if the creation of transaction fails. /// - Some `ZcashError.rust*` if the creation of transaction fails.
func proposeFulfillingPaymentFromURI( func proposeFulfillingPaymentFromURI(
_ uri: String, _ uri: String,
account: Zip32Account accountIndex: Zip32AccountIndex
) async throws -> Proposal ) async throws -> Proposal
/// submits a transaction to the Zcash peer-to-peer network. /// submits a transaction to the Zcash peer-to-peer network.

View File

@ -56,13 +56,13 @@ class WalletTransactionEncoder: TransactionEncoder {
} }
func proposeTransfer( func proposeTransfer(
account: Zip32Account, accountIndex: Zip32AccountIndex,
recipient: String, recipient: String,
amount: Zatoshi, amount: Zatoshi,
memoBytes: MemoBytes? memoBytes: MemoBytes?
) async throws -> Proposal { ) async throws -> Proposal {
let proposal = try await rustBackend.proposeTransfer( let proposal = try await rustBackend.proposeTransfer(
account: account, accountIndex: accountIndex,
to: recipient, to: recipient,
value: amount.amount, value: amount.amount,
memo: memoBytes memo: memoBytes
@ -72,13 +72,13 @@ class WalletTransactionEncoder: TransactionEncoder {
} }
func proposeShielding( func proposeShielding(
account: Zip32Account, accountIndex: Zip32AccountIndex,
shieldingThreshold: Zatoshi, shieldingThreshold: Zatoshi,
memoBytes: MemoBytes?, memoBytes: MemoBytes?,
transparentReceiver: String? = nil transparentReceiver: String? = nil
) async throws -> Proposal? { ) async throws -> Proposal? {
guard let proposal = try await rustBackend.proposeShielding( guard let proposal = try await rustBackend.proposeShielding(
account: account, accountIndex: accountIndex,
memo: memoBytes, memo: memoBytes,
shieldingThreshold: shieldingThreshold, shieldingThreshold: shieldingThreshold,
transparentReceiver: transparentReceiver transparentReceiver: transparentReceiver
@ -89,11 +89,11 @@ class WalletTransactionEncoder: TransactionEncoder {
func proposeFulfillingPaymentFromURI( func proposeFulfillingPaymentFromURI(
_ uri: String, _ uri: String,
account: Zip32Account accountIndex: Zip32AccountIndex
) async throws -> Proposal { ) async throws -> Proposal {
let proposal = try await rustBackend.proposeTransferFromURI( let proposal = try await rustBackend.proposeTransferFromURI(
uri, uri,
account: account accountIndex: accountIndex
) )
return Proposal(inner: proposal) return Proposal(inner: proposal)
} }

View File

@ -113,7 +113,7 @@ class PaymentURIFulfillmentTests: ZcashTestCase {
do { do {
let proposal = try await coordinator.synchronizer.proposefulfillingPaymentURI( let proposal = try await coordinator.synchronizer.proposefulfillingPaymentURI(
paymentURI, paymentURI,
account: Account(0) accountIndex: Zip32AccountIndex(0)
) )
let transactions = try await coordinator.synchronizer.createProposedTransactions( let transactions = try await coordinator.synchronizer.createProposedTransactions(
@ -320,7 +320,7 @@ class PaymentURIFulfillmentTests: ZcashTestCase {
do { do {
_ = try await coordinator.synchronizer.proposefulfillingPaymentURI( _ = try await coordinator.synchronizer.proposefulfillingPaymentURI(
paymentURI, paymentURI,
account: Account(0) accountIndex: Zip32AccountIndex(0)
) )
XCTFail("`fulfillPaymentURI` should have failed") XCTFail("`fulfillPaymentURI` should have failed")

View File

@ -86,7 +86,7 @@ class ShieldFundsTests: ZcashTestCase {
/// verify that the shielded transactions are confirmed /// verify that the shielded transactions are confirmed
/// ///
func testShieldFunds() async throws { func testShieldFunds() async throws {
let account = Account(0) let accountIndex = Zip32AccountIndex(0)
// 1. load the dataset // 1. load the dataset
try coordinator.service.useDataset(from: "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/shield-funds/1631000.txt") try coordinator.service.useDataset(from: "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/shield-funds/1631000.txt")
@ -101,7 +101,7 @@ class ShieldFundsTests: ZcashTestCase {
var initialTotalBalance = Zatoshi(-1) var initialTotalBalance = Zatoshi(-1)
var initialVerifiedBalance = Zatoshi(-1) var initialVerifiedBalance = Zatoshi(-1)
var initialTransparentBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance(account: account)?.unshielded ?? .zero var initialTransparentBalance: Zatoshi = try await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex)?.unshielded ?? .zero
let utxo = try GetAddressUtxosReply(jsonString: let utxo = try GetAddressUtxosReply(jsonString:
""" """
@ -123,8 +123,8 @@ class ShieldFundsTests: ZcashTestCase {
do { do {
try await coordinator.sync( try await coordinator.sync(
completion: { synchronizer in completion: { synchronizer in
initialVerifiedBalance = try await synchronizer.getAccountBalance(account: account)?.saplingBalance.spendableValue ?? .zero initialVerifiedBalance = try await synchronizer.getAccountBalance(accountIndex: accountIndex)?.saplingBalance.spendableValue ?? .zero
initialTotalBalance = try await synchronizer.getAccountBalance(account: account)?.saplingBalance.total() ?? .zero initialTotalBalance = try await synchronizer.getAccountBalance(accountIndex: accountIndex)?.saplingBalance.total() ?? .zero
preTxExpectation.fulfill() preTxExpectation.fulfill()
shouldContinue = true shouldContinue = true
}, },
@ -144,7 +144,7 @@ class ShieldFundsTests: ZcashTestCase {
// at this point the balance should be all zeroes for transparent and shielded funds // at this point the balance should be all zeroes for transparent and shielded funds
XCTAssertEqual(initialTotalBalance, Zatoshi.zero) XCTAssertEqual(initialTotalBalance, Zatoshi.zero)
XCTAssertEqual(initialVerifiedBalance, Zatoshi.zero) XCTAssertEqual(initialVerifiedBalance, Zatoshi.zero)
initialTransparentBalance = (try? await coordinator.synchronizer.getAccountBalance(account: account))?.unshielded ?? .zero initialTransparentBalance = (try? await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex))?.unshielded ?? .zero
XCTAssertEqual(initialTransparentBalance, .zero) XCTAssertEqual(initialTransparentBalance, .zero)
@ -177,7 +177,7 @@ class ShieldFundsTests: ZcashTestCase {
// at this point the balance should be zero for shielded, then zero verified transparent funds // at this point the balance should be zero for shielded, then zero verified transparent funds
// and 10000 zatoshi of total (not verified) transparent funds. // and 10000 zatoshi of total (not verified) transparent funds.
let tFundsDetectedBalance = try await coordinator.synchronizer.getAccountBalance(account: account)?.unshielded ?? .zero let tFundsDetectedBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex)?.unshielded ?? .zero
XCTAssertEqual(tFundsDetectedBalance, Zatoshi(10000)) XCTAssertEqual(tFundsDetectedBalance, Zatoshi(10000))
@ -206,7 +206,7 @@ class ShieldFundsTests: ZcashTestCase {
await fulfillment(of: [tFundsConfirmationSyncExpectation], timeout: 5) await fulfillment(of: [tFundsConfirmationSyncExpectation], timeout: 5)
// the transparent funds should be 10000 zatoshis both total and verified // the transparent funds should be 10000 zatoshis both total and verified
let confirmedTFundsBalance = try await coordinator.synchronizer.getAccountBalance(account: account)?.unshielded ?? .zero let confirmedTFundsBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex)?.unshielded ?? .zero
XCTAssertEqual(confirmedTFundsBalance, Zatoshi(10000)) XCTAssertEqual(confirmedTFundsBalance, Zatoshi(10000))
@ -237,13 +237,13 @@ class ShieldFundsTests: ZcashTestCase {
guard shouldContinue else { return } guard shouldContinue else { return }
let postShieldingBalance = try await coordinator.synchronizer.getAccountBalance(account: account)?.unshielded ?? .zero let postShieldingBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex)?.unshielded ?? .zero
// when funds are shielded the UTXOs should be marked as spend and not shown on the balance. // when funds are shielded the UTXOs should be marked as spend and not shown on the balance.
// now balance should be zero shielded, zero transaparent. // now balance should be zero shielded, zero transaparent.
// verify that the balance has been marked as spent regardless of confirmation // verify that the balance has been marked as spent regardless of confirmation
// FIXME: [#720] this should be zero, https://github.com/zcash/ZcashLightClientKit/issues/720 // FIXME: [#720] this should be zero, https://github.com/zcash/ZcashLightClientKit/issues/720
XCTAssertEqual(postShieldingBalance, Zatoshi(10000)) XCTAssertEqual(postShieldingBalance, Zatoshi(10000))
var expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero var expectedBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex)?.saplingBalance.total() ?? .zero
XCTAssertEqual(expectedBalance, .zero) XCTAssertEqual(expectedBalance, .zero)
// 10. clear the UTXO from darksidewalletd's cache // 10. clear the UTXO from darksidewalletd's cache
@ -290,11 +290,11 @@ class ShieldFundsTests: ZcashTestCase {
// Now it should verify that the balance has been shielded. The resulting balance should be zero // Now it should verify that the balance has been shielded. The resulting balance should be zero
// transparent funds and `10000 - fee` total shielded funds, zero verified shielded funds. // transparent funds and `10000 - fee` total shielded funds, zero verified shielded funds.
let postShieldingShieldedBalance = try await coordinator.synchronizer.getAccountBalance(account: account)?.unshielded ?? .zero let postShieldingShieldedBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex)?.unshielded ?? .zero
XCTAssertEqual(postShieldingShieldedBalance, .zero) XCTAssertEqual(postShieldingShieldedBalance, .zero)
expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero expectedBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex)?.saplingBalance.total() ?? .zero
XCTAssertEqual(expectedBalance, Zatoshi(9000)) XCTAssertEqual(expectedBalance, Zatoshi(9000))
// 14. proceed confirm the shielded funds by staging ten more blocks // 14. proceed confirm the shielded funds by staging ten more blocks
@ -330,9 +330,9 @@ class ShieldFundsTests: ZcashTestCase {
XCTAssertNotNil(clearedTransaction) XCTAssertNotNil(clearedTransaction)
expectedBalance = try await coordinator.synchronizer.getAccountBalance()?.saplingBalance.total() ?? .zero expectedBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex)?.saplingBalance.total() ?? .zero
XCTAssertEqual(expectedBalance, Zatoshi(9000)) XCTAssertEqual(expectedBalance, Zatoshi(9000))
let postShieldingConfirmationShieldedBalance = try await coordinator.synchronizer.getAccountBalance(account: account)?.unshielded ?? .zero let postShieldingConfirmationShieldedBalance = try await coordinator.synchronizer.getAccountBalance(accountIndex: accountIndex)?.unshielded ?? .zero
XCTAssertEqual(postShieldingConfirmationShieldedBalance, .zero) XCTAssertEqual(postShieldingConfirmationShieldedBalance, .zero)
} }

View File

@ -184,14 +184,14 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
} }
func testGetSaplingAddressSucceed() { func testGetSaplingAddressSucceed() {
synchronizerMock.getSaplingAddressAccountClosure = { account in synchronizerMock.getSaplingAddressAccountIndexClosure = { accountIndex in
XCTAssertEqual(account, Account(3)) XCTAssertEqual(accountIndex, Zip32AccountIndex(3))
return self.data.saplingAddress return self.data.saplingAddress
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getSaplingAddress(account: Account(3)) { result in synchronizer.getSaplingAddress(accountIndex: Zip32AccountIndex(3)) { accountIndex in
switch result { switch result {
case let .success(address): case let .success(address):
XCTAssertEqual(address, self.data.saplingAddress) XCTAssertEqual(address, self.data.saplingAddress)
@ -205,13 +205,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
} }
func testGetSaplingAddressThrowsError() { func testGetSaplingAddressThrowsError() {
synchronizerMock.getSaplingAddressAccountClosure = { _ in synchronizerMock.getSaplingAddressAccountIndexClosure = { _ in
throw "Some error" throw "Some error"
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getSaplingAddress(account: Account(3)) { result in synchronizer.getSaplingAddress(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case .success: case .success:
XCTFail("Error should be thrown.") XCTFail("Error should be thrown.")
@ -224,14 +224,14 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
} }
func testGetUnifiedAddressSucceed() { func testGetUnifiedAddressSucceed() {
synchronizerMock.getUnifiedAddressAccountClosure = { account in synchronizerMock.getUnifiedAddressAccountIndexClosure = { accountIndex in
XCTAssertEqual(account, Account(3)) XCTAssertEqual(accountIndex, Zip32AccountIndex(3))
return self.data.unifiedAddress return self.data.unifiedAddress
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getUnifiedAddress(account: Account(3)) { result in synchronizer.getUnifiedAddress(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case let .success(address): case let .success(address):
XCTAssertEqual(address, self.data.unifiedAddress) XCTAssertEqual(address, self.data.unifiedAddress)
@ -245,13 +245,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
} }
func testGetUnifiedAddressThrowsError() { func testGetUnifiedAddressThrowsError() {
synchronizerMock.getUnifiedAddressAccountClosure = { _ in synchronizerMock.getUnifiedAddressAccountIndexClosure = { _ in
throw "Some error" throw "Some error"
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getUnifiedAddress(account: Account(3)) { result in synchronizer.getUnifiedAddress(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case .success: case .success:
XCTFail("Error should be thrown.") XCTFail("Error should be thrown.")
@ -264,14 +264,14 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
} }
func testGetTransparentAddressSucceed() { func testGetTransparentAddressSucceed() {
synchronizerMock.getTransparentAddressAccountClosure = { account in synchronizerMock.getTransparentAddressAccountIndexClosure = { accountIndex in
XCTAssertEqual(account, Account(3)) XCTAssertEqual(accountIndex, Zip32AccountIndex(3))
return self.data.transparentAddress return self.data.transparentAddress
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getTransparentAddress(account: Account(3)) { result in synchronizer.getTransparentAddress(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case let .success(address): case let .success(address):
XCTAssertEqual(address, self.data.transparentAddress) XCTAssertEqual(address, self.data.transparentAddress)
@ -285,13 +285,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
} }
func testGetTransparentAddressThrowsError() { func testGetTransparentAddressThrowsError() {
synchronizerMock.getTransparentAddressAccountClosure = { _ in synchronizerMock.getTransparentAddressAccountIndexClosure = { _ in
throw "Some error" throw "Some error"
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getTransparentAddress(account: Account(3)) { result in synchronizer.getTransparentAddress(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case .success: case .success:
XCTFail("Error should be thrown.") XCTFail("Error should be thrown.")
@ -640,14 +640,14 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
func testGetTransparentBalanceSucceed() { func testGetTransparentBalanceSucceed() {
let expectedBalance = AccountBalance(saplingBalance: .zero, orchardBalance: .zero, unshielded: Zatoshi(200)) let expectedBalance = AccountBalance(saplingBalance: .zero, orchardBalance: .zero, unshielded: Zatoshi(200))
synchronizerMock.getAccountBalanceAccountClosure = { receivedAccount in synchronizerMock.getAccountBalanceAccountIndexClosure = { receivedAccountIndex in
XCTAssertEqual(receivedAccount, Account(3)) XCTAssertEqual(receivedAccountIndex, Zip32AccountIndex(3))
return expectedBalance return expectedBalance
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getAccountBalance(account: Account(3)) { result in synchronizer.getAccountBalance(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case let .success(receivedBalance): case let .success(receivedBalance):
XCTAssertEqual(receivedBalance, expectedBalance) XCTAssertEqual(receivedBalance, expectedBalance)
@ -661,13 +661,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
} }
func testGetTransparentBalanceThrowsError() { func testGetTransparentBalanceThrowsError() {
synchronizerMock.getAccountBalanceAccountClosure = { _ in synchronizerMock.getAccountBalanceAccountIndexClosure = { _ in
throw "Some error" throw "Some error"
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getAccountBalance(account: Account(3)) { result in synchronizer.getAccountBalance(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case .success: case .success:
XCTFail("Error should be thrown.") XCTFail("Error should be thrown.")
@ -696,14 +696,14 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
unshielded: .zero unshielded: .zero
) )
synchronizerMock.getAccountBalanceAccountClosure = { receivedAccount in synchronizerMock.getAccountBalanceAccountIndexClosure = { receivedAccountIndex in
XCTAssertEqual(receivedAccount, Account(3)) XCTAssertEqual(receivedAccountIndex, Zip32AccountIndex(3))
return expectedBalance return expectedBalance
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getAccountBalance(account: Account(3)) { result in synchronizer.getAccountBalance(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case let .success(receivedBalance): case let .success(receivedBalance):
XCTAssertEqual(receivedBalance, expectedBalance) XCTAssertEqual(receivedBalance, expectedBalance)
@ -717,13 +717,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
} }
func testGetShieldedBalanceThrowsError() { func testGetShieldedBalanceThrowsError() {
synchronizerMock.getAccountBalanceAccountClosure = { _ in synchronizerMock.getAccountBalanceAccountIndexClosure = { _ in
throw "Some error" throw "Some error"
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getAccountBalance(account: Account(3)) { result in synchronizer.getAccountBalance(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case .success: case .success:
XCTFail("Error should be thrown.") XCTFail("Error should be thrown.")
@ -752,14 +752,14 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
unshielded: .zero unshielded: .zero
) )
synchronizerMock.getAccountBalanceAccountClosure = { receivedAccount in synchronizerMock.getAccountBalanceAccountIndexClosure = { receivedAccountIndex in
XCTAssertEqual(receivedAccount, Account(3)) XCTAssertEqual(receivedAccountIndex, Zip32AccountIndex(3))
return expectedBalance return expectedBalance
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getAccountBalance(account: Account(3)) { result in synchronizer.getAccountBalance(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case let .success(receivedBalance): case let .success(receivedBalance):
XCTAssertEqual(receivedBalance, expectedBalance) XCTAssertEqual(receivedBalance, expectedBalance)
@ -773,13 +773,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
} }
func testGetShieldedVerifiedBalanceThrowsError() { func testGetShieldedVerifiedBalanceThrowsError() {
synchronizerMock.getAccountBalanceAccountClosure = { _ in synchronizerMock.getAccountBalanceAccountIndexClosure = { _ in
throw "Some error" throw "Some error"
} }
let expectation = XCTestExpectation() let expectation = XCTestExpectation()
synchronizer.getAccountBalance(account: Account(3)) { result in synchronizer.getAccountBalance(accountIndex: Zip32AccountIndex(3)) { result in
switch result { switch result {
case .success: case .success:
XCTFail("Error should be thrown.") XCTFail("Error should be thrown.")

View File

@ -67,16 +67,16 @@ class DerivationToolMainnetTests: XCTestCase {
func testDeriveSpendingKeysFromSeed() throws { func testDeriveSpendingKeysFromSeed() throws {
let seedBytes = [UInt8](seedData) let seedBytes = [UInt8](seedData)
let spendingKey = try derivationTool.deriveUnifiedSpendingKey(seed: seedBytes, account: Account(0)) let spendingKey = try derivationTool.deriveUnifiedSpendingKey(seed: seedBytes, accountIndex: Zip32AccountIndex(0))
XCTAssertEqual(expectedSpendingKey, spendingKey) XCTAssertEqual(expectedSpendingKey, spendingKey)
} }
func testDeriveUnifiedSpendingKeyFromSeed() throws { func testDeriveUnifiedSpendingKeyFromSeed() throws {
let account = Account(0) let accountIndex = Zip32AccountIndex(0)
let seedBytes = [UInt8](seedData) let seedBytes = [UInt8](seedData)
_ = try derivationTool.deriveUnifiedSpendingKey(seed: seedBytes, account: account) _ = try derivationTool.deriveUnifiedSpendingKey(seed: seedBytes, accountIndex: accountIndex)
} }
func testGetTransparentAddressFromUA() throws { func testGetTransparentAddressFromUA() throws {
@ -108,7 +108,7 @@ class DerivationToolMainnetTests: XCTestCase {
let numberOfAccounts: Int = 10 let numberOfAccounts: Int = 10
var ufvks: [UnifiedFullViewingKey] = [] var ufvks: [UnifiedFullViewingKey] = []
for i in 0..<numberOfAccounts { for i in 0..<numberOfAccounts {
let spendingKey = try derivationTool.deriveUnifiedSpendingKey(seed: [UInt8](seedData), account: Account(i)) let spendingKey = try derivationTool.deriveUnifiedSpendingKey(seed: [UInt8](seedData), accountIndex: Zip32AccountIndex(UInt32(i)))
let viewingKey = try derivationTool.deriveUnifiedFullViewingKey(from: spendingKey) let viewingKey = try derivationTool.deriveUnifiedFullViewingKey(from: spendingKey)
ufvks.append(viewingKey) ufvks.append(viewingKey)
} }
@ -151,7 +151,7 @@ class DerivationToolMainnetTests: XCTestCase {
let contextString = [UInt8]("Zcash test vectors".utf8) let contextString = [UInt8]("Zcash test vectors".utf8)
let seed = Data(fromHexEncodedString: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")!.bytes let seed = Data(fromHexEncodedString: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")!.bytes
let expectedKey = Data(fromHexEncodedString: "bf60078362a09234fcbc6bf6c8a87bde9fc73776bf93f37adbcc439a85574a9a")!.bytes let expectedKey = Data(fromHexEncodedString: "bf60078362a09234fcbc6bf6c8a87bde9fc73776bf93f37adbcc439a85574a9a")!.bytes
let key = try DerivationTool(networkType: .mainnet).deriveArbitraryAccountKey(contextString: contextString, seed: seed, account: Account(0)) let key = try DerivationTool(networkType: .mainnet).deriveArbitraryAccountKey(contextString: contextString, seed: seed, accountIndex: Zip32AccountIndex(0))
XCTAssertEqual(key, expectedKey) XCTAssertEqual(key, expectedKey)
} }
} }

View File

@ -1289,19 +1289,21 @@ class SaplingParametersHandlerMock: SaplingParametersHandler {
// MARK: - handleIfNeeded // MARK: - handleIfNeeded
var handleIfNeededThrowableError: Error? var handleIfNeededAccountIndexThrowableError: Error?
var handleIfNeededCallsCount = 0 var handleIfNeededAccountIndexCallsCount = 0
var handleIfNeededCalled: Bool { var handleIfNeededAccountIndexCalled: Bool {
return handleIfNeededCallsCount > 0 return handleIfNeededAccountIndexCallsCount > 0
} }
var handleIfNeededClosure: (() async throws -> Void)? var handleIfNeededAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var handleIfNeededAccountIndexClosure: ((Zip32AccountIndex) async throws -> Void)?
func handleIfNeeded() async throws { func handleIfNeeded(accountIndex: Zip32AccountIndex) async throws {
if let error = handleIfNeededThrowableError { if let error = handleIfNeededAccountIndexThrowableError {
throw error throw error
} }
handleIfNeededCallsCount += 1 handleIfNeededAccountIndexCallsCount += 1
try await handleIfNeededClosure!() handleIfNeededAccountIndexReceivedAccountIndex = accountIndex
try await handleIfNeededAccountIndexClosure!(accountIndex)
} }
} }
@ -1406,121 +1408,121 @@ class SynchronizerMock: Synchronizer {
// MARK: - getSaplingAddress // MARK: - getSaplingAddress
var getSaplingAddressAccountThrowableError: Error? var getSaplingAddressAccountIndexThrowableError: Error?
var getSaplingAddressAccountCallsCount = 0 var getSaplingAddressAccountIndexCallsCount = 0
var getSaplingAddressAccountCalled: Bool { var getSaplingAddressAccountIndexCalled: Bool {
return getSaplingAddressAccountCallsCount > 0 return getSaplingAddressAccountIndexCallsCount > 0
} }
var getSaplingAddressAccountReceivedAccount: Account? var getSaplingAddressAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var getSaplingAddressAccountReturnValue: SaplingAddress! var getSaplingAddressAccountIndexReturnValue: SaplingAddress!
var getSaplingAddressAccountClosure: ((Account) async throws -> SaplingAddress)? var getSaplingAddressAccountIndexClosure: ((Zip32AccountIndex) async throws -> SaplingAddress)?
func getSaplingAddress(account: Account) async throws -> SaplingAddress { func getSaplingAddress(accountIndex: Zip32AccountIndex) async throws -> SaplingAddress {
if let error = getSaplingAddressAccountThrowableError { if let error = getSaplingAddressAccountIndexThrowableError {
throw error throw error
} }
getSaplingAddressAccountCallsCount += 1 getSaplingAddressAccountIndexCallsCount += 1
getSaplingAddressAccountReceivedAccount = account getSaplingAddressAccountIndexReceivedAccountIndex = accountIndex
if let closure = getSaplingAddressAccountClosure { if let closure = getSaplingAddressAccountIndexClosure {
return try await closure(account) return try await closure(accountIndex)
} else { } else {
return getSaplingAddressAccountReturnValue return getSaplingAddressAccountIndexReturnValue
} }
} }
// MARK: - getUnifiedAddress // MARK: - getUnifiedAddress
var getUnifiedAddressAccountThrowableError: Error? var getUnifiedAddressAccountIndexThrowableError: Error?
var getUnifiedAddressAccountCallsCount = 0 var getUnifiedAddressAccountIndexCallsCount = 0
var getUnifiedAddressAccountCalled: Bool { var getUnifiedAddressAccountIndexCalled: Bool {
return getUnifiedAddressAccountCallsCount > 0 return getUnifiedAddressAccountIndexCallsCount > 0
} }
var getUnifiedAddressAccountReceivedAccount: Account? var getUnifiedAddressAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var getUnifiedAddressAccountReturnValue: UnifiedAddress! var getUnifiedAddressAccountIndexReturnValue: UnifiedAddress!
var getUnifiedAddressAccountClosure: ((Account) async throws -> UnifiedAddress)? var getUnifiedAddressAccountIndexClosure: ((Zip32AccountIndex) async throws -> UnifiedAddress)?
func getUnifiedAddress(account: Account) async throws -> UnifiedAddress { func getUnifiedAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress {
if let error = getUnifiedAddressAccountThrowableError { if let error = getUnifiedAddressAccountIndexThrowableError {
throw error throw error
} }
getUnifiedAddressAccountCallsCount += 1 getUnifiedAddressAccountIndexCallsCount += 1
getUnifiedAddressAccountReceivedAccount = account getUnifiedAddressAccountIndexReceivedAccountIndex = accountIndex
if let closure = getUnifiedAddressAccountClosure { if let closure = getUnifiedAddressAccountIndexClosure {
return try await closure(account) return try await closure(accountIndex)
} else { } else {
return getUnifiedAddressAccountReturnValue return getUnifiedAddressAccountIndexReturnValue
} }
} }
// MARK: - getTransparentAddress // MARK: - getTransparentAddress
var getTransparentAddressAccountThrowableError: Error? var getTransparentAddressAccountIndexThrowableError: Error?
var getTransparentAddressAccountCallsCount = 0 var getTransparentAddressAccountIndexCallsCount = 0
var getTransparentAddressAccountCalled: Bool { var getTransparentAddressAccountIndexCalled: Bool {
return getTransparentAddressAccountCallsCount > 0 return getTransparentAddressAccountIndexCallsCount > 0
} }
var getTransparentAddressAccountReceivedAccount: Account? var getTransparentAddressAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var getTransparentAddressAccountReturnValue: TransparentAddress! var getTransparentAddressAccountIndexReturnValue: TransparentAddress!
var getTransparentAddressAccountClosure: ((Account) async throws -> TransparentAddress)? var getTransparentAddressAccountIndexClosure: ((Zip32AccountIndex) async throws -> TransparentAddress)?
func getTransparentAddress(account: Account) async throws -> TransparentAddress { func getTransparentAddress(accountIndex: Zip32AccountIndex) async throws -> TransparentAddress {
if let error = getTransparentAddressAccountThrowableError { if let error = getTransparentAddressAccountIndexThrowableError {
throw error throw error
} }
getTransparentAddressAccountCallsCount += 1 getTransparentAddressAccountIndexCallsCount += 1
getTransparentAddressAccountReceivedAccount = account getTransparentAddressAccountIndexReceivedAccountIndex = accountIndex
if let closure = getTransparentAddressAccountClosure { if let closure = getTransparentAddressAccountIndexClosure {
return try await closure(account) return try await closure(accountIndex)
} else { } else {
return getTransparentAddressAccountReturnValue return getTransparentAddressAccountIndexReturnValue
} }
} }
// MARK: - proposeTransfer // MARK: - proposeTransfer
var proposeTransferAccountRecipientAmountMemoThrowableError: Error? var proposeTransferAccountIndexRecipientAmountMemoThrowableError: Error?
var proposeTransferAccountRecipientAmountMemoCallsCount = 0 var proposeTransferAccountIndexRecipientAmountMemoCallsCount = 0
var proposeTransferAccountRecipientAmountMemoCalled: Bool { var proposeTransferAccountIndexRecipientAmountMemoCalled: Bool {
return proposeTransferAccountRecipientAmountMemoCallsCount > 0 return proposeTransferAccountIndexRecipientAmountMemoCallsCount > 0
} }
var proposeTransferAccountRecipientAmountMemoReceivedArguments: (account: Account, recipient: Recipient, amount: Zatoshi, memo: Memo?)? var proposeTransferAccountIndexRecipientAmountMemoReceivedArguments: (accountIndex: Zip32AccountIndex, recipient: Recipient, amount: Zatoshi, memo: Memo?)?
var proposeTransferAccountRecipientAmountMemoReturnValue: Proposal! var proposeTransferAccountIndexRecipientAmountMemoReturnValue: Proposal!
var proposeTransferAccountRecipientAmountMemoClosure: ((Account, Recipient, Zatoshi, Memo?) async throws -> Proposal)? var proposeTransferAccountIndexRecipientAmountMemoClosure: ((Zip32AccountIndex, Recipient, Zatoshi, Memo?) async throws -> Proposal)?
func proposeTransfer(account: Account, recipient: Recipient, amount: Zatoshi, memo: Memo?) async throws -> Proposal { func proposeTransfer(accountIndex: Zip32AccountIndex, recipient: Recipient, amount: Zatoshi, memo: Memo?) async throws -> Proposal {
if let error = proposeTransferAccountRecipientAmountMemoThrowableError { if let error = proposeTransferAccountIndexRecipientAmountMemoThrowableError {
throw error throw error
} }
proposeTransferAccountRecipientAmountMemoCallsCount += 1 proposeTransferAccountIndexRecipientAmountMemoCallsCount += 1
proposeTransferAccountRecipientAmountMemoReceivedArguments = (account: account, recipient: recipient, amount: amount, memo: memo) proposeTransferAccountIndexRecipientAmountMemoReceivedArguments = (accountIndex: accountIndex, recipient: recipient, amount: amount, memo: memo)
if let closure = proposeTransferAccountRecipientAmountMemoClosure { if let closure = proposeTransferAccountIndexRecipientAmountMemoClosure {
return try await closure(account, recipient, amount, memo) return try await closure(accountIndex, recipient, amount, memo)
} else { } else {
return proposeTransferAccountRecipientAmountMemoReturnValue return proposeTransferAccountIndexRecipientAmountMemoReturnValue
} }
} }
// MARK: - proposeShielding // MARK: - proposeShielding
var proposeShieldingAccountShieldingThresholdMemoTransparentReceiverThrowableError: Error? var proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverThrowableError: Error?
var proposeShieldingAccountShieldingThresholdMemoTransparentReceiverCallsCount = 0 var proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverCallsCount = 0
var proposeShieldingAccountShieldingThresholdMemoTransparentReceiverCalled: Bool { var proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverCalled: Bool {
return proposeShieldingAccountShieldingThresholdMemoTransparentReceiverCallsCount > 0 return proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverCallsCount > 0
} }
var proposeShieldingAccountShieldingThresholdMemoTransparentReceiverReceivedArguments: (account: Account, shieldingThreshold: Zatoshi, memo: Memo, transparentReceiver: TransparentAddress?)? var proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverReceivedArguments: (accountIndex: Zip32AccountIndex, shieldingThreshold: Zatoshi, memo: Memo, transparentReceiver: TransparentAddress?)?
var proposeShieldingAccountShieldingThresholdMemoTransparentReceiverReturnValue: Proposal? var proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverReturnValue: Proposal?
var proposeShieldingAccountShieldingThresholdMemoTransparentReceiverClosure: ((Account, Zatoshi, Memo, TransparentAddress?) async throws -> Proposal?)? var proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverClosure: ((Zip32AccountIndex, Zatoshi, Memo, TransparentAddress?) async throws -> Proposal?)?
func proposeShielding(account: Account, shieldingThreshold: Zatoshi, memo: Memo, transparentReceiver: TransparentAddress?) async throws -> Proposal? { func proposeShielding(accountIndex: Zip32AccountIndex, shieldingThreshold: Zatoshi, memo: Memo, transparentReceiver: TransparentAddress?) async throws -> Proposal? {
if let error = proposeShieldingAccountShieldingThresholdMemoTransparentReceiverThrowableError { if let error = proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverThrowableError {
throw error throw error
} }
proposeShieldingAccountShieldingThresholdMemoTransparentReceiverCallsCount += 1 proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverCallsCount += 1
proposeShieldingAccountShieldingThresholdMemoTransparentReceiverReceivedArguments = (account: account, shieldingThreshold: shieldingThreshold, memo: memo, transparentReceiver: transparentReceiver) proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverReceivedArguments = (accountIndex: accountIndex, shieldingThreshold: shieldingThreshold, memo: memo, transparentReceiver: transparentReceiver)
if let closure = proposeShieldingAccountShieldingThresholdMemoTransparentReceiverClosure { if let closure = proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverClosure {
return try await closure(account, shieldingThreshold, memo, transparentReceiver) return try await closure(accountIndex, shieldingThreshold, memo, transparentReceiver)
} else { } else {
return proposeShieldingAccountShieldingThresholdMemoTransparentReceiverReturnValue return proposeShieldingAccountIndexShieldingThresholdMemoTransparentReceiverReturnValue
} }
} }
@ -1574,25 +1576,25 @@ class SynchronizerMock: Synchronizer {
// MARK: - proposefulfillingPaymentURI // MARK: - proposefulfillingPaymentURI
var proposefulfillingPaymentURIAccountThrowableError: Error? var proposefulfillingPaymentURIAccountIndexThrowableError: Error?
var proposefulfillingPaymentURIAccountCallsCount = 0 var proposefulfillingPaymentURIAccountIndexCallsCount = 0
var proposefulfillingPaymentURIAccountCalled: Bool { var proposefulfillingPaymentURIAccountIndexCalled: Bool {
return proposefulfillingPaymentURIAccountCallsCount > 0 return proposefulfillingPaymentURIAccountIndexCallsCount > 0
} }
var proposefulfillingPaymentURIAccountReceivedArguments: (uri: String, account: Account)? var proposefulfillingPaymentURIAccountIndexReceivedArguments: (uri: String, accountIndex: Zip32AccountIndex)?
var proposefulfillingPaymentURIAccountReturnValue: Proposal! var proposefulfillingPaymentURIAccountIndexReturnValue: Proposal!
var proposefulfillingPaymentURIAccountClosure: ((String, Account) async throws -> Proposal)? var proposefulfillingPaymentURIAccountIndexClosure: ((String, Zip32AccountIndex) async throws -> Proposal)?
func proposefulfillingPaymentURI(_ uri: String, account: Account) async throws -> Proposal { func proposefulfillingPaymentURI(_ uri: String, accountIndex: Zip32AccountIndex) async throws -> Proposal {
if let error = proposefulfillingPaymentURIAccountThrowableError { if let error = proposefulfillingPaymentURIAccountIndexThrowableError {
throw error throw error
} }
proposefulfillingPaymentURIAccountCallsCount += 1 proposefulfillingPaymentURIAccountIndexCallsCount += 1
proposefulfillingPaymentURIAccountReceivedArguments = (uri: uri, account: account) proposefulfillingPaymentURIAccountIndexReceivedArguments = (uri: uri, accountIndex: accountIndex)
if let closure = proposefulfillingPaymentURIAccountClosure { if let closure = proposefulfillingPaymentURIAccountIndexClosure {
return try await closure(uri, account) return try await closure(uri, accountIndex)
} else { } else {
return proposefulfillingPaymentURIAccountReturnValue return proposefulfillingPaymentURIAccountIndexReturnValue
} }
} }
@ -1800,25 +1802,25 @@ class SynchronizerMock: Synchronizer {
// MARK: - getAccountBalance // MARK: - getAccountBalance
var getAccountBalanceAccountThrowableError: Error? var getAccountBalanceAccountIndexThrowableError: Error?
var getAccountBalanceAccountCallsCount = 0 var getAccountBalanceAccountIndexCallsCount = 0
var getAccountBalanceAccountCalled: Bool { var getAccountBalanceAccountIndexCalled: Bool {
return getAccountBalanceAccountCallsCount > 0 return getAccountBalanceAccountIndexCallsCount > 0
} }
var getAccountBalanceAccountReceivedAccount: Account? var getAccountBalanceAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var getAccountBalanceAccountReturnValue: AccountBalance? var getAccountBalanceAccountIndexReturnValue: AccountBalance?
var getAccountBalanceAccountClosure: ((Account) async throws -> AccountBalance?)? var getAccountBalanceAccountIndexClosure: ((Zip32AccountIndex) async throws -> AccountBalance?)?
func getAccountBalance(account: Account) async throws -> AccountBalance? { func getAccountBalance(accountIndex: Zip32AccountIndex) async throws -> AccountBalance? {
if let error = getAccountBalanceAccountThrowableError { if let error = getAccountBalanceAccountIndexThrowableError {
throw error throw error
} }
getAccountBalanceAccountCallsCount += 1 getAccountBalanceAccountIndexCallsCount += 1
getAccountBalanceAccountReceivedAccount = account getAccountBalanceAccountIndexReceivedAccountIndex = accountIndex
if let closure = getAccountBalanceAccountClosure { if let closure = getAccountBalanceAccountIndexClosure {
return try await closure(account) return try await closure(accountIndex)
} else { } else {
return getAccountBalanceAccountReturnValue return getAccountBalanceAccountIndexReturnValue
} }
} }
@ -2425,10 +2427,10 @@ class ZcashRustBackendWeldingMock: ZcashRustBackendWelding {
var listAccountsCalled: Bool { var listAccountsCalled: Bool {
return listAccountsCallsCount > 0 return listAccountsCallsCount > 0
} }
var listAccountsReturnValue: [Account]! var listAccountsReturnValue: [Zip32AccountIndex]!
var listAccountsClosure: (() async throws -> [Account])? var listAccountsClosure: (() async throws -> [Zip32AccountIndex])?
func listAccounts() async throws -> [Account] { func listAccounts() async throws -> [Zip32AccountIndex] {
if let error = listAccountsThrowableError { if let error = listAccountsThrowableError {
throw error throw error
} }
@ -2509,49 +2511,49 @@ class ZcashRustBackendWeldingMock: ZcashRustBackendWelding {
// MARK: - getCurrentAddress // MARK: - getCurrentAddress
var getCurrentAddressAccountThrowableError: Error? var getCurrentAddressAccountIndexThrowableError: Error?
var getCurrentAddressAccountCallsCount = 0 var getCurrentAddressAccountIndexCallsCount = 0
var getCurrentAddressAccountCalled: Bool { var getCurrentAddressAccountIndexCalled: Bool {
return getCurrentAddressAccountCallsCount > 0 return getCurrentAddressAccountIndexCallsCount > 0
} }
var getCurrentAddressAccountReceivedAccount: Account? var getCurrentAddressAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var getCurrentAddressAccountReturnValue: UnifiedAddress! var getCurrentAddressAccountIndexReturnValue: UnifiedAddress!
var getCurrentAddressAccountClosure: ((Account) async throws -> UnifiedAddress)? var getCurrentAddressAccountIndexClosure: ((Zip32AccountIndex) async throws -> UnifiedAddress)?
func getCurrentAddress(account: Account) async throws -> UnifiedAddress { func getCurrentAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress {
if let error = getCurrentAddressAccountThrowableError { if let error = getCurrentAddressAccountIndexThrowableError {
throw error throw error
} }
getCurrentAddressAccountCallsCount += 1 getCurrentAddressAccountIndexCallsCount += 1
getCurrentAddressAccountReceivedAccount = account getCurrentAddressAccountIndexReceivedAccountIndex = accountIndex
if let closure = getCurrentAddressAccountClosure { if let closure = getCurrentAddressAccountIndexClosure {
return try await closure(account) return try await closure(accountIndex)
} else { } else {
return getCurrentAddressAccountReturnValue return getCurrentAddressAccountIndexReturnValue
} }
} }
// MARK: - getNextAvailableAddress // MARK: - getNextAvailableAddress
var getNextAvailableAddressAccountThrowableError: Error? var getNextAvailableAddressAccountIndexThrowableError: Error?
var getNextAvailableAddressAccountCallsCount = 0 var getNextAvailableAddressAccountIndexCallsCount = 0
var getNextAvailableAddressAccountCalled: Bool { var getNextAvailableAddressAccountIndexCalled: Bool {
return getNextAvailableAddressAccountCallsCount > 0 return getNextAvailableAddressAccountIndexCallsCount > 0
} }
var getNextAvailableAddressAccountReceivedAccount: Account? var getNextAvailableAddressAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var getNextAvailableAddressAccountReturnValue: UnifiedAddress! var getNextAvailableAddressAccountIndexReturnValue: UnifiedAddress!
var getNextAvailableAddressAccountClosure: ((Account) async throws -> UnifiedAddress)? var getNextAvailableAddressAccountIndexClosure: ((Zip32AccountIndex) async throws -> UnifiedAddress)?
func getNextAvailableAddress(account: Account) async throws -> UnifiedAddress { func getNextAvailableAddress(accountIndex: Zip32AccountIndex) async throws -> UnifiedAddress {
if let error = getNextAvailableAddressAccountThrowableError { if let error = getNextAvailableAddressAccountIndexThrowableError {
throw error throw error
} }
getNextAvailableAddressAccountCallsCount += 1 getNextAvailableAddressAccountIndexCallsCount += 1
getNextAvailableAddressAccountReceivedAccount = account getNextAvailableAddressAccountIndexReceivedAccountIndex = accountIndex
if let closure = getNextAvailableAddressAccountClosure { if let closure = getNextAvailableAddressAccountIndexClosure {
return try await closure(account) return try await closure(accountIndex)
} else { } else {
return getNextAvailableAddressAccountReturnValue return getNextAvailableAddressAccountIndexReturnValue
} }
} }
@ -2581,25 +2583,25 @@ class ZcashRustBackendWeldingMock: ZcashRustBackendWelding {
// MARK: - getTransparentBalance // MARK: - getTransparentBalance
var getTransparentBalanceAccountThrowableError: Error? var getTransparentBalanceAccountIndexThrowableError: Error?
var getTransparentBalanceAccountCallsCount = 0 var getTransparentBalanceAccountIndexCallsCount = 0
var getTransparentBalanceAccountCalled: Bool { var getTransparentBalanceAccountIndexCalled: Bool {
return getTransparentBalanceAccountCallsCount > 0 return getTransparentBalanceAccountIndexCallsCount > 0
} }
var getTransparentBalanceAccountReceivedAccount: Account? var getTransparentBalanceAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var getTransparentBalanceAccountReturnValue: Int64! var getTransparentBalanceAccountIndexReturnValue: Int64!
var getTransparentBalanceAccountClosure: ((Account) async throws -> Int64)? var getTransparentBalanceAccountIndexClosure: ((Zip32AccountIndex) async throws -> Int64)?
func getTransparentBalance(account: Account) async throws -> Int64 { func getTransparentBalance(accountIndex: Zip32AccountIndex) async throws -> Int64 {
if let error = getTransparentBalanceAccountThrowableError { if let error = getTransparentBalanceAccountIndexThrowableError {
throw error throw error
} }
getTransparentBalanceAccountCallsCount += 1 getTransparentBalanceAccountIndexCallsCount += 1
getTransparentBalanceAccountReceivedAccount = account getTransparentBalanceAccountIndexReceivedAccountIndex = accountIndex
if let closure = getTransparentBalanceAccountClosure { if let closure = getTransparentBalanceAccountIndexClosure {
return try await closure(account) return try await closure(accountIndex)
} else { } else {
return getTransparentBalanceAccountReturnValue return getTransparentBalanceAccountIndexReturnValue
} }
} }
@ -2629,49 +2631,49 @@ class ZcashRustBackendWeldingMock: ZcashRustBackendWelding {
// MARK: - listTransparentReceivers // MARK: - listTransparentReceivers
var listTransparentReceiversAccountThrowableError: Error? var listTransparentReceiversAccountIndexThrowableError: Error?
var listTransparentReceiversAccountCallsCount = 0 var listTransparentReceiversAccountIndexCallsCount = 0
var listTransparentReceiversAccountCalled: Bool { var listTransparentReceiversAccountIndexCalled: Bool {
return listTransparentReceiversAccountCallsCount > 0 return listTransparentReceiversAccountIndexCallsCount > 0
} }
var listTransparentReceiversAccountReceivedAccount: Account? var listTransparentReceiversAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var listTransparentReceiversAccountReturnValue: [TransparentAddress]! var listTransparentReceiversAccountIndexReturnValue: [TransparentAddress]!
var listTransparentReceiversAccountClosure: ((Account) async throws -> [TransparentAddress])? var listTransparentReceiversAccountIndexClosure: ((Zip32AccountIndex) async throws -> [TransparentAddress])?
func listTransparentReceivers(account: Account) async throws -> [TransparentAddress] { func listTransparentReceivers(accountIndex: Zip32AccountIndex) async throws -> [TransparentAddress] {
if let error = listTransparentReceiversAccountThrowableError { if let error = listTransparentReceiversAccountIndexThrowableError {
throw error throw error
} }
listTransparentReceiversAccountCallsCount += 1 listTransparentReceiversAccountIndexCallsCount += 1
listTransparentReceiversAccountReceivedAccount = account listTransparentReceiversAccountIndexReceivedAccountIndex = accountIndex
if let closure = listTransparentReceiversAccountClosure { if let closure = listTransparentReceiversAccountIndexClosure {
return try await closure(account) return try await closure(accountIndex)
} else { } else {
return listTransparentReceiversAccountReturnValue return listTransparentReceiversAccountIndexReturnValue
} }
} }
// MARK: - getVerifiedTransparentBalance // MARK: - getVerifiedTransparentBalance
var getVerifiedTransparentBalanceAccountThrowableError: Error? var getVerifiedTransparentBalanceAccountIndexThrowableError: Error?
var getVerifiedTransparentBalanceAccountCallsCount = 0 var getVerifiedTransparentBalanceAccountIndexCallsCount = 0
var getVerifiedTransparentBalanceAccountCalled: Bool { var getVerifiedTransparentBalanceAccountIndexCalled: Bool {
return getVerifiedTransparentBalanceAccountCallsCount > 0 return getVerifiedTransparentBalanceAccountIndexCallsCount > 0
} }
var getVerifiedTransparentBalanceAccountReceivedAccount: Account? var getVerifiedTransparentBalanceAccountIndexReceivedAccountIndex: Zip32AccountIndex?
var getVerifiedTransparentBalanceAccountReturnValue: Int64! var getVerifiedTransparentBalanceAccountIndexReturnValue: Int64!
var getVerifiedTransparentBalanceAccountClosure: ((Account) async throws -> Int64)? var getVerifiedTransparentBalanceAccountIndexClosure: ((Zip32AccountIndex) async throws -> Int64)?
func getVerifiedTransparentBalance(account: Account) async throws -> Int64 { func getVerifiedTransparentBalance(accountIndex: Zip32AccountIndex) async throws -> Int64 {
if let error = getVerifiedTransparentBalanceAccountThrowableError { if let error = getVerifiedTransparentBalanceAccountIndexThrowableError {
throw error throw error
} }
getVerifiedTransparentBalanceAccountCallsCount += 1 getVerifiedTransparentBalanceAccountIndexCallsCount += 1
getVerifiedTransparentBalanceAccountReceivedAccount = account getVerifiedTransparentBalanceAccountIndexReceivedAccountIndex = accountIndex
if let closure = getVerifiedTransparentBalanceAccountClosure { if let closure = getVerifiedTransparentBalanceAccountIndexClosure {
return try await closure(account) return try await closure(accountIndex)
} else { } else {
return getVerifiedTransparentBalanceAccountReturnValue return getVerifiedTransparentBalanceAccountIndexReturnValue
} }
} }
@ -2908,73 +2910,73 @@ class ZcashRustBackendWeldingMock: ZcashRustBackendWelding {
// MARK: - proposeTransfer // MARK: - proposeTransfer
var proposeTransferAccountToValueMemoThrowableError: Error? var proposeTransferAccountIndexToValueMemoThrowableError: Error?
var proposeTransferAccountToValueMemoCallsCount = 0 var proposeTransferAccountIndexToValueMemoCallsCount = 0
var proposeTransferAccountToValueMemoCalled: Bool { var proposeTransferAccountIndexToValueMemoCalled: Bool {
return proposeTransferAccountToValueMemoCallsCount > 0 return proposeTransferAccountIndexToValueMemoCallsCount > 0
} }
var proposeTransferAccountToValueMemoReceivedArguments: (account: Account, address: String, value: Int64, memo: MemoBytes?)? var proposeTransferAccountIndexToValueMemoReceivedArguments: (accountIndex: Zip32AccountIndex, address: String, value: Int64, memo: MemoBytes?)?
var proposeTransferAccountToValueMemoReturnValue: FfiProposal! var proposeTransferAccountIndexToValueMemoReturnValue: FfiProposal!
var proposeTransferAccountToValueMemoClosure: ((Account, String, Int64, MemoBytes?) async throws -> FfiProposal)? var proposeTransferAccountIndexToValueMemoClosure: ((Zip32AccountIndex, String, Int64, MemoBytes?) async throws -> FfiProposal)?
func proposeTransfer(account: Account, to address: String, value: Int64, memo: MemoBytes?) async throws -> FfiProposal { func proposeTransfer(accountIndex: Zip32AccountIndex, to address: String, value: Int64, memo: MemoBytes?) async throws -> FfiProposal {
if let error = proposeTransferAccountToValueMemoThrowableError { if let error = proposeTransferAccountIndexToValueMemoThrowableError {
throw error throw error
} }
proposeTransferAccountToValueMemoCallsCount += 1 proposeTransferAccountIndexToValueMemoCallsCount += 1
proposeTransferAccountToValueMemoReceivedArguments = (account: account, address: address, value: value, memo: memo) proposeTransferAccountIndexToValueMemoReceivedArguments = (accountIndex: accountIndex, address: address, value: value, memo: memo)
if let closure = proposeTransferAccountToValueMemoClosure { if let closure = proposeTransferAccountIndexToValueMemoClosure {
return try await closure(account, address, value, memo) return try await closure(accountIndex, address, value, memo)
} else { } else {
return proposeTransferAccountToValueMemoReturnValue return proposeTransferAccountIndexToValueMemoReturnValue
} }
} }
// MARK: - proposeTransferFromURI // MARK: - proposeTransferFromURI
var proposeTransferFromURIAccountThrowableError: Error? var proposeTransferFromURIAccountIndexThrowableError: Error?
var proposeTransferFromURIAccountCallsCount = 0 var proposeTransferFromURIAccountIndexCallsCount = 0
var proposeTransferFromURIAccountCalled: Bool { var proposeTransferFromURIAccountIndexCalled: Bool {
return proposeTransferFromURIAccountCallsCount > 0 return proposeTransferFromURIAccountIndexCallsCount > 0
} }
var proposeTransferFromURIAccountReceivedArguments: (uri: String, account: Account)? var proposeTransferFromURIAccountIndexReceivedArguments: (uri: String, accountIndex: Zip32AccountIndex)?
var proposeTransferFromURIAccountReturnValue: FfiProposal! var proposeTransferFromURIAccountIndexReturnValue: FfiProposal!
var proposeTransferFromURIAccountClosure: ((String, Account) async throws -> FfiProposal)? var proposeTransferFromURIAccountIndexClosure: ((String, Zip32AccountIndex) async throws -> FfiProposal)?
func proposeTransferFromURI(_ uri: String, account: Account) async throws -> FfiProposal { func proposeTransferFromURI(_ uri: String, accountIndex: Zip32AccountIndex) async throws -> FfiProposal {
if let error = proposeTransferFromURIAccountThrowableError { if let error = proposeTransferFromURIAccountIndexThrowableError {
throw error throw error
} }
proposeTransferFromURIAccountCallsCount += 1 proposeTransferFromURIAccountIndexCallsCount += 1
proposeTransferFromURIAccountReceivedArguments = (uri: uri, account: account) proposeTransferFromURIAccountIndexReceivedArguments = (uri: uri, accountIndex: accountIndex)
if let closure = proposeTransferFromURIAccountClosure { if let closure = proposeTransferFromURIAccountIndexClosure {
return try await closure(uri, account) return try await closure(uri, accountIndex)
} else { } else {
return proposeTransferFromURIAccountReturnValue return proposeTransferFromURIAccountIndexReturnValue
} }
} }
// MARK: - proposeShielding // MARK: - proposeShielding
var proposeShieldingAccountMemoShieldingThresholdTransparentReceiverThrowableError: Error? var proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverThrowableError: Error?
var proposeShieldingAccountMemoShieldingThresholdTransparentReceiverCallsCount = 0 var proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverCallsCount = 0
var proposeShieldingAccountMemoShieldingThresholdTransparentReceiverCalled: Bool { var proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverCalled: Bool {
return proposeShieldingAccountMemoShieldingThresholdTransparentReceiverCallsCount > 0 return proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverCallsCount > 0
} }
var proposeShieldingAccountMemoShieldingThresholdTransparentReceiverReceivedArguments: (account: Account, memo: MemoBytes?, shieldingThreshold: Zatoshi, transparentReceiver: String?)? var proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverReceivedArguments: (accountIndex: Zip32AccountIndex, memo: MemoBytes?, shieldingThreshold: Zatoshi, transparentReceiver: String?)?
var proposeShieldingAccountMemoShieldingThresholdTransparentReceiverReturnValue: FfiProposal? var proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverReturnValue: FfiProposal?
var proposeShieldingAccountMemoShieldingThresholdTransparentReceiverClosure: ((Account, MemoBytes?, Zatoshi, String?) async throws -> FfiProposal?)? var proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverClosure: ((Zip32AccountIndex, MemoBytes?, Zatoshi, String?) async throws -> FfiProposal?)?
func proposeShielding(account: Account, memo: MemoBytes?, shieldingThreshold: Zatoshi, transparentReceiver: String?) async throws -> FfiProposal? { func proposeShielding(accountIndex: Zip32AccountIndex, memo: MemoBytes?, shieldingThreshold: Zatoshi, transparentReceiver: String?) async throws -> FfiProposal? {
if let error = proposeShieldingAccountMemoShieldingThresholdTransparentReceiverThrowableError { if let error = proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverThrowableError {
throw error throw error
} }
proposeShieldingAccountMemoShieldingThresholdTransparentReceiverCallsCount += 1 proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverCallsCount += 1
proposeShieldingAccountMemoShieldingThresholdTransparentReceiverReceivedArguments = (account: account, memo: memo, shieldingThreshold: shieldingThreshold, transparentReceiver: transparentReceiver) proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverReceivedArguments = (accountIndex: accountIndex, memo: memo, shieldingThreshold: shieldingThreshold, transparentReceiver: transparentReceiver)
if let closure = proposeShieldingAccountMemoShieldingThresholdTransparentReceiverClosure { if let closure = proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverClosure {
return try await closure(account, memo, shieldingThreshold, transparentReceiver) return try await closure(accountIndex, memo, shieldingThreshold, transparentReceiver)
} else { } else {
return proposeShieldingAccountMemoShieldingThresholdTransparentReceiverReturnValue return proposeShieldingAccountIndexMemoShieldingThresholdTransparentReceiverReturnValue
} }
} }

View File

@ -86,7 +86,7 @@ class TestCoordinator {
self.spendingKey = try derivationTool.deriveUnifiedSpendingKey( self.spendingKey = try derivationTool.deriveUnifiedSpendingKey(
seed: Environment.seedBytes, seed: Environment.seedBytes,
account: Account(0) accountIndex: Zip32AccountIndex(0)
) )
self.viewingKey = try derivationTool.deriveUnifiedFullViewingKey(from: spendingKey) self.viewingKey = try derivationTool.deriveUnifiedFullViewingKey(from: spendingKey)