[98] [Scaffold] Full Wallet History (#376)
- concept of activities instead of transactions - the drawer is now fully universal and data driven, rendering some View, going to some detail View - unit tests work again - refactor of Activity -> WalletEvent - WalletEvent view builders simplified - transactions & wallet events timestamps instead of Date type - review comments resolved - missing 'Transactions' terms updated to 'WalletEvents'
This commit is contained in:
parent
675a067437
commit
e321114214
|
@ -112,7 +112,7 @@
|
||||||
9E39115E284E3E350073DD9A /* secantUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4E7A2526B364180058B01E /* secantUITests.swift */; };
|
9E39115E284E3E350073DD9A /* secantUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4E7A2526B364180058B01E /* secantUITests.swift */; };
|
||||||
9E4DC6E027C409A100E657F4 /* NeumorphicDesignModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E4DC6DF27C409A100E657F4 /* NeumorphicDesignModifier.swift */; };
|
9E4DC6E027C409A100E657F4 /* NeumorphicDesignModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E4DC6DF27C409A100E657F4 /* NeumorphicDesignModifier.swift */; };
|
||||||
9E4DC6E227C4C6B700E657F4 /* SecantButtonStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E4DC6E127C4C6B700E657F4 /* SecantButtonStyles.swift */; };
|
9E4DC6E227C4C6B700E657F4 /* SecantButtonStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E4DC6E127C4C6B700E657F4 /* SecantButtonStyles.swift */; };
|
||||||
9E5BF63F2819542C00BA3F17 /* TransactionHistoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF63E2819542C00BA3F17 /* TransactionHistoryTests.swift */; };
|
9E5BF63F2819542C00BA3F17 /* WalletEventsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF63E2819542C00BA3F17 /* WalletEventsTests.swift */; };
|
||||||
9E5BF641281FD7B600BA3F17 /* TransactionFailedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */; };
|
9E5BF641281FD7B600BA3F17 /* TransactionFailedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */; };
|
||||||
9E5BF644281FEC9900BA3F17 /* SendTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF643281FEC9900BA3F17 /* SendTests.swift */; };
|
9E5BF644281FEC9900BA3F17 /* SendTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF643281FEC9900BA3F17 /* SendTests.swift */; };
|
||||||
9E5BF6462821028C00BA3F17 /* WrappedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF6452821028C00BA3F17 /* WrappedUserDefaults.swift */; };
|
9E5BF6462821028C00BA3F17 /* WrappedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF6452821028C00BA3F17 /* WrappedUserDefaults.swift */; };
|
||||||
|
@ -146,6 +146,8 @@
|
||||||
9EAB466F285A0468002904A0 /* _URLRouting in Frameworks */ = {isa = PBXBuildFile; productRef = 9EAB466E285A0468002904A0 /* _URLRouting */; };
|
9EAB466F285A0468002904A0 /* _URLRouting in Frameworks */ = {isa = PBXBuildFile; productRef = 9EAB466E285A0468002904A0 /* _URLRouting */; };
|
||||||
9EAB4671285A1C77002904A0 /* DeeplinkHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAB4670285A1C77002904A0 /* DeeplinkHandler.swift */; };
|
9EAB4671285A1C77002904A0 /* DeeplinkHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAB4670285A1C77002904A0 /* DeeplinkHandler.swift */; };
|
||||||
9EAB4676285B5C7C002904A0 /* DeeplinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAB4675285B5C7C002904A0 /* DeeplinkTests.swift */; };
|
9EAB4676285B5C7C002904A0 /* DeeplinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAB4675285B5C7C002904A0 /* DeeplinkTests.swift */; };
|
||||||
|
9EAB46782860A1D2002904A0 /* WalletEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAB46772860A1D2002904A0 /* WalletEvent.swift */; };
|
||||||
|
9EAB467A2861EA6A002904A0 /* TransactionRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAB46792861EA6A002904A0 /* TransactionRowView.swift */; };
|
||||||
9EAFEB822805793200199FC9 /* AppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB812805793200199FC9 /* AppTests.swift */; };
|
9EAFEB822805793200199FC9 /* AppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB812805793200199FC9 /* AppTests.swift */; };
|
||||||
9EAFEB84280597B700199FC9 /* WrappedSecItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */; };
|
9EAFEB84280597B700199FC9 /* WrappedSecItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */; };
|
||||||
9EAFEB862805A23100199FC9 /* WrappedSecItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB852805A23100199FC9 /* WrappedSecItemTests.swift */; };
|
9EAFEB862805A23100199FC9 /* WrappedSecItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB852805A23100199FC9 /* WrappedSecItemTests.swift */; };
|
||||||
|
@ -166,9 +168,9 @@
|
||||||
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 */; };
|
||||||
F96B41E7273B501F0021B49A /* TransactionHistoryFlowStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E3273B501F0021B49A /* TransactionHistoryFlowStore.swift */; };
|
F96B41E7273B501F0021B49A /* WalletEventsFlowStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E3273B501F0021B49A /* WalletEventsFlowStore.swift */; };
|
||||||
F96B41E8273B501F0021B49A /* TransactionDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E5273B501F0021B49A /* TransactionDetailView.swift */; };
|
F96B41E8273B501F0021B49A /* TransactionDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E5273B501F0021B49A /* TransactionDetailView.swift */; };
|
||||||
F96B41E9273B501F0021B49A /* TransactionHistoryFlowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E6273B501F0021B49A /* TransactionHistoryFlowView.swift */; };
|
F96B41E9273B501F0021B49A /* WalletEventsFlowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E6273B501F0021B49A /* WalletEventsFlowView.swift */; };
|
||||||
F96B41EB273B50520021B49A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41EA273B50520021B49A /* Strings.swift */; };
|
F96B41EB273B50520021B49A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41EA273B50520021B49A /* Strings.swift */; };
|
||||||
F9971A4D27680DC400A2DB75 /* AppStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A4A27680DC400A2DB75 /* AppStore.swift */; };
|
F9971A4D27680DC400A2DB75 /* AppStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A4A27680DC400A2DB75 /* AppStore.swift */; };
|
||||||
F9971A4E27680DC400A2DB75 /* AppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A4C27680DC400A2DB75 /* AppView.swift */; };
|
F9971A4E27680DC400A2DB75 /* AppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A4C27680DC400A2DB75 /* AppView.swift */; };
|
||||||
|
@ -319,7 +321,7 @@
|
||||||
9E4DC6DF27C409A100E657F4 /* NeumorphicDesignModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NeumorphicDesignModifier.swift; sourceTree = "<group>"; };
|
9E4DC6DF27C409A100E657F4 /* NeumorphicDesignModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NeumorphicDesignModifier.swift; sourceTree = "<group>"; };
|
||||||
9E4DC6E127C4C6B700E657F4 /* SecantButtonStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecantButtonStyles.swift; sourceTree = "<group>"; };
|
9E4DC6E127C4C6B700E657F4 /* SecantButtonStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecantButtonStyles.swift; sourceTree = "<group>"; };
|
||||||
9E5BF63B2818305D00BA3F17 /* TransactionState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionState.swift; sourceTree = "<group>"; };
|
9E5BF63B2818305D00BA3F17 /* TransactionState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionState.swift; sourceTree = "<group>"; };
|
||||||
9E5BF63E2819542C00BA3F17 /* TransactionHistoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionHistoryTests.swift; sourceTree = "<group>"; };
|
9E5BF63E2819542C00BA3F17 /* WalletEventsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletEventsTests.swift; sourceTree = "<group>"; };
|
||||||
9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionFailedView.swift; sourceTree = "<group>"; };
|
9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionFailedView.swift; sourceTree = "<group>"; };
|
||||||
9E5BF643281FEC9900BA3F17 /* SendTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTests.swift; sourceTree = "<group>"; };
|
9E5BF643281FEC9900BA3F17 /* SendTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTests.swift; sourceTree = "<group>"; };
|
||||||
9E5BF6452821028C00BA3F17 /* WrappedUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedUserDefaults.swift; sourceTree = "<group>"; };
|
9E5BF6452821028C00BA3F17 /* WrappedUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedUserDefaults.swift; sourceTree = "<group>"; };
|
||||||
|
@ -350,6 +352,8 @@
|
||||||
9EAB46692859F42E002904A0 /* WrappedDeeplinkHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedDeeplinkHandler.swift; sourceTree = "<group>"; };
|
9EAB46692859F42E002904A0 /* WrappedDeeplinkHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedDeeplinkHandler.swift; sourceTree = "<group>"; };
|
||||||
9EAB4670285A1C77002904A0 /* DeeplinkHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeeplinkHandler.swift; sourceTree = "<group>"; };
|
9EAB4670285A1C77002904A0 /* DeeplinkHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeeplinkHandler.swift; sourceTree = "<group>"; };
|
||||||
9EAB4675285B5C7C002904A0 /* DeeplinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeeplinkTests.swift; sourceTree = "<group>"; };
|
9EAB4675285B5C7C002904A0 /* DeeplinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeeplinkTests.swift; sourceTree = "<group>"; };
|
||||||
|
9EAB46772860A1D2002904A0 /* WalletEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletEvent.swift; sourceTree = "<group>"; };
|
||||||
|
9EAB46792861EA6A002904A0 /* TransactionRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionRowView.swift; sourceTree = "<group>"; };
|
||||||
9EAFEB812805793200199FC9 /* AppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTests.swift; sourceTree = "<group>"; };
|
9EAFEB812805793200199FC9 /* AppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTests.swift; sourceTree = "<group>"; };
|
||||||
9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItem.swift; sourceTree = "<group>"; };
|
9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItem.swift; sourceTree = "<group>"; };
|
||||||
9EAFEB852805A23100199FC9 /* WrappedSecItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItemTests.swift; sourceTree = "<group>"; };
|
9EAFEB852805A23100199FC9 /* WrappedSecItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItemTests.swift; sourceTree = "<group>"; };
|
||||||
|
@ -369,9 +373,9 @@
|
||||||
F93673D52742CB840099C6AF /* Previews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Previews.swift; sourceTree = "<group>"; };
|
F93673D52742CB840099C6AF /* Previews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Previews.swift; sourceTree = "<group>"; };
|
||||||
F93874ED273C4DE200F0E875 /* HomeStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeStore.swift; sourceTree = "<group>"; };
|
F93874ED273C4DE200F0E875 /* HomeStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeStore.swift; sourceTree = "<group>"; };
|
||||||
F93874EF273C4DE200F0E875 /* HomeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
|
F93874EF273C4DE200F0E875 /* HomeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
|
||||||
F96B41E3273B501F0021B49A /* TransactionHistoryFlowStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionHistoryFlowStore.swift; sourceTree = "<group>"; };
|
F96B41E3273B501F0021B49A /* WalletEventsFlowStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletEventsFlowStore.swift; sourceTree = "<group>"; };
|
||||||
F96B41E5273B501F0021B49A /* TransactionDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionDetailView.swift; sourceTree = "<group>"; };
|
F96B41E5273B501F0021B49A /* TransactionDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionDetailView.swift; sourceTree = "<group>"; };
|
||||||
F96B41E6273B501F0021B49A /* TransactionHistoryFlowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionHistoryFlowView.swift; sourceTree = "<group>"; };
|
F96B41E6273B501F0021B49A /* WalletEventsFlowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletEventsFlowView.swift; sourceTree = "<group>"; };
|
||||||
F96B41EA273B50520021B49A /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
|
F96B41EA273B50520021B49A /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
|
||||||
F9971A4A27680DC400A2DB75 /* AppStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppStore.swift; sourceTree = "<group>"; };
|
F9971A4A27680DC400A2DB75 /* AppStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppStore.swift; sourceTree = "<group>"; };
|
||||||
F9971A4C27680DC400A2DB75 /* AppView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppView.swift; sourceTree = "<group>"; };
|
F9971A4C27680DC400A2DB75 /* AppView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppView.swift; sourceTree = "<group>"; };
|
||||||
|
@ -516,7 +520,7 @@
|
||||||
9E391122283E4C970073DD9A /* ImportWalletTests */,
|
9E391122283E4C970073DD9A /* ImportWalletTests */,
|
||||||
9E01F8262833CD84000EFC57 /* ScanTests */,
|
9E01F8262833CD84000EFC57 /* ScanTests */,
|
||||||
9E5BF642281FEC8700BA3F17 /* SendTests */,
|
9E5BF642281FEC8700BA3F17 /* SendTests */,
|
||||||
9E5BF63D281953F900BA3F17 /* TransactionHistoryTests */,
|
9E5BF63D281953F900BA3F17 /* WalletEventsTests */,
|
||||||
9EAFEB802805791400199FC9 /* AppTests */,
|
9EAFEB802805791400199FC9 /* AppTests */,
|
||||||
9EF8135927ECC25E0075AF48 /* UtilTests */,
|
9EF8135927ECC25E0075AF48 /* UtilTests */,
|
||||||
0DFE93E4272CB6D0000FCCA5 /* RecoveryPhraseValidationTests */,
|
0DFE93E4272CB6D0000FCCA5 /* RecoveryPhraseValidationTests */,
|
||||||
|
@ -577,6 +581,7 @@
|
||||||
9E7FE0D6282D286500C374E8 /* RecoveryPhrase.swift */,
|
9E7FE0D6282D286500C374E8 /* RecoveryPhrase.swift */,
|
||||||
9E7FE0DC282D298900C374E8 /* ValidationWord.swift */,
|
9E7FE0DC282D298900C374E8 /* ValidationWord.swift */,
|
||||||
9E7FE0E5282E7B1100C374E8 /* StoredWallet.swift */,
|
9E7FE0E5282E7B1100C374E8 /* StoredWallet.swift */,
|
||||||
|
9EAB46772860A1D2002904A0 /* WalletEvent.swift */,
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -673,7 +678,7 @@
|
||||||
F9971A5B27680DF600A2DB75 /* Scan */,
|
F9971A5B27680DF600A2DB75 /* Scan */,
|
||||||
F9C165B62740403600592F76 /* SendFlow */,
|
F9C165B62740403600592F76 /* SendFlow */,
|
||||||
F9971A6127680DFE00A2DB75 /* Settings */,
|
F9971A6127680DFE00A2DB75 /* Settings */,
|
||||||
F96B41E2273B501F0021B49A /* TransactionHistoryFlow */,
|
F96B41E2273B501F0021B49A /* WalletEventsFlow */,
|
||||||
9E7FE0E4282E753700C374E8 /* RecoveryPhraseDisplay */,
|
9E7FE0E4282E753700C374E8 /* RecoveryPhraseDisplay */,
|
||||||
9E7FE0E3282E751A00C374E8 /* RecoveryPhraseValidationFlow */,
|
9E7FE0E3282E751A00C374E8 /* RecoveryPhraseValidationFlow */,
|
||||||
6654C73C2715A3FA00901167 /* OnboardingFlow */,
|
6654C73C2715A3FA00901167 /* OnboardingFlow */,
|
||||||
|
@ -816,12 +821,12 @@
|
||||||
path = SnapshotTests;
|
path = SnapshotTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
9E5BF63D281953F900BA3F17 /* TransactionHistoryTests */ = {
|
9E5BF63D281953F900BA3F17 /* WalletEventsTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
9E5BF63E2819542C00BA3F17 /* TransactionHistoryTests.swift */,
|
9E5BF63E2819542C00BA3F17 /* WalletEventsTests.swift */,
|
||||||
);
|
);
|
||||||
path = TransactionHistoryTests;
|
path = WalletEventsTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
9E5BF642281FEC8700BA3F17 /* SendTests */ = {
|
9E5BF642281FEC8700BA3F17 /* SendTests */ = {
|
||||||
|
@ -1087,20 +1092,21 @@
|
||||||
path = Home;
|
path = Home;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
F96B41E2273B501F0021B49A /* TransactionHistoryFlow */ = {
|
F96B41E2273B501F0021B49A /* WalletEventsFlow */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
F96B41E3273B501F0021B49A /* TransactionHistoryFlowStore.swift */,
|
F96B41E3273B501F0021B49A /* WalletEventsFlowStore.swift */,
|
||||||
F96B41E6273B501F0021B49A /* TransactionHistoryFlowView.swift */,
|
F96B41E6273B501F0021B49A /* WalletEventsFlowView.swift */,
|
||||||
F96B41E4273B501F0021B49A /* Views */,
|
F96B41E4273B501F0021B49A /* Views */,
|
||||||
);
|
);
|
||||||
path = TransactionHistoryFlow;
|
path = WalletEventsFlow;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
F96B41E4273B501F0021B49A /* Views */ = {
|
F96B41E4273B501F0021B49A /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
F96B41E5273B501F0021B49A /* TransactionDetailView.swift */,
|
F96B41E5273B501F0021B49A /* TransactionDetailView.swift */,
|
||||||
|
9EAB46792861EA6A002904A0 /* TransactionRowView.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1396,7 +1402,7 @@
|
||||||
0D35CC46277A36E00074316A /* ScrollableWhenScaled.swift in Sources */,
|
0D35CC46277A36E00074316A /* ScrollableWhenScaled.swift in Sources */,
|
||||||
9E39114A2848EEB90073DD9A /* UserPreferencesStorage.swift in Sources */,
|
9E39114A2848EEB90073DD9A /* UserPreferencesStorage.swift in Sources */,
|
||||||
9EAB466A2859F42E002904A0 /* WrappedDeeplinkHandler.swift in Sources */,
|
9EAB466A2859F42E002904A0 /* WrappedDeeplinkHandler.swift in Sources */,
|
||||||
F96B41E9273B501F0021B49A /* TransactionHistoryFlowView.swift in Sources */,
|
F96B41E9273B501F0021B49A /* WalletEventsFlowView.swift in Sources */,
|
||||||
9E01F8202833861A000EFC57 /* WrappedCaptureDevice.swift in Sources */,
|
9E01F8202833861A000EFC57 /* WrappedCaptureDevice.swift in Sources */,
|
||||||
2EDA07A027EDE18C00D6F09B /* TCATextField.swift in Sources */,
|
2EDA07A027EDE18C00D6F09B /* TCATextField.swift in Sources */,
|
||||||
9E7FE0DB282D28F100C374E8 /* WrappedPasteboard.swift in Sources */,
|
9E7FE0DB282D28F100C374E8 /* WrappedPasteboard.swift in Sources */,
|
||||||
|
@ -1414,6 +1420,7 @@
|
||||||
9E7FE0CF282D257400C374E8 /* SDKSynchronizer+SyncStatus.swift in Sources */,
|
9E7FE0CF282D257400C374E8 /* SDKSynchronizer+SyncStatus.swift in Sources */,
|
||||||
9E4DC6E027C409A100E657F4 /* NeumorphicDesignModifier.swift in Sources */,
|
9E4DC6E027C409A100E657F4 /* NeumorphicDesignModifier.swift in Sources */,
|
||||||
0DACFA7F27208CE00039EEA5 /* Clamped.swift in Sources */,
|
0DACFA7F27208CE00039EEA5 /* Clamped.swift in Sources */,
|
||||||
|
9EAB467A2861EA6A002904A0 /* TransactionRowView.swift in Sources */,
|
||||||
0DFE93E3272CA1AA000FCCA5 /* RecoveryPhraseValidationFlowStore.swift in Sources */,
|
0DFE93E3272CA1AA000FCCA5 /* RecoveryPhraseValidationFlowStore.swift in Sources */,
|
||||||
9E2DF99E27CF704D00649636 /* ImportWalletView.swift in Sources */,
|
9E2DF99E27CF704D00649636 /* ImportWalletView.swift in Sources */,
|
||||||
0D535FE2271F9476009A9E3E /* EnumeratedChip.swift in Sources */,
|
0D535FE2271F9476009A9E3E /* EnumeratedChip.swift in Sources */,
|
||||||
|
@ -1465,7 +1472,7 @@
|
||||||
9E2AC10127D8EF0B0042AA47 /* WrappedMnemonic.swift in Sources */,
|
9E2AC10127D8EF0B0042AA47 /* WrappedMnemonic.swift in Sources */,
|
||||||
9E7FE0D7282D286500C374E8 /* RecoveryPhrase.swift in Sources */,
|
9E7FE0D7282D286500C374E8 /* RecoveryPhrase.swift in Sources */,
|
||||||
660558F7270C862F009D6954 /* Fonts+Generated.swift in Sources */,
|
660558F7270C862F009D6954 /* Fonts+Generated.swift in Sources */,
|
||||||
F96B41E7273B501F0021B49A /* TransactionHistoryFlowStore.swift in Sources */,
|
F96B41E7273B501F0021B49A /* WalletEventsFlowStore.swift in Sources */,
|
||||||
9E7FE0E6282E7B1100C374E8 /* StoredWallet.swift in Sources */,
|
9E7FE0E6282E7B1100C374E8 /* StoredWallet.swift in Sources */,
|
||||||
9EAFEB9128081E9400199FC9 /* HomeStore.swift in Sources */,
|
9EAFEB9128081E9400199FC9 /* HomeStore.swift in Sources */,
|
||||||
F9971A5A27680DDE00A2DB75 /* RequestView.swift in Sources */,
|
F9971A5A27680DDE00A2DB75 /* RequestView.swift in Sources */,
|
||||||
|
@ -1505,6 +1512,7 @@
|
||||||
F9971A5427680DD000A2DB75 /* ProfileView.swift in Sources */,
|
F9971A5427680DD000A2DB75 /* ProfileView.swift in Sources */,
|
||||||
F9971A6027680DF600A2DB75 /* ScanStore.swift in Sources */,
|
F9971A6027680DF600A2DB75 /* ScanStore.swift in Sources */,
|
||||||
9EF8139127F191BF0075AF48 /* WrappedWalletStorage.swift in Sources */,
|
9EF8139127F191BF0075AF48 /* WrappedWalletStorage.swift in Sources */,
|
||||||
|
9EAB46782860A1D2002904A0 /* WalletEvent.swift in Sources */,
|
||||||
0DFE93E1272C9ECB000FCCA5 /* RecoveryPhraseBackupView.swift in Sources */,
|
0DFE93E1272C9ECB000FCCA5 /* RecoveryPhraseBackupView.swift in Sources */,
|
||||||
9E69A24D27FB002800A55317 /* WelcomeStore.swift in Sources */,
|
9E69A24D27FB002800A55317 /* WelcomeStore.swift in Sources */,
|
||||||
F9C165CB2741AB5D00592F76 /* SendFlowView.swift in Sources */,
|
F9C165CB2741AB5D00592F76 /* SendFlowView.swift in Sources */,
|
||||||
|
@ -1542,7 +1550,7 @@
|
||||||
9E391132284644580073DD9A /* AppInitializationTests.swift in Sources */,
|
9E391132284644580073DD9A /* AppInitializationTests.swift in Sources */,
|
||||||
9E9ECC9928589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift in Sources */,
|
9E9ECC9928589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift in Sources */,
|
||||||
9E391124283E4CAC0073DD9A /* ImportWalletTests.swift in Sources */,
|
9E391124283E4CAC0073DD9A /* ImportWalletTests.swift in Sources */,
|
||||||
9E5BF63F2819542C00BA3F17 /* TransactionHistoryTests.swift in Sources */,
|
9E5BF63F2819542C00BA3F17 /* WalletEventsTests.swift in Sources */,
|
||||||
0D4E7A1B26B364180058B01E /* secantTests.swift in Sources */,
|
0D4E7A1B26B364180058B01E /* secantTests.swift in Sources */,
|
||||||
0DFE93E6272CB6F7000FCCA5 /* RecoveryPhraseValidationTests.swift in Sources */,
|
0DFE93E6272CB6F7000FCCA5 /* RecoveryPhraseValidationTests.swift in Sources */,
|
||||||
9EAB4676285B5C7C002904A0 /* DeeplinkTests.swift in Sources */,
|
9EAB4676285B5C7C002904A0 /* DeeplinkTests.swift in Sources */,
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct HomeState: Equatable {
|
||||||
var scanState: ScanState
|
var scanState: ScanState
|
||||||
var synchronizerStatus: String
|
var synchronizerStatus: String
|
||||||
var totalBalance: Zatoshi
|
var totalBalance: Zatoshi
|
||||||
var transactionHistoryState: TransactionHistoryFlowState
|
var walletEventsState: WalletEventsFlowState
|
||||||
var verifiedBalance: Zatoshi
|
var verifiedBalance: Zatoshi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,12 +43,12 @@ enum HomeAction: Equatable {
|
||||||
case send(SendFlowAction)
|
case send(SendFlowAction)
|
||||||
case scan(ScanAction)
|
case scan(ScanAction)
|
||||||
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
||||||
case transactionHistory(TransactionHistoryFlowAction)
|
case walletEvents(WalletEventsFlowAction)
|
||||||
case updateBalance(Balance)
|
case updateBalance(Balance)
|
||||||
case updateDrawer(DrawerOverlay)
|
case updateDrawer(DrawerOverlay)
|
||||||
case updateRoute(HomeState.Route?)
|
case updateRoute(HomeState.Route?)
|
||||||
case updateSynchronizerStatus
|
case updateSynchronizerStatus
|
||||||
case updateTransactions([TransactionState])
|
case updateWalletEvents([WalletEvent])
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Environment
|
// MARK: Environment
|
||||||
|
@ -106,7 +106,7 @@ extension HomeReducer {
|
||||||
return .merge(
|
return .merge(
|
||||||
environment.SDKSynchronizer.getAllClearedTransactions()
|
environment.SDKSynchronizer.getAllClearedTransactions()
|
||||||
.receive(on: environment.scheduler)
|
.receive(on: environment.scheduler)
|
||||||
.map(HomeAction.updateTransactions)
|
.map(HomeAction.updateWalletEvents)
|
||||||
.eraseToEffect(),
|
.eraseToEffect(),
|
||||||
|
|
||||||
environment.SDKSynchronizer.getShieldedBalance()
|
environment.SDKSynchronizer.getShieldedBalance()
|
||||||
|
@ -128,10 +128,10 @@ extension HomeReducer {
|
||||||
|
|
||||||
case .updateDrawer(let drawerOverlay):
|
case .updateDrawer(let drawerOverlay):
|
||||||
state.drawerOverlay = drawerOverlay
|
state.drawerOverlay = drawerOverlay
|
||||||
state.transactionHistoryState.isScrollable = drawerOverlay == .full ? true : false
|
state.walletEventsState.isScrollable = drawerOverlay == .full ? true : false
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .updateTransactions(let transactions):
|
case .updateWalletEvents(let walletEvents):
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .updateSynchronizerStatus:
|
case .updateSynchronizerStatus:
|
||||||
|
@ -148,13 +148,13 @@ extension HomeReducer {
|
||||||
case .request(let action):
|
case .request(let action):
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .transactionHistory(.updateRoute(.all)):
|
case .walletEvents(.updateRoute(.all)):
|
||||||
return state.drawerOverlay != .full ? Effect(value: .updateDrawer(.full)) : .none
|
return state.drawerOverlay != .full ? Effect(value: .updateDrawer(.full)) : .none
|
||||||
|
|
||||||
case .transactionHistory(.updateRoute(.latest)):
|
case .walletEvents(.updateRoute(.latest)):
|
||||||
return state.drawerOverlay != .partial ? Effect(value: .updateDrawer(.partial)) : .none
|
return state.drawerOverlay != .partial ? Effect(value: .updateDrawer(.partial)) : .none
|
||||||
|
|
||||||
case .transactionHistory(let historyAction):
|
case .walletEvents(let historyAction):
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .send(.updateRoute(.done)):
|
case .send(.updateRoute(.done)):
|
||||||
|
@ -175,11 +175,11 @@ extension HomeReducer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static let historyReducer: HomeReducer = TransactionHistoryFlowReducer.default.pullback(
|
private static let historyReducer: HomeReducer = WalletEventsFlowReducer.default.pullback(
|
||||||
state: \HomeState.transactionHistoryState,
|
state: \HomeState.walletEventsState,
|
||||||
action: /HomeAction.transactionHistory,
|
action: /HomeAction.walletEvents,
|
||||||
environment: { environment in
|
environment: { environment in
|
||||||
TransactionHistoryFlowEnvironment(
|
WalletEventsFlowEnvironment(
|
||||||
scheduler: environment.scheduler,
|
scheduler: environment.scheduler,
|
||||||
SDKSynchronizer: environment.SDKSynchronizer
|
SDKSynchronizer: environment.SDKSynchronizer
|
||||||
)
|
)
|
||||||
|
@ -228,10 +228,10 @@ extension HomeReducer {
|
||||||
// MARK: - Store
|
// MARK: - Store
|
||||||
|
|
||||||
extension HomeStore {
|
extension HomeStore {
|
||||||
func historyStore() -> TransactionHistoryFlowStore {
|
func historyStore() -> WalletEventsFlowStore {
|
||||||
self.scope(
|
self.scope(
|
||||||
state: \.transactionHistoryState,
|
state: \.walletEventsState,
|
||||||
action: HomeAction.transactionHistory
|
action: HomeAction.walletEvents
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ extension HomeState {
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
synchronizerStatus: "",
|
synchronizerStatus: "",
|
||||||
totalBalance: Zatoshi.zero,
|
totalBalance: Zatoshi.zero,
|
||||||
transactionHistoryState: .emptyPlaceHolder,
|
walletEventsState: .emptyPlaceHolder,
|
||||||
verifiedBalance: Zatoshi.zero
|
verifiedBalance: Zatoshi.zero
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ struct HomeView: View {
|
||||||
if proxy.size.height > 0 {
|
if proxy.size.height > 0 {
|
||||||
Drawer(overlay: viewStore.bindingForDrawer(), maxHeight: proxy.size.height) {
|
Drawer(overlay: viewStore.bindingForDrawer(), maxHeight: proxy.size.height) {
|
||||||
VStack {
|
VStack {
|
||||||
TransactionHistoryFlowView(store: store.historyStore())
|
WalletEventsFlowView(store: store.historyStore())
|
||||||
.padding(.top, 10)
|
.padding(.top, 10)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
|
@ -16,7 +16,7 @@ struct SandboxState: Equatable {
|
||||||
case scan
|
case scan
|
||||||
case request
|
case request
|
||||||
}
|
}
|
||||||
var transactionHistoryState: TransactionHistoryFlowState
|
var walletEventsState: WalletEventsFlowState
|
||||||
var profileState: ProfileState
|
var profileState: ProfileState
|
||||||
var route: Route?
|
var route: Route?
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ struct SandboxState: Equatable {
|
||||||
|
|
||||||
enum SandboxAction: Equatable {
|
enum SandboxAction: Equatable {
|
||||||
case updateRoute(SandboxState.Route?)
|
case updateRoute(SandboxState.Route?)
|
||||||
case transactionHistory(TransactionHistoryFlowAction)
|
case walletEvents(WalletEventsFlowAction)
|
||||||
case profile(ProfileAction)
|
case profile(ProfileAction)
|
||||||
case reset
|
case reset
|
||||||
}
|
}
|
||||||
|
@ -42,18 +42,18 @@ extension SandboxReducer {
|
||||||
case let .updateRoute(route):
|
case let .updateRoute(route):
|
||||||
state.route = route
|
state.route = route
|
||||||
return .none
|
return .none
|
||||||
case let .transactionHistory(transactionHistoryAction):
|
case let .walletEvents(walletEventsAction):
|
||||||
return TransactionHistoryFlowReducer
|
return WalletEventsFlowReducer
|
||||||
.default
|
.default
|
||||||
.run(
|
.run(
|
||||||
&state.transactionHistoryState,
|
&state.walletEventsState,
|
||||||
transactionHistoryAction,
|
walletEventsAction,
|
||||||
TransactionHistoryFlowEnvironment(
|
WalletEventsFlowEnvironment(
|
||||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
||||||
SDKSynchronizer: LiveWrappedSDKSynchronizer()
|
SDKSynchronizer: LiveWrappedSDKSynchronizer()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.map(SandboxAction.transactionHistory)
|
.map(SandboxAction.walletEvents)
|
||||||
case let .profile(profileAction):
|
case let .profile(profileAction):
|
||||||
return ProfileReducer
|
return ProfileReducer
|
||||||
.default
|
.default
|
||||||
|
@ -72,10 +72,10 @@ extension SandboxReducer {
|
||||||
// MARK: - Store
|
// MARK: - Store
|
||||||
|
|
||||||
extension SandboxStore {
|
extension SandboxStore {
|
||||||
func historyStore() -> TransactionHistoryFlowStore {
|
func historyStore() -> WalletEventsFlowStore {
|
||||||
self.scope(
|
self.scope(
|
||||||
state: \.transactionHistoryState,
|
state: \.walletEventsState,
|
||||||
action: SandboxAction.transactionHistory
|
action: SandboxAction.walletEvents
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,15 +92,15 @@ extension SandboxStore {
|
||||||
extension SandboxViewStore {
|
extension SandboxViewStore {
|
||||||
func toggleSelectedTransaction() {
|
func toggleSelectedTransaction() {
|
||||||
let isAlreadySelected = (self.selectedTranactionID != nil)
|
let isAlreadySelected = (self.selectedTranactionID != nil)
|
||||||
let transcation = self.transactionHistoryState.transactions[5]
|
let walletEvent = self.walletEventsState.walletEvents[5]
|
||||||
let newRoute = isAlreadySelected ? nil : TransactionHistoryFlowState.Route.showTransaction(transcation)
|
let newRoute = isAlreadySelected ? nil : WalletEventsFlowState.Route.showWalletEvent(walletEvent)
|
||||||
send(.transactionHistory(.updateRoute(newRoute)))
|
send(.walletEvents(.updateRoute(newRoute)))
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedTranactionID: String? {
|
var selectedTranactionID: String? {
|
||||||
self.transactionHistoryState
|
self.walletEventsState
|
||||||
.route
|
.route
|
||||||
.flatMap(/TransactionHistoryFlowState.Route.showTransaction)
|
.flatMap(/WalletEventsFlowState.Route.showWalletEvent)
|
||||||
.map(\.id)
|
.map(\.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ extension SandboxViewStore {
|
||||||
extension SandboxState {
|
extension SandboxState {
|
||||||
static var placeholder: Self {
|
static var placeholder: Self {
|
||||||
.init(
|
.init(
|
||||||
transactionHistoryState: .placeHolder,
|
walletEventsState: .placeHolder,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
route: nil
|
route: nil
|
||||||
)
|
)
|
||||||
|
@ -130,7 +130,7 @@ extension SandboxStore {
|
||||||
static var placeholder: SandboxStore {
|
static var placeholder: SandboxStore {
|
||||||
SandboxStore(
|
SandboxStore(
|
||||||
initialState: SandboxState(
|
initialState: SandboxState(
|
||||||
transactionHistoryState: .placeHolder,
|
walletEventsState: .placeHolder,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
route: nil
|
route: nil
|
||||||
),
|
),
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct SandboxView: View {
|
||||||
@ViewBuilder func view(for route: SandboxState.Route) -> some View {
|
@ViewBuilder func view(for route: SandboxState.Route) -> some View {
|
||||||
switch route {
|
switch route {
|
||||||
case .history:
|
case .history:
|
||||||
TransactionHistoryFlowView(store: store.historyStore())
|
WalletEventsFlowView(store: store.historyStore())
|
||||||
case .send:
|
case .send:
|
||||||
SendFlowView(
|
SendFlowView(
|
||||||
store: .init(
|
store: .init(
|
||||||
|
@ -94,7 +94,7 @@ struct SandboxView: View {
|
||||||
isPresented: viewStore.bindingForRoute(.history),
|
isPresented: viewStore.bindingForRoute(.history),
|
||||||
content: {
|
content: {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
TransactionHistoryFlowView(store: store.historyStore())
|
WalletEventsFlowView(store: store.historyStore())
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem {
|
ToolbarItem {
|
||||||
Button("Done") { viewStore.send(.updateRoute(nil)) }
|
Button("Done") { viewStore.send(.updateRoute(nil)) }
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
import ComposableArchitecture
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
typealias TransactionHistoryFlowReducer = Reducer<TransactionHistoryFlowState, TransactionHistoryFlowAction, TransactionHistoryFlowEnvironment>
|
|
||||||
typealias TransactionHistoryFlowStore = Store<TransactionHistoryFlowState, TransactionHistoryFlowAction>
|
|
||||||
typealias TransactionHistoryFlowViewStore = ViewStore<TransactionHistoryFlowState, TransactionHistoryFlowAction>
|
|
||||||
|
|
||||||
// MARK: - State
|
|
||||||
|
|
||||||
struct TransactionHistoryFlowState: Equatable {
|
|
||||||
enum Route: Equatable {
|
|
||||||
case latest
|
|
||||||
case all
|
|
||||||
case showTransaction(TransactionState)
|
|
||||||
}
|
|
||||||
|
|
||||||
var route: Route?
|
|
||||||
|
|
||||||
var isScrollable = false
|
|
||||||
var transactions: IdentifiedArrayOf<TransactionState>
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Action
|
|
||||||
|
|
||||||
enum TransactionHistoryFlowAction: Equatable {
|
|
||||||
case onAppear
|
|
||||||
case onDisappear
|
|
||||||
case updateRoute(TransactionHistoryFlowState.Route?)
|
|
||||||
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
|
||||||
case updateTransactions([TransactionState])
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Environment
|
|
||||||
|
|
||||||
struct TransactionHistoryFlowEnvironment {
|
|
||||||
let scheduler: AnySchedulerOf<DispatchQueue>
|
|
||||||
let SDKSynchronizer: WrappedSDKSynchronizer
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Reducer
|
|
||||||
|
|
||||||
extension TransactionHistoryFlowReducer {
|
|
||||||
private struct CancelId: Hashable {}
|
|
||||||
|
|
||||||
static let `default` = TransactionHistoryFlowReducer { state, action, environment in
|
|
||||||
switch action {
|
|
||||||
case .onAppear:
|
|
||||||
return environment.SDKSynchronizer.stateChanged
|
|
||||||
.map(TransactionHistoryFlowAction.synchronizerStateChanged)
|
|
||||||
.eraseToEffect()
|
|
||||||
.cancellable(id: CancelId(), cancelInFlight: true)
|
|
||||||
|
|
||||||
case .onDisappear:
|
|
||||||
return Effect.cancel(id: CancelId())
|
|
||||||
|
|
||||||
case .synchronizerStateChanged(.synced):
|
|
||||||
return environment.SDKSynchronizer.getAllTransactions()
|
|
||||||
.receive(on: environment.scheduler)
|
|
||||||
.map(TransactionHistoryFlowAction.updateTransactions)
|
|
||||||
.eraseToEffect()
|
|
||||||
|
|
||||||
case .synchronizerStateChanged(let synchronizerState):
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .updateTransactions(let transactions):
|
|
||||||
let sortedTransactions = transactions
|
|
||||||
.sorted(by: { lhs, rhs in
|
|
||||||
lhs.date > rhs.date
|
|
||||||
})
|
|
||||||
state.transactions = IdentifiedArrayOf(uniqueElements: sortedTransactions)
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case let .updateRoute(route):
|
|
||||||
state.route = route
|
|
||||||
return .none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - ViewStore
|
|
||||||
|
|
||||||
extension TransactionHistoryFlowViewStore {
|
|
||||||
private typealias Route = TransactionHistoryFlowState.Route
|
|
||||||
|
|
||||||
func bindingForSelectingTransaction(_ transaction: TransactionState) -> Binding<Bool> {
|
|
||||||
self.binding(
|
|
||||||
get: { $0.route.map(/TransactionHistoryFlowState.Route.showTransaction) == transaction },
|
|
||||||
send: { isActive in
|
|
||||||
TransactionHistoryFlowAction.updateRoute( isActive ? TransactionHistoryFlowState.Route.showTransaction(transaction) : nil)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Placeholders
|
|
||||||
|
|
||||||
extension TransactionState {
|
|
||||||
static var placeholder: Self {
|
|
||||||
.init(
|
|
||||||
date: Date.init(timeIntervalSince1970: 1234567),
|
|
||||||
id: "2",
|
|
||||||
status: .paid(success: true),
|
|
||||||
subtitle: "",
|
|
||||||
zecAmount: Zatoshi(amount: 25)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionHistoryFlowState {
|
|
||||||
static var placeHolder: Self {
|
|
||||||
.init(transactions: .placeholder)
|
|
||||||
}
|
|
||||||
|
|
||||||
static var emptyPlaceHolder: Self {
|
|
||||||
.init(transactions: [])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionHistoryFlowStore {
|
|
||||||
static var placeholder: Store<TransactionHistoryFlowState, TransactionHistoryFlowAction> {
|
|
||||||
return Store(
|
|
||||||
initialState: .placeHolder,
|
|
||||||
reducer: .default,
|
|
||||||
environment: TransactionHistoryFlowEnvironment(
|
|
||||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
|
||||||
SDKSynchronizer: LiveWrappedSDKSynchronizer()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
static var demoWithSelectedTransaction: Store<TransactionHistoryFlowState, TransactionHistoryFlowAction> {
|
|
||||||
let transactions = IdentifiedArrayOf<TransactionState>.placeholder
|
|
||||||
return Store(
|
|
||||||
initialState: TransactionHistoryFlowState(
|
|
||||||
route: .showTransaction(transactions[3]),
|
|
||||||
transactions: transactions
|
|
||||||
),
|
|
||||||
reducer: .default.debug(),
|
|
||||||
environment: TransactionHistoryFlowEnvironment(
|
|
||||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
|
||||||
SDKSynchronizer: LiveWrappedSDKSynchronizer()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension IdentifiedArrayOf where Element == TransactionState {
|
|
||||||
static var placeholder: IdentifiedArrayOf<TransactionState> {
|
|
||||||
return .init(
|
|
||||||
uniqueElements: (0..<30).map {
|
|
||||||
TransactionState(
|
|
||||||
date: Date.init(timeIntervalSince1970: 1234567),
|
|
||||||
id: String($0),
|
|
||||||
status: .paid(success: true),
|
|
||||||
subtitle: "",
|
|
||||||
zecAmount: Zatoshi(amount: 25)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// TransactionRowView.swift
|
||||||
|
// secant-testnet
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 21.06.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct TransactionRowView: View {
|
||||||
|
var transaction: TransactionState
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
Circle()
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.frame(width: 30, height: 30, alignment: .center)
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Text(transaction.status == .received ? "Unknown paid you" : "You sent to")
|
||||||
|
.font(.system(size: 14))
|
||||||
|
.fontWeight(.bold)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Text(transaction.status == .received ? "+" : "")
|
||||||
|
+ Text("\(transaction.zecAmount.decimalString()) ZEC")
|
||||||
|
}
|
||||||
|
HStack {
|
||||||
|
Text(transaction.address)
|
||||||
|
.font(.system(size: 14))
|
||||||
|
.fontWeight(.thin)
|
||||||
|
.truncationMode(.middle)
|
||||||
|
.lineLimit(1)
|
||||||
|
|
||||||
|
Spacer(minLength: 80)
|
||||||
|
|
||||||
|
Text("$145")
|
||||||
|
.font(.system(size: 14))
|
||||||
|
.fontWeight(.thin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SendTransactionRowView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
VStack {
|
||||||
|
TransactionRowView(transaction: .placeholder)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.preferredColorScheme(.dark)
|
||||||
|
.previewLayout(.fixed(width: 428, height: 60))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
import ComposableArchitecture
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
typealias WalletEventsFlowReducer = Reducer<WalletEventsFlowState, WalletEventsFlowAction, WalletEventsFlowEnvironment>
|
||||||
|
typealias WalletEventsFlowStore = Store<WalletEventsFlowState, WalletEventsFlowAction>
|
||||||
|
typealias WalletEventsFlowViewStore = ViewStore<WalletEventsFlowState, WalletEventsFlowAction>
|
||||||
|
|
||||||
|
// MARK: - State
|
||||||
|
|
||||||
|
struct WalletEventsFlowState: Equatable {
|
||||||
|
enum Route: Equatable {
|
||||||
|
case latest
|
||||||
|
case all
|
||||||
|
case showWalletEvent(WalletEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
var route: Route?
|
||||||
|
|
||||||
|
var isScrollable = false
|
||||||
|
var walletEvents = IdentifiedArrayOf<WalletEvent>.placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Action
|
||||||
|
|
||||||
|
enum WalletEventsFlowAction: Equatable {
|
||||||
|
case onAppear
|
||||||
|
case onDisappear
|
||||||
|
case updateRoute(WalletEventsFlowState.Route?)
|
||||||
|
case synchronizerStateChanged(WrappedSDKSynchronizerState)
|
||||||
|
case updateWalletEvents([WalletEvent])
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Environment
|
||||||
|
|
||||||
|
struct WalletEventsFlowEnvironment {
|
||||||
|
let scheduler: AnySchedulerOf<DispatchQueue>
|
||||||
|
let SDKSynchronizer: WrappedSDKSynchronizer
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Reducer
|
||||||
|
|
||||||
|
extension WalletEventsFlowReducer {
|
||||||
|
private struct CancelId: Hashable {}
|
||||||
|
|
||||||
|
static let `default` = WalletEventsFlowReducer { state, action, environment in
|
||||||
|
switch action {
|
||||||
|
case .onAppear:
|
||||||
|
return environment.SDKSynchronizer.stateChanged
|
||||||
|
.map(WalletEventsFlowAction.synchronizerStateChanged)
|
||||||
|
.eraseToEffect()
|
||||||
|
.cancellable(id: CancelId(), cancelInFlight: true)
|
||||||
|
|
||||||
|
case .onDisappear:
|
||||||
|
return Effect.cancel(id: CancelId())
|
||||||
|
|
||||||
|
case .synchronizerStateChanged(.synced):
|
||||||
|
return environment.SDKSynchronizer.getAllTransactions()
|
||||||
|
.receive(on: environment.scheduler)
|
||||||
|
.map(WalletEventsFlowAction.updateWalletEvents)
|
||||||
|
.eraseToEffect()
|
||||||
|
|
||||||
|
case .synchronizerStateChanged(let synchronizerState):
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case .updateWalletEvents(let walletEvents):
|
||||||
|
let sortedWalletEvents = walletEvents
|
||||||
|
.sorted(by: { lhs, rhs in
|
||||||
|
lhs.timestamp > rhs.timestamp
|
||||||
|
})
|
||||||
|
state.walletEvents = IdentifiedArrayOf(uniqueElements: sortedWalletEvents)
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case let .updateRoute(route):
|
||||||
|
state.route = route
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - ViewStore
|
||||||
|
|
||||||
|
extension WalletEventsFlowViewStore {
|
||||||
|
private typealias Route = WalletEventsFlowState.Route
|
||||||
|
|
||||||
|
func bindingForSelectingWalletEvent(_ walletEvent: WalletEvent) -> Binding<Bool> {
|
||||||
|
self.binding(
|
||||||
|
get: { $0.route.map(/WalletEventsFlowState.Route.showWalletEvent) == walletEvent },
|
||||||
|
send: { isActive in
|
||||||
|
WalletEventsFlowAction.updateRoute( isActive ? WalletEventsFlowState.Route.showWalletEvent(walletEvent) : nil)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Placeholders
|
||||||
|
|
||||||
|
extension TransactionState {
|
||||||
|
static var placeholder: Self {
|
||||||
|
.init(
|
||||||
|
id: "2",
|
||||||
|
status: .paid(success: true),
|
||||||
|
subtitle: "",
|
||||||
|
timestamp: 1234567,
|
||||||
|
zecAmount: Zatoshi(amount: 25)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension WalletEventsFlowState {
|
||||||
|
static var placeHolder: Self {
|
||||||
|
.init(walletEvents: .placeholder)
|
||||||
|
}
|
||||||
|
|
||||||
|
static var emptyPlaceHolder: Self {
|
||||||
|
.init(walletEvents: [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension WalletEventsFlowStore {
|
||||||
|
static var placeholder: Store<WalletEventsFlowState, WalletEventsFlowAction> {
|
||||||
|
return Store(
|
||||||
|
initialState: .placeHolder,
|
||||||
|
reducer: .default,
|
||||||
|
environment: WalletEventsFlowEnvironment(
|
||||||
|
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
||||||
|
SDKSynchronizer: LiveWrappedSDKSynchronizer()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension IdentifiedArrayOf where Element == TransactionState {
|
||||||
|
static var placeholder: IdentifiedArrayOf<TransactionState> {
|
||||||
|
return .init(
|
||||||
|
uniqueElements: (0..<30).map {
|
||||||
|
TransactionState(
|
||||||
|
id: String($0),
|
||||||
|
status: .paid(success: true),
|
||||||
|
subtitle: "",
|
||||||
|
timestamp: 1234567,
|
||||||
|
zecAmount: Zatoshi(amount: 25)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import ComposableArchitecture
|
import ComposableArchitecture
|
||||||
|
|
||||||
struct TransactionHistoryFlowView: View {
|
struct WalletEventsFlowView: View {
|
||||||
let store: TransactionHistoryFlowStore
|
let store: WalletEventsFlowStore
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
UITableView.appearance().backgroundColor = .clear
|
UITableView.appearance().backgroundColor = .clear
|
||||||
|
@ -14,11 +14,11 @@ struct TransactionHistoryFlowView: View {
|
||||||
|
|
||||||
if viewStore.isScrollable {
|
if viewStore.isScrollable {
|
||||||
List {
|
List {
|
||||||
transactionsList(with: viewStore)
|
walletEventsList(with: viewStore)
|
||||||
}
|
}
|
||||||
.listStyle(.sidebar)
|
.listStyle(.sidebar)
|
||||||
} else {
|
} else {
|
||||||
transactionsList(with: viewStore)
|
walletEventsList(with: viewStore)
|
||||||
.padding(.horizontal, 32)
|
.padding(.horizontal, 32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,36 +28,16 @@ struct TransactionHistoryFlowView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TransactionHistoryFlowView {
|
extension WalletEventsFlowView {
|
||||||
func transactionsList(with viewStore: TransactionHistoryFlowViewStore) -> some View {
|
func walletEventsList(with viewStore: WalletEventsFlowViewStore) -> some View {
|
||||||
ForEach(viewStore.transactions) { transaction in
|
ForEach(viewStore.walletEvents) { walletEvent in
|
||||||
WithStateBinding(binding: viewStore.bindingForSelectingTransaction(transaction)) { active in
|
WithStateBinding(binding: viewStore.bindingForSelectingWalletEvent(walletEvent)) { active in
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
walletEvent.rowView()
|
||||||
Text(transaction.date.asHumanReadable())
|
|
||||||
.font(.system(size: 12))
|
|
||||||
.fontWeight(.thin)
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Text(transaction.subtitle)
|
|
||||||
.font(.system(size: 12))
|
|
||||||
.fontWeight(.thin)
|
|
||||||
.foregroundColor(transaction.subtitle == "pending" ? .red : .green)
|
|
||||||
}
|
|
||||||
|
|
||||||
HStack {
|
|
||||||
Text(transaction.status == .received ? "Recevied" : "Sent")
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Text(transaction.status == .received ? "+" : "")
|
|
||||||
+ Text("\(transaction.zecAmount.decimalString()) ZEC")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.navigationLink(
|
.navigationLink(
|
||||||
isActive: active,
|
isActive: active,
|
||||||
destination: { TransactionDetailView(transaction: transaction) }
|
destination: { walletEvent.detailView() }
|
||||||
)
|
)
|
||||||
.foregroundColor(Asset.Colors.Text.body.color)
|
.foregroundColor(Asset.Colors.Text.body.color)
|
||||||
.listRowBackground(Color.clear)
|
.listRowBackground(Color.clear)
|
||||||
|
@ -65,7 +45,7 @@ extension TransactionHistoryFlowView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func header(with viewStore: TransactionHistoryFlowViewStore) -> some View {
|
func header(with viewStore: WalletEventsFlowViewStore) -> some View {
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
VStack {
|
VStack {
|
||||||
Button("Latest") {
|
Button("Latest") {
|
||||||
|
@ -95,7 +75,7 @@ extension TransactionHistoryFlowView {
|
||||||
struct TransactionView_Previews: PreviewProvider {
|
struct TransactionView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
TransactionHistoryFlowView(store: .placeholder)
|
WalletEventsFlowView(store: .placeholder)
|
||||||
.preferredColorScheme(.dark)
|
.preferredColorScheme(.dark)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,6 +13,7 @@ struct TransactionState: Equatable, Identifiable {
|
||||||
enum Status: Equatable {
|
enum Status: Equatable {
|
||||||
case paid(success: Bool)
|
case paid(success: Bool)
|
||||||
case received
|
case received
|
||||||
|
case failed
|
||||||
}
|
}
|
||||||
|
|
||||||
var expirationHeight = -1
|
var expirationHeight = -1
|
||||||
|
@ -21,16 +22,18 @@ struct TransactionState: Equatable, Identifiable {
|
||||||
var shielded = true
|
var shielded = true
|
||||||
var zAddress: String?
|
var zAddress: String?
|
||||||
|
|
||||||
var date: Date
|
|
||||||
var id: String
|
var id: String
|
||||||
var status: Status
|
var status: Status
|
||||||
var subtitle: String
|
var subtitle: String
|
||||||
|
var timestamp: TimeInterval
|
||||||
var zecAmount: Zatoshi
|
var zecAmount: Zatoshi
|
||||||
|
|
||||||
|
var address: String { zAddress ?? "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TransactionState {
|
extension TransactionState {
|
||||||
init(confirmedTransaction: ConfirmedTransactionEntity, sent: Bool = false) {
|
init(confirmedTransaction: ConfirmedTransactionEntity, sent: Bool = false) {
|
||||||
date = Date(timeIntervalSince1970: confirmedTransaction.blockTimeInSeconds)
|
timestamp = confirmedTransaction.blockTimeInSeconds
|
||||||
id = confirmedTransaction.transactionEntity.transactionId.toHexStringTxId()
|
id = confirmedTransaction.transactionEntity.transactionId.toHexStringTxId()
|
||||||
shielded = true
|
shielded = true
|
||||||
status = sent ? .paid(success: confirmedTransaction.minedHeight > 0) : .received
|
status = sent ? .paid(success: confirmedTransaction.minedHeight > 0) : .received
|
||||||
|
@ -44,7 +47,7 @@ extension TransactionState {
|
||||||
}
|
}
|
||||||
|
|
||||||
init(pendingTransaction: PendingTransactionEntity, latestBlockHeight: BlockHeight? = nil) {
|
init(pendingTransaction: PendingTransactionEntity, latestBlockHeight: BlockHeight? = nil) {
|
||||||
date = Date(timeIntervalSince1970: pendingTransaction.createTime)
|
timestamp = pendingTransaction.createTime
|
||||||
id = pendingTransaction.rawTransactionId?.toHexStringTxId() ?? String(pendingTransaction.createTime)
|
id = pendingTransaction.rawTransactionId?.toHexStringTxId() ?? String(pendingTransaction.createTime)
|
||||||
shielded = true
|
shielded = true
|
||||||
status = .paid(success: pendingTransaction.isSubmitSuccess)
|
status = .paid(success: pendingTransaction.isSubmitSuccess)
|
||||||
|
@ -63,11 +66,11 @@ extension TransactionState {
|
||||||
|
|
||||||
extension TransactionState {
|
extension TransactionState {
|
||||||
static func placeholder(
|
static func placeholder(
|
||||||
date: Date,
|
|
||||||
amount: Zatoshi,
|
amount: Zatoshi,
|
||||||
shielded: Bool = true,
|
shielded: Bool = true,
|
||||||
status: Status = .received,
|
status: Status = .received,
|
||||||
subtitle: String = "",
|
subtitle: String = "",
|
||||||
|
timestamp: TimeInterval,
|
||||||
uuid: String = UUID().debugDescription
|
uuid: String = UUID().debugDescription
|
||||||
) -> TransactionState {
|
) -> TransactionState {
|
||||||
.init(
|
.init(
|
||||||
|
@ -76,10 +79,10 @@ extension TransactionState {
|
||||||
minedHeight: -1,
|
minedHeight: -1,
|
||||||
shielded: shielded,
|
shielded: shielded,
|
||||||
zAddress: nil,
|
zAddress: nil,
|
||||||
date: date,
|
|
||||||
id: uuid,
|
id: uuid,
|
||||||
status: status,
|
status: status,
|
||||||
subtitle: subtitle,
|
subtitle: subtitle,
|
||||||
|
timestamp: timestamp,
|
||||||
zecAmount: status == .received ? amount : Zatoshi(amount: -amount.amount)
|
zecAmount: status == .received ? amount : Zatoshi(amount: -amount.amount)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
//
|
||||||
|
// WalletEvent.swift
|
||||||
|
// secant-testnet
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 20.06.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ComposableArchitecture
|
||||||
|
import SwiftUI
|
||||||
|
import ZcashLightClientKit
|
||||||
|
|
||||||
|
// MARK: - Model
|
||||||
|
|
||||||
|
struct WalletEvent: Equatable, Identifiable {
|
||||||
|
enum WalletEventState: Equatable {
|
||||||
|
case send(TransactionState)
|
||||||
|
case pending(TransactionState)
|
||||||
|
case received(TransactionState)
|
||||||
|
case failed(TransactionState)
|
||||||
|
case shielded(Zatoshi)
|
||||||
|
case walletImport(BlockHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
let id: String
|
||||||
|
let state: WalletEventState
|
||||||
|
var timestamp: TimeInterval
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Rows
|
||||||
|
|
||||||
|
extension WalletEvent {
|
||||||
|
@ViewBuilder func rowView() -> some View {
|
||||||
|
switch state {
|
||||||
|
case .send(let transaction):
|
||||||
|
TransactionRowView(transaction: transaction)
|
||||||
|
case .pending:
|
||||||
|
Text("pending wallet event")
|
||||||
|
case .received:
|
||||||
|
Text("received wallet event")
|
||||||
|
case .failed:
|
||||||
|
Text("failed wallet event")
|
||||||
|
case .shielded(let zatoshi):
|
||||||
|
Text("shielded wallet event \(zatoshi.decimalString())")
|
||||||
|
case .walletImport:
|
||||||
|
Text("wallet import wallet event")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Details
|
||||||
|
|
||||||
|
extension WalletEvent {
|
||||||
|
@ViewBuilder func detailView() -> some View {
|
||||||
|
switch state {
|
||||||
|
case .send(let transaction):
|
||||||
|
TransactionDetailView(transaction: transaction)
|
||||||
|
case .pending:
|
||||||
|
Text("pending transaction detail")
|
||||||
|
case .received:
|
||||||
|
Text("received transaction detail")
|
||||||
|
case .failed:
|
||||||
|
Text("failed transaction detail")
|
||||||
|
case .shielded(let zatoshi):
|
||||||
|
Text("shielded \(zatoshi.decimalString()) detail")
|
||||||
|
case .walletImport:
|
||||||
|
Text("wallet import wallet event")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Placeholders
|
||||||
|
|
||||||
|
private extension WalletEvent {
|
||||||
|
static func randomWalletEventState() -> WalletEvent.WalletEventState {
|
||||||
|
switch Int.random(in: 0..<5) {
|
||||||
|
case 1: return .received(.placeholder)
|
||||||
|
case 2: return .failed(.placeholder)
|
||||||
|
case 3: return .shielded(Zatoshi(amount: 234_000_000))
|
||||||
|
case 4: return .walletImport(BlockHeight(1_629_724))
|
||||||
|
default: return .send(.placeholder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension IdentifiedArrayOf where Element == WalletEvent {
|
||||||
|
static var placeholder: IdentifiedArrayOf<WalletEvent> {
|
||||||
|
return .init(
|
||||||
|
uniqueElements: (0..<30).map {
|
||||||
|
WalletEvent(
|
||||||
|
id: String($0),
|
||||||
|
state: WalletEvent.randomWalletEventState(),
|
||||||
|
timestamp: 1234567
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,9 +48,9 @@ protocol WrappedSDKSynchronizer {
|
||||||
func status() -> String
|
func status() -> String
|
||||||
|
|
||||||
func getShieldedBalance() -> Effect<Balance, Never>
|
func getShieldedBalance() -> Effect<Balance, Never>
|
||||||
func getAllClearedTransactions() -> Effect<[TransactionState], Never>
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never>
|
||||||
func getAllPendingTransactions() -> Effect<[TransactionState], Never>
|
func getAllPendingTransactions() -> Effect<[WalletEvent], Never>
|
||||||
func getAllTransactions() -> Effect<[TransactionState], Never>
|
func getAllTransactions() -> Effect<[WalletEvent], Never>
|
||||||
|
|
||||||
func getTransparentAddress(account: Int) -> TransparentAddress?
|
func getTransparentAddress(account: Int) -> TransparentAddress?
|
||||||
func getShieldedAddress(account: Int) -> SaplingShieldedAddress?
|
func getShieldedAddress(account: Int) -> SaplingShieldedAddress?
|
||||||
|
@ -160,37 +160,40 @@ class LiveWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[TransactionState], Never> {
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
if let clearedTransactions = try? synchronizer?.allClearedTransactions() {
|
if let clearedTransactions = try? synchronizer?.allClearedTransactions() {
|
||||||
return Effect(value: clearedTransactions.map {
|
return Effect(value: clearedTransactions.map {
|
||||||
TransactionState.init(confirmedTransaction: $0, sent: ($0.toAddress != nil))
|
let transaction = TransactionState.init(confirmedTransaction: $0, sent: ($0.toAddress != nil))
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllPendingTransactions() -> Effect<[TransactionState], Never> {
|
func getAllPendingTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
if let pendingTransactions = try? synchronizer?.allPendingTransactions(),
|
if let pendingTransactions = try? synchronizer?.allPendingTransactions(),
|
||||||
let syncedBlockHeight = synchronizer?.latestScannedHeight {
|
let syncedBlockHeight = synchronizer?.latestScannedHeight {
|
||||||
return Effect(value: pendingTransactions.map {
|
return Effect(value: pendingTransactions.map {
|
||||||
// TODO: - can we initialize it with latestBlockHeight: = nil?
|
let transaction = TransactionState.init(pendingTransaction: $0, latestBlockHeight: syncedBlockHeight)
|
||||||
TransactionState.init(pendingTransaction: $0, latestBlockHeight: syncedBlockHeight)
|
return WalletEvent(id: transaction.id, state: .pending(transaction), timestamp: transaction.timestamp)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllTransactions() -> Effect<[TransactionState], Never> {
|
func getAllTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
if let pendingTransactions = try? synchronizer?.allPendingTransactions(),
|
if let pendingTransactions = try? synchronizer?.allPendingTransactions(),
|
||||||
let clearedTransactions = try? synchronizer?.allClearedTransactions(),
|
let clearedTransactions = try? synchronizer?.allClearedTransactions(),
|
||||||
let syncedBlockHeight = synchronizer?.latestScannedHeight {
|
let syncedBlockHeight = synchronizer?.latestScannedHeight {
|
||||||
let clearedTxs = clearedTransactions.map {
|
let clearedTxs: [WalletEvent] = clearedTransactions.map {
|
||||||
TransactionState.init(confirmedTransaction: $0, sent: ($0.toAddress != nil))
|
let transaction = TransactionState.init(confirmedTransaction: $0, sent: ($0.toAddress != nil))
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
let pendingTxs = pendingTransactions.map {
|
let pendingTxs: [WalletEvent] = pendingTransactions.map {
|
||||||
TransactionState.init(pendingTransaction: $0, latestBlockHeight: syncedBlockHeight)
|
let transaction = TransactionState.init(pendingTransaction: $0, latestBlockHeight: syncedBlockHeight)
|
||||||
|
return WalletEvent(id: transaction.id, state: .pending(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
let txs = clearedTxs.filter { cleared in
|
let txs = clearedTxs.filter { cleared in
|
||||||
|
@ -290,7 +293,7 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
return Effect(value: Balance(verified: 12345000, total: 12345000))
|
return Effect(value: Balance(verified: 12345000, total: 12345000))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[TransactionState], Never> {
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
let mocked: [TransactionStateMockHelper] = [
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(amount: 1), status: .paid(success: false), uuid: "1"),
|
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(amount: 1), status: .paid(success: false), uuid: "1"),
|
||||||
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(amount: 2), uuid: "2"),
|
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(amount: 2), uuid: "2"),
|
||||||
|
@ -302,19 +305,20 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
return Effect(
|
return Effect(
|
||||||
value:
|
value:
|
||||||
mocked.map {
|
mocked.map {
|
||||||
TransactionState.placeholder(
|
let transaction = TransactionState.placeholder(
|
||||||
date: Date.init(timeIntervalSince1970: $0.date),
|
|
||||||
amount: $0.amount,
|
amount: $0.amount,
|
||||||
shielded: $0.shielded,
|
shielded: $0.shielded,
|
||||||
status: $0.status,
|
status: $0.status,
|
||||||
subtitle: $0.subtitle,
|
subtitle: $0.subtitle,
|
||||||
|
timestamp: $0.date,
|
||||||
uuid: $0.uuid
|
uuid: $0.uuid
|
||||||
)
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllPendingTransactions() -> Effect<[TransactionState], Never> {
|
func getAllPendingTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
let mocked: [TransactionStateMockHelper] = [
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
TransactionStateMockHelper(date: 1651039606, amount: Zatoshi(amount: 6), status: .paid(success: false), subtitle: "pending"),
|
TransactionStateMockHelper(date: 1651039606, amount: Zatoshi(amount: 6), status: .paid(success: false), subtitle: "pending"),
|
||||||
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(amount: 7), subtitle: "pending"),
|
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(amount: 7), subtitle: "pending"),
|
||||||
|
@ -325,18 +329,19 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
return Effect(
|
return Effect(
|
||||||
value:
|
value:
|
||||||
mocked.map {
|
mocked.map {
|
||||||
TransactionState.placeholder(
|
let transaction = TransactionState.placeholder(
|
||||||
date: Date.init(timeIntervalSince1970: $0.date),
|
|
||||||
amount: $0.amount,
|
amount: $0.amount,
|
||||||
shielded: $0.shielded,
|
shielded: $0.shielded,
|
||||||
status: $0.status,
|
status: $0.status,
|
||||||
subtitle: $0.subtitle
|
subtitle: $0.subtitle,
|
||||||
|
timestamp: $0.date
|
||||||
)
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .pending(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllTransactions() -> Effect<[TransactionState], Never> {
|
func getAllTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
return .merge(
|
return .merge(
|
||||||
getAllClearedTransactions(),
|
getAllClearedTransactions(),
|
||||||
getAllPendingTransactions()
|
getAllPendingTransactions()
|
||||||
|
@ -363,10 +368,10 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
minedHeight: 50,
|
minedHeight: 50,
|
||||||
shielded: true,
|
shielded: true,
|
||||||
zAddress: "tteafadlamnelkqe",
|
zAddress: "tteafadlamnelkqe",
|
||||||
date: Date.init(timeIntervalSince1970: 1234567),
|
|
||||||
id: "id",
|
id: "id",
|
||||||
status: .paid(success: true),
|
status: .paid(success: true),
|
||||||
subtitle: "sub",
|
subtitle: "sub",
|
||||||
|
timestamp: 1234567,
|
||||||
zecAmount: Zatoshi(amount: 10)
|
zecAmount: Zatoshi(amount: 10)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -398,7 +403,7 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[TransactionState], Never> {
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
let mocked: [TransactionStateMockHelper] = [
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(amount: 1), status: .paid(success: false), uuid: "aa11"),
|
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(amount: 1), status: .paid(success: false), uuid: "aa11"),
|
||||||
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(amount: 2), uuid: "bb22"),
|
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(amount: 2), uuid: "bb22"),
|
||||||
|
@ -410,19 +415,20 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
return Effect(
|
return Effect(
|
||||||
value:
|
value:
|
||||||
mocked.map {
|
mocked.map {
|
||||||
TransactionState.placeholder(
|
let transaction = TransactionState.placeholder(
|
||||||
date: Date.init(timeIntervalSince1970: $0.date),
|
|
||||||
amount: $0.amount,
|
amount: $0.amount,
|
||||||
shielded: $0.shielded,
|
shielded: $0.shielded,
|
||||||
status: $0.status,
|
status: $0.status,
|
||||||
subtitle: $0.subtitle,
|
subtitle: $0.subtitle,
|
||||||
|
timestamp: $0.date,
|
||||||
uuid: $0.uuid
|
uuid: $0.uuid
|
||||||
)
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllPendingTransactions() -> Effect<[TransactionState], Never> {
|
func getAllPendingTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
let mocked: [TransactionStateMockHelper] = [
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
TransactionStateMockHelper(
|
TransactionStateMockHelper(
|
||||||
date: 1651039606,
|
date: 1651039606,
|
||||||
|
@ -439,19 +445,20 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
||||||
return Effect(
|
return Effect(
|
||||||
value:
|
value:
|
||||||
mocked.map {
|
mocked.map {
|
||||||
TransactionState.placeholder(
|
let transaction = TransactionState.placeholder(
|
||||||
date: Date.init(timeIntervalSince1970: $0.date),
|
|
||||||
amount: $0.amount,
|
amount: $0.amount,
|
||||||
shielded: $0.shielded,
|
shielded: $0.shielded,
|
||||||
status: $0.status,
|
status: $0.status,
|
||||||
subtitle: $0.subtitle,
|
subtitle: $0.subtitle,
|
||||||
|
timestamp: $0.date,
|
||||||
uuid: $0.uuid
|
uuid: $0.uuid
|
||||||
)
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .pending(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllTransactions() -> Effect<[TransactionState], Never> {
|
func getAllTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
return .merge(
|
return .merge(
|
||||||
getAllClearedTransactions(),
|
getAllClearedTransactions(),
|
||||||
getAllPendingTransactions()
|
getAllPendingTransactions()
|
||||||
|
|
|
@ -74,18 +74,19 @@ class HomeTests: XCTestCase {
|
||||||
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(amount: 4), uuid: "4"),
|
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(amount: 4), uuid: "4"),
|
||||||
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(amount: 5), uuid: "5")
|
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(amount: 5), uuid: "5")
|
||||||
]
|
]
|
||||||
let transactions = transactionsHelper.map {
|
let walletEvents: [WalletEvent] = transactionsHelper.map {
|
||||||
TransactionState.placeholder(
|
let transaction = TransactionState.placeholder(
|
||||||
date: Date.init(timeIntervalSince1970: $0.date),
|
|
||||||
amount: $0.amount,
|
amount: $0.amount,
|
||||||
shielded: $0.shielded,
|
shielded: $0.shielded,
|
||||||
status: $0.status,
|
status: $0.status,
|
||||||
subtitle: $0.subtitle,
|
subtitle: $0.subtitle,
|
||||||
|
timestamp: $0.date,
|
||||||
uuid: $0.uuid
|
uuid: $0.uuid
|
||||||
)
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
store.receive(.updateTransactions(transactions))
|
store.receive(.updateWalletEvents(walletEvents))
|
||||||
|
|
||||||
// ad 3.
|
// ad 3.
|
||||||
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
||||||
|
@ -96,7 +97,7 @@ class HomeTests: XCTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testTransactionHistoryPartial_to_FullDrawer() throws {
|
func testWalletEventsPartial_to_FullDrawer() 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
|
||||||
|
|
||||||
|
@ -118,7 +119,7 @@ class HomeTests: XCTestCase {
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
synchronizerStatus: "",
|
synchronizerStatus: "",
|
||||||
totalBalance: Zatoshi.zero,
|
totalBalance: Zatoshi.zero,
|
||||||
transactionHistoryState: .emptyPlaceHolder,
|
walletEventsState: .emptyPlaceHolder,
|
||||||
verifiedBalance: Zatoshi.zero
|
verifiedBalance: Zatoshi.zero
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -128,17 +129,17 @@ class HomeTests: XCTestCase {
|
||||||
environment: testEnvironment
|
environment: testEnvironment
|
||||||
)
|
)
|
||||||
|
|
||||||
store.send(.transactionHistory(.updateRoute(.all))) { state in
|
store.send(.walletEvents(.updateRoute(.all))) { state in
|
||||||
state.transactionHistoryState.route = .all
|
state.walletEventsState.route = .all
|
||||||
}
|
}
|
||||||
|
|
||||||
store.receive(.updateDrawer(.full)) { state in
|
store.receive(.updateDrawer(.full)) { state in
|
||||||
state.drawerOverlay = .full
|
state.drawerOverlay = .full
|
||||||
state.transactionHistoryState.isScrollable = true
|
state.walletEventsState.isScrollable = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testTransactionHistoryFull_to_PartialDrawer() throws {
|
func testWalletEventsFull_to_PartialDrawer() 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
|
||||||
|
|
||||||
|
@ -160,7 +161,7 @@ class HomeTests: XCTestCase {
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
synchronizerStatus: "",
|
synchronizerStatus: "",
|
||||||
totalBalance: Zatoshi.zero,
|
totalBalance: Zatoshi.zero,
|
||||||
transactionHistoryState: .emptyPlaceHolder,
|
walletEventsState: .emptyPlaceHolder,
|
||||||
verifiedBalance: Zatoshi.zero
|
verifiedBalance: Zatoshi.zero
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -170,13 +171,13 @@ class HomeTests: XCTestCase {
|
||||||
environment: testEnvironment
|
environment: testEnvironment
|
||||||
)
|
)
|
||||||
|
|
||||||
store.send(.transactionHistory(.updateRoute(.latest))) { state in
|
store.send(.walletEvents(.updateRoute(.latest))) { state in
|
||||||
state.transactionHistoryState.route = .latest
|
state.walletEventsState.route = .latest
|
||||||
}
|
}
|
||||||
|
|
||||||
store.receive(.updateDrawer(.partial)) { state in
|
store.receive(.updateDrawer(.partial)) { state in
|
||||||
state.drawerOverlay = .partial
|
state.drawerOverlay = .partial
|
||||||
state.transactionHistoryState.isScrollable = false
|
state.walletEventsState.isScrollable = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,10 +64,10 @@ class SendTests: XCTestCase {
|
||||||
minedHeight: 50,
|
minedHeight: 50,
|
||||||
shielded: true,
|
shielded: true,
|
||||||
zAddress: "tteafadlamnelkqe",
|
zAddress: "tteafadlamnelkqe",
|
||||||
date: Date.init(timeIntervalSince1970: 1234567),
|
|
||||||
id: "id",
|
id: "id",
|
||||||
status: .paid(success: true),
|
status: .paid(success: true),
|
||||||
subtitle: "sub",
|
subtitle: "sub",
|
||||||
|
timestamp: 1234567,
|
||||||
zecAmount: Zatoshi(amount: 10)
|
zecAmount: Zatoshi(amount: 10)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -18,15 +18,16 @@ class HomeSnapshotTests: XCTestCase {
|
||||||
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(amount: 4), uuid: "4"),
|
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(amount: 4), uuid: "4"),
|
||||||
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(amount: 5), uuid: "5")
|
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(amount: 5), uuid: "5")
|
||||||
]
|
]
|
||||||
let transactions = transactionsHelper.map {
|
let transactions: [WalletEvent] = transactionsHelper.map {
|
||||||
TransactionState.placeholder(
|
let transaction = TransactionState.placeholder(
|
||||||
date: Date.init(timeIntervalSince1970: $0.date),
|
|
||||||
amount: $0.amount,
|
amount: $0.amount,
|
||||||
shielded: $0.shielded,
|
shielded: $0.shielded,
|
||||||
status: $0.status,
|
status: $0.status,
|
||||||
subtitle: $0.subtitle,
|
subtitle: $0.subtitle,
|
||||||
|
timestamp: $0.date,
|
||||||
uuid: $0.uuid
|
uuid: $0.uuid
|
||||||
)
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
||||||
|
@ -40,7 +41,7 @@ class HomeSnapshotTests: XCTestCase {
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
synchronizerStatus: "",
|
synchronizerStatus: "",
|
||||||
totalBalance: Zatoshi(amount: balance.total),
|
totalBalance: Zatoshi(amount: balance.total),
|
||||||
transactionHistoryState: .init(transactions: IdentifiedArrayOf(uniqueElements: transactions)),
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: transactions)),
|
||||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||||
),
|
),
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
|
@ -56,7 +57,7 @@ class HomeSnapshotTests: XCTestCase {
|
||||||
// all transactions
|
// all transactions
|
||||||
ViewStore(store).send(.updateDrawer(.full))
|
ViewStore(store).send(.updateDrawer(.full))
|
||||||
addAttachments(
|
addAttachments(
|
||||||
name: "\(#function)_fullTransactionHistory",
|
name: "\(#function)_fullWalletEvents",
|
||||||
HomeView(store: store)
|
HomeView(store: store)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// TransactionHistoryTests.swift
|
// WalletEventsTests.swift
|
||||||
// secantTests
|
// secantTests
|
||||||
//
|
//
|
||||||
// Created by Lukáš Korba on 27.04.2022.
|
// Created by Lukáš Korba on 27.04.2022.
|
||||||
|
@ -9,22 +9,22 @@ import XCTest
|
||||||
@testable import secant_testnet
|
@testable import secant_testnet
|
||||||
import ComposableArchitecture
|
import ComposableArchitecture
|
||||||
|
|
||||||
class TransactionHistoryTests: XCTestCase {
|
class WalletEventsTests: XCTestCase {
|
||||||
static let testScheduler = DispatchQueue.test
|
static let testScheduler = DispatchQueue.test
|
||||||
|
|
||||||
let testEnvironment = TransactionHistoryFlowEnvironment(
|
let testEnvironment = WalletEventsFlowEnvironment(
|
||||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||||
SDKSynchronizer: TestWrappedSDKSynchronizer()
|
SDKSynchronizer: TestWrappedSDKSynchronizer()
|
||||||
)
|
)
|
||||||
|
|
||||||
func testSynchronizerSubscription() throws {
|
func testSynchronizerSubscription() throws {
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionHistoryFlowState(
|
initialState: WalletEventsFlowState(
|
||||||
route: .latest,
|
route: .latest,
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
transactions: []
|
walletEvents: []
|
||||||
),
|
),
|
||||||
reducer: TransactionHistoryFlowReducer.default,
|
reducer: WalletEventsFlowReducer.default,
|
||||||
environment: testEnvironment
|
environment: testEnvironment
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,26 +55,31 @@ class TransactionHistoryTests: XCTestCase {
|
||||||
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(amount: 9), subtitle: "pending", uuid: "ii99")
|
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(amount: 9), subtitle: "pending", uuid: "ii99")
|
||||||
]
|
]
|
||||||
|
|
||||||
let transactions = mocked.map {
|
let walletEvents: [WalletEvent] = mocked.map {
|
||||||
TransactionState.placeholder(
|
let transaction = TransactionState.placeholder(
|
||||||
date: Date.init(timeIntervalSince1970: $0.date),
|
|
||||||
amount: $0.amount,
|
amount: $0.amount,
|
||||||
shielded: $0.shielded,
|
shielded: $0.shielded,
|
||||||
status: $0.status,
|
status: $0.status,
|
||||||
subtitle: $0.subtitle,
|
subtitle: $0.subtitle,
|
||||||
|
timestamp: $0.date,
|
||||||
uuid: $0.uuid
|
uuid: $0.uuid
|
||||||
)
|
)
|
||||||
|
return WalletEvent(
|
||||||
|
id: transaction.id,
|
||||||
|
state: transaction.subtitle == "pending" ? .pending(transaction) : .send(transaction),
|
||||||
|
timestamp: transaction.timestamp
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let identifiedTransactions = IdentifiedArrayOf(uniqueElements: transactions)
|
let identifiedTransactions = IdentifiedArrayOf(uniqueElements: walletEvents)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionHistoryFlowState(
|
initialState: WalletEventsFlowState(
|
||||||
route: .latest,
|
route: .latest,
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
transactions: identifiedTransactions
|
walletEvents: identifiedTransactions
|
||||||
),
|
),
|
||||||
reducer: TransactionHistoryFlowReducer.default,
|
reducer: WalletEventsFlowReducer.default,
|
||||||
environment: testEnvironment
|
environment: testEnvironment
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -82,16 +87,16 @@ class TransactionHistoryTests: XCTestCase {
|
||||||
|
|
||||||
Self.testScheduler.advance(by: 0.01)
|
Self.testScheduler.advance(by: 0.01)
|
||||||
|
|
||||||
store.receive(.updateTransactions(transactions)) { state in
|
store.receive(.updateWalletEvents(walletEvents)) { state in
|
||||||
let receivedTransactions = IdentifiedArrayOf(
|
let receivedTransactions = IdentifiedArrayOf(
|
||||||
uniqueElements:
|
uniqueElements:
|
||||||
transactions
|
walletEvents
|
||||||
.sorted(by: { lhs, rhs in
|
.sorted(by: { lhs, rhs in
|
||||||
lhs.date > rhs.date
|
lhs.timestamp > rhs.timestamp
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
state.transactions = receivedTransactions
|
state.walletEvents = receivedTransactions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue