- full screen cover for the balance breakdown - clearing out the background so we can do semi transparency - bindings for the full screen cover [224] [Scaffold] Balance Breakdown - draft of UI [224] [Scaffold] Balance Breakdown - latest block business logic - mocked auto shielding threshold - unit tests - snapshot tests [224] [Scaffold] Balance Breakdown (412) - comments resolved - bigger refactor of the synchronizer, taking advantage of SynchronizerState being reported every time .synced pass - unit tests fixed and refactored [224] [Scaffold] Balance Breakdown (412) - ClearBackgroundView documented, reference to the proposed solution added
This commit is contained in:
parent
558675aced
commit
368f95e7a7
|
@ -128,6 +128,9 @@
|
||||||
9E66129B28884BFB00C75B70 /* LocalAuthenticationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E66129A28884BFB00C75B70 /* LocalAuthenticationHandler.swift */; };
|
9E66129B28884BFB00C75B70 /* LocalAuthenticationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E66129A28884BFB00C75B70 /* LocalAuthenticationHandler.swift */; };
|
||||||
9E66129E288938A300C75B70 /* SettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E66129D288938A300C75B70 /* SettingsTests.swift */; };
|
9E66129E288938A300C75B70 /* SettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E66129D288938A300C75B70 /* SettingsTests.swift */; };
|
||||||
9E6713F12897F81B00A6796F /* MultiLineTextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6713F02897F81B00A6796F /* MultiLineTextFieldTests.swift */; };
|
9E6713F12897F81B00A6796F /* MultiLineTextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6713F02897F81B00A6796F /* MultiLineTextFieldTests.swift */; };
|
||||||
|
9E6713F7289BC58C00A6796F /* BalanceBreakdownStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6713F6289BC58C00A6796F /* BalanceBreakdownStore.swift */; };
|
||||||
|
9E6713F8289BC58C00A6796F /* BalanceBreakdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6713F5289BC58C00A6796F /* BalanceBreakdownView.swift */; };
|
||||||
|
9E6713FA289BE0E100A6796F /* ClearBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6713F9289BE0E100A6796F /* ClearBackgroundView.swift */; };
|
||||||
9E69A24D27FB002800A55317 /* WelcomeStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E69A24C27FB002800A55317 /* WelcomeStore.swift */; };
|
9E69A24D27FB002800A55317 /* WelcomeStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E69A24C27FB002800A55317 /* WelcomeStore.swift */; };
|
||||||
9E7225F12889539300DF7F17 /* SettingsSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7225F02889539300DF7F17 /* SettingsSnapshotTests.swift */; };
|
9E7225F12889539300DF7F17 /* SettingsSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7225F02889539300DF7F17 /* SettingsSnapshotTests.swift */; };
|
||||||
9E7225F3288AB6DD00DF7F17 /* MultipleLineTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7225F2288AB6DD00DF7F17 /* MultipleLineTextField.swift */; };
|
9E7225F3288AB6DD00DF7F17 /* MultipleLineTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7225F2288AB6DD00DF7F17 /* MultipleLineTextField.swift */; };
|
||||||
|
@ -155,6 +158,8 @@
|
||||||
9E7FE0F92832824C00C374E8 /* QRCodeScanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0F82832824C00C374E8 /* QRCodeScanView.swift */; };
|
9E7FE0F92832824C00C374E8 /* QRCodeScanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0F82832824C00C374E8 /* QRCodeScanView.swift */; };
|
||||||
9E87ADF128363DE400122FCC /* WrappedAudioServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E87ADF028363DE400122FCC /* WrappedAudioServices.swift */; };
|
9E87ADF128363DE400122FCC /* WrappedAudioServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E87ADF028363DE400122FCC /* WrappedAudioServices.swift */; };
|
||||||
9E92AF0828530EBF007367AD /* View+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E92AF0728530EBF007367AD /* View+UIImage.swift */; };
|
9E92AF0828530EBF007367AD /* View+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E92AF0728530EBF007367AD /* View+UIImage.swift */; };
|
||||||
|
9E94C62028AA7DEE008256E9 /* BalanceBreakdownTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E94C61F28AA7DEE008256E9 /* BalanceBreakdownTests.swift */; };
|
||||||
|
9E94C62328AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E94C62228AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift */; };
|
||||||
9E9ECC9728589E150099D5A2 /* HomeSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9ECC8C28589E150099D5A2 /* HomeSnapshotTests.swift */; };
|
9E9ECC9728589E150099D5A2 /* HomeSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9ECC8C28589E150099D5A2 /* HomeSnapshotTests.swift */; };
|
||||||
9E9ECC9828589E150099D5A2 /* WelcomeSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9ECC8E28589E150099D5A2 /* WelcomeSnapshotTests.swift */; };
|
9E9ECC9828589E150099D5A2 /* WelcomeSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9ECC8E28589E150099D5A2 /* WelcomeSnapshotTests.swift */; };
|
||||||
9E9ECC9928589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9ECC9028589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift */; };
|
9E9ECC9928589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9ECC9028589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift */; };
|
||||||
|
@ -184,7 +189,6 @@
|
||||||
9EF8135D27ECC25E0075AF48 /* UserPreferencesStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8135B27ECC25E0075AF48 /* UserPreferencesStorageTests.swift */; };
|
9EF8135D27ECC25E0075AF48 /* UserPreferencesStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8135B27ECC25E0075AF48 /* UserPreferencesStorageTests.swift */; };
|
||||||
9EF8136027F043CC0075AF48 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8135F27F043CC0075AF48 /* AppDelegate.swift */; };
|
9EF8136027F043CC0075AF48 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8135F27F043CC0075AF48 /* AppDelegate.swift */; };
|
||||||
9EF8139127F191BF0075AF48 /* WrappedWalletStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8139027F191BF0075AF48 /* WrappedWalletStorage.swift */; };
|
9EF8139127F191BF0075AF48 /* WrappedWalletStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8139027F191BF0075AF48 /* WrappedWalletStorage.swift */; };
|
||||||
9EF8139827F1FAEC0075AF48 /* ZcashLightClientKit in Frameworks */ = {isa = PBXBuildFile; productRef = 9EF8139727F1FAEC0075AF48 /* ZcashLightClientKit */; };
|
|
||||||
9EF8139C27F47AED0075AF48 /* InitializationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8139B27F47AED0075AF48 /* InitializationState.swift */; };
|
9EF8139C27F47AED0075AF48 /* InitializationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8139B27F47AED0075AF48 /* InitializationState.swift */; };
|
||||||
F9322DC0273B555C00C105B5 /* NavigationLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9322DBF273B555C00C105B5 /* NavigationLinks.swift */; };
|
F9322DC0273B555C00C105B5 /* NavigationLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9322DBF273B555C00C105B5 /* NavigationLinks.swift */; };
|
||||||
F93673D62742CB840099C6AF /* Previews.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93673D52742CB840099C6AF /* Previews.swift */; };
|
F93673D62742CB840099C6AF /* Previews.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93673D52742CB840099C6AF /* Previews.swift */; };
|
||||||
|
@ -355,6 +359,9 @@
|
||||||
9E66129A28884BFB00C75B70 /* LocalAuthenticationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAuthenticationHandler.swift; sourceTree = "<group>"; };
|
9E66129A28884BFB00C75B70 /* LocalAuthenticationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAuthenticationHandler.swift; sourceTree = "<group>"; };
|
||||||
9E66129D288938A300C75B70 /* SettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTests.swift; sourceTree = "<group>"; };
|
9E66129D288938A300C75B70 /* SettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTests.swift; sourceTree = "<group>"; };
|
||||||
9E6713F02897F81B00A6796F /* MultiLineTextFieldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiLineTextFieldTests.swift; sourceTree = "<group>"; };
|
9E6713F02897F81B00A6796F /* MultiLineTextFieldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiLineTextFieldTests.swift; sourceTree = "<group>"; };
|
||||||
|
9E6713F5289BC58C00A6796F /* BalanceBreakdownView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceBreakdownView.swift; sourceTree = "<group>"; };
|
||||||
|
9E6713F6289BC58C00A6796F /* BalanceBreakdownStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceBreakdownStore.swift; sourceTree = "<group>"; };
|
||||||
|
9E6713F9289BE0E100A6796F /* ClearBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearBackgroundView.swift; sourceTree = "<group>"; };
|
||||||
9E69A24C27FB002800A55317 /* WelcomeStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeStore.swift; sourceTree = "<group>"; };
|
9E69A24C27FB002800A55317 /* WelcomeStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeStore.swift; sourceTree = "<group>"; };
|
||||||
9E7225F02889539300DF7F17 /* SettingsSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSnapshotTests.swift; sourceTree = "<group>"; };
|
9E7225F02889539300DF7F17 /* SettingsSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSnapshotTests.swift; sourceTree = "<group>"; };
|
||||||
9E7225F2288AB6DD00DF7F17 /* MultipleLineTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleLineTextField.swift; sourceTree = "<group>"; };
|
9E7225F2288AB6DD00DF7F17 /* MultipleLineTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleLineTextField.swift; sourceTree = "<group>"; };
|
||||||
|
@ -380,6 +387,8 @@
|
||||||
9E7FE0F82832824C00C374E8 /* QRCodeScanView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScanView.swift; sourceTree = "<group>"; };
|
9E7FE0F82832824C00C374E8 /* QRCodeScanView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScanView.swift; sourceTree = "<group>"; };
|
||||||
9E87ADF028363DE400122FCC /* WrappedAudioServices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedAudioServices.swift; sourceTree = "<group>"; };
|
9E87ADF028363DE400122FCC /* WrappedAudioServices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedAudioServices.swift; sourceTree = "<group>"; };
|
||||||
9E92AF0728530EBF007367AD /* View+UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+UIImage.swift"; sourceTree = "<group>"; };
|
9E92AF0728530EBF007367AD /* View+UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+UIImage.swift"; sourceTree = "<group>"; };
|
||||||
|
9E94C61F28AA7DEE008256E9 /* BalanceBreakdownTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceBreakdownTests.swift; sourceTree = "<group>"; };
|
||||||
|
9E94C62228AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceBreakdownSnapshotTests.swift; sourceTree = "<group>"; };
|
||||||
9E9ECC8C28589E150099D5A2 /* HomeSnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeSnapshotTests.swift; sourceTree = "<group>"; };
|
9E9ECC8C28589E150099D5A2 /* HomeSnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeSnapshotTests.swift; sourceTree = "<group>"; };
|
||||||
9E9ECC8E28589E150099D5A2 /* WelcomeSnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WelcomeSnapshotTests.swift; sourceTree = "<group>"; };
|
9E9ECC8E28589E150099D5A2 /* WelcomeSnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WelcomeSnapshotTests.swift; sourceTree = "<group>"; };
|
||||||
9E9ECC9028589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecoveryPhraseDisplaySnapshotTests.swift; sourceTree = "<group>"; };
|
9E9ECC9028589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecoveryPhraseDisplaySnapshotTests.swift; sourceTree = "<group>"; };
|
||||||
|
@ -440,7 +449,6 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
9EF8139827F1FAEC0075AF48 /* ZcashLightClientKit in Frameworks */,
|
|
||||||
9E6612312878337F00C75B70 /* Lottie in Frameworks */,
|
9E6612312878337F00C75B70 /* Lottie in Frameworks */,
|
||||||
9E7CB6182872D3DF00A02233 /* URLRouting in Frameworks */,
|
9E7CB6182872D3DF00A02233 /* URLRouting in Frameworks */,
|
||||||
0DB4E0B42881FD9100947B78 /* ZcashLightClientKit in Frameworks */,
|
0DB4E0B42881FD9100947B78 /* ZcashLightClientKit in Frameworks */,
|
||||||
|
@ -555,6 +563,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
9E391162284E3ECF0073DD9A /* SnapshotTests */,
|
9E391162284E3ECF0073DD9A /* SnapshotTests */,
|
||||||
|
9E94C61E28AA7DD5008256E9 /* BalanceBreakdownTests */,
|
||||||
9E6713EF2897F80A00A6796F /* MultiLineTextFieldTests */,
|
9E6713EF2897F80A00A6796F /* MultiLineTextFieldTests */,
|
||||||
9E7CB6222874245400A02233 /* ProfileTests */,
|
9E7CB6222874245400A02233 /* ProfileTests */,
|
||||||
9EAB4674285B5C68002904A0 /* DeeplinkTests */,
|
9EAB4674285B5C68002904A0 /* DeeplinkTests */,
|
||||||
|
@ -718,6 +727,7 @@
|
||||||
0D0781C2278750C00083ACD7 /* Welcome */,
|
0D0781C2278750C00083ACD7 /* Welcome */,
|
||||||
F9971A4927680DC400A2DB75 /* App */,
|
F9971A4927680DC400A2DB75 /* App */,
|
||||||
F93874EC273C4DE200F0E875 /* Home */,
|
F93874EC273C4DE200F0E875 /* Home */,
|
||||||
|
9E6713F2289BC51200A6796F /* BalanceBreakdown */,
|
||||||
F9971A4F27680DD000A2DB75 /* Profile */,
|
F9971A4F27680DD000A2DB75 /* Profile */,
|
||||||
9E7CB61B2874140900A02233 /* AddressDetails */,
|
9E7CB61B2874140900A02233 /* AddressDetails */,
|
||||||
F9971A5527680DDE00A2DB75 /* Request */,
|
F9971A5527680DDE00A2DB75 /* Request */,
|
||||||
|
@ -856,6 +866,7 @@
|
||||||
9E391162284E3ECF0073DD9A /* SnapshotTests */ = {
|
9E391162284E3ECF0073DD9A /* SnapshotTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
9E94C62128AA7ECD008256E9 /* BalanceBreakdownSnapshotTests */,
|
||||||
9E7225EF2889537E00DF7F17 /* SettingsSnapshotTests */,
|
9E7225EF2889537E00DF7F17 /* SettingsSnapshotTests */,
|
||||||
9E7CB6252874267B00A02233 /* ProfileSnapshotTests */,
|
9E7CB6252874267B00A02233 /* ProfileSnapshotTests */,
|
||||||
9E7CB6102869881300A02233 /* WalletEventsSnapshotTests */,
|
9E7CB6102869881300A02233 /* WalletEventsSnapshotTests */,
|
||||||
|
@ -931,6 +942,15 @@
|
||||||
path = MultiLineTextFieldTests;
|
path = MultiLineTextFieldTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
9E6713F2289BC51200A6796F /* BalanceBreakdown */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9E6713F6289BC58C00A6796F /* BalanceBreakdownStore.swift */,
|
||||||
|
9E6713F5289BC58C00A6796F /* BalanceBreakdownView.swift */,
|
||||||
|
);
|
||||||
|
path = BalanceBreakdown;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9E7225EF2889537E00DF7F17 /* SettingsSnapshotTests */ = {
|
9E7225EF2889537E00DF7F17 /* SettingsSnapshotTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1029,6 +1049,7 @@
|
||||||
2EDA07A327EDE2A900D6F09B /* DebugFrame.swift */,
|
2EDA07A327EDE2A900D6F09B /* DebugFrame.swift */,
|
||||||
9E2F1C832809B606004E65FE /* DebugMenu.swift */,
|
9E2F1C832809B606004E65FE /* DebugMenu.swift */,
|
||||||
9E7CB619287310EC00A02233 /* QRCodeGenerator.swift */,
|
9E7CB619287310EC00A02233 /* QRCodeGenerator.swift */,
|
||||||
|
9E6713F9289BE0E100A6796F /* ClearBackgroundView.swift */,
|
||||||
);
|
);
|
||||||
path = Utils;
|
path = Utils;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1132,6 +1153,22 @@
|
||||||
path = UIKitBridge;
|
path = UIKitBridge;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
9E94C61E28AA7DD5008256E9 /* BalanceBreakdownTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9E94C61F28AA7DEE008256E9 /* BalanceBreakdownTests.swift */,
|
||||||
|
);
|
||||||
|
path = BalanceBreakdownTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9E94C62128AA7ECD008256E9 /* BalanceBreakdownSnapshotTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9E94C62228AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift */,
|
||||||
|
);
|
||||||
|
path = BalanceBreakdownSnapshotTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9E9ECC8B28589E150099D5A2 /* HomeSnapshotTests */ = {
|
9E9ECC8B28589E150099D5A2 /* HomeSnapshotTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1345,7 +1382,6 @@
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
6654C7392715A38000901167 /* ComposableArchitecture */,
|
6654C7392715A38000901167 /* ComposableArchitecture */,
|
||||||
9E2AC0FE27D8EC120042AA47 /* MnemonicSwift */,
|
9E2AC0FE27D8EC120042AA47 /* MnemonicSwift */,
|
||||||
9EF8139727F1FAEC0075AF48 /* ZcashLightClientKit */,
|
|
||||||
9EAB466C285A0468002904A0 /* Parsing */,
|
9EAB466C285A0468002904A0 /* Parsing */,
|
||||||
9EAB466E285A0468002904A0 /* _URLRouting */,
|
9EAB466E285A0468002904A0 /* _URLRouting */,
|
||||||
9E7CB6172872D3DF00A02233 /* URLRouting */,
|
9E7CB6172872D3DF00A02233 /* URLRouting */,
|
||||||
|
@ -1428,7 +1464,6 @@
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */,
|
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */,
|
||||||
9E2AC0FD27D8EC120042AA47 /* XCRemoteSwiftPackageReference "MnemonicSwift" */,
|
9E2AC0FD27D8EC120042AA47 /* XCRemoteSwiftPackageReference "MnemonicSwift" */,
|
||||||
9EF8139627F1FAEC0075AF48 /* XCRemoteSwiftPackageReference "ZcashLightClientKit" */,
|
|
||||||
9EAB466B285A0468002904A0 /* XCRemoteSwiftPackageReference "swift-parsing" */,
|
9EAB466B285A0468002904A0 /* XCRemoteSwiftPackageReference "swift-parsing" */,
|
||||||
9E7CB6162872D3DF00A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */,
|
9E7CB6162872D3DF00A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */,
|
||||||
9E66122F2878337F00C75B70 /* XCRemoteSwiftPackageReference "lottie-ios" */,
|
9E66122F2878337F00C75B70 /* XCRemoteSwiftPackageReference "lottie-ios" */,
|
||||||
|
@ -1574,6 +1609,7 @@
|
||||||
9E7FE0D9282D289B00C374E8 /* WrappedFeedbackGenerator.swift in Sources */,
|
9E7FE0D9282D289B00C374E8 /* WrappedFeedbackGenerator.swift in Sources */,
|
||||||
2E6CF8DD27D78319004DCD7A /* CurrencySelectionStore.swift in Sources */,
|
2E6CF8DD27D78319004DCD7A /* CurrencySelectionStore.swift in Sources */,
|
||||||
9EBEF87A27CE369800B4F343 /* RecoveryPhraseValidationFlowView.swift in Sources */,
|
9EBEF87A27CE369800B4F343 /* RecoveryPhraseValidationFlowView.swift in Sources */,
|
||||||
|
9E6713F7289BC58C00A6796F /* BalanceBreakdownStore.swift in Sources */,
|
||||||
9E66122C2877188700C75B70 /* SyncStatusSnapshot.swift in Sources */,
|
9E66122C2877188700C75B70 /* SyncStatusSnapshot.swift in Sources */,
|
||||||
9E4DC6E227C4C6B700E657F4 /* SecantButtonStyles.swift in Sources */,
|
9E4DC6E227C4C6B700E657F4 /* SecantButtonStyles.swift in Sources */,
|
||||||
0DDB6A5127737D4A0012A410 /* RecoveryPhraseBackupFailedView.swift in Sources */,
|
0DDB6A5127737D4A0012A410 /* RecoveryPhraseBackupFailedView.swift in Sources */,
|
||||||
|
@ -1657,6 +1693,7 @@
|
||||||
F9C165B4274031F600592F76 /* Bindings.swift in Sources */,
|
F9C165B4274031F600592F76 /* Bindings.swift in Sources */,
|
||||||
2E35F99A27B3E99C00EB79CD /* TextFieldTitleAccessoryButtonStyle.swift in Sources */,
|
2E35F99A27B3E99C00EB79CD /* TextFieldTitleAccessoryButtonStyle.swift in Sources */,
|
||||||
9E2DF99C27CF704D00649636 /* ImportWalletStore.swift in Sources */,
|
9E2DF99C27CF704D00649636 /* ImportWalletStore.swift in Sources */,
|
||||||
|
9E6713F8289BC58C00A6796F /* BalanceBreakdownView.swift in Sources */,
|
||||||
F9971A6627680DFE00A2DB75 /* SettingsView.swift in Sources */,
|
F9971A6627680DFE00A2DB75 /* SettingsView.swift in Sources */,
|
||||||
F96B41EB273B50520021B49A /* Strings.swift in Sources */,
|
F96B41EB273B50520021B49A /* Strings.swift in Sources */,
|
||||||
2EDA07A227EDE1AE00D6F09B /* TextFieldFooter.swift in Sources */,
|
2EDA07A227EDE1AE00D6F09B /* TextFieldFooter.swift in Sources */,
|
||||||
|
@ -1675,6 +1712,7 @@
|
||||||
0D0781C9278776D20083ACD7 /* ZcashSymbol.swift in Sources */,
|
0D0781C9278776D20083ACD7 /* ZcashSymbol.swift in Sources */,
|
||||||
2E8719CB27FB09990082C926 /* TransactionAmountTextField.swift in Sources */,
|
2E8719CB27FB09990082C926 /* TransactionAmountTextField.swift in Sources */,
|
||||||
9E7CB6212874143800A02233 /* AddressDetailsView.swift in Sources */,
|
9E7CB6212874143800A02233 /* AddressDetailsView.swift in Sources */,
|
||||||
|
9E6713FA289BE0E100A6796F /* ClearBackgroundView.swift in Sources */,
|
||||||
F9C165C42740403600592F76 /* TransactionSentView.swift in Sources */,
|
F9C165C42740403600592F76 /* TransactionSentView.swift in Sources */,
|
||||||
F9971A5927680DDE00A2DB75 /* RequestStore.swift in Sources */,
|
F9971A5927680DDE00A2DB75 /* RequestStore.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
@ -1694,6 +1732,7 @@
|
||||||
9E7CB6272874269F00A02233 /* ProfileSnapshotTests.swift in Sources */,
|
9E7CB6272874269F00A02233 /* ProfileSnapshotTests.swift in Sources */,
|
||||||
9E92AF0828530EBF007367AD /* View+UIImage.swift in Sources */,
|
9E92AF0828530EBF007367AD /* View+UIImage.swift in Sources */,
|
||||||
6654C7442715A4AC00901167 /* OnboardingStoreTests.swift in Sources */,
|
6654C7442715A4AC00901167 /* OnboardingStoreTests.swift in Sources */,
|
||||||
|
9E94C62328AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift in Sources */,
|
||||||
9E39112E283F91600073DD9A /* ZatoshiTests.swift in Sources */,
|
9E39112E283F91600073DD9A /* ZatoshiTests.swift in Sources */,
|
||||||
9E9ECC9B28589E150099D5A2 /* ImportWalletSnapshotTests.swift in Sources */,
|
9E9ECC9B28589E150099D5A2 /* ImportWalletSnapshotTests.swift in Sources */,
|
||||||
9EDDEAA32829610D00B4100C /* TransactionAmountInputTests.swift in Sources */,
|
9EDDEAA32829610D00B4100C /* TransactionAmountInputTests.swift in Sources */,
|
||||||
|
@ -1720,6 +1759,7 @@
|
||||||
0DB4E0B12881F2DB00947B78 /* WalletBalance+testing.swift in Sources */,
|
0DB4E0B12881F2DB00947B78 /* WalletBalance+testing.swift in Sources */,
|
||||||
9E02B56C27FED475005B809B /* DatabaseFilesTests.swift in Sources */,
|
9E02B56C27FED475005B809B /* DatabaseFilesTests.swift in Sources */,
|
||||||
9EF8135D27ECC25E0075AF48 /* UserPreferencesStorageTests.swift in Sources */,
|
9EF8135D27ECC25E0075AF48 /* UserPreferencesStorageTests.swift in Sources */,
|
||||||
|
9E94C62028AA7DEE008256E9 /* BalanceBreakdownTests.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -2041,8 +2081,8 @@
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/zcash/ZcashLightClientKit/";
|
repositoryURL = "https://github.com/zcash/ZcashLightClientKit/";
|
||||||
requirement = {
|
requirement = {
|
||||||
branch = master;
|
kind = exactVersion;
|
||||||
kind = branch;
|
version = "0.16.6-beta";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
|
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
|
||||||
|
@ -2085,14 +2125,6 @@
|
||||||
minimumVersion = 0.9.2;
|
minimumVersion = 0.9.2;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
9EF8139627F1FAEC0075AF48 /* XCRemoteSwiftPackageReference "ZcashLightClientKit" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/zcash/ZcashLightClientKit";
|
|
||||||
requirement = {
|
|
||||||
branch = master;
|
|
||||||
kind = branch;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
|
@ -2131,11 +2163,6 @@
|
||||||
package = 9EAB466B285A0468002904A0 /* XCRemoteSwiftPackageReference "swift-parsing" */;
|
package = 9EAB466B285A0468002904A0 /* XCRemoteSwiftPackageReference "swift-parsing" */;
|
||||||
productName = _URLRouting;
|
productName = _URLRouting;
|
||||||
};
|
};
|
||||||
9EF8139727F1FAEC0075AF48 /* ZcashLightClientKit */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = 9EF8139627F1FAEC0075AF48 /* XCRemoteSwiftPackageReference "ZcashLightClientKit" */;
|
|
||||||
productName = ZcashLightClientKit;
|
|
||||||
};
|
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = 0D4E79FD26B364170058B01E /* Project object */;
|
rootObject = 0D4E79FD26B364170058B01E /* Project object */;
|
||||||
|
|
|
@ -203,8 +203,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/zcash/ZcashLightClientKit",
|
"location" : "https://github.com/zcash/ZcashLightClientKit",
|
||||||
"state" : {
|
"state" : {
|
||||||
"branch" : "master",
|
"revision" : "a37c140441d78fa6ad9c89e2fbb539f1ddb7e5a1",
|
||||||
"revision" : "fba4cecbe61cce424ada9fe1f98b05b88d5c8920"
|
"version" : "0.16.6-beta"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -16,6 +16,7 @@ fileprivate enum ZcashSDKConstants {
|
||||||
static let endpointPort = 9067
|
static let endpointPort = 9067
|
||||||
static let mnemonicWordsMaxCount = 24
|
static let mnemonicWordsMaxCount = 24
|
||||||
static let requiredTransactionConfirmations = 10
|
static let requiredTransactionConfirmations = 10
|
||||||
|
static let streamingCallTimeoutInMillis = Int64(10 * 60 * 60 * 1000) // ten hours
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ZCashSDKEnvironment {
|
struct ZCashSDKEnvironment {
|
||||||
|
@ -33,29 +34,49 @@ struct ZCashSDKEnvironment {
|
||||||
extension ZCashSDKEnvironment {
|
extension ZCashSDKEnvironment {
|
||||||
static let mainnet = ZCashSDKEnvironment(
|
static let mainnet = ZCashSDKEnvironment(
|
||||||
defaultBirthday: BlockHeight(ZcashSDKConstants.defaultBlockHeight),
|
defaultBirthday: BlockHeight(ZcashSDKConstants.defaultBlockHeight),
|
||||||
endpoint: LightWalletEndpoint(address: ZcashSDKConstants.endpointMainnetAddress, port: ZcashSDKConstants.endpointPort),
|
endpoint: LightWalletEndpoint(
|
||||||
|
address: ZcashSDKConstants.endpointMainnetAddress,
|
||||||
|
port: ZcashSDKConstants.endpointPort,
|
||||||
|
secure: true,
|
||||||
|
streamingCallTimeoutInMillis: ZcashSDKConstants.streamingCallTimeoutInMillis
|
||||||
|
),
|
||||||
isMainnet: { true },
|
isMainnet: { true },
|
||||||
lightWalletService: LightWalletGRPCService(
|
lightWalletService: LightWalletGRPCService(
|
||||||
endpoint: LightWalletEndpoint(address: ZcashSDKConstants.endpointMainnetAddress, port: ZcashSDKConstants.endpointPort)
|
endpoint: LightWalletEndpoint(
|
||||||
|
address: ZcashSDKConstants.endpointMainnetAddress,
|
||||||
|
port: ZcashSDKConstants.endpointPort,
|
||||||
|
secure: true,
|
||||||
|
streamingCallTimeoutInMillis: ZcashSDKConstants.streamingCallTimeoutInMillis
|
||||||
|
)
|
||||||
),
|
),
|
||||||
memoCharLimit: 512,
|
memoCharLimit: 512,
|
||||||
mnemonicWordsMaxCount: ZcashSDKConstants.mnemonicWordsMaxCount,
|
mnemonicWordsMaxCount: ZcashSDKConstants.mnemonicWordsMaxCount,
|
||||||
network: ZcashNetworkBuilder.network(for: .mainnet),
|
network: ZcashNetworkBuilder.network(for: .mainnet),
|
||||||
requiredTransactionConfirmations: ZcashSDKConstants.requiredTransactionConfirmations,
|
requiredTransactionConfirmations: ZcashSDKConstants.requiredTransactionConfirmations,
|
||||||
sdkVersion: "0.14.0-beta"
|
sdkVersion: "0.16.5-beta"
|
||||||
)
|
)
|
||||||
|
|
||||||
static let testnet = ZCashSDKEnvironment(
|
static let testnet = ZCashSDKEnvironment(
|
||||||
defaultBirthday: BlockHeight(ZcashSDKConstants.defaultBlockHeight),
|
defaultBirthday: BlockHeight(ZcashSDKConstants.defaultBlockHeight),
|
||||||
endpoint: LightWalletEndpoint(address: ZcashSDKConstants.endpointTestnetAddress, port: ZcashSDKConstants.endpointPort),
|
endpoint: LightWalletEndpoint(
|
||||||
|
address: ZcashSDKConstants.endpointTestnetAddress,
|
||||||
|
port: ZcashSDKConstants.endpointPort,
|
||||||
|
secure: true,
|
||||||
|
streamingCallTimeoutInMillis: ZcashSDKConstants.streamingCallTimeoutInMillis
|
||||||
|
),
|
||||||
isMainnet: { false },
|
isMainnet: { false },
|
||||||
lightWalletService: LightWalletGRPCService(
|
lightWalletService: LightWalletGRPCService(
|
||||||
endpoint: LightWalletEndpoint(address: ZcashSDKConstants.endpointTestnetAddress, port: ZcashSDKConstants.endpointPort)
|
endpoint: LightWalletEndpoint(
|
||||||
|
address: ZcashSDKConstants.endpointTestnetAddress,
|
||||||
|
port: ZcashSDKConstants.endpointPort,
|
||||||
|
secure: true,
|
||||||
|
streamingCallTimeoutInMillis: ZcashSDKConstants.streamingCallTimeoutInMillis
|
||||||
|
)
|
||||||
),
|
),
|
||||||
memoCharLimit: 512,
|
memoCharLimit: 512,
|
||||||
mnemonicWordsMaxCount: ZcashSDKConstants.mnemonicWordsMaxCount,
|
mnemonicWordsMaxCount: ZcashSDKConstants.mnemonicWordsMaxCount,
|
||||||
network: ZcashNetworkBuilder.network(for: .testnet),
|
network: ZcashNetworkBuilder.network(for: .testnet),
|
||||||
requiredTransactionConfirmations: ZcashSDKConstants.requiredTransactionConfirmations,
|
requiredTransactionConfirmations: ZcashSDKConstants.requiredTransactionConfirmations,
|
||||||
sdkVersion: "0.14.0-beta"
|
sdkVersion: "0.16.5-beta"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
//
|
||||||
|
// BalanceBreakdownStore.swift
|
||||||
|
// secant-testnet
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 04.08.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ComposableArchitecture
|
||||||
|
import ZcashLightClientKit
|
||||||
|
|
||||||
|
typealias BalanceBreakdownReducer = Reducer<BalanceBreakdownState, BalanceBreakdownAction, BalanceBreakdownEnvironment>
|
||||||
|
typealias BalanceBreakdownStore = Store<BalanceBreakdownState, BalanceBreakdownAction>
|
||||||
|
typealias BalanceBreakdownViewStore = ViewStore<BalanceBreakdownState, BalanceBreakdownAction>
|
||||||
|
|
||||||
|
// MARK: - State
|
||||||
|
|
||||||
|
struct BalanceBreakdownState: Equatable {
|
||||||
|
var autoShieldingTreshold: Zatoshi
|
||||||
|
var latestBlock: String
|
||||||
|
var shieldedBalance: WalletBalance
|
||||||
|
var transparentBalance: WalletBalance
|
||||||
|
|
||||||
|
var totalBalance: Zatoshi {
|
||||||
|
shieldedBalance.total + transparentBalance.total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Action
|
||||||
|
|
||||||
|
enum BalanceBreakdownAction: Equatable {
|
||||||
|
case onAppear
|
||||||
|
case onDisappear
|
||||||
|
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
||||||
|
case updateLatestBlock
|
||||||
|
case updateSynchronizerStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Environment
|
||||||
|
|
||||||
|
struct BalanceBreakdownEnvironment {
|
||||||
|
let numberFormatter: WrappedNumberFormatter
|
||||||
|
let SDKSynchronizer: WrappedSDKSynchronizer
|
||||||
|
let scheduler: AnySchedulerOf<DispatchQueue>
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BalanceBreakdownEnvironment {
|
||||||
|
static let live = BalanceBreakdownEnvironment(
|
||||||
|
numberFormatter: .live(),
|
||||||
|
SDKSynchronizer: LiveWrappedSDKSynchronizer(),
|
||||||
|
scheduler: DispatchQueue.main.eraseToAnyScheduler()
|
||||||
|
)
|
||||||
|
|
||||||
|
static let mock = BalanceBreakdownEnvironment(
|
||||||
|
numberFormatter: .live(),
|
||||||
|
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||||
|
scheduler: DispatchQueue.main.eraseToAnyScheduler()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Reducer
|
||||||
|
|
||||||
|
extension BalanceBreakdownReducer {
|
||||||
|
private enum CancelId {}
|
||||||
|
|
||||||
|
static let `default` = BalanceBreakdownReducer { state, action, environment in
|
||||||
|
switch action {
|
||||||
|
case .onAppear:
|
||||||
|
return environment.SDKSynchronizer.stateChanged
|
||||||
|
.map(BalanceBreakdownAction.synchronizerStateChanged)
|
||||||
|
.eraseToEffect()
|
||||||
|
.cancellable(id: CancelId.self, cancelInFlight: true)
|
||||||
|
|
||||||
|
case .onDisappear:
|
||||||
|
return Effect.cancel(id: CancelId.self)
|
||||||
|
|
||||||
|
case .synchronizerStateChanged(.synced):
|
||||||
|
return Effect(value: .updateSynchronizerStatus)
|
||||||
|
|
||||||
|
case .synchronizerStateChanged(let synchronizerState):
|
||||||
|
return Effect(value: .updateSynchronizerStatus)
|
||||||
|
|
||||||
|
case .updateSynchronizerStatus:
|
||||||
|
if let shieldedBalance = environment.SDKSynchronizer.latestScannedSynchronizerState?.shieldedBalance {
|
||||||
|
state.shieldedBalance = shieldedBalance
|
||||||
|
}
|
||||||
|
if let transparentBalance = environment.SDKSynchronizer.latestScannedSynchronizerState?.transparentBalance {
|
||||||
|
state.transparentBalance = transparentBalance
|
||||||
|
}
|
||||||
|
return Effect(value: .updateLatestBlock)
|
||||||
|
|
||||||
|
case .updateLatestBlock:
|
||||||
|
guard let latestBlockNumber = environment.SDKSynchronizer.latestScannedSynchronizerState?.latestScannedHeight,
|
||||||
|
let latestBlock = environment.numberFormatter.string(NSDecimalNumber(value: latestBlockNumber)) else {
|
||||||
|
state.latestBlock = "unknown"
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
state.latestBlock = "\(latestBlock)"
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Placeholders
|
||||||
|
|
||||||
|
extension BalanceBreakdownState {
|
||||||
|
static let placeholder = BalanceBreakdownState(
|
||||||
|
autoShieldingTreshold: Zatoshi(1_000_000),
|
||||||
|
latestBlock: "unknown",
|
||||||
|
shieldedBalance: WalletBalance.zero,
|
||||||
|
transparentBalance: WalletBalance.zero
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BalanceBreakdownStore {
|
||||||
|
static let placeholder = BalanceBreakdownStore(
|
||||||
|
initialState: .placeholder,
|
||||||
|
reducer: .default,
|
||||||
|
environment: .live
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
//
|
||||||
|
// BalanceBreakdownView.swift
|
||||||
|
// secant-testnet
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 04.08.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import ComposableArchitecture
|
||||||
|
import ZcashLightClientKit
|
||||||
|
|
||||||
|
struct BalanceBreakdown: View {
|
||||||
|
let store: BalanceBreakdownStore
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
WithViewStore(store) { viewStore in
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Text("Block: \(viewStore.latestBlock)")
|
||||||
|
}
|
||||||
|
|
||||||
|
.padding(.horizontal, 50)
|
||||||
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
|
balanceView(title: "SHIELDED ZEC (SPENDABLE)", viewStore.shieldedBalance.total, titleColor: Asset.Colors.Text.balanceText.color)
|
||||||
|
balanceView(title: "TRANSPARENT BALANCE", viewStore.transparentBalance.total)
|
||||||
|
balanceView(title: "TOTAL BALANCE", viewStore.totalBalance)
|
||||||
|
}
|
||||||
|
.padding(30)
|
||||||
|
.background(Asset.Colors.ScreenBackground.modalDialog.color)
|
||||||
|
.cornerRadius(8)
|
||||||
|
.onAppear { viewStore.send(.onAppear) }
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Text("Auto Shielding Treshold: \(viewStore.autoShieldingTreshold.decimalString()) ZEC")
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 50)
|
||||||
|
}
|
||||||
|
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
|
||||||
|
.applySemiTransparentScreenBackground()
|
||||||
|
.edgesIgnoringSafeArea(.all)
|
||||||
|
.onTapGesture {
|
||||||
|
viewStore.send(.onDisappear)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.background(ClearBackgroundView())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BalanceBreakdown {
|
||||||
|
func balanceView(title: String, _ balance: Zatoshi, titleColor: Color = .white) -> some View {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text("\(title)")
|
||||||
|
.foregroundColor(titleColor)
|
||||||
|
Text("$\(balance.decimalString(formatter: NumberFormatter.zcashNumberFormatter8FractionDigits))")
|
||||||
|
.font(.custom(FontFamily.Zboto.regular.name, size: 40))
|
||||||
|
.foregroundColor(Color.white)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BalanceBreakdown_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
BalanceBreakdown(store: .placeholder)
|
||||||
|
.preferredColorScheme(.dark)
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,25 +17,26 @@ struct HomeState: Equatable {
|
||||||
case request
|
case request
|
||||||
case send
|
case send
|
||||||
case scan
|
case scan
|
||||||
|
case balanceBreakdown
|
||||||
}
|
}
|
||||||
|
|
||||||
var route: Route?
|
var route: Route?
|
||||||
|
|
||||||
|
var balanceBreakdown: BalanceBreakdownState
|
||||||
var drawerOverlay: DrawerOverlay
|
var drawerOverlay: DrawerOverlay
|
||||||
var profileState: ProfileState
|
var profileState: ProfileState
|
||||||
var requestState: RequestState
|
var requestState: RequestState
|
||||||
var requiredTransactionConfirmations = 0
|
var requiredTransactionConfirmations = 0
|
||||||
var sendState: SendFlowState
|
|
||||||
var scanState: ScanState
|
var scanState: ScanState
|
||||||
|
var sendState: SendFlowState
|
||||||
|
var shieldedBalance: WalletBalance
|
||||||
var synchronizerStatusSnapshot: SyncStatusSnapshot
|
var synchronizerStatusSnapshot: SyncStatusSnapshot
|
||||||
var totalBalance: Zatoshi
|
|
||||||
var walletEventsState: WalletEventsFlowState
|
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
|
// 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 zecPrice = Decimal(140.0)
|
||||||
|
|
||||||
var totalCurrencyBalance: Zatoshi {
|
var totalCurrencyBalance: Zatoshi {
|
||||||
Zatoshi.from(decimal: totalBalance.decimalValue.decimalValue * zecPrice)
|
Zatoshi.from(decimal: shieldedBalance.total.decimalValue.decimalValue * zecPrice)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isDownloading: Bool {
|
var isDownloading: Bool {
|
||||||
|
@ -56,6 +57,7 @@ struct HomeState: Equatable {
|
||||||
// MARK: Action
|
// MARK: Action
|
||||||
|
|
||||||
enum HomeAction: Equatable {
|
enum HomeAction: Equatable {
|
||||||
|
case balanceBreakdown(BalanceBreakdownAction)
|
||||||
case debugMenuStartup
|
case debugMenuStartup
|
||||||
case onAppear
|
case onAppear
|
||||||
case onDisappear
|
case onDisappear
|
||||||
|
@ -65,7 +67,6 @@ enum HomeAction: Equatable {
|
||||||
case scan(ScanAction)
|
case scan(ScanAction)
|
||||||
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
||||||
case walletEvents(WalletEventsFlowAction)
|
case walletEvents(WalletEventsFlowAction)
|
||||||
case updateBalance(WalletBalance)
|
|
||||||
case updateDrawer(DrawerOverlay)
|
case updateDrawer(DrawerOverlay)
|
||||||
case updateRoute(HomeState.Route?)
|
case updateRoute(HomeState.Route?)
|
||||||
case updateSynchronizerStatus
|
case updateSynchronizerStatus
|
||||||
|
@ -109,7 +110,8 @@ extension HomeReducer {
|
||||||
historyReducer,
|
historyReducer,
|
||||||
sendReducer,
|
sendReducer,
|
||||||
scanReducer,
|
scanReducer,
|
||||||
profileReducer
|
profileReducer,
|
||||||
|
balanceBreakdownReducer
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -137,11 +139,6 @@ extension HomeReducer {
|
||||||
case .synchronizerStateChanged(let synchronizerState):
|
case .synchronizerStateChanged(let synchronizerState):
|
||||||
return Effect(value: .updateSynchronizerStatus)
|
return Effect(value: .updateSynchronizerStatus)
|
||||||
|
|
||||||
case .updateBalance(let balance):
|
|
||||||
state.totalBalance = balance.total
|
|
||||||
state.verifiedBalance = balance.verified
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .updateDrawer(let drawerOverlay):
|
case .updateDrawer(let drawerOverlay):
|
||||||
state.drawerOverlay = drawerOverlay
|
state.drawerOverlay = drawerOverlay
|
||||||
state.walletEventsState.isScrollable = drawerOverlay == .full ? true : false
|
state.walletEventsState.isScrollable = drawerOverlay == .full ? true : false
|
||||||
|
@ -152,11 +149,10 @@ extension HomeReducer {
|
||||||
|
|
||||||
case .updateSynchronizerStatus:
|
case .updateSynchronizerStatus:
|
||||||
state.synchronizerStatusSnapshot = environment.SDKSynchronizer.statusSnapshot()
|
state.synchronizerStatusSnapshot = environment.SDKSynchronizer.statusSnapshot()
|
||||||
return environment.SDKSynchronizer.getShieldedBalance()
|
if let shieldedBalance = environment.SDKSynchronizer.latestScannedSynchronizerState?.shieldedBalance {
|
||||||
.receive(on: environment.scheduler)
|
state.shieldedBalance = shieldedBalance
|
||||||
.map({ WalletBalance(verified: $0.verified, total: $0.total) })
|
}
|
||||||
.map(HomeAction.updateBalance)
|
return .none
|
||||||
.eraseToEffect()
|
|
||||||
|
|
||||||
case .updateRoute(let route):
|
case .updateRoute(let route):
|
||||||
state.route = route
|
state.route = route
|
||||||
|
@ -212,6 +208,13 @@ extension HomeReducer {
|
||||||
case .scan(let action):
|
case .scan(let action):
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
case .balanceBreakdown(.onDisappear):
|
||||||
|
state.route = nil
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case .balanceBreakdown:
|
||||||
|
return .none
|
||||||
|
|
||||||
case .debugMenuStartup:
|
case .debugMenuStartup:
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
@ -272,6 +275,18 @@ extension HomeReducer {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private static let balanceBreakdownReducer: HomeReducer = BalanceBreakdownReducer.default.pullback(
|
||||||
|
state: \HomeState.balanceBreakdown,
|
||||||
|
action: /HomeAction.balanceBreakdown,
|
||||||
|
environment: { environment in
|
||||||
|
BalanceBreakdownEnvironment(
|
||||||
|
numberFormatter: .live(),
|
||||||
|
SDKSynchronizer: environment.SDKSynchronizer,
|
||||||
|
scheduler: environment.scheduler
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Store
|
// MARK: - Store
|
||||||
|
@ -311,6 +326,13 @@ extension HomeStore {
|
||||||
action: HomeAction.scan
|
action: HomeAction.scan
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func balanceBreakdownStore() -> BalanceBreakdownStore {
|
||||||
|
self.scope(
|
||||||
|
state: \.balanceBreakdown,
|
||||||
|
action: HomeAction.balanceBreakdown
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - ViewStore
|
// MARK: - ViewStore
|
||||||
|
@ -338,15 +360,15 @@ extension HomeViewStore {
|
||||||
extension HomeState {
|
extension HomeState {
|
||||||
static var placeholder: Self {
|
static var placeholder: Self {
|
||||||
.init(
|
.init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: WalletBalance.zero,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: Zatoshi.zero,
|
walletEventsState: .emptyPlaceHolder
|
||||||
walletEventsState: .emptyPlaceHolder,
|
|
||||||
verifiedBalance: Zatoshi.zero
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,9 @@ struct HomeView: View {
|
||||||
.navigationBarHidden(true)
|
.navigationBarHidden(true)
|
||||||
.onAppear(perform: { viewStore.send(.onAppear) })
|
.onAppear(perform: { viewStore.send(.onAppear) })
|
||||||
.onDisappear(perform: { viewStore.send(.onDisappear) })
|
.onDisappear(perform: { viewStore.send(.onDisappear) })
|
||||||
|
.fullScreenCover(isPresented: viewStore.bindingForRoute(.balanceBreakdown)) {
|
||||||
|
BalanceBreakdown(store: store.balanceBreakdownStore())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,13 +123,14 @@ extension HomeView {
|
||||||
.padding(.top, 50)
|
.padding(.top, 50)
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
Text("$\(viewStore.totalBalance.decimalString())")
|
Button {
|
||||||
.font(.custom(FontFamily.Zboto.regular.name, size: 40))
|
viewStore.send(.updateRoute(.balanceBreakdown))
|
||||||
.foregroundColor(Asset.Colors.Text.balanceText.color)
|
} label: {
|
||||||
.accessDebugMenuWithHiddenGesture {
|
Text("$\(viewStore.shieldedBalance.total.decimalString())")
|
||||||
viewStore.send(.debugMenuStartup)
|
.font(.custom(FontFamily.Zboto.regular.name, size: 40))
|
||||||
}
|
.foregroundColor(Asset.Colors.Text.balanceText.color)
|
||||||
.padding(.top, 80)
|
.padding(.top, 80)
|
||||||
|
}
|
||||||
|
|
||||||
Text("$\(viewStore.totalCurrencyBalance.decimalString())")
|
Text("$\(viewStore.totalCurrencyBalance.decimalString())")
|
||||||
.font(.custom(FontFamily.Rubik.regular.name, size: 13))
|
.font(.custom(FontFamily.Rubik.regular.name, size: 13))
|
||||||
|
@ -134,6 +138,9 @@ extension HomeView {
|
||||||
.padding(.bottom, 50)
|
.padding(.bottom, 50)
|
||||||
|
|
||||||
Text("\(viewStore.synchronizerStatusSnapshot.message)")
|
Text("\(viewStore.synchronizerStatusSnapshot.message)")
|
||||||
|
.accessDebugMenuWithHiddenGesture {
|
||||||
|
viewStore.send(.debugMenuStartup)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct SendFlowState: Equatable {
|
||||||
var isSendingTransaction = false
|
var isSendingTransaction = false
|
||||||
var memoState: MultiLineTextFieldState
|
var memoState: MultiLineTextFieldState
|
||||||
var route: Route?
|
var route: Route?
|
||||||
var totalBalance = Zatoshi.zero
|
var shieldedBalance = WalletBalance.zero
|
||||||
var transactionAddressInputState: TransactionAddressTextFieldState
|
var transactionAddressInputState: TransactionAddressTextFieldState
|
||||||
var transactionAmountInputState: TransactionAmountTextFieldState
|
var transactionAmountInputState: TransactionAmountTextFieldState
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ struct SendFlowState: Equatable {
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalCurrencyBalance: Zatoshi {
|
var totalCurrencyBalance: Zatoshi {
|
||||||
Zatoshi.from(decimal: totalBalance.decimalValue.decimalValue * transactionAmountInputState.zecPrice)
|
Zatoshi.from(decimal: shieldedBalance.total.decimalValue.decimalValue * transactionAmountInputState.zecPrice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,6 @@ enum SendFlowAction: Equatable {
|
||||||
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
||||||
case transactionAddressInput(TransactionAddressTextFieldAction)
|
case transactionAddressInput(TransactionAddressTextFieldAction)
|
||||||
case transactionAmountInput(TransactionAmountTextFieldAction)
|
case transactionAmountInput(TransactionAmountTextFieldAction)
|
||||||
case updateBalance(Zatoshi)
|
|
||||||
case updateRoute(SendFlowState.Route?)
|
case updateRoute(SendFlowState.Route?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,18 +182,13 @@ extension SendFlowReducer {
|
||||||
return Effect.cancel(id: SyncStatusUpdatesID())
|
return Effect.cancel(id: SyncStatusUpdatesID())
|
||||||
|
|
||||||
case .synchronizerStateChanged(.synced):
|
case .synchronizerStateChanged(.synced):
|
||||||
return environment.SDKSynchronizer.getShieldedBalance()
|
if let shieldedBalance = environment.SDKSynchronizer.latestScannedSynchronizerState?.shieldedBalance {
|
||||||
.receive(on: environment.scheduler)
|
state.shieldedBalance = shieldedBalance
|
||||||
.map({ $0.total })
|
state.transactionAmountInputState.maxValue = shieldedBalance.total.amount
|
||||||
.map(SendFlowAction.updateBalance)
|
}
|
||||||
.eraseToEffect()
|
|
||||||
|
|
||||||
case .synchronizerStateChanged(let synchronizerState):
|
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .updateBalance(let balance):
|
case .synchronizerStateChanged(let synchronizerState):
|
||||||
state.totalBalance = balance
|
|
||||||
state.transactionAmountInputState.maxValue = balance.amount
|
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .memo:
|
case .memo:
|
||||||
|
|
|
@ -10,7 +10,7 @@ struct CreateTransaction: View {
|
||||||
return WithViewStore(store) { viewStore in
|
return WithViewStore(store) { viewStore in
|
||||||
VStack {
|
VStack {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
Text("WalletBalance \(viewStore.totalBalance.decimalString()) ZEC")
|
Text("WalletBalance \(viewStore.shieldedBalance.total.decimalString()) ZEC")
|
||||||
Text("($\(viewStore.totalCurrencyBalance.decimalString()))")
|
Text("($\(viewStore.totalCurrencyBalance.decimalString()))")
|
||||||
.font(.system(size: 13))
|
.font(.system(size: 13))
|
||||||
.opacity(0.6)
|
.opacity(0.6)
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "243",
|
"blue" : "0xF3",
|
||||||
"green" : "228",
|
"green" : "0xE4",
|
||||||
"red" : "210"
|
"red" : "0xD2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "249",
|
"blue" : "0xF9",
|
||||||
"green" : "239",
|
"green" : "0xEF",
|
||||||
"red" : "227"
|
"red" : "0xE3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.953",
|
||||||
|
"green" : "0.894",
|
||||||
|
"red" : "0.824"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.323",
|
||||||
|
"green" : "0.099",
|
||||||
|
"red" : "0.083"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "0.900",
|
||||||
|
"blue" : "0xF3",
|
||||||
|
"green" : "0xE4",
|
||||||
|
"red" : "0xD2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "0.900",
|
||||||
|
"blue" : "0x55",
|
||||||
|
"green" : "0x31",
|
||||||
|
"red" : "0x24"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "0.900",
|
||||||
|
"blue" : "0xF9",
|
||||||
|
"green" : "0xEF",
|
||||||
|
"red" : "0xE3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "0.900",
|
||||||
|
"blue" : "0x5A",
|
||||||
|
"green" : "0x36",
|
||||||
|
"red" : "0x29"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -95,8 +95,11 @@ internal enum Asset {
|
||||||
internal static let gradientStart = ColorAsset(name: "gradientStart")
|
internal static let gradientStart = ColorAsset(name: "gradientStart")
|
||||||
internal static let greenGradientEnd = ColorAsset(name: "greenGradientEnd")
|
internal static let greenGradientEnd = ColorAsset(name: "greenGradientEnd")
|
||||||
internal static let greenGradientStart = ColorAsset(name: "greenGradientStart")
|
internal static let greenGradientStart = ColorAsset(name: "greenGradientStart")
|
||||||
|
internal static let modalDialog = ColorAsset(name: "modalDialog")
|
||||||
internal static let redGradientEnd = ColorAsset(name: "redGradientEnd")
|
internal static let redGradientEnd = ColorAsset(name: "redGradientEnd")
|
||||||
internal static let redGradientStart = ColorAsset(name: "redGradientStart")
|
internal static let redGradientStart = ColorAsset(name: "redGradientStart")
|
||||||
|
internal static let semiTransparentGradientEnd = ColorAsset(name: "semiTransparentGradientEnd")
|
||||||
|
internal static let semiTransparentGradientStart = ColorAsset(name: "semiTransparentGradientStart")
|
||||||
}
|
}
|
||||||
internal enum Shadow {
|
internal enum Shadow {
|
||||||
internal static let drawerShadow = ColorAsset(name: "drawerShadow")
|
internal static let drawerShadow = ColorAsset(name: "drawerShadow")
|
||||||
|
|
|
@ -86,6 +86,17 @@ extension View {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applySemiTransparentScreenBackground() -> some View {
|
||||||
|
self.modifier(
|
||||||
|
ScreenBackgroundModifier(
|
||||||
|
colors: [
|
||||||
|
Asset.Colors.ScreenBackground.semiTransparentGradientStart.color,
|
||||||
|
Asset.Colors.ScreenBackground.semiTransparentGradientEnd.color
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScreenBackground_Previews: PreviewProvider {
|
struct ScreenBackground_Previews: PreviewProvider {
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// ClearBackgroundView.swift
|
||||||
|
// secant-testnet
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 04.08.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
/// Purpose of this utility is to solve background transparency of the view used for example in `.fullScreenCover`.
|
||||||
|
/// Usually used for the modal full screen views with semi-transparent backgrounds.
|
||||||
|
struct ClearBackgroundView: UIViewRepresentable {
|
||||||
|
func makeUIView(context: Context) -> UIView {
|
||||||
|
let view = UIView()
|
||||||
|
/// Wrapped in the dispatch queue to achieve the background clearance,
|
||||||
|
/// it doesn't work otherwise (opaque background instead of fully transparent).
|
||||||
|
/// Comes from https://stackoverflow.com/a/66925883
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
view.superview?.superview?.backgroundColor = .clear
|
||||||
|
}
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIView(_ uiView: UIView, context: Context) {}
|
||||||
|
}
|
|
@ -16,6 +16,15 @@ extension NumberFormatter {
|
||||||
formatter.usesGroupingSeparator = true
|
formatter.usesGroupingSeparator = true
|
||||||
return formatter
|
return formatter
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
static let zcashNumberFormatter8FractionDigits: NumberFormatter = {
|
||||||
|
var formatter = NumberFormatter()
|
||||||
|
formatter.minimumFractionDigits = 8
|
||||||
|
formatter.maximumIntegerDigits = 8
|
||||||
|
formatter.numberStyle = .decimal
|
||||||
|
formatter.usesGroupingSeparator = true
|
||||||
|
return formatter
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WrappedNumberFormatter {
|
struct WrappedNumberFormatter {
|
||||||
|
|
|
@ -37,15 +37,18 @@ protocol WrappedSDKSynchronizer {
|
||||||
var synchronizer: SDKSynchronizer? { get }
|
var synchronizer: SDKSynchronizer? { get }
|
||||||
var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never> { get }
|
var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never> { get }
|
||||||
var walletBirthday: BlockHeight? { get }
|
var walletBirthday: BlockHeight? { get }
|
||||||
|
var latestScannedSynchronizerState: SDKSynchronizer.SynchronizerState? { get }
|
||||||
|
|
||||||
func prepareWith(initializer: Initializer) throws
|
func prepareWith(initializer: Initializer) throws
|
||||||
func start(retry: Bool) throws
|
func start(retry: Bool) throws
|
||||||
func stop()
|
func stop()
|
||||||
|
func synchronizerSynced(_ synchronizerState: SDKSynchronizer.SynchronizerState?)
|
||||||
func statusSnapshot() -> SyncStatusSnapshot
|
func statusSnapshot() -> SyncStatusSnapshot
|
||||||
|
|
||||||
func rewind(_ policy: RewindPolicy) throws
|
func rewind(_ policy: RewindPolicy) throws
|
||||||
|
|
||||||
func getShieldedBalance() -> Effect<WalletBalance, Never>
|
func getShieldedBalance() -> WalletBalance?
|
||||||
|
func getTransparentBalance() -> WalletBalance?
|
||||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never>
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never>
|
||||||
func getAllPendingTransactions() -> Effect<[WalletEvent], Never>
|
func getAllPendingTransactions() -> Effect<[WalletEvent], Never>
|
||||||
func getAllTransactions() -> Effect<[WalletEvent], Never>
|
func getAllTransactions() -> Effect<[WalletEvent], Never>
|
||||||
|
@ -83,6 +86,7 @@ class LiveWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
private(set) var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never>
|
private(set) var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never>
|
||||||
private(set) var notificationCenter: WrappedNotificationCenter
|
private(set) var notificationCenter: WrappedNotificationCenter
|
||||||
private(set) var walletBirthday: BlockHeight?
|
private(set) var walletBirthday: BlockHeight?
|
||||||
|
private(set) var latestScannedSynchronizerState: SDKSynchronizer.SynchronizerState?
|
||||||
|
|
||||||
init(notificationCenter: WrappedNotificationCenter = .live) {
|
init(notificationCenter: WrappedNotificationCenter = .live) {
|
||||||
self.notificationCenter = notificationCenter
|
self.notificationCenter = notificationCenter
|
||||||
|
@ -103,7 +107,10 @@ class LiveWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
|
|
||||||
notificationCenter.publisherFor(.synchronizerSynced)?
|
notificationCenter.publisherFor(.synchronizerSynced)?
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] _ in self?.synchronizerSynced() }
|
.sink { [weak self] output in
|
||||||
|
let synchronizerState = output.userInfo?[SDKSynchronizer.NotificationKeys.synchronizerState] as? SDKSynchronizer.SynchronizerState
|
||||||
|
self?.synchronizerSynced(synchronizerState)
|
||||||
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
notificationCenter.publisherFor(.synchronizerProgressUpdated)?
|
notificationCenter.publisherFor(.synchronizerProgressUpdated)?
|
||||||
|
@ -133,8 +140,9 @@ class LiveWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
stateChanged.send(.started)
|
stateChanged.send(.started)
|
||||||
}
|
}
|
||||||
|
|
||||||
func synchronizerSynced() {
|
func synchronizerSynced(_ synchronizerState: SDKSynchronizer.SynchronizerState?) {
|
||||||
stateChanged.send(.synced)
|
stateChanged.send(.synced)
|
||||||
|
latestScannedSynchronizerState = synchronizerState
|
||||||
}
|
}
|
||||||
|
|
||||||
func synchronizerProgressUpdated() {
|
func synchronizerProgressUpdated() {
|
||||||
|
@ -176,13 +184,12 @@ class LiveWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getShieldedBalance() -> Effect<WalletBalance, Never> {
|
func getShieldedBalance() -> WalletBalance? {
|
||||||
if let shieldedVerifiedBalance: Zatoshi = synchronizer?.getShieldedVerifiedBalance(),
|
latestScannedSynchronizerState?.shieldedBalance
|
||||||
let shieldedTotalBalance: Zatoshi = synchronizer?.getShieldedBalance(accountIndex: 0) {
|
}
|
||||||
return Effect(value: WalletBalance(verified: shieldedVerifiedBalance, total: shieldedTotalBalance))
|
|
||||||
}
|
|
||||||
|
|
||||||
return .none
|
func getTransparentBalance() -> WalletBalance? {
|
||||||
|
latestScannedSynchronizerState?.transparentBalance
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
|
@ -282,6 +289,7 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
private(set) var synchronizer: SDKSynchronizer?
|
private(set) var synchronizer: SDKSynchronizer?
|
||||||
private(set) var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never>
|
private(set) var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never>
|
||||||
private(set) var walletBirthday: BlockHeight?
|
private(set) var walletBirthday: BlockHeight?
|
||||||
|
private(set) var latestScannedSynchronizerState: SDKSynchronizer.SynchronizerState?
|
||||||
|
|
||||||
init(notificationCenter: WrappedNotificationCenter = .mock) {
|
init(notificationCenter: WrappedNotificationCenter = .mock) {
|
||||||
self.notificationCenter = notificationCenter
|
self.notificationCenter = notificationCenter
|
||||||
|
@ -304,7 +312,7 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
synchronizer?.stop()
|
synchronizer?.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
func synchronizerSynced() {
|
func synchronizerSynced(_ synchronizerState: SDKSynchronizer.SynchronizerState?) {
|
||||||
stateChanged.send(.synced)
|
stateChanged.send(.synced)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,8 +326,12 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
|
|
||||||
func rewind(_ policy: RewindPolicy) throws { }
|
func rewind(_ policy: RewindPolicy) throws { }
|
||||||
|
|
||||||
func getShieldedBalance() -> Effect<WalletBalance, Never> {
|
func getShieldedBalance() -> WalletBalance? {
|
||||||
return Effect(value: WalletBalance(verified: Zatoshi(12345000), total: Zatoshi(12345000)))
|
WalletBalance(verified: Zatoshi(12345000), total: Zatoshi(12345000))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTransparentBalance() -> WalletBalance? {
|
||||||
|
WalletBalance(verified: Zatoshi(12345000), total: Zatoshi(12345000))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
|
@ -414,6 +426,7 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
private(set) var synchronizer: SDKSynchronizer?
|
private(set) var synchronizer: SDKSynchronizer?
|
||||||
private(set) var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never>
|
private(set) var stateChanged: CurrentValueSubject<WrappedSDKSynchronizerState, Never>
|
||||||
private(set) var walletBirthday: BlockHeight?
|
private(set) var walletBirthday: BlockHeight?
|
||||||
|
private(set) var latestScannedSynchronizerState: SDKSynchronizer.SynchronizerState?
|
||||||
|
|
||||||
init(notificationCenter: WrappedNotificationCenter = .mock) {
|
init(notificationCenter: WrappedNotificationCenter = .mock) {
|
||||||
self.notificationCenter = notificationCenter
|
self.notificationCenter = notificationCenter
|
||||||
|
@ -426,15 +439,15 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
|
|
||||||
func stop() { }
|
func stop() { }
|
||||||
|
|
||||||
func synchronizerSynced() { }
|
func synchronizerSynced(_ synchronizerState: SDKSynchronizer.SynchronizerState?) { }
|
||||||
|
|
||||||
func statusSnapshot() -> SyncStatusSnapshot { .default }
|
func statusSnapshot() -> SyncStatusSnapshot { .default }
|
||||||
|
|
||||||
func rewind(_ policy: RewindPolicy) throws { }
|
func rewind(_ policy: RewindPolicy) throws { }
|
||||||
|
|
||||||
func getShieldedBalance() -> Effect<WalletBalance, Never> {
|
func getShieldedBalance() -> WalletBalance? { nil }
|
||||||
return .none
|
|
||||||
}
|
func getTransparentBalance() -> WalletBalance? { nil }
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
let mocked: [TransactionStateMockHelper] = [
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
//
|
||||||
|
// BalanceBreakdownTests.swift
|
||||||
|
// secantTests
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 15.08.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
@testable import secant_testnet
|
||||||
|
import ComposableArchitecture
|
||||||
|
import ZcashLightClientKit
|
||||||
|
|
||||||
|
class BalanceBreakdownTests: XCTestCase {
|
||||||
|
func testOnAppear() throws {
|
||||||
|
// setup the store and environment to be fully mocked
|
||||||
|
let testScheduler = DispatchQueue.test
|
||||||
|
|
||||||
|
let store = TestStore(
|
||||||
|
initialState: .placeholder,
|
||||||
|
reducer: BalanceBreakdownReducer.default,
|
||||||
|
environment:
|
||||||
|
BalanceBreakdownEnvironment(
|
||||||
|
numberFormatter: .live(),
|
||||||
|
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||||
|
scheduler: testScheduler.eraseToAnyScheduler()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
store.send(.onAppear)
|
||||||
|
|
||||||
|
testScheduler.advance(by: 0.1)
|
||||||
|
|
||||||
|
// expected side effects as a result of .onAppear registration
|
||||||
|
store.receive(.synchronizerStateChanged(.unknown))
|
||||||
|
store.receive(.updateSynchronizerStatus)
|
||||||
|
store.receive(.updateLatestBlock)
|
||||||
|
|
||||||
|
// long-living (cancelable) effects need to be properly canceled.
|
||||||
|
// the .onDisappear action cancles the observer of the synchronizer status change.
|
||||||
|
store.send(.onDisappear)
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,6 @@ import XCTest
|
||||||
import ComposableArchitecture
|
import ComposableArchitecture
|
||||||
import ZcashLightClientKit
|
import ZcashLightClientKit
|
||||||
|
|
||||||
// swiftlint:disable type_body_length
|
|
||||||
class HomeTests: XCTestCase {
|
class HomeTests: XCTestCase {
|
||||||
func testSynchronizerStateChanged_AnyButSynced() throws {
|
func testSynchronizerStateChanged_AnyButSynced() throws {
|
||||||
// setup the store and environment to be fully mocked
|
// setup the store and environment to be fully mocked
|
||||||
|
@ -38,18 +37,11 @@ class HomeTests: XCTestCase {
|
||||||
testScheduler.advance(by: 0.01)
|
testScheduler.advance(by: 0.01)
|
||||||
|
|
||||||
store.receive(.updateSynchronizerStatus)
|
store.receive(.updateSynchronizerStatus)
|
||||||
|
|
||||||
let balance = WalletBalance(verified: Zatoshi(12_345_000), total: Zatoshi(12_345_000))
|
|
||||||
store.receive(.updateBalance(balance)) { state in
|
|
||||||
state.totalBalance = Zatoshi(12_345_000)
|
|
||||||
state.verifiedBalance = Zatoshi(12_345_000)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When the synchronizer status change to .synced, several things happen
|
/// When the synchronizer status change to .synced, several things happen
|
||||||
/// 1. the .updateSynchronizerStatus is called
|
/// 1. the .updateSynchronizerStatus is called
|
||||||
/// 2. the side effect to update the transactions history is called
|
/// 2. the side effect to update the transactions history is called
|
||||||
/// 3. the side effect to update the balance is called
|
|
||||||
func testSynchronizerStateChanged_Synced() throws {
|
func testSynchronizerStateChanged_Synced() throws {
|
||||||
// setup the store and environment to be fully mocked
|
// setup the store and environment to be fully mocked
|
||||||
let testScheduler = DispatchQueue.test
|
let testScheduler = DispatchQueue.test
|
||||||
|
@ -99,14 +91,6 @@ class HomeTests: XCTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
store.receive(.updateWalletEvents(walletEvents))
|
store.receive(.updateWalletEvents(walletEvents))
|
||||||
|
|
||||||
// ad 3.
|
|
||||||
let balance = WalletBalance(verified: Zatoshi(12_345_000), total: Zatoshi(12_345_000))
|
|
||||||
|
|
||||||
store.receive(.updateBalance(balance)) { state in
|
|
||||||
state.verifiedBalance = Zatoshi(12_345_000)
|
|
||||||
state.totalBalance = Zatoshi(12_345_000)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testWalletEventsPartial_to_FullDrawer() throws {
|
func testWalletEventsPartial_to_FullDrawer() throws {
|
||||||
|
@ -125,15 +109,15 @@ class HomeTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let homeState = HomeState(
|
let homeState = HomeState(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: WalletBalance.zero,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: Zatoshi.zero,
|
walletEventsState: .emptyPlaceHolder
|
||||||
walletEventsState: .emptyPlaceHolder,
|
|
||||||
verifiedBalance: Zatoshi.zero
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
|
@ -168,15 +152,15 @@ class HomeTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let homeState = HomeState(
|
let homeState = HomeState(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .full,
|
drawerOverlay: .full,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: WalletBalance.zero,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: Zatoshi.zero,
|
walletEventsState: .emptyPlaceHolder
|
||||||
walletEventsState: .emptyPlaceHolder,
|
|
||||||
verifiedBalance: Zatoshi.zero
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
|
@ -228,12 +212,6 @@ class HomeTests: XCTestCase {
|
||||||
store.receive(.synchronizerStateChanged(.unknown))
|
store.receive(.synchronizerStateChanged(.unknown))
|
||||||
store.receive(.updateSynchronizerStatus)
|
store.receive(.updateSynchronizerStatus)
|
||||||
|
|
||||||
let balance = WalletBalance(verified: Zatoshi(12_345_000), total: Zatoshi(12_345_000))
|
|
||||||
store.receive(.updateBalance(balance)) { state in
|
|
||||||
state.totalBalance = Zatoshi(12_345_000)
|
|
||||||
state.verifiedBalance = Zatoshi(12_345_000)
|
|
||||||
}
|
|
||||||
|
|
||||||
// long-living (cancelable) effects need to be properly canceled.
|
// long-living (cancelable) effects need to be properly canceled.
|
||||||
// the .onDisappear action cancles the observer of the synchronizer status change.
|
// the .onDisappear action cancles the observer of the synchronizer status change.
|
||||||
store.send(.onDisappear)
|
store.send(.onDisappear)
|
||||||
|
@ -256,15 +234,15 @@ class HomeTests: XCTestCase {
|
||||||
|
|
||||||
let homeState = HomeState(
|
let homeState = HomeState(
|
||||||
route: .profile,
|
route: .profile,
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .full,
|
drawerOverlay: .full,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: WalletBalance.zero,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: Zatoshi.zero,
|
walletEventsState: .emptyPlaceHolder
|
||||||
walletEventsState: .emptyPlaceHolder,
|
|
||||||
verifiedBalance: Zatoshi.zero
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
|
@ -295,15 +273,15 @@ class HomeTests: XCTestCase {
|
||||||
|
|
||||||
let homeState = HomeState(
|
let homeState = HomeState(
|
||||||
route: .profile,
|
route: .profile,
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .full,
|
drawerOverlay: .full,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: WalletBalance.zero,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: Zatoshi.zero,
|
walletEventsState: .emptyPlaceHolder
|
||||||
walletEventsState: .emptyPlaceHolder,
|
|
||||||
verifiedBalance: Zatoshi.zero
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
|
|
|
@ -32,7 +32,7 @@ class ProfileTests: XCTestCase {
|
||||||
state.address = "ff3927e1f83df9b1b0dc75540ddc59ee435eecebae914d2e6dfe8576fbedc9a8"
|
state.address = "ff3927e1f83df9b1b0dc75540ddc59ee435eecebae914d2e6dfe8576fbedc9a8"
|
||||||
state.appVersion = "0.0.1"
|
state.appVersion = "0.0.1"
|
||||||
state.appBuild = "31"
|
state.appBuild = "31"
|
||||||
state.sdkVersion = "0.14.0-beta"
|
state.sdkVersion = "0.16.5-beta"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -536,7 +536,7 @@ class SendTests: XCTestCase {
|
||||||
func testInvalidForm_ExceededMemoCharLimit() throws {
|
func testInvalidForm_ExceededMemoCharLimit() throws {
|
||||||
let sendState = SendFlowState(
|
let sendState = SendFlowState(
|
||||||
memoState: MultiLineTextFieldState(charLimit: 3),
|
memoState: MultiLineTextFieldState(charLimit: 3),
|
||||||
totalBalance: Zatoshi(1),
|
shieldedBalance: WalletBalance(verified: Zatoshi(1), total: Zatoshi(1)),
|
||||||
transactionAddressInputState:
|
transactionAddressInputState:
|
||||||
TransactionAddressTextFieldState(
|
TransactionAddressTextFieldState(
|
||||||
isValidAddress: true,
|
isValidAddress: true,
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// BalanceBreakdownSnapshotTests.swift
|
||||||
|
// secantTests
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 15.08.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
@testable import secant_testnet
|
||||||
|
import ComposableArchitecture
|
||||||
|
import ZcashLightClientKit
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
class BalanceBreakdownSnapshotTests: XCTestCase {
|
||||||
|
func testBalanceBreakdownSnapshot() throws {
|
||||||
|
let store = Store(
|
||||||
|
initialState: BalanceBreakdownState(
|
||||||
|
autoShieldingTreshold: Zatoshi(1_000_000),
|
||||||
|
latestBlock: "unknown",
|
||||||
|
shieldedBalance: WalletBalance(verified: Zatoshi(123_000_000_000), total: Zatoshi(123_000_000_000)),
|
||||||
|
transparentBalance: WalletBalance(verified: Zatoshi(850_000_000), total: Zatoshi(850_000_000))
|
||||||
|
),
|
||||||
|
reducer: BalanceBreakdownReducer.default,
|
||||||
|
environment: .mock
|
||||||
|
)
|
||||||
|
|
||||||
|
addAttachments(BalanceBreakdown(store: store))
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,15 +42,15 @@ class HomeCircularProgressSnapshotTests: XCTestCase {
|
||||||
|
|
||||||
let store = HomeStore(
|
let store = HomeStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: balance,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: balance.total,
|
walletEventsState: .emptyPlaceHolder
|
||||||
walletEventsState: .emptyPlaceHolder,
|
|
||||||
verifiedBalance: balance.verified
|
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: testEnvironment
|
environment: testEnvironment
|
||||||
|
@ -90,15 +90,15 @@ class HomeCircularProgressSnapshotTests: XCTestCase {
|
||||||
|
|
||||||
let store = HomeStore(
|
let store = HomeStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: balance,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: balance.total,
|
walletEventsState: .emptyPlaceHolder
|
||||||
walletEventsState: .emptyPlaceHolder,
|
|
||||||
verifiedBalance: balance.verified
|
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: testEnvironment
|
environment: testEnvironment
|
||||||
|
@ -131,15 +131,15 @@ class HomeCircularProgressSnapshotTests: XCTestCase {
|
||||||
|
|
||||||
let store = HomeStore(
|
let store = HomeStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: balance,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: balance.total,
|
walletEventsState: .emptyPlaceHolder
|
||||||
walletEventsState: .emptyPlaceHolder,
|
|
||||||
verifiedBalance: balance.verified
|
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: testEnvironment
|
environment: testEnvironment
|
||||||
|
|
|
@ -37,15 +37,15 @@ class HomeSnapshotTests: XCTestCase {
|
||||||
|
|
||||||
let store = HomeStore(
|
let store = HomeStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: balance,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: balance.total,
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: walletEvents))
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: walletEvents)),
|
|
||||||
verifiedBalance: balance.verified
|
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: .demo
|
environment: .demo
|
||||||
|
|
|
@ -38,15 +38,15 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
|
|
||||||
let store = HomeStore(
|
let store = HomeStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: balance,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: balance.total,
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: walletEvents))
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: walletEvents)),
|
|
||||||
verifiedBalance: balance.verified
|
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: .demo
|
environment: .demo
|
||||||
|
@ -85,15 +85,15 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
let balance = WalletBalance(verified: 12_345_000, total: 12_345_000)
|
let balance = WalletBalance(verified: 12_345_000, total: 12_345_000)
|
||||||
let store = HomeStore(
|
let store = HomeStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: balance,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: balance.total,
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
|
||||||
verifiedBalance: balance.verified
|
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: .demo
|
environment: .demo
|
||||||
|
@ -142,15 +142,15 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
let balance = WalletBalance(verified: 12_345_000, total: 12_345_000)
|
let balance = WalletBalance(verified: 12_345_000, total: 12_345_000)
|
||||||
let store = HomeStore(
|
let store = HomeStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: balance,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: balance.total,
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
|
||||||
verifiedBalance: balance.verified
|
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: .demo
|
environment: .demo
|
||||||
|
@ -199,15 +199,15 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
let balance = WalletBalance(verified: 12_345_000, total: 12_345_000)
|
let balance = WalletBalance(verified: 12_345_000, total: 12_345_000)
|
||||||
let store = HomeStore(
|
let store = HomeStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: balance,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: balance.total,
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
|
||||||
verifiedBalance: balance.verified
|
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: .demo
|
environment: .demo
|
||||||
|
@ -262,15 +262,15 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
let balance = WalletBalance(verified: 12_345_000, total: 12_345_000)
|
let balance = WalletBalance(verified: 12_345_000, total: 12_345_000)
|
||||||
let store = HomeStore(
|
let store = HomeStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
balanceBreakdown: .placeholder,
|
||||||
drawerOverlay: .partial,
|
drawerOverlay: .partial,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
requestState: .placeholder,
|
||||||
sendState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
|
sendState: .placeholder,
|
||||||
|
shieldedBalance: balance,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
totalBalance: balance.total,
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
|
||||||
verifiedBalance: balance.verified
|
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: .demo
|
environment: .demo
|
||||||
|
|
Loading…
Reference in New Issue