Merge pull request #1364 from LukasKorba/1363-Expose-PoolBalance-Zatoshi-values

[#1363] Account balances in the SynchronizerState
This commit is contained in:
Lukas Korba 2024-02-01 08:59:41 -08:00 committed by GitHub
commit 170408d5d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 86 additions and 44 deletions

View File

@ -4,6 +4,13 @@ All notable changes to this library will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# [Unreleased]
## Changed
### [#1363] Account balances in the SynchronizerState
`shieldedBalance: WalletBalance` has been replaced with `accountBalances: AccountBalance`. `AccountBalance` provides the same values as `shieldedBalance` but adds up a pending changes. Under the hood this calls rust's `getWalletSummary` which improved also the syncing initial values of % and balances.
# 2.0.8 - 2024-01-30
Adopt `zcash-light-client-ffi 0.5.1`. This fixes a serialization problem

View File

@ -17,7 +17,7 @@ final class ScanAction {
let rustBackend: ZcashRustBackendWelding
let latestBlocksDataProvider: LatestBlocksDataProvider
let logger: Logger
var progressReportReducer = Constants.reportDelay
var progressReportReducer = 0
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
self.configProvider = configProvider
@ -99,7 +99,7 @@ extension ScanAction: Action {
}
func stop() async {
progressReportReducer = Constants.reportDelay
progressReportReducer = 0
}
}

View File

@ -7,19 +7,23 @@
import Foundation
struct PoolBalance: Equatable {
let spendableValue: Zatoshi
let changePendingConfirmation: Zatoshi
let valuePendingSpendability: Zatoshi
public struct PoolBalance: Equatable {
public let spendableValue: Zatoshi
public let changePendingConfirmation: Zatoshi
public let valuePendingSpendability: Zatoshi
func total() -> Zatoshi {
static let zero = PoolBalance(spendableValue: .zero, changePendingConfirmation: .zero, valuePendingSpendability: .zero)
public func total() -> Zatoshi {
self.spendableValue + self.changePendingConfirmation + self.valuePendingSpendability
}
}
struct AccountBalance: Equatable {
let saplingBalance: PoolBalance
let unshielded: Zatoshi
public struct AccountBalance: Equatable {
public let saplingBalance: PoolBalance
public let unshielded: Zatoshi
static let zero = AccountBalance(saplingBalance: .zero, unshielded: .zero)
}
struct ScanProgress: Equatable {

View File

@ -35,8 +35,8 @@ public struct SynchronizerState: Equatable {
/// given how application lifecycle varies between OS Versions, platforms, etc.
/// SyncSessionIDs are provided to users
public var syncSessionID: UUID
/// shielded balance known to this synchronizer given the data that has processed locally
public var shieldedBalance: WalletBalance
/// account (shielded) balances known to this synchronizer given the data that has processed locally
public var accountBalances: AccountBalance
/// transparent balance known to this synchronizer given the data that has processed locally
public var transparentBalance: WalletBalance
/// status of the whole sync process
@ -49,7 +49,7 @@ public struct SynchronizerState: Equatable {
public static var zero: SynchronizerState {
SynchronizerState(
syncSessionID: .nullID,
shieldedBalance: .zero,
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .unprepared,
latestBlockHeight: .zero
@ -58,13 +58,13 @@ public struct SynchronizerState: Equatable {
init(
syncSessionID: UUID,
shieldedBalance: WalletBalance,
accountBalances: AccountBalance,
transparentBalance: WalletBalance,
internalSyncStatus: InternalSyncStatus,
latestBlockHeight: BlockHeight
) {
self.syncSessionID = syncSessionID
self.shieldedBalance = shieldedBalance
self.accountBalances = accountBalances
self.transparentBalance = transparentBalance
self.internalSyncStatus = internalSyncStatus
self.latestBlockHeight = latestBlockHeight
@ -249,6 +249,11 @@ public protocol Synchronizer: AnyObject {
/// - Returns: balance in `Zatoshi`
func getShieldedVerifiedBalance(accountIndex: Int) async throws -> Zatoshi
/// get account balances from the given account index
/// - Parameter accountIndex: the index of the account
/// - Returns: balances
func getAccountBalances(accountIndex: Int) async throws -> AccountBalance?
/// Rescans the known blocks with the current keys.
///
/// `rewind(policy:)` can be called anytime. If the sync process is in progress then it is stopped first. In this case, it make some significant

View File

@ -164,7 +164,8 @@ public class SDKSynchronizer: Synchronizer {
await blockProcessor.start(retry: retry)
case .stopped, .synced, .disconnected, .error:
await updateStatus(.syncing(0))
let syncProgress = (try? await initializer.rustBackend.getWalletSummary()?.scanProgress?.progress()) ?? 0
await updateStatus(.syncing(syncProgress))
await blockProcessor.start(retry: retry)
}
}
@ -413,6 +414,10 @@ public class SDKSynchronizer: Synchronizer {
return try await blockProcessor.refreshUTXOs(tAddress: address, startHeight: height)
}
public func getAccountBalances(accountIndex: Int = 0) async throws -> AccountBalance? {
try await initializer.rustBackend.getWalletSummary()?.accountBalances[UInt32(accountIndex)]
}
public func getShieldedBalance(accountIndex: Int = 0) async throws -> Zatoshi {
try await initializer.rustBackend.getWalletSummary()?.accountBalances[UInt32(accountIndex)]?
.saplingBalance.total() ?? Zatoshi.zero
@ -530,12 +535,9 @@ public class SDKSynchronizer: Synchronizer {
// MARK: notify state
private func snapshotState(status: InternalSyncStatus) async -> SynchronizerState {
return await SynchronizerState(
await SynchronizerState(
syncSessionID: syncSession.value,
shieldedBalance: WalletBalance(
verified: (try? await getShieldedVerifiedBalance()) ?? .zero,
total: (try? await getShieldedBalance()) ?? .zero
),
accountBalances: (try? await getAccountBalances()) ?? .zero,
transparentBalance: (try? await blockProcessor.getTransparentBalance(accountIndex: 0)) ?? .zero,
internalSyncStatus: status,
latestBlockHeight: latestBlocksDataProvider.latestBlockHeight

View File

@ -190,35 +190,35 @@ class SynchronizerDarksideTests: ZcashTestCase {
let expectedStates: [SynchronizerState] = [
SynchronizerState(
syncSessionID: .nullID,
shieldedBalance: .zero,
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .unprepared,
latestBlockHeight: 0
),
SynchronizerState(
syncSessionID: uuids[0],
shieldedBalance: .zero,
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .syncing(0),
latestBlockHeight: 0
),
SynchronizerState(
syncSessionID: uuids[0],
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .syncing(0.9),
latestBlockHeight: 663189
),
SynchronizerState(
syncSessionID: uuids[0],
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .syncing(1.0),
latestBlockHeight: 663189
),
SynchronizerState(
syncSessionID: uuids[0],
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .synced,
latestBlockHeight: 663189
@ -267,36 +267,36 @@ class SynchronizerDarksideTests: ZcashTestCase {
let expectedStates: [SynchronizerState] = [
SynchronizerState(
syncSessionID: .nullID,
shieldedBalance: .zero,
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .unprepared,
latestBlockHeight: 0
),
SynchronizerState(
syncSessionID: uuids[0],
shieldedBalance: .zero,
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .syncing(0),
latestBlockHeight: 0
),
SynchronizerState(
syncSessionID: uuids[0],
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .syncing(0.9),
latestBlockHeight: 663189
),
SynchronizerState(
syncSessionID: uuids[0],
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .syncing(1.0),
latestBlockHeight: 663189
),
SynchronizerState(
syncSessionID: uuids[0],
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .synced,
latestBlockHeight: 663189
)
@ -329,29 +329,29 @@ class SynchronizerDarksideTests: ZcashTestCase {
let secondBatchOfExpectedStates: [SynchronizerState] = [
SynchronizerState(
syncSessionID: uuids[1],
shieldedBalance: WalletBalance(verified: Zatoshi(100000), total: Zatoshi(200000)),
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .syncing(0),
latestBlockHeight: 663189
),
SynchronizerState(
syncSessionID: uuids[1],
shieldedBalance: WalletBalance(verified: Zatoshi(200000), total: Zatoshi(200000)),
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .syncing(0.9),
latestBlockHeight: 663200
),
SynchronizerState(
syncSessionID: uuids[1],
shieldedBalance: WalletBalance(verified: Zatoshi(200000), total: Zatoshi(200000)),
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .syncing(1.0),
latestBlockHeight: 663200
),
SynchronizerState(
syncSessionID: uuids[1],
shieldedBalance: WalletBalance(verified: Zatoshi(200000), total: Zatoshi(200000)),
transparentBalance: WalletBalance(verified: Zatoshi(0), total: Zatoshi(0)),
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: .synced,
latestBlockHeight: 663200
)

View File

@ -472,7 +472,7 @@ class SynchronizerOfflineTests: ZcashTestCase {
func synchronizerState(for internalSyncStatus: InternalSyncStatus) -> SynchronizerState {
SynchronizerState(
syncSessionID: .nullID,
shieldedBalance: .zero,
accountBalances: .zero,
transparentBalance: .zero,
internalSyncStatus: internalSyncStatus,
latestBlockHeight: .zero

View File

@ -1,4 +1,4 @@
// Generated using Sourcery 2.1.4 https://github.com/krzysztofzablocki/Sourcery
// Generated using Sourcery 2.1.7 https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
import Combine
@testable import ZcashLightClientKit
@ -1671,6 +1671,30 @@ class SynchronizerMock: Synchronizer {
}
}
// MARK: - getAccountBalances
var getAccountBalancesAccountIndexThrowableError: Error?
var getAccountBalancesAccountIndexCallsCount = 0
var getAccountBalancesAccountIndexCalled: Bool {
return getAccountBalancesAccountIndexCallsCount > 0
}
var getAccountBalancesAccountIndexReceivedAccountIndex: Int?
var getAccountBalancesAccountIndexReturnValue: AccountBalance?
var getAccountBalancesAccountIndexClosure: ((Int) async throws -> AccountBalance?)?
func getAccountBalances(accountIndex: Int) async throws -> AccountBalance? {
if let error = getAccountBalancesAccountIndexThrowableError {
throw error
}
getAccountBalancesAccountIndexCallsCount += 1
getAccountBalancesAccountIndexReceivedAccountIndex = accountIndex
if let closure = getAccountBalancesAccountIndexClosure {
return try await closure(accountIndex)
} else {
return getAccountBalancesAccountIndexReturnValue
}
}
// MARK: - rewind
var rewindCallsCount = 0

View File

@ -3,7 +3,7 @@
scriptDir=${0:a:h}
cd "${scriptDir}"
sourcery_version=2.1.4
sourcery_version=2.1.7
if which sourcery >/dev/null; then
if [[ $(sourcery --version) != $sourcery_version ]]; then

View File

@ -145,7 +145,7 @@ extension SynchronizerState {
static var mock: SynchronizerState {
SynchronizerState(
syncSessionID: .nullID,
shieldedBalance: WalletBalance(verified: Zatoshi(100), total: Zatoshi(200)),
accountBalances: .zero,
transparentBalance: WalletBalance(verified: Zatoshi(200), total: Zatoshi(300)),
internalSyncStatus: .syncing(0),
latestBlockHeight: 222222