WrappedSyncrhonizer (#292)
(un)subscribed logic added cleanup refactor commented solved final agreed naming
This commit is contained in:
parent
7e7ba0d11d
commit
ccb9301fb2
|
@ -106,7 +106,7 @@
|
|||
9EAFEB822805793200199FC9 /* AppReducerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB812805793200199FC9 /* AppReducerTests.swift */; };
|
||||
9EAFEB84280597B700199FC9 /* WrappedSecItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */; };
|
||||
9EAFEB862805A23100199FC9 /* WrappedSecItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB852805A23100199FC9 /* WrappedSecItemTests.swift */; };
|
||||
9EAFEB882806E5AE00199FC9 /* CombineSynchronizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB872806E5AE00199FC9 /* CombineSynchronizer.swift */; };
|
||||
9EAFEB882806E5AE00199FC9 /* WrappedSDKSynchronizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB872806E5AE00199FC9 /* WrappedSDKSynchronizer.swift */; };
|
||||
9EAFEB8A2806F48100199FC9 /* ZCashSDKEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB892806F48100199FC9 /* ZCashSDKEnvironment.swift */; };
|
||||
9EAFEB8F2808183D00199FC9 /* SandboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB8D2808183D00199FC9 /* SandboxView.swift */; };
|
||||
9EAFEB902808183D00199FC9 /* SandboxStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB8E2808183D00199FC9 /* SandboxStore.swift */; };
|
||||
|
@ -269,7 +269,7 @@
|
|||
9EAFEB812805793200199FC9 /* AppReducerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppReducerTests.swift; sourceTree = "<group>"; };
|
||||
9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItem.swift; sourceTree = "<group>"; };
|
||||
9EAFEB852805A23100199FC9 /* WrappedSecItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItemTests.swift; sourceTree = "<group>"; };
|
||||
9EAFEB872806E5AE00199FC9 /* CombineSynchronizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineSynchronizer.swift; sourceTree = "<group>"; };
|
||||
9EAFEB872806E5AE00199FC9 /* WrappedSDKSynchronizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSDKSynchronizer.swift; sourceTree = "<group>"; };
|
||||
9EAFEB892806F48100199FC9 /* ZCashSDKEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZCashSDKEnvironment.swift; sourceTree = "<group>"; };
|
||||
9EAFEB8D2808183D00199FC9 /* SandboxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SandboxView.swift; sourceTree = "<group>"; };
|
||||
9EAFEB8E2808183D00199FC9 /* SandboxStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SandboxStore.swift; sourceTree = "<group>"; };
|
||||
|
@ -561,7 +561,6 @@
|
|||
9EF8139B27F47AED0075AF48 /* InitializationState.swift */,
|
||||
9EF8139027F191BF0075AF48 /* WalletStorageInteractor.swift */,
|
||||
9ECAE56727FC713C0089A0EF /* DatabaseFiles.swift */,
|
||||
9EAFEB872806E5AE00199FC9 /* CombineSynchronizer.swift */,
|
||||
9EAFEB892806F48100199FC9 /* ZCashSDKEnvironment.swift */,
|
||||
9E2F1C8128095AFE004E65FE /* Int64+Zcash.swift */,
|
||||
9E2F1C832809B606004E65FE /* DebugMenu.swift */,
|
||||
|
@ -749,6 +748,7 @@
|
|||
9E02B56927FED43E005B809B /* WrappedFileManager.swift */,
|
||||
9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */,
|
||||
9E02B5C2280458D2005B809B /* WrappedDerivationTool.swift */,
|
||||
9EAFEB872806E5AE00199FC9 /* WrappedSDKSynchronizer.swift */,
|
||||
);
|
||||
path = Wrappers;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1225,7 +1225,7 @@
|
|||
0DF482BA2787ADA800EB37D6 /* ConditionalModifier.swift in Sources */,
|
||||
9E2F1C8F280EDE09004E65FE /* Drawer.swift in Sources */,
|
||||
665C963F272C26E600BC04FB /* CircularFrameBackground.swift in Sources */,
|
||||
9EAFEB882806E5AE00199FC9 /* CombineSynchronizer.swift in Sources */,
|
||||
9EAFEB882806E5AE00199FC9 /* WrappedSDKSynchronizer.swift in Sources */,
|
||||
0DB8AA81271DC7520035BC9D /* DesignGuide.swift in Sources */,
|
||||
F9971A4D27680DC400A2DB75 /* App.swift in Sources */,
|
||||
9EAFEB9228081E9400199FC9 /* HomeView.swift in Sources */,
|
||||
|
|
|
@ -41,7 +41,7 @@ enum AppAction: Equatable {
|
|||
}
|
||||
|
||||
struct AppEnvironment {
|
||||
let combineSynchronizer: CombineSynchronizer
|
||||
let wrappedSDKSynchronizer: WrappedSDKSynchronizer
|
||||
let databaseFiles: DatabaseFilesInteractor
|
||||
let mnemonicSeedPhraseProvider: MnemonicSeedPhraseProvider
|
||||
let scheduler: AnySchedulerOf<DispatchQueue>
|
||||
|
@ -52,7 +52,7 @@ struct AppEnvironment {
|
|||
|
||||
extension AppEnvironment {
|
||||
static let live = AppEnvironment(
|
||||
combineSynchronizer: LiveCombineSynchronizer(),
|
||||
wrappedSDKSynchronizer: LiveWrappedSDKSynchronizer(),
|
||||
databaseFiles: .live(),
|
||||
mnemonicSeedPhraseProvider: .live,
|
||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
||||
|
@ -62,7 +62,7 @@ extension AppEnvironment {
|
|||
)
|
||||
|
||||
static let mock = AppEnvironment(
|
||||
combineSynchronizer: LiveCombineSynchronizer(),
|
||||
wrappedSDKSynchronizer: LiveWrappedSDKSynchronizer(),
|
||||
databaseFiles: .live(),
|
||||
mnemonicSeedPhraseProvider: .mock,
|
||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
||||
|
@ -153,8 +153,8 @@ extension AppReducer {
|
|||
birthday: birthday,
|
||||
with: environment
|
||||
)
|
||||
try environment.combineSynchronizer.prepareWith(initializer: initializer)
|
||||
try environment.combineSynchronizer.start()
|
||||
try environment.wrappedSDKSynchronizer.prepareWith(initializer: initializer)
|
||||
try environment.wrappedSDKSynchronizer.start()
|
||||
} catch {
|
||||
state.appInitializationState = .failed
|
||||
// TODO: error we need to handle, issue #221 (https://github.com/zcash/secant-ios-wallet/issues/221)
|
||||
|
@ -291,7 +291,7 @@ extension AppReducer {
|
|||
action: /AppAction.home,
|
||||
environment: { environment in
|
||||
HomeEnvironment(
|
||||
combineSynchronizer: environment.combineSynchronizer
|
||||
wrappedSDKSynchronizer: environment.wrappedSDKSynchronizer
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -9,7 +9,6 @@ struct HomeState: Equatable {
|
|||
case scan
|
||||
}
|
||||
|
||||
var arePublishersPrepared = false
|
||||
var route: Route?
|
||||
|
||||
var drawerOverlay: DrawerOverlay
|
||||
|
@ -24,11 +23,13 @@ struct HomeState: Equatable {
|
|||
|
||||
enum HomeAction: Equatable {
|
||||
case debugMenuStartup
|
||||
case preparePublishers
|
||||
case onAppear
|
||||
case onDisappear
|
||||
case profile(ProfileAction)
|
||||
case request(RequestAction)
|
||||
case send(SendAction)
|
||||
case scan(ScanAction)
|
||||
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
||||
case transactionHistory(TransactionHistoryAction)
|
||||
case updateBalance(Balance)
|
||||
case updateDrawer(DrawerOverlay)
|
||||
|
@ -36,26 +37,35 @@ enum HomeAction: Equatable {
|
|||
}
|
||||
|
||||
struct HomeEnvironment {
|
||||
let combineSynchronizer: CombineSynchronizer
|
||||
let wrappedSDKSynchronizer: WrappedSDKSynchronizer
|
||||
}
|
||||
|
||||
// MARK: - HomeReducer
|
||||
|
||||
private struct ListenerId: Hashable {}
|
||||
|
||||
typealias HomeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
|
||||
|
||||
extension HomeReducer {
|
||||
static let `default` = HomeReducer { state, action, environment in
|
||||
switch action {
|
||||
case .preparePublishers:
|
||||
if !state.arePublishersPrepared {
|
||||
state.arePublishersPrepared = true
|
||||
case .onAppear:
|
||||
return environment.wrappedSDKSynchronizer.stateChanged
|
||||
.map(HomeAction.synchronizerStateChanged)
|
||||
.eraseToEffect()
|
||||
.cancellable(id: ListenerId(), cancelInFlight: true)
|
||||
|
||||
return environment.combineSynchronizer.shieldedBalance
|
||||
.receive(on: DispatchQueue.main)
|
||||
.map({ Balance(verified: $0.verified, total: $0.total) })
|
||||
.map(HomeAction.updateBalance)
|
||||
.eraseToEffect()
|
||||
}
|
||||
case .onDisappear:
|
||||
return Effect.cancel(id: ListenerId())
|
||||
|
||||
case .synchronizerStateChanged(.synced):
|
||||
return environment.wrappedSDKSynchronizer.getShieldedBalance()
|
||||
.receive(on: DispatchQueue.main)
|
||||
.map({ Balance(verified: $0.verified, total: $0.total) })
|
||||
.map(HomeAction.updateBalance)
|
||||
.eraseToEffect()
|
||||
|
||||
case .synchronizerStateChanged(let synchronizerState):
|
||||
return .none
|
||||
|
||||
case .updateBalance(let balance):
|
||||
|
|
|
@ -41,7 +41,8 @@ struct HomeView: View {
|
|||
}
|
||||
.applyScreenBackground()
|
||||
.navigationBarHidden(true)
|
||||
.onAppear(perform: { viewStore.send(.preparePublishers) })
|
||||
.onAppear(perform: { viewStore.send(.onAppear) })
|
||||
.onDisappear(perform: { viewStore.send(.onDisappear) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +161,7 @@ extension HomeStore {
|
|||
initialState: .placeholder,
|
||||
reducer: .default.debug(),
|
||||
environment: HomeEnvironment(
|
||||
combineSynchronizer: LiveCombineSynchronizer()
|
||||
wrappedSDKSynchronizer: LiveWrappedSDKSynchronizer()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// CombineSynchronizer.swift
|
||||
// WrappedSDKSynchronizer.swift
|
||||
// secant-testnet
|
||||
//
|
||||
// Created by Lukáš Korba on 13.04.2022.
|
||||
|
@ -8,26 +8,51 @@
|
|||
import Foundation
|
||||
import ZcashLightClientKit
|
||||
import Combine
|
||||
import ComposableArchitecture
|
||||
|
||||
enum WrappedSDKSynchronizerState: Equatable {
|
||||
case unknown
|
||||
|
||||
case transactionsUpdated
|
||||
case started
|
||||
case progressUpdated
|
||||
case statusWillUpdate
|
||||
case synced
|
||||
case stopped
|
||||
case disconnected
|
||||
case syncing
|
||||
case downloading
|
||||
case validating
|
||||
case scanning
|
||||
case enhancing
|
||||
case fetching
|
||||
case minedTransaction
|
||||
case foundTransactions
|
||||
case failed
|
||||
case connectionStateChanged
|
||||
}
|
||||
|
||||
struct Balance: WalletBalance, Equatable {
|
||||
var verified: Int64
|
||||
var total: Int64
|
||||
}
|
||||
|
||||
protocol CombineSynchronizer {
|
||||
protocol WrappedSDKSynchronizer {
|
||||
var synchronizer: SDKSynchronizer? { get }
|
||||
var shieldedBalance: CurrentValueSubject<WalletBalance, Never> { get }
|
||||
var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never> { get }
|
||||
|
||||
func prepareWith(initializer: Initializer) throws
|
||||
func start(retry: Bool) throws
|
||||
func stop()
|
||||
func updatePublishers()
|
||||
func synchronizerSynced()
|
||||
|
||||
func getShieldedBalance() -> Effect<Balance, Never>
|
||||
|
||||
func getTransparentAddress(account: Int) -> TransparentAddress?
|
||||
func getShieldedAddress(account: Int) -> SaplingShieldedAddress?
|
||||
}
|
||||
|
||||
extension CombineSynchronizer {
|
||||
extension WrappedSDKSynchronizer {
|
||||
func start() throws {
|
||||
try start(retry: false)
|
||||
}
|
||||
|
@ -41,13 +66,17 @@ extension CombineSynchronizer {
|
|||
}
|
||||
}
|
||||
|
||||
class LiveCombineSynchronizer: CombineSynchronizer {
|
||||
class LiveWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||
private var cancellables: [AnyCancellable] = []
|
||||
private(set) var synchronizer: SDKSynchronizer?
|
||||
private(set) var shieldedBalance: CurrentValueSubject<WalletBalance, Never>
|
||||
private(set) var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never>
|
||||
|
||||
init() {
|
||||
self.shieldedBalance = CurrentValueSubject<WalletBalance, Never>(Balance(verified: 0, total: 0))
|
||||
self.stateChanged = CurrentValueSubject<WrappedSDKSynchronizerState, Never>(.unknown)
|
||||
}
|
||||
|
||||
deinit {
|
||||
synchronizer?.stop()
|
||||
}
|
||||
|
||||
func prepareWith(initializer: Initializer) throws {
|
||||
|
@ -56,7 +85,7 @@ class LiveCombineSynchronizer: CombineSynchronizer {
|
|||
NotificationCenter.default.publisher(for: .synchronizerSynced)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] _ in
|
||||
self?.updatePublishers()
|
||||
self?.synchronizerSynced()
|
||||
})
|
||||
.store(in: &cancellables)
|
||||
|
||||
|
@ -71,13 +100,17 @@ class LiveCombineSynchronizer: CombineSynchronizer {
|
|||
synchronizer?.stop()
|
||||
}
|
||||
|
||||
func updatePublishers() {
|
||||
func synchronizerSynced() {
|
||||
stateChanged.send(.synced)
|
||||
}
|
||||
|
||||
func getShieldedBalance() -> Effect<Balance, Never> {
|
||||
if let shieldedVerifiedBalance = synchronizer?.getShieldedVerifiedBalance(),
|
||||
let shieldedTotalBalance = synchronizer?.getShieldedBalance(accountIndex: 0) {
|
||||
shieldedBalance.send(Balance(verified: shieldedVerifiedBalance, total: shieldedTotalBalance))
|
||||
} else {
|
||||
shieldedBalance.send(Balance(verified: 0, total: 0))
|
||||
return Effect(value: Balance(verified: shieldedVerifiedBalance, total: shieldedTotalBalance))
|
||||
}
|
||||
|
||||
return .none
|
||||
}
|
||||
|
||||
func getTransparentAddress(account: Int) -> TransparentAddress? {
|
||||
|
@ -89,38 +122,27 @@ class LiveCombineSynchronizer: CombineSynchronizer {
|
|||
}
|
||||
}
|
||||
|
||||
class MockCombineSynchronizer: CombineSynchronizer {
|
||||
class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||
private(set) var synchronizer: SDKSynchronizer?
|
||||
private(set) var shieldedBalance: CurrentValueSubject<WalletBalance, Never>
|
||||
private(set) var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never>
|
||||
|
||||
init() {
|
||||
self.shieldedBalance = CurrentValueSubject<WalletBalance, Never>(Balance(verified: 0, total: 0))
|
||||
self.stateChanged = CurrentValueSubject<WrappedSDKSynchronizerState, Never>(.unknown)
|
||||
}
|
||||
|
||||
func prepareWith(initializer: Initializer) throws {
|
||||
synchronizer = try SDKSynchronizer(initializer: initializer)
|
||||
shieldedBalance = CurrentValueSubject<WalletBalance, Never>(
|
||||
Balance(verified: 0, total: 0)
|
||||
)
|
||||
try synchronizer?.prepare()
|
||||
func prepareWith(initializer: Initializer) throws { }
|
||||
|
||||
func start(retry: Bool) throws { }
|
||||
|
||||
func stop() { }
|
||||
|
||||
func synchronizerSynced() { }
|
||||
|
||||
func getShieldedBalance() -> Effect<Balance, Never> {
|
||||
return .none
|
||||
}
|
||||
|
||||
func start(retry: Bool) throws {
|
||||
try synchronizer?.start(retry: retry)
|
||||
}
|
||||
func getTransparentAddress(account: Int) -> TransparentAddress? { nil }
|
||||
|
||||
func stop() {
|
||||
synchronizer?.stop()
|
||||
}
|
||||
|
||||
func updatePublishers() {
|
||||
}
|
||||
|
||||
func getTransparentAddress(account: Int) -> TransparentAddress? {
|
||||
synchronizer?.getTransparentAddress(accountIndex: account)
|
||||
}
|
||||
|
||||
func getShieldedAddress(account: Int) -> SaplingShieldedAddress? {
|
||||
synchronizer?.getShieldedAddress(accountIndex: account)
|
||||
}
|
||||
func getShieldedAddress(account: Int) -> SaplingShieldedAddress? { nil }
|
||||
}
|
|
@ -13,7 +13,7 @@ class AppReducerTests: XCTestCase {
|
|||
static let testScheduler = DispatchQueue.test
|
||||
|
||||
let testEnvironment = AppEnvironment(
|
||||
combineSynchronizer: MockCombineSynchronizer(),
|
||||
wrappedSDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
databaseFiles: .throwing,
|
||||
mnemonicSeedPhraseProvider: .mock,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
|
@ -24,7 +24,7 @@ class AppReducerTests: XCTestCase {
|
|||
|
||||
func testWalletInitializationState_Uninitialized() throws {
|
||||
let uninitializedEnvironment = AppEnvironment(
|
||||
combineSynchronizer: MockCombineSynchronizer(),
|
||||
wrappedSDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
databaseFiles: .throwing,
|
||||
mnemonicSeedPhraseProvider: .mock,
|
||||
scheduler: DispatchQueue.test.eraseToAnyScheduler(),
|
||||
|
@ -46,7 +46,7 @@ class AppReducerTests: XCTestCase {
|
|||
)
|
||||
|
||||
let keysMissingEnvironment = AppEnvironment(
|
||||
combineSynchronizer: MockCombineSynchronizer(),
|
||||
wrappedSDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)),
|
||||
mnemonicSeedPhraseProvider: .mock,
|
||||
scheduler: Self.testScheduler.eraseToAnyScheduler(),
|
||||
|
@ -68,7 +68,7 @@ class AppReducerTests: XCTestCase {
|
|||
)
|
||||
|
||||
let keysMissingEnvironment = AppEnvironment(
|
||||
combineSynchronizer: MockCombineSynchronizer(),
|
||||
wrappedSDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
databaseFiles: .live(databaseFiles: DatabaseFiles(fileManager: wfmMock)),
|
||||
mnemonicSeedPhraseProvider: .mock,
|
||||
scheduler: Self.testScheduler.eraseToAnyScheduler(),
|
||||
|
|
Loading…
Reference in New Issue