Skip to content

Commit

Permalink
Update zcash library
Browse files Browse the repository at this point in the history
- Implement spend-before-sync
- Refactor balanceData. separate custom balanceData types
- Fix zcash transactions memos and recipients
  • Loading branch information
ant013 committed Sep 27, 2023
1 parent 688021a commit e256a5e
Show file tree
Hide file tree
Showing 31 changed files with 378 additions and 202 deletions.
6 changes: 6 additions & 0 deletions UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2238,6 +2238,7 @@
ABC9AB0F8FE5808DB889C081 /* WalletConnectScanQrViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A3DBB89D0AE0C127742B /* WalletConnectScanQrViewModel.swift */; };
ABC9AB11FDD018A96BB86557 /* BottomGradientHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9ADE822BC024F9B798211 /* BottomGradientHolder.swift */; };
ABC9AB1E703AE57DF856ECD9 /* SendAmountCautionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A07A33870908ED1BA338 /* SendAmountCautionViewModel.swift */; };
ABC9AB2E235EA006E2DAD8DD /* EnabledWalletCache_v_0_36.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A68AFE3CF24D2B88808F /* EnabledWalletCache_v_0_36.swift */; };
ABC9AB308727D81FBB8EBCDD /* BackupCloudPassphraseService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9AF6AA02DA39787C053F0 /* BackupCloudPassphraseService.swift */; };
ABC9AB3DAD30AA400DEB719C /* SendBitcoinService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A696DCBBE4761E77311C /* SendBitcoinService.swift */; };
ABC9AB401FD98F99EF6B07C6 /* RestoreTypeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A939DD222D4A2BD3D71C /* RestoreTypeViewController.swift */; };
Expand Down Expand Up @@ -2302,6 +2303,7 @@
ABC9AD3001AAA0570B503876 /* ManageBarButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A6CFDF38D413679D2088 /* ManageBarButtonView.swift */; };
ABC9AD3276132B33F6045AFF /* MarketCategoryMarketCapFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9ADC1A3B17225B6CC0869 /* MarketCategoryMarketCapFetcher.swift */; };
ABC9AD41E7C88963F6512905 /* ChartIndicatorsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A3758FE2D56036DF27FF /* ChartIndicatorsRepository.swift */; };
ABC9AD46006A85E907826E2B /* EnabledWalletCache_v_0_36.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A68AFE3CF24D2B88808F /* EnabledWalletCache_v_0_36.swift */; };
ABC9AD46AE6B5F432E0D2085 /* WalletTokenBalanceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A52822CE6B8830CF5EF4 /* WalletTokenBalanceViewModel.swift */; };
ABC9AD49CCD14F97CD912454 /* SendBitcoinAdapterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A1BD3B1B53C72DDF923A /* SendBitcoinAdapterService.swift */; };
ABC9AD565E3BAB7074D02D40 /* ProFeaturesAuthorizationAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC9A8D3446ABE98F4D1C0CC /* ProFeaturesAuthorizationAdapter.swift */; };
Expand Down Expand Up @@ -3800,6 +3802,7 @@
ABC9A6363DB5DAE5B58AFDC0 /* UniswapV3Module.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UniswapV3Module.swift; sourceTree = "<group>"; };
ABC9A64A66778C137FA9642C /* WalletTokenViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletTokenViewController.swift; sourceTree = "<group>"; };
ABC9A6663522498A53CF4174 /* KdfParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KdfParams.swift; sourceTree = "<group>"; };
ABC9A68AFE3CF24D2B88808F /* EnabledWalletCache_v_0_36.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnabledWalletCache_v_0_36.swift; sourceTree = "<group>"; };
ABC9A696DCBBE4761E77311C /* SendBitcoinService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendBitcoinService.swift; sourceTree = "<group>"; };
ABC9A6B2EF46FF7EDA4728D3 /* CheckboxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxView.swift; sourceTree = "<group>"; };
ABC9A6CFDF38D413679D2088 /* ManageBarButtonView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManageBarButtonView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -5048,6 +5051,7 @@
11B35799B0DCCF655F0766BF /* CexDepositNetwork.swift */,
11B35B617A9CE668EEF4978B /* AmountData.swift */,
11B359A35AEB7964A94AFFC0 /* BiometryType.swift */,
ABC9A68AFE3CF24D2B88808F /* EnabledWalletCache_v_0_36.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -9243,6 +9247,7 @@
11B35353A5C1E254839CD61B /* InteractiveDismiss.swift in Sources */,
11B3553AD73FD1179249F277 /* SecondaryButtonStyle.swift in Sources */,
11B3523E8B466F259DB32E37 /* SecondaryCircleButtonStyle.swift in Sources */,
ABC9AD46006A85E907826E2B /* EnabledWalletCache_v_0_36.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -10545,6 +10550,7 @@
11B350A27335B798701EE7B3 /* InteractiveDismiss.swift in Sources */,
11B35DDBD7EC98FAE5794F76 /* SecondaryButtonStyle.swift in Sources */,
11B35224D7A5A864C1C6F167 /* SecondaryCircleButtonStyle.swift in Sources */,
ABC9AB2E235EA006E2DAD8DD /* EnabledWalletCache_v_0_36.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class BinanceAdapter {
}

private func balanceInfo(balance: Decimal) -> BalanceData {
BalanceData(balance: balance)
BalanceData(available: balance)
}

}
Expand Down Expand Up @@ -114,7 +114,7 @@ extension BinanceAdapter: IBalanceAdapter {

var balanceDataUpdatedObservable: Observable<BalanceData> {
asset.balanceObservable.map { [weak self] in
self?.balanceInfo(balance: $0) ?? BalanceData(balance: 0)
self?.balanceInfo(balance: $0) ?? BalanceData(available: 0)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ class BitcoinBaseAdapter {
}

private func balanceData(balanceInfo: BalanceInfo) -> BalanceData {
BalanceData(
balance: Decimal(balanceInfo.spendable) / coinRate,
LockedBalanceData(
available: Decimal(balanceInfo.spendable) / coinRate,
locked: Decimal(balanceInfo.unspendable) / coinRate
)
}
Expand Down Expand Up @@ -389,6 +389,6 @@ class DepositAddress {
let address: String

init(_ receiveAddress: String) {
self.address = receiveAddress
address = receiveAddress
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class BaseEvmAdapter {
}

func balanceData(balance: BigUInt?) -> BalanceData {
BalanceData(balance: balanceDecimal(kitBalance: balance, decimals: decimals))
BalanceData(available: balanceDecimal(kitBalance: balance, decimals: decimals))
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ extension Eip20Adapter: IBalanceAdapter {

var balanceDataUpdatedObservable: Observable<BalanceData> {
eip20Kit.balanceObservable.map { [weak self] in
self?.balanceData(balance: $0) ?? BalanceData(balance: 0)
self?.balanceData(balance: $0) ?? BalanceData(available: 0)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ extension EvmAdapter: IBalanceAdapter {

var balanceDataUpdatedObservable: Observable<BalanceData> {
evmKit.accountStateObservable.map { [weak self] in
self?.balanceData(balance: $0.balance) ?? BalanceData(balance: 0)
self?.balanceData(balance: $0.balance) ?? BalanceData(available: 0)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class BaseTronAdapter {
}

func balanceData(balance: BigUInt?) -> BalanceData {
BalanceData(balance: balanceDecimal(kitBalance: balance, decimals: decimals))
BalanceData(available: balanceDecimal(kitBalance: balance, decimals: decimals))
}

func accountActive(address: TronKit.Address) async -> Bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ extension Trc20Adapter: IBalanceAdapter {

var balanceDataUpdatedObservable: Observable<BalanceData> {
tronKit.trc20BalancePublisher(contractAddress: contractAddress).asObservable().map { [weak self] in
self?.balanceData(balance: $0) ?? BalanceData(balance: 0)
self?.balanceData(balance: $0) ?? BalanceData(available: 0)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ extension TronAdapter: IBalanceAdapter {

var balanceDataUpdatedObservable: Observable<BalanceData> {
tronKit.trxBalancePublisher.asObservable().map { [weak self] in
self?.balanceData(balance: $0) ?? BalanceData(balance: 0)
self?.balanceData(balance: $0) ?? BalanceData(available: 0)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@ class ZcashAdapter {
private var started = false
private var lastBlockHeight: Int = 0

private var waitForStart: Bool = false {
didSet {
print("Change waitForStart to \(waitForStart) : zAddress : \(zAddress != nil)")
if waitForStart, zAddress != nil { // already prepared and has address
syncMain()
}
}
}

private var synchronizerState: SynchronizerState? {
didSet {
lastBlockUpdatedSubject.onNext(())
Expand Down Expand Up @@ -89,7 +80,7 @@ class ZcashAdapter {
}

init(wallet: Wallet, restoreSettings: RestoreSettings) throws {
logger = HsToolKit.Logger(minLogLevel: .debug) // App.shared.logger.scoped(with: "ZCashKit") //
logger = App.shared.logger.scoped(with: "ZCashKit") // HsToolKit.Logger(minLogLevel: .debug) //

guard let seed = wallet.account.type.mnemonicSeed else {
throw AdapterError.unsupportedAccount
Expand Down Expand Up @@ -141,7 +132,6 @@ class ZcashAdapter {

// subscribe on background and events from sapling downloader
NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
prepare(seedData: seedData, walletBirthday: birthday, for: initMode)
}

private func prepare(seedData: [UInt8], walletBirthday: BlockHeight, for initMode: WalletInitMode) {
Expand Down Expand Up @@ -195,9 +185,9 @@ class ZcashAdapter {
let shielded = await (try? synchronizer.getShieldedBalance(accountIndex: 0).decimalValue.decimalValue) ?? 0
let shieldedVerified = await (try? synchronizer.getShieldedVerifiedBalance(accountIndex: 0).decimalValue.decimalValue) ?? 0
self?.balanceSubject.onNext(
BalanceData(
balance: shieldedVerified,
locked: shielded - shieldedVerified
VerifiedBalanceData(
fullBalance: shielded,
available: shieldedVerified
)
)
self?.lastBlockHeight = try await synchronizer.latestHeight()
Expand All @@ -218,9 +208,26 @@ class ZcashAdapter {
private func finishPrepare() {
state = .idle

if waitForStart {
logger?.log(level: .debug, message: "Start kit after finish preparing!")
start()
logger?.log(level: .debug, message: "Start kit after finish preparing!")
startSynchronizer()
}

private func startSynchronizer() {
guard !state.isPrepairing else { // postpone start library until preparing will finish
logger?.log(level: .debug, message: "Can't start because preparing!")
return
}

if zAddress == nil { // else we need to try prepare library again
logger?.log(level: .debug, message: "No address, try to prepare kit again!")
prepare(seedData: seedData, walletBirthday: birthday, for: initMode)

return
}

if saplingDataExist() {
logger?.log(level: .debug, message: "Start syncing kit!")
syncMain()
}
}

Expand Down Expand Up @@ -298,7 +305,7 @@ class ZcashAdapter {
transactions.forEach { overview in
logger?.log(level: .debug, message: "tx: v =\(overview.value.decimalValue.decimalString) : fee = \(overview.fee?.decimalString() ?? "N/A") : height = \(overview.minedHeight?.description ?? "N/A")")
}
let lastBlockHeight = inRange.upperBound
let lastBlockHeight = max(inRange.upperBound, lastBlockHeight)
Task {
let newTxs = await transactionPool?.sync(transactions: transactions, lastBlockHeight: lastBlockHeight) ?? []
transactionRecordsSubject.onNext(newTxs.map {
Expand Down Expand Up @@ -474,16 +481,12 @@ class ZcashAdapter {

private var _balanceData: BalanceData {
guard let synchronizerState = synchronizerState else {
return BalanceData(balance: 0)
return BalanceData(available: 0)
}

let verifiedBalance: Zatoshi = synchronizerState.shieldedBalance.verified
let balance: Zatoshi = synchronizerState.shieldedBalance.total
let diff = balance - verifiedBalance

return BalanceData(
balance: verifiedBalance.decimalValue.decimalValue,
locked: diff.decimalValue.decimalValue
return VerifiedBalanceData(
fullBalance: synchronizerState.shieldedBalance.total.decimalValue.decimalValue,
available: synchronizerState.shieldedBalance.verified.decimalValue.decimalValue
)
}

Expand Down Expand Up @@ -571,24 +574,7 @@ extension ZcashAdapter: IAdapter {
}

func start() {
guard !state.isPrepairing else { // postpone start library until preparing will finish
logger?.log(level: .debug, message: "Can't start because preparing!")
waitForStart = true
return
}

if zAddress == nil { // else we need to try prepare library again
logger?.log(level: .debug, message: "No address, try to prepare kit again!")
prepare(seedData: seedData, walletBirthday: birthday, for: initMode)

return
}

waitForStart = false // if we has address just start syncing library or downloading sapling data
if saplingDataExist() {
logger?.log(level: .debug, message: "Start syncing kit!")
syncMain()
}
prepare(seedData: seedData, walletBirthday: birthday, for: initMode)
}

func stop() {
Expand All @@ -597,7 +583,7 @@ extension ZcashAdapter: IAdapter {
}

func refresh() {
start()
startSynchronizer()
}

private func syncMain() {
Expand Down Expand Up @@ -632,7 +618,7 @@ extension ZcashAdapter: IAdapter {
balanceState = """
shielded balance
total: \(balanceData.balanceTotal.description)
verified: \(balanceData.balance)
verified: \(balanceData.available)
transparent balance
total: \(String(describing: status.transparentBalance.total))
verified: \(String(describing: status.transparentBalance.verified))
Expand Down Expand Up @@ -726,7 +712,7 @@ extension ZcashAdapter: ISendZcashAdapter {
}

var availableBalance: Decimal {
max(0, balanceData.balance - fee) // TODO: check
max(0, balanceData.available - fee)
}

func validate(address: String) throws -> AddressType {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import Foundation
import ZcashLightClientKit
import RxSwift
import ZcashLightClientKit

class ZcashTransactionPool {
private var confirmedTransactions = Set<ZcashTransactionWrapper>()
private var pendingTransactions = Set<ZcashTransactionWrapper>()
private let synchronizer: Synchronizer
private let receiveAddress: SaplingAddress


init(receiveAddress: SaplingAddress, synchronizer: Synchronizer) {
self.receiveAddress = receiveAddress
self.synchronizer = synchronizer
Expand Down Expand Up @@ -45,8 +44,16 @@ class ZcashTransactionPool {

private func transactionWithAdditional(tx: ZcashTransaction.Overview, lastBlockHeight: Int) async throws -> ZcashTransactionWrapper? {
let memos: [Memo] = (try? await synchronizer.getMemos(for: tx)) ?? []
let firstMemo = memos
.compactMap { $0.toString() }
.first

let recipients = await synchronizer.getRecipients(for: tx)
return ZcashTransactionWrapper(tx: tx, memo: memos.first, recipient: recipients.first, lastBlockHeight: lastBlockHeight)
let firstAddress = recipients
.filter { $0.hasAddress }
.first

return ZcashTransactionWrapper(tx: tx, memo: firstMemo, recipient: firstAddress, lastBlockHeight: lastBlockHeight)
}

private func sync(own: inout Set<ZcashTransactionWrapper>, incoming: [ZcashTransactionWrapper]) {
Expand All @@ -63,19 +70,17 @@ class ZcashTransactionPool {

func sync(transactions: [ZcashTransaction.Overview], lastBlockHeight: Int) async -> [ZcashTransactionWrapper] {
let txs = await zcashTransactions(transactions, lastBlockHeight: lastBlockHeight)
// todo: sync pending and confirmed but How?
// TODO: sync pending and confirmed but How?
sync(own: &confirmedTransactions, incoming: txs)
return txs
}

func transaction(by hash: String) -> ZcashTransactionWrapper? {
transactions(filter: .all).first { $0.transactionHash == hash }
}

}

extension ZcashTransactionPool {

var all: [ZcashTransactionWrapper] {
transactions(filter: .all)
}
Expand All @@ -88,9 +93,17 @@ extension ZcashTransactionPool {
}

if let index = transactions.firstIndex(where: { $0.transactionHash == transaction.transactionHash }) {
return Single.just((Array(transactions.suffix(from: index + 1).prefix(limit))))
return Single.just(Array(transactions.suffix(from: index + 1).prefix(limit)))
}
return Single.just([])
}
}

extension TransactionRecipient {
var hasAddress: Bool {
switch self {
case .address: return true
case .internalAccount: return false
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ZcashTransactionWrapper {
let memo: String?
let failed: Bool

init?(tx: ZcashTransaction.Overview, memo: Memo?, recipient: TransactionRecipient?, lastBlockHeight: Int) {
init?(tx: ZcashTransaction.Overview, memo: String?, recipient: TransactionRecipient?, lastBlockHeight: Int) {
raw = tx.raw
transactionHash = tx.rawID.hs.reversedHex
transactionIndex = tx.index ?? 0
Expand All @@ -32,7 +32,7 @@ class ZcashTransactionWrapper {
timestamp = failed ? 0 : (tx.blockTime ?? Date().timeIntervalSince1970) // need this to update pending transactions and shows on transaction tab
value = tx.value
fee = tx.fee
self.memo = memo.flatMap { $0.toString() }
self.memo = memo
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class RateAppManager {
return false
}

return adapter.balanceData.balance > 0
return adapter.balanceData.available > 0
}

guard hasBalance else {
Expand Down
Loading

0 comments on commit e256a5e

Please sign in to comment.