[153] [Scaffold] Progress Status Circular Bar (#389)
- initial frame connected to available data (progress) - zboto balance - $ balance - inner / outer progress logic - isDownloading and isUpToDate controls added - outer circle parametrical solution implemented - unit tests fixed - SyncStatusSnapshot implemented - snapshot tests
This commit is contained in:
parent
180a5a9bc2
commit
282fdbcdf0
|
@ -119,15 +119,18 @@
|
|||
9E5BF648282277BE00BA3F17 /* WrappedNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF647282277BE00BA3F17 /* WrappedNotificationCenter.swift */; };
|
||||
9E5BF64F2823E94900BA3F17 /* TransactionAddressTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF64D2823E94900BA3F17 /* TransactionAddressTextField.swift */; };
|
||||
9E5BF6502823E94900BA3F17 /* TransactionAddressTextFieldStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF64E2823E94900BA3F17 /* TransactionAddressTextFieldStore.swift */; };
|
||||
9E66122A287717A900C75B70 /* HomeCircularProgressSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E661229287717A900C75B70 /* HomeCircularProgressSnapshotTests.swift */; };
|
||||
9E66122C2877188700C75B70 /* SyncStatusSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E66122B2877188700C75B70 /* SyncStatusSnapshot.swift */; };
|
||||
9E69A24D27FB002800A55317 /* WelcomeStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E69A24C27FB002800A55317 /* WelcomeStore.swift */; };
|
||||
9E7CB6122869882D00A02233 /* WalletEventsSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB6112869882D00A02233 /* WalletEventsSnapshotTests.swift */; };
|
||||
9E7CB6152869E8C300A02233 /* CircularProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB6142869E8C300A02233 /* CircularProgress.swift */; };
|
||||
9E7CB61A287310EC00A02233 /* QRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB619287310EC00A02233 /* QRCodeGenerator.swift */; };
|
||||
9E7CB6202874143800A02233 /* AddressDetailsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB61F2874143800A02233 /* AddressDetailsStore.swift */; };
|
||||
9E7CB6212874143800A02233 /* AddressDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB61E2874143800A02233 /* AddressDetailsView.swift */; };
|
||||
9E7CB6242874246800A02233 /* ProfileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB6232874246800A02233 /* ProfileTests.swift */; };
|
||||
9E7CB6272874269F00A02233 /* ProfileSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB6262874269F00A02233 /* ProfileSnapshotTests.swift */; };
|
||||
9E7CB6292875AC2D00A02233 /* AppVersionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB6282875AC2D00A02233 /* AppVersionHandler.swift */; };
|
||||
9E7FE0CF282D257400C374E8 /* SDKSynchronizer+SyncStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0CE282D257400C374E8 /* SDKSynchronizer+SyncStatus.swift */; };
|
||||
9E7CB62C2875C6E700A02233 /* URLRouting in Frameworks */ = {isa = PBXBuildFile; productRef = 9E7CB62B2875C6E700A02233 /* URLRouting */; };
|
||||
9E7FE0D3282D274E00C374E8 /* Date+Readable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0D2282D274E00C374E8 /* Date+Readable.swift */; };
|
||||
9E7FE0D5282D281800C374E8 /* Array+Chunked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0D4282D281800C374E8 /* Array+Chunked.swift */; };
|
||||
9E7FE0D7282D286500C374E8 /* RecoveryPhrase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0D6282D286500C374E8 /* RecoveryPhrase.swift */; };
|
||||
|
@ -335,15 +338,17 @@
|
|||
9E5BF647282277BE00BA3F17 /* WrappedNotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedNotificationCenter.swift; sourceTree = "<group>"; };
|
||||
9E5BF64D2823E94900BA3F17 /* TransactionAddressTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionAddressTextField.swift; sourceTree = "<group>"; };
|
||||
9E5BF64E2823E94900BA3F17 /* TransactionAddressTextFieldStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionAddressTextFieldStore.swift; sourceTree = "<group>"; };
|
||||
9E661229287717A900C75B70 /* HomeCircularProgressSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCircularProgressSnapshotTests.swift; sourceTree = "<group>"; };
|
||||
9E66122B2877188700C75B70 /* SyncStatusSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncStatusSnapshot.swift; sourceTree = "<group>"; };
|
||||
9E69A24C27FB002800A55317 /* WelcomeStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeStore.swift; sourceTree = "<group>"; };
|
||||
9E7CB6112869882D00A02233 /* WalletEventsSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletEventsSnapshotTests.swift; sourceTree = "<group>"; };
|
||||
9E7CB6142869E8C300A02233 /* CircularProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgress.swift; sourceTree = "<group>"; };
|
||||
9E7CB619287310EC00A02233 /* QRCodeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeGenerator.swift; sourceTree = "<group>"; };
|
||||
9E7CB61E2874143800A02233 /* AddressDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressDetailsView.swift; sourceTree = "<group>"; };
|
||||
9E7CB61F2874143800A02233 /* AddressDetailsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressDetailsStore.swift; sourceTree = "<group>"; };
|
||||
9E7CB6232874246800A02233 /* ProfileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileTests.swift; sourceTree = "<group>"; };
|
||||
9E7CB6262874269F00A02233 /* ProfileSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileSnapshotTests.swift; sourceTree = "<group>"; };
|
||||
9E7CB6282875AC2D00A02233 /* AppVersionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersionHandler.swift; sourceTree = "<group>"; };
|
||||
9E7FE0CE282D257400C374E8 /* SDKSynchronizer+SyncStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SDKSynchronizer+SyncStatus.swift"; sourceTree = "<group>"; };
|
||||
9E7FE0D2282D274E00C374E8 /* Date+Readable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Readable.swift"; sourceTree = "<group>"; };
|
||||
9E7FE0D4282D281800C374E8 /* Array+Chunked.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Chunked.swift"; sourceTree = "<group>"; };
|
||||
9E7FE0D6282D286500C374E8 /* RecoveryPhrase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecoveryPhrase.swift; sourceTree = "<group>"; };
|
||||
|
@ -418,6 +423,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9EF8139827F1FAEC0075AF48 /* ZcashLightClientKit in Frameworks */,
|
||||
9E7CB62C2875C6E700A02233 /* URLRouting in Frameworks */,
|
||||
9E2AC0FF27D8EC120042AA47 /* MnemonicSwift in Frameworks */,
|
||||
6654C73A2715A38000901167 /* ComposableArchitecture in Frameworks */,
|
||||
9EAB466F285A0468002904A0 /* _URLRouting in Frameworks */,
|
||||
|
@ -597,6 +603,7 @@
|
|||
9E7FE0DC282D298900C374E8 /* ValidationWord.swift */,
|
||||
9E7FE0E5282E7B1100C374E8 /* StoredWallet.swift */,
|
||||
9EAB46772860A1D2002904A0 /* WalletEvent.swift */,
|
||||
9E66122B2877188700C75B70 /* SyncStatusSnapshot.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
|
@ -884,6 +891,14 @@
|
|||
path = WalletEventsSnapshotTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9E7CB6132869E8A700A02233 /* CircularProgress */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9E7CB6142869E8C300A02233 /* CircularProgress.swift */,
|
||||
);
|
||||
path = CircularProgress;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9E7CB61B2874140900A02233 /* AddressDetails */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -938,7 +953,6 @@
|
|||
0DACFA8027208D940039EEA5 /* UInt+SuperscriptText.swift */,
|
||||
0D7CE63327349B5D0020E050 /* View+WhenDraggable.swift */,
|
||||
9E7FE0D2282D274E00C374E8 /* Date+Readable.swift */,
|
||||
9E7FE0CE282D257400C374E8 /* SDKSynchronizer+SyncStatus.swift */,
|
||||
0DACFA7E27208CE00039EEA5 /* Clamped.swift */,
|
||||
F9322DBF273B555C00C105B5 /* NavigationLinks.swift */,
|
||||
F9C165B3274031F600592F76 /* Bindings.swift */,
|
||||
|
@ -971,6 +985,7 @@
|
|||
9E7FE0BE282D1DFE00C374E8 /* UI Components */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9E7CB6132869E8A700A02233 /* CircularProgress */,
|
||||
0DF2DC5227235E1F00FA31E2 /* Extensions */,
|
||||
0DB8AA80271DC7520035BC9D /* DesignGuide.swift */,
|
||||
9E7FE0E9282E7CF800C374E8 /* ImportSeedEditor */,
|
||||
|
@ -1054,6 +1069,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
9E9ECC8C28589E150099D5A2 /* HomeSnapshotTests.swift */,
|
||||
9E661229287717A900C75B70 /* HomeCircularProgressSnapshotTests.swift */,
|
||||
);
|
||||
path = HomeSnapshotTests;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1264,6 +1280,7 @@
|
|||
9EF8139727F1FAEC0075AF48 /* ZcashLightClientKit */,
|
||||
9EAB466C285A0468002904A0 /* Parsing */,
|
||||
9EAB466E285A0468002904A0 /* _URLRouting */,
|
||||
9E7CB62B2875C6E700A02233 /* URLRouting */,
|
||||
);
|
||||
productName = secant;
|
||||
productReference = 0D4E7A0526B364170058B01E /* secant-testnet.app */;
|
||||
|
@ -1343,6 +1360,7 @@
|
|||
9E2AC0FD27D8EC120042AA47 /* XCRemoteSwiftPackageReference "MnemonicSwift" */,
|
||||
9EF8139627F1FAEC0075AF48 /* XCRemoteSwiftPackageReference "ZcashLightClientKit" */,
|
||||
9EAB466B285A0468002904A0 /* XCRemoteSwiftPackageReference "swift-parsing" */,
|
||||
9E7CB62A2875C6E700A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */,
|
||||
);
|
||||
productRefGroup = 0D4E7A0626B364170058B01E /* Products */;
|
||||
projectDirPath = "";
|
||||
|
@ -1471,7 +1489,6 @@
|
|||
9E5BF648282277BE00BA3F17 /* WrappedNotificationCenter.swift in Sources */,
|
||||
0D8A43C4272AEEDE005A6414 /* SecantTextStyles.swift in Sources */,
|
||||
9E5BF641281FD7B600BA3F17 /* TransactionFailedView.swift in Sources */,
|
||||
9E7FE0CF282D257400C374E8 /* SDKSynchronizer+SyncStatus.swift in Sources */,
|
||||
9E4DC6E027C409A100E657F4 /* NeumorphicDesignModifier.swift in Sources */,
|
||||
9E7CB6292875AC2D00A02233 /* AppVersionHandler.swift in Sources */,
|
||||
0DACFA7F27208CE00039EEA5 /* Clamped.swift in Sources */,
|
||||
|
@ -1484,6 +1501,7 @@
|
|||
9E7FE0D9282D289B00C374E8 /* WrappedFeedbackGenerator.swift in Sources */,
|
||||
2E6CF8DD27D78319004DCD7A /* CurrencySelectionStore.swift in Sources */,
|
||||
9EBEF87A27CE369800B4F343 /* RecoveryPhraseValidationFlowView.swift in Sources */,
|
||||
9E66122C2877188700C75B70 /* SyncStatusSnapshot.swift in Sources */,
|
||||
9E4DC6E227C4C6B700E657F4 /* SecantButtonStyles.swift in Sources */,
|
||||
0DDB6A5127737D4A0012A410 /* RecoveryPhraseBackupFailedView.swift in Sources */,
|
||||
9E391129283F74590073DD9A /* Zatoshi.swift in Sources */,
|
||||
|
@ -1551,6 +1569,7 @@
|
|||
9E7FE0F628327F6F00C374E8 /* ScanUIView.swift in Sources */,
|
||||
0D185819272723FF0046B928 /* ColoredChip.swift in Sources */,
|
||||
2EA11F5D27467F7700709571 /* OnboardingContentView.swift in Sources */,
|
||||
9E7CB6152869E8C300A02233 /* CircularProgress.swift in Sources */,
|
||||
2E58E73B274679F000B2B84B /* OnboardingHeaderView.swift in Sources */,
|
||||
9E5BF64F2823E94900BA3F17 /* TransactionAddressTextField.swift in Sources */,
|
||||
2E35F99227B28E7600EB79CD /* SingleLineTextField.swift in Sources */,
|
||||
|
@ -1613,6 +1632,7 @@
|
|||
9E5BF63F2819542C00BA3F17 /* WalletEventsTests.swift in Sources */,
|
||||
0D4E7A1B26B364180058B01E /* secantTests.swift in Sources */,
|
||||
0DFE93E6272CB6F7000FCCA5 /* RecoveryPhraseValidationTests.swift in Sources */,
|
||||
9E66122A287717A900C75B70 /* HomeCircularProgressSnapshotTests.swift in Sources */,
|
||||
9EAB4676285B5C7C002904A0 /* DeeplinkTests.swift in Sources */,
|
||||
9E3911392848AD500073DD9A /* HomeTests.swift in Sources */,
|
||||
9E9ECC9C28589E150099D5A2 /* OnboardingSnapshotTests.swift in Sources */,
|
||||
|
@ -1953,6 +1973,14 @@
|
|||
minimumVersion = 2.0.0;
|
||||
};
|
||||
};
|
||||
9E7CB62A2875C6E700A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "http://github.com/pointfreeco/swift-url-routing";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.3.0;
|
||||
};
|
||||
};
|
||||
9EAB466B285A0468002904A0 /* XCRemoteSwiftPackageReference "swift-parsing" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/pointfreeco/swift-parsing";
|
||||
|
@ -1982,6 +2010,11 @@
|
|||
package = 9E2AC0FD27D8EC120042AA47 /* XCRemoteSwiftPackageReference "MnemonicSwift" */;
|
||||
productName = MnemonicSwift;
|
||||
};
|
||||
9E7CB62B2875C6E700A02233 /* URLRouting */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9E7CB62A2875C6E700A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */;
|
||||
productName = URLRouting;
|
||||
};
|
||||
9EAB466C285A0468002904A0 /* Parsing */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9EAB466B285A0468002904A0 /* XCRemoteSwiftPackageReference "swift-parsing" */;
|
||||
|
|
|
@ -162,6 +162,15 @@
|
|||
"version" : "1.19.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-url-routing",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "http://github.com/pointfreeco/swift-url-routing",
|
||||
"state" : {
|
||||
"revision" : "5bf79bb370015e43842a61d558a9ee053171124e",
|
||||
"version" : "0.3.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "xctest-dynamic-overlay",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import _URLRouting
|
||||
import URLRouting
|
||||
import ComposableArchitecture
|
||||
import ZcashLightClientKit
|
||||
|
||||
|
|
|
@ -24,12 +24,33 @@ struct HomeState: Equatable {
|
|||
var drawerOverlay: DrawerOverlay
|
||||
var profileState: ProfileState
|
||||
var requestState: RequestState
|
||||
var requiredTransactionConfirmations = 0
|
||||
var sendState: SendFlowState
|
||||
var scanState: ScanState
|
||||
var synchronizerStatus: String
|
||||
var synchronizerStatusSnapshot: SyncStatusSnapshot
|
||||
var totalBalance: Zatoshi
|
||||
var walletEventsState: WalletEventsFlowState
|
||||
var verifiedBalance: Zatoshi
|
||||
// TODO: - Get the ZEC price from the SDK, issue 311, https://github.com/zcash/secant-ios-wallet/issues/311
|
||||
var zecPrice = Decimal(140.0)
|
||||
|
||||
var totalCurrencyBalance: Zatoshi {
|
||||
Zatoshi.from(decimal: totalBalance.decimalValue.decimalValue * zecPrice)
|
||||
}
|
||||
|
||||
var isDownloading: Bool {
|
||||
if case .downloading = synchronizerStatusSnapshot.syncStatus {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var isUpToDate: Bool {
|
||||
if case .synced = synchronizerStatusSnapshot.syncStatus {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Action
|
||||
|
@ -96,6 +117,7 @@ extension HomeReducer {
|
|||
private static let homeReducer = HomeReducer { state, action, environment in
|
||||
switch action {
|
||||
case .onAppear:
|
||||
state.requiredTransactionConfirmations = environment.zcashSDKEnvironment.requiredTransactionConfirmations
|
||||
return environment.SDKSynchronizer.stateChanged
|
||||
.map(HomeAction.synchronizerStateChanged)
|
||||
.eraseToEffect()
|
||||
|
@ -110,13 +132,6 @@ extension HomeReducer {
|
|||
.receive(on: environment.scheduler)
|
||||
.map(HomeAction.updateWalletEvents)
|
||||
.eraseToEffect(),
|
||||
|
||||
environment.SDKSynchronizer.getShieldedBalance()
|
||||
.receive(on: environment.scheduler)
|
||||
.map({ Balance(verified: $0.verified, total: $0.total) })
|
||||
.map(HomeAction.updateBalance)
|
||||
.eraseToEffect(),
|
||||
|
||||
Effect(value: .updateSynchronizerStatus)
|
||||
)
|
||||
|
||||
|
@ -137,8 +152,12 @@ extension HomeReducer {
|
|||
return .none
|
||||
|
||||
case .updateSynchronizerStatus:
|
||||
state.synchronizerStatus = environment.SDKSynchronizer.status()
|
||||
return .none
|
||||
state.synchronizerStatusSnapshot = environment.SDKSynchronizer.statusSnapshot()
|
||||
return environment.SDKSynchronizer.getShieldedBalance()
|
||||
.receive(on: environment.scheduler)
|
||||
.map({ Balance(verified: $0.verified, total: $0.total) })
|
||||
.map(HomeAction.updateBalance)
|
||||
.eraseToEffect()
|
||||
|
||||
case .updateRoute(let route):
|
||||
state.route = route
|
||||
|
@ -305,7 +324,7 @@ extension HomeState {
|
|||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi.zero,
|
||||
walletEventsState: .emptyPlaceHolder,
|
||||
verifiedBalance: Zatoshi.zero
|
||||
|
|
|
@ -12,21 +12,10 @@ struct HomeView: View {
|
|||
|
||||
profileButton(viewStore)
|
||||
|
||||
circularArea(viewStore, proxy.size)
|
||||
|
||||
sendButton(viewStore)
|
||||
|
||||
VStack {
|
||||
Text("\(viewStore.synchronizerStatus)")
|
||||
.padding(.top, 60)
|
||||
|
||||
Text("balance \(viewStore.totalBalance.decimalString()) ZEC")
|
||||
.accessDebugMenuWithHiddenGesture {
|
||||
viewStore.send(.debugMenuStartup)
|
||||
}
|
||||
.padding(.top, 120)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
if proxy.size.height > 0 {
|
||||
Drawer(overlay: viewStore.bindingForDrawer(), maxHeight: proxy.size.height) {
|
||||
VStack {
|
||||
|
@ -122,6 +111,40 @@ extension HomeView {
|
|||
Spacer()
|
||||
}
|
||||
}
|
||||
|
||||
func circularArea(_ viewStore: HomeViewStore, _ size: CGSize) -> some View {
|
||||
VStack {
|
||||
ZStack {
|
||||
CircularProgress(
|
||||
outerCircleProgress: viewStore.isDownloading ? 0 : viewStore.synchronizerStatusSnapshot.progress,
|
||||
innerCircleProgress: viewStore.isDownloading ? viewStore.synchronizerStatusSnapshot.progress : 1,
|
||||
maxSegments: viewStore.requiredTransactionConfirmations,
|
||||
innerCircleHidden: viewStore.isUpToDate
|
||||
)
|
||||
.frame(width: size.width * 0.65, height: size.width * 0.65)
|
||||
.padding(.top, 50)
|
||||
|
||||
VStack {
|
||||
Text("$\(viewStore.totalBalance.decimalString())")
|
||||
.font(.custom(FontFamily.Zboto.regular.name, size: 40))
|
||||
.foregroundColor(Asset.Colors.Text.balanceText.color)
|
||||
.accessDebugMenuWithHiddenGesture {
|
||||
viewStore.send(.debugMenuStartup)
|
||||
}
|
||||
.padding(.top, 80)
|
||||
|
||||
Text("$\(viewStore.totalCurrencyBalance.decimalString())")
|
||||
.font(.custom(FontFamily.Rubik.regular.name, size: 13))
|
||||
.opacity(0.6)
|
||||
.padding(.bottom, 50)
|
||||
|
||||
Text("\(viewStore.synchronizerStatusSnapshot.message)")
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// SyncStatusSnapshot.swift
|
||||
// secant-testnet
|
||||
//
|
||||
// Created by Lukáš Korba on 07.07.2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import ZcashLightClientKit
|
||||
|
||||
struct SyncStatusSnapshot: Equatable {
|
||||
let message: String
|
||||
let progress: Float
|
||||
let syncStatus: SyncStatus
|
||||
|
||||
init(_ syncStatus: SyncStatus = .unprepared, _ message: String = "", _ progress: Float = 0) {
|
||||
self.message = message
|
||||
self.progress = progress
|
||||
self.syncStatus = syncStatus
|
||||
}
|
||||
|
||||
static func snapshotFor(state: SyncStatus) -> SyncStatusSnapshot {
|
||||
switch state {
|
||||
case .downloading(let progress):
|
||||
return SyncStatusSnapshot(state, "downloading - \(String(format: "%d%%", Int(progress.progress * 100.0)))", progress.progress)
|
||||
|
||||
case .enhancing(let enhanceProgress):
|
||||
return SyncStatusSnapshot(state, "Enhancing tx \(enhanceProgress.enhancedTransactions) of \(enhanceProgress.totalTransactions)")
|
||||
|
||||
case .fetching:
|
||||
return SyncStatusSnapshot(state, "fetching UTXOs")
|
||||
|
||||
case .scanning(let progress):
|
||||
return SyncStatusSnapshot(state, "scanning - \(String(format: "%d%%", Int(progress.progress * 100.0)))", progress.progress)
|
||||
|
||||
case .disconnected:
|
||||
return SyncStatusSnapshot(state, "disconnected 💔")
|
||||
|
||||
case .stopped:
|
||||
return SyncStatusSnapshot(state, "Stopped 🚫")
|
||||
|
||||
case .synced:
|
||||
return SyncStatusSnapshot(state, "Up-To-Date")
|
||||
|
||||
case .unprepared:
|
||||
return SyncStatusSnapshot(state, "Unprepared 😅")
|
||||
|
||||
case .validating:
|
||||
return SyncStatusSnapshot(state, "Validating")
|
||||
|
||||
case .error(let err):
|
||||
return SyncStatusSnapshot(state, "Error: \(err.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SyncStatusSnapshot {
|
||||
static let `default` = SyncStatusSnapshot()
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0xB8",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0xB8",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -113,6 +113,7 @@ internal enum Asset {
|
|||
internal static let titleText = ColorAsset(name: "TitleText")
|
||||
internal static let transactionDetailText = ColorAsset(name: "TransactionDetailText")
|
||||
internal static let validMnemonic = ColorAsset(name: "ValidMnemonic")
|
||||
internal static let balanceText = ColorAsset(name: "balanceText")
|
||||
internal static let captionText = ColorAsset(name: "captionText")
|
||||
internal static let captionTextShadow = ColorAsset(name: "captionTextShadow")
|
||||
internal static let highlightedSuperscriptText = ColorAsset(name: "highlightedSuperscriptText")
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
//
|
||||
// CircularProgress.swift
|
||||
// secant-testnet
|
||||
//
|
||||
// Created by Lukáš Korba on 27.06.2022.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CircularProgress: View {
|
||||
let outerCircleProgress: Float
|
||||
let innerCircleProgress: Float
|
||||
let maxSegments: Int
|
||||
let innerCircleHidden: Bool
|
||||
|
||||
var outerCircleProgressCG: CGFloat {
|
||||
CGFloat(outerCircleProgress)
|
||||
}
|
||||
|
||||
var innerCircleProgressCG: CGFloat {
|
||||
CGFloat(innerCircleProgress)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
let segmentTrimComputed = segmentTrim
|
||||
let gap = (2.0 / 360.0) // 2 degrees
|
||||
|
||||
return ZStack {
|
||||
if !innerCircleHidden {
|
||||
Circle()
|
||||
.trim(
|
||||
from: 0.0,
|
||||
to: innerCircleProgressCG
|
||||
)
|
||||
.stroke(
|
||||
Asset.Colors.ProgressIndicator.negativeSpace.color,
|
||||
style: StrokeStyle(lineWidth: 17.0, dash: [2])
|
||||
)
|
||||
.rotationEffect(Angle(degrees: -90))
|
||||
}
|
||||
|
||||
ForEach((0..<maxSegments), id: \.self) {
|
||||
Circle()
|
||||
.trim(
|
||||
from: fromValue($0, segmentTrimComputed, 1.0),
|
||||
to: toValue($0, segmentTrimComputed, 1.0, gap)
|
||||
)
|
||||
.stroke(
|
||||
Asset.Colors.ProgressIndicator.negativeSpace.color,
|
||||
lineWidth: 5.0
|
||||
)
|
||||
.scaleEffect(1.15)
|
||||
.opacity(0.2)
|
||||
.rotationEffect(Angle(degrees: -90))
|
||||
|
||||
Circle()
|
||||
.trim(
|
||||
from: fromValue($0, segmentTrimComputed, outerCircleProgressCG),
|
||||
to: toValue($0, segmentTrimComputed, outerCircleProgressCG, gap)
|
||||
)
|
||||
.stroke(
|
||||
Asset.Colors.ProgressIndicator.negativeSpace.color,
|
||||
lineWidth: 5.0
|
||||
)
|
||||
.scaleEffect(1.15)
|
||||
.rotationEffect(Angle(degrees: -90))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension CircularProgress {
|
||||
var segmentTrim: CGFloat {
|
||||
guard maxSegments != 0 else { return 1.0 }
|
||||
return CGFloat(1.0 / Double(maxSegments))
|
||||
}
|
||||
|
||||
func fromValue(_ segmentIndex: Int, _ segmentTrim: CGFloat, _ progress: CGFloat) -> CGFloat {
|
||||
var result = segmentTrim * CGFloat(segmentIndex)
|
||||
|
||||
if result > progress {
|
||||
result = 0
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func toValue(_ segmentIndex: Int, _ segmentTrim: CGFloat, _ progress: CGFloat, _ gap: CGFloat) -> CGFloat {
|
||||
var result = fromValue(segmentIndex, segmentTrim, progress)
|
||||
|
||||
if result > progress {
|
||||
result = 0
|
||||
} else if result + segmentTrim - gap < progress {
|
||||
result += segmentTrim - gap
|
||||
} else {
|
||||
result += progress - (segmentTrim * CGFloat(segmentIndex)) - gap
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
struct CircularProgress_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
GeometryReader { proxy in
|
||||
CircularProgress(
|
||||
outerCircleProgress: 0.33,
|
||||
innerCircleProgress: 0.8,
|
||||
maxSegments: 10,
|
||||
innerCircleHidden: true
|
||||
)
|
||||
.frame(width: proxy.size.width * 0.8, height: proxy.size.width * 0.8)
|
||||
.offset(x: 40, y: 200)
|
||||
}
|
||||
.applyScreenBackground()
|
||||
.preferredColorScheme(.dark)
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
//
|
||||
// SDKSynchronizer+SyncStatus.swift
|
||||
// secant-testnet
|
||||
//
|
||||
// Created by Lukáš Korba on 12.05.2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import ZcashLightClientKit
|
||||
|
||||
extension SDKSynchronizer {
|
||||
static func textFor(state: SyncStatus) -> String {
|
||||
switch state {
|
||||
case .downloading(let progress):
|
||||
return "Downloading \(progress.progressHeight)/\(progress.targetHeight)"
|
||||
|
||||
case .enhancing(let enhanceProgress):
|
||||
return "Enhancing tx \(enhanceProgress.enhancedTransactions) of \(enhanceProgress.totalTransactions)"
|
||||
|
||||
case .fetching:
|
||||
return "fetching UTXOs"
|
||||
|
||||
case .scanning(let scanProgress):
|
||||
return "Scanning: \(scanProgress.progressHeight)/\(scanProgress.targetHeight)"
|
||||
|
||||
case .disconnected:
|
||||
return "disconnected 💔"
|
||||
|
||||
case .stopped:
|
||||
return "Stopped 🚫"
|
||||
|
||||
case .synced:
|
||||
return "Synced 😎"
|
||||
|
||||
case .unprepared:
|
||||
return "Unprepared 😅"
|
||||
|
||||
case .validating:
|
||||
return "Validating"
|
||||
|
||||
case .error(let err):
|
||||
return "Error: \(err.localizedDescription)"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,7 +45,7 @@ protocol WrappedSDKSynchronizer {
|
|||
func prepareWith(initializer: Initializer) throws
|
||||
func start(retry: Bool) throws
|
||||
func stop()
|
||||
func status() -> String
|
||||
func statusSnapshot() -> SyncStatusSnapshot
|
||||
|
||||
func getShieldedBalance() -> Effect<Balance, Never>
|
||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never>
|
||||
|
@ -143,12 +143,12 @@ class LiveWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
stateChanged.send(.stopped)
|
||||
}
|
||||
|
||||
func status() -> String {
|
||||
func statusSnapshot() -> SyncStatusSnapshot {
|
||||
guard let synchronizer = synchronizer else {
|
||||
return ""
|
||||
return .default
|
||||
}
|
||||
|
||||
return SDKSynchronizer.textFor(state: synchronizer.status)
|
||||
return SyncStatusSnapshot.snapshotFor(state: synchronizer.status)
|
||||
}
|
||||
|
||||
func getShieldedBalance() -> Effect<Balance, Never> {
|
||||
|
@ -281,12 +281,12 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
stateChanged.send(.synced)
|
||||
}
|
||||
|
||||
func status() -> String {
|
||||
func statusSnapshot() -> SyncStatusSnapshot {
|
||||
guard let synchronizer = synchronizer else {
|
||||
return ""
|
||||
return .default
|
||||
}
|
||||
|
||||
return SDKSynchronizer.textFor(state: synchronizer.status)
|
||||
return SyncStatusSnapshot.snapshotFor(state: synchronizer.status)
|
||||
}
|
||||
|
||||
func getShieldedBalance() -> Effect<Balance, Never> {
|
||||
|
@ -397,7 +397,7 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
|
||||
func synchronizerSynced() { }
|
||||
|
||||
func status() -> String { "" }
|
||||
func statusSnapshot() -> SyncStatusSnapshot { .default }
|
||||
|
||||
func getShieldedBalance() -> Effect<Balance, Never> {
|
||||
return .none
|
||||
|
|
|
@ -33,7 +33,15 @@ class HomeTests: XCTestCase {
|
|||
|
||||
store.send(.synchronizerStateChanged(.downloading))
|
||||
|
||||
testScheduler.advance(by: 0.01)
|
||||
|
||||
store.receive(.updateSynchronizerStatus)
|
||||
|
||||
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
||||
store.receive(.updateBalance(balance)) { state in
|
||||
state.totalBalance = Zatoshi(amount: 12_345_000)
|
||||
state.verifiedBalance = Zatoshi(amount: 12_345_000)
|
||||
}
|
||||
}
|
||||
|
||||
/// When the synchronizer status change to .synced, several things happen
|
||||
|
@ -120,7 +128,7 @@ class HomeTests: XCTestCase {
|
|||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi.zero,
|
||||
walletEventsState: .emptyPlaceHolder,
|
||||
verifiedBalance: Zatoshi.zero
|
||||
|
@ -163,7 +171,7 @@ class HomeTests: XCTestCase {
|
|||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi.zero,
|
||||
walletEventsState: .emptyPlaceHolder,
|
||||
verifiedBalance: Zatoshi.zero
|
||||
|
@ -208,7 +216,9 @@ class HomeTests: XCTestCase {
|
|||
environment: testEnvironment
|
||||
)
|
||||
|
||||
store.send(.onAppear)
|
||||
store.send(.onAppear) { state in
|
||||
state.requiredTransactionConfirmations = 10
|
||||
}
|
||||
|
||||
testScheduler.advance(by: 0.01)
|
||||
|
||||
|
@ -216,6 +226,12 @@ class HomeTests: XCTestCase {
|
|||
store.receive(.synchronizerStateChanged(.unknown))
|
||||
store.receive(.updateSynchronizerStatus)
|
||||
|
||||
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
||||
store.receive(.updateBalance(balance)) { state in
|
||||
state.totalBalance = Zatoshi(amount: 12_345_000)
|
||||
state.verifiedBalance = Zatoshi(amount: 12_345_000)
|
||||
}
|
||||
|
||||
// long-living (cancelable) effects need to be properly canceled.
|
||||
// the .onDisappear action cancles the observer of the synchronizer status change.
|
||||
store.send(.onDisappear)
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// HomeCircularProgressSnapshotTests.swift
|
||||
// secantTests
|
||||
//
|
||||
// Created by Lukáš Korba on 07.07.2022.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import ComposableArchitecture
|
||||
@testable import secant_testnet
|
||||
@testable import ZcashLightClientKit
|
||||
|
||||
class HomeCircularProgressSnapshotTests: XCTestCase {
|
||||
func testCircularProgress_DownloadingInnerCircle() throws {
|
||||
class SnapshotTestWrappedSDKSynchronizer: TestWrappedSDKSynchronizer {
|
||||
// heights purposely set so we visually see 55% progress
|
||||
override func statusSnapshot() -> SyncStatusSnapshot {
|
||||
let blockProgress = BlockProgress(
|
||||
startHeight: BlockHeight(0),
|
||||
targetHeight: BlockHeight(100),
|
||||
progressHeight: BlockHeight(55)
|
||||
)
|
||||
|
||||
return SyncStatusSnapshot.snapshotFor(state: .downloading(blockProgress))
|
||||
}
|
||||
}
|
||||
|
||||
let balance = Balance(verified: 15_345_000, total: 15_345_000)
|
||||
|
||||
let testScheduler = DispatchQueue.test
|
||||
|
||||
let testEnvironment = HomeEnvironment(
|
||||
audioServices: .silent,
|
||||
derivationTool: .live(),
|
||||
feedbackGenerator: .silent,
|
||||
mnemonic: .mock,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: SnapshotTestWrappedSDKSynchronizer(),
|
||||
walletStorage: .throwing,
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let store = HomeStore(
|
||||
initialState: .init(
|
||||
drawerOverlay: .partial,
|
||||
profileState: .placeholder,
|
||||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .emptyPlaceHolder,
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
),
|
||||
reducer: .default,
|
||||
environment: testEnvironment
|
||||
)
|
||||
|
||||
addAttachments(HomeView(store: store))
|
||||
}
|
||||
|
||||
func testCircularProgress_ScanningOuterCircle() throws {
|
||||
class SnapshotTestWrappedSDKSynchronizer: TestWrappedSDKSynchronizer {
|
||||
override func statusSnapshot() -> SyncStatusSnapshot {
|
||||
// heights purposely set so we visually see 72% progress
|
||||
let blockProgress = BlockProgress(
|
||||
startHeight: BlockHeight(0),
|
||||
targetHeight: BlockHeight(100),
|
||||
progressHeight: BlockHeight(72)
|
||||
)
|
||||
|
||||
return SyncStatusSnapshot.snapshotFor(state: .scanning(blockProgress))
|
||||
}
|
||||
}
|
||||
|
||||
let balance = Balance(verified: 15_345_000, total: 15_345_000)
|
||||
|
||||
let testScheduler = DispatchQueue.test
|
||||
|
||||
let testEnvironment = HomeEnvironment(
|
||||
audioServices: .silent,
|
||||
derivationTool: .live(),
|
||||
feedbackGenerator: .silent,
|
||||
mnemonic: .mock,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: SnapshotTestWrappedSDKSynchronizer(),
|
||||
walletStorage: .throwing,
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let store = HomeStore(
|
||||
initialState: .init(
|
||||
drawerOverlay: .partial,
|
||||
profileState: .placeholder,
|
||||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .emptyPlaceHolder,
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
),
|
||||
reducer: .default,
|
||||
environment: testEnvironment
|
||||
)
|
||||
|
||||
addAttachments(HomeView(store: store))
|
||||
}
|
||||
|
||||
func testCircularProgress_UpToDateOnlyOuterCircle() throws {
|
||||
class SnapshotTestWrappedSDKSynchronizer: TestWrappedSDKSynchronizer {
|
||||
override func statusSnapshot() -> SyncStatusSnapshot {
|
||||
SyncStatusSnapshot.snapshotFor(state: .synced)
|
||||
}
|
||||
}
|
||||
|
||||
let balance = Balance(verified: 15_345_000, total: 15_345_000)
|
||||
|
||||
let testScheduler = DispatchQueue.test
|
||||
|
||||
let testEnvironment = HomeEnvironment(
|
||||
audioServices: .silent,
|
||||
derivationTool: .live(),
|
||||
feedbackGenerator: .silent,
|
||||
mnemonic: .mock,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: SnapshotTestWrappedSDKSynchronizer(),
|
||||
walletStorage: .throwing,
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let store = HomeStore(
|
||||
initialState: .init(
|
||||
drawerOverlay: .partial,
|
||||
profileState: .placeholder,
|
||||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .emptyPlaceHolder,
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
),
|
||||
reducer: .default,
|
||||
environment: testEnvironment
|
||||
)
|
||||
|
||||
addAttachments(HomeView(store: store))
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@ class HomeSnapshotTests: XCTestCase {
|
|||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: walletEvents)),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
|
@ -90,7 +90,7 @@ class HomeSnapshotTests: XCTestCase {
|
|||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
|
|
|
@ -37,7 +37,7 @@ class WalletEventsSnapshotTests: XCTestCase {
|
|||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
|
@ -94,7 +94,7 @@ class WalletEventsSnapshotTests: XCTestCase {
|
|||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
|
@ -151,7 +151,7 @@ class WalletEventsSnapshotTests: XCTestCase {
|
|||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
|
@ -214,7 +214,7 @@ class WalletEventsSnapshotTests: XCTestCase {
|
|||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
|
|
Loading…
Reference in New Issue