diff --git a/secant.xcodeproj/project.pbxproj b/secant.xcodeproj/project.pbxproj index 693c9e2..d14e11a 100644 --- a/secant.xcodeproj/project.pbxproj +++ b/secant.xcodeproj/project.pbxproj @@ -112,7 +112,7 @@ 9E39115E284E3E350073DD9A /* secantUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4E7A2526B364180058B01E /* secantUITests.swift */; }; 9E4DC6E027C409A100E657F4 /* NeumorphicDesignModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E4DC6DF27C409A100E657F4 /* NeumorphicDesignModifier.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 */; }; 9E5BF644281FEC9900BA3F17 /* SendTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5BF643281FEC9900BA3F17 /* SendTests.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 */; }; 9EAB4671285A1C77002904A0 /* DeeplinkHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAB4670285A1C77002904A0 /* DeeplinkHandler.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 */; }; 9EAFEB84280597B700199FC9 /* WrappedSecItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB83280597B700199FC9 /* WrappedSecItem.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 */; }; F9322DC0273B555C00C105B5 /* NavigationLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9322DBF273B555C00C105B5 /* NavigationLinks.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 */; }; - 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 */; }; F9971A4D27680DC400A2DB75 /* AppStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A4A27680DC400A2DB75 /* AppStore.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 = ""; }; 9E4DC6E127C4C6B700E657F4 /* SecantButtonStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecantButtonStyles.swift; sourceTree = ""; }; 9E5BF63B2818305D00BA3F17 /* TransactionState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionState.swift; sourceTree = ""; }; - 9E5BF63E2819542C00BA3F17 /* TransactionHistoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionHistoryTests.swift; sourceTree = ""; }; + 9E5BF63E2819542C00BA3F17 /* WalletEventsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletEventsTests.swift; sourceTree = ""; }; 9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionFailedView.swift; sourceTree = ""; }; 9E5BF643281FEC9900BA3F17 /* SendTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTests.swift; sourceTree = ""; }; 9E5BF6452821028C00BA3F17 /* WrappedUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedUserDefaults.swift; sourceTree = ""; }; @@ -350,6 +352,8 @@ 9EAB46692859F42E002904A0 /* WrappedDeeplinkHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedDeeplinkHandler.swift; sourceTree = ""; }; 9EAB4670285A1C77002904A0 /* DeeplinkHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeeplinkHandler.swift; sourceTree = ""; }; 9EAB4675285B5C7C002904A0 /* DeeplinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeeplinkTests.swift; sourceTree = ""; }; + 9EAB46772860A1D2002904A0 /* WalletEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletEvent.swift; sourceTree = ""; }; + 9EAB46792861EA6A002904A0 /* TransactionRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionRowView.swift; sourceTree = ""; }; 9EAFEB812805793200199FC9 /* AppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTests.swift; sourceTree = ""; }; 9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItem.swift; sourceTree = ""; }; 9EAFEB852805A23100199FC9 /* WrappedSecItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItemTests.swift; sourceTree = ""; }; @@ -369,9 +373,9 @@ F93673D52742CB840099C6AF /* Previews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Previews.swift; sourceTree = ""; }; F93874ED273C4DE200F0E875 /* HomeStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeStore.swift; sourceTree = ""; }; F93874EF273C4DE200F0E875 /* HomeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; - F96B41E3273B501F0021B49A /* TransactionHistoryFlowStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionHistoryFlowStore.swift; sourceTree = ""; }; + F96B41E3273B501F0021B49A /* WalletEventsFlowStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletEventsFlowStore.swift; sourceTree = ""; }; F96B41E5273B501F0021B49A /* TransactionDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionDetailView.swift; sourceTree = ""; }; - F96B41E6273B501F0021B49A /* TransactionHistoryFlowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionHistoryFlowView.swift; sourceTree = ""; }; + F96B41E6273B501F0021B49A /* WalletEventsFlowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletEventsFlowView.swift; sourceTree = ""; }; F96B41EA273B50520021B49A /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = ""; }; F9971A4A27680DC400A2DB75 /* AppStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppStore.swift; sourceTree = ""; }; F9971A4C27680DC400A2DB75 /* AppView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppView.swift; sourceTree = ""; }; @@ -516,7 +520,7 @@ 9E391122283E4C970073DD9A /* ImportWalletTests */, 9E01F8262833CD84000EFC57 /* ScanTests */, 9E5BF642281FEC8700BA3F17 /* SendTests */, - 9E5BF63D281953F900BA3F17 /* TransactionHistoryTests */, + 9E5BF63D281953F900BA3F17 /* WalletEventsTests */, 9EAFEB802805791400199FC9 /* AppTests */, 9EF8135927ECC25E0075AF48 /* UtilTests */, 0DFE93E4272CB6D0000FCCA5 /* RecoveryPhraseValidationTests */, @@ -577,6 +581,7 @@ 9E7FE0D6282D286500C374E8 /* RecoveryPhrase.swift */, 9E7FE0DC282D298900C374E8 /* ValidationWord.swift */, 9E7FE0E5282E7B1100C374E8 /* StoredWallet.swift */, + 9EAB46772860A1D2002904A0 /* WalletEvent.swift */, ); path = Models; sourceTree = ""; @@ -673,7 +678,7 @@ F9971A5B27680DF600A2DB75 /* Scan */, F9C165B62740403600592F76 /* SendFlow */, F9971A6127680DFE00A2DB75 /* Settings */, - F96B41E2273B501F0021B49A /* TransactionHistoryFlow */, + F96B41E2273B501F0021B49A /* WalletEventsFlow */, 9E7FE0E4282E753700C374E8 /* RecoveryPhraseDisplay */, 9E7FE0E3282E751A00C374E8 /* RecoveryPhraseValidationFlow */, 6654C73C2715A3FA00901167 /* OnboardingFlow */, @@ -816,12 +821,12 @@ path = SnapshotTests; sourceTree = ""; }; - 9E5BF63D281953F900BA3F17 /* TransactionHistoryTests */ = { + 9E5BF63D281953F900BA3F17 /* WalletEventsTests */ = { isa = PBXGroup; children = ( - 9E5BF63E2819542C00BA3F17 /* TransactionHistoryTests.swift */, + 9E5BF63E2819542C00BA3F17 /* WalletEventsTests.swift */, ); - path = TransactionHistoryTests; + path = WalletEventsTests; sourceTree = ""; }; 9E5BF642281FEC8700BA3F17 /* SendTests */ = { @@ -1087,20 +1092,21 @@ path = Home; sourceTree = ""; }; - F96B41E2273B501F0021B49A /* TransactionHistoryFlow */ = { + F96B41E2273B501F0021B49A /* WalletEventsFlow */ = { isa = PBXGroup; children = ( - F96B41E3273B501F0021B49A /* TransactionHistoryFlowStore.swift */, - F96B41E6273B501F0021B49A /* TransactionHistoryFlowView.swift */, + F96B41E3273B501F0021B49A /* WalletEventsFlowStore.swift */, + F96B41E6273B501F0021B49A /* WalletEventsFlowView.swift */, F96B41E4273B501F0021B49A /* Views */, ); - path = TransactionHistoryFlow; + path = WalletEventsFlow; sourceTree = ""; }; F96B41E4273B501F0021B49A /* Views */ = { isa = PBXGroup; children = ( F96B41E5273B501F0021B49A /* TransactionDetailView.swift */, + 9EAB46792861EA6A002904A0 /* TransactionRowView.swift */, ); path = Views; sourceTree = ""; @@ -1396,7 +1402,7 @@ 0D35CC46277A36E00074316A /* ScrollableWhenScaled.swift in Sources */, 9E39114A2848EEB90073DD9A /* UserPreferencesStorage.swift in Sources */, 9EAB466A2859F42E002904A0 /* WrappedDeeplinkHandler.swift in Sources */, - F96B41E9273B501F0021B49A /* TransactionHistoryFlowView.swift in Sources */, + F96B41E9273B501F0021B49A /* WalletEventsFlowView.swift in Sources */, 9E01F8202833861A000EFC57 /* WrappedCaptureDevice.swift in Sources */, 2EDA07A027EDE18C00D6F09B /* TCATextField.swift in Sources */, 9E7FE0DB282D28F100C374E8 /* WrappedPasteboard.swift in Sources */, @@ -1414,6 +1420,7 @@ 9E7FE0CF282D257400C374E8 /* SDKSynchronizer+SyncStatus.swift in Sources */, 9E4DC6E027C409A100E657F4 /* NeumorphicDesignModifier.swift in Sources */, 0DACFA7F27208CE00039EEA5 /* Clamped.swift in Sources */, + 9EAB467A2861EA6A002904A0 /* TransactionRowView.swift in Sources */, 0DFE93E3272CA1AA000FCCA5 /* RecoveryPhraseValidationFlowStore.swift in Sources */, 9E2DF99E27CF704D00649636 /* ImportWalletView.swift in Sources */, 0D535FE2271F9476009A9E3E /* EnumeratedChip.swift in Sources */, @@ -1465,7 +1472,7 @@ 9E2AC10127D8EF0B0042AA47 /* WrappedMnemonic.swift in Sources */, 9E7FE0D7282D286500C374E8 /* RecoveryPhrase.swift in Sources */, 660558F7270C862F009D6954 /* Fonts+Generated.swift in Sources */, - F96B41E7273B501F0021B49A /* TransactionHistoryFlowStore.swift in Sources */, + F96B41E7273B501F0021B49A /* WalletEventsFlowStore.swift in Sources */, 9E7FE0E6282E7B1100C374E8 /* StoredWallet.swift in Sources */, 9EAFEB9128081E9400199FC9 /* HomeStore.swift in Sources */, F9971A5A27680DDE00A2DB75 /* RequestView.swift in Sources */, @@ -1505,6 +1512,7 @@ F9971A5427680DD000A2DB75 /* ProfileView.swift in Sources */, F9971A6027680DF600A2DB75 /* ScanStore.swift in Sources */, 9EF8139127F191BF0075AF48 /* WrappedWalletStorage.swift in Sources */, + 9EAB46782860A1D2002904A0 /* WalletEvent.swift in Sources */, 0DFE93E1272C9ECB000FCCA5 /* RecoveryPhraseBackupView.swift in Sources */, 9E69A24D27FB002800A55317 /* WelcomeStore.swift in Sources */, F9C165CB2741AB5D00592F76 /* SendFlowView.swift in Sources */, @@ -1542,7 +1550,7 @@ 9E391132284644580073DD9A /* AppInitializationTests.swift in Sources */, 9E9ECC9928589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift in Sources */, 9E391124283E4CAC0073DD9A /* ImportWalletTests.swift in Sources */, - 9E5BF63F2819542C00BA3F17 /* TransactionHistoryTests.swift in Sources */, + 9E5BF63F2819542C00BA3F17 /* WalletEventsTests.swift in Sources */, 0D4E7A1B26B364180058B01E /* secantTests.swift in Sources */, 0DFE93E6272CB6F7000FCCA5 /* RecoveryPhraseValidationTests.swift in Sources */, 9EAB4676285B5C7C002904A0 /* DeeplinkTests.swift in Sources */, diff --git a/secant/Features/Home/HomeStore.swift b/secant/Features/Home/HomeStore.swift index e10530d..e0f77f6 100644 --- a/secant/Features/Home/HomeStore.swift +++ b/secant/Features/Home/HomeStore.swift @@ -28,7 +28,7 @@ struct HomeState: Equatable { var scanState: ScanState var synchronizerStatus: String var totalBalance: Zatoshi - var transactionHistoryState: TransactionHistoryFlowState + var walletEventsState: WalletEventsFlowState var verifiedBalance: Zatoshi } @@ -43,12 +43,12 @@ enum HomeAction: Equatable { case send(SendFlowAction) case scan(ScanAction) case synchronizerStateChanged(WrappedSDKSynchronizerState) - case transactionHistory(TransactionHistoryFlowAction) + case walletEvents(WalletEventsFlowAction) case updateBalance(Balance) case updateDrawer(DrawerOverlay) case updateRoute(HomeState.Route?) case updateSynchronizerStatus - case updateTransactions([TransactionState]) + case updateWalletEvents([WalletEvent]) } // MARK: Environment @@ -106,7 +106,7 @@ extension HomeReducer { return .merge( environment.SDKSynchronizer.getAllClearedTransactions() .receive(on: environment.scheduler) - .map(HomeAction.updateTransactions) + .map(HomeAction.updateWalletEvents) .eraseToEffect(), environment.SDKSynchronizer.getShieldedBalance() @@ -128,10 +128,10 @@ extension HomeReducer { case .updateDrawer(let drawerOverlay): state.drawerOverlay = drawerOverlay - state.transactionHistoryState.isScrollable = drawerOverlay == .full ? true : false + state.walletEventsState.isScrollable = drawerOverlay == .full ? true : false return .none - case .updateTransactions(let transactions): + case .updateWalletEvents(let walletEvents): return .none case .updateSynchronizerStatus: @@ -148,13 +148,13 @@ extension HomeReducer { case .request(let action): return .none - case .transactionHistory(.updateRoute(.all)): + case .walletEvents(.updateRoute(.all)): 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 - case .transactionHistory(let historyAction): + case .walletEvents(let historyAction): return .none case .send(.updateRoute(.done)): @@ -175,11 +175,11 @@ extension HomeReducer { } } - private static let historyReducer: HomeReducer = TransactionHistoryFlowReducer.default.pullback( - state: \HomeState.transactionHistoryState, - action: /HomeAction.transactionHistory, + private static let historyReducer: HomeReducer = WalletEventsFlowReducer.default.pullback( + state: \HomeState.walletEventsState, + action: /HomeAction.walletEvents, environment: { environment in - TransactionHistoryFlowEnvironment( + WalletEventsFlowEnvironment( scheduler: environment.scheduler, SDKSynchronizer: environment.SDKSynchronizer ) @@ -228,10 +228,10 @@ extension HomeReducer { // MARK: - Store extension HomeStore { - func historyStore() -> TransactionHistoryFlowStore { + func historyStore() -> WalletEventsFlowStore { self.scope( - state: \.transactionHistoryState, - action: HomeAction.transactionHistory + state: \.walletEventsState, + action: HomeAction.walletEvents ) } @@ -296,7 +296,7 @@ extension HomeState { scanState: .placeholder, synchronizerStatus: "", totalBalance: Zatoshi.zero, - transactionHistoryState: .emptyPlaceHolder, + walletEventsState: .emptyPlaceHolder, verifiedBalance: Zatoshi.zero ) } diff --git a/secant/Features/Home/HomeView.swift b/secant/Features/Home/HomeView.swift index 4754722..a9ee855 100644 --- a/secant/Features/Home/HomeView.swift +++ b/secant/Features/Home/HomeView.swift @@ -30,7 +30,7 @@ struct HomeView: View { if proxy.size.height > 0 { Drawer(overlay: viewStore.bindingForDrawer(), maxHeight: proxy.size.height) { VStack { - TransactionHistoryFlowView(store: store.historyStore()) + WalletEventsFlowView(store: store.historyStore()) .padding(.top, 10) Spacer() diff --git a/secant/Features/Sandbox/SandboxStore.swift b/secant/Features/Sandbox/SandboxStore.swift index dd4bb30..3b752a8 100644 --- a/secant/Features/Sandbox/SandboxStore.swift +++ b/secant/Features/Sandbox/SandboxStore.swift @@ -16,7 +16,7 @@ struct SandboxState: Equatable { case scan case request } - var transactionHistoryState: TransactionHistoryFlowState + var walletEventsState: WalletEventsFlowState var profileState: ProfileState var route: Route? } @@ -25,7 +25,7 @@ struct SandboxState: Equatable { enum SandboxAction: Equatable { case updateRoute(SandboxState.Route?) - case transactionHistory(TransactionHistoryFlowAction) + case walletEvents(WalletEventsFlowAction) case profile(ProfileAction) case reset } @@ -42,18 +42,18 @@ extension SandboxReducer { case let .updateRoute(route): state.route = route return .none - case let .transactionHistory(transactionHistoryAction): - return TransactionHistoryFlowReducer + case let .walletEvents(walletEventsAction): + return WalletEventsFlowReducer .default .run( - &state.transactionHistoryState, - transactionHistoryAction, - TransactionHistoryFlowEnvironment( + &state.walletEventsState, + walletEventsAction, + WalletEventsFlowEnvironment( scheduler: DispatchQueue.main.eraseToAnyScheduler(), SDKSynchronizer: LiveWrappedSDKSynchronizer() ) ) - .map(SandboxAction.transactionHistory) + .map(SandboxAction.walletEvents) case let .profile(profileAction): return ProfileReducer .default @@ -72,10 +72,10 @@ extension SandboxReducer { // MARK: - Store extension SandboxStore { - func historyStore() -> TransactionHistoryFlowStore { + func historyStore() -> WalletEventsFlowStore { self.scope( - state: \.transactionHistoryState, - action: SandboxAction.transactionHistory + state: \.walletEventsState, + action: SandboxAction.walletEvents ) } @@ -92,15 +92,15 @@ extension SandboxStore { extension SandboxViewStore { func toggleSelectedTransaction() { let isAlreadySelected = (self.selectedTranactionID != nil) - let transcation = self.transactionHistoryState.transactions[5] - let newRoute = isAlreadySelected ? nil : TransactionHistoryFlowState.Route.showTransaction(transcation) - send(.transactionHistory(.updateRoute(newRoute))) + let walletEvent = self.walletEventsState.walletEvents[5] + let newRoute = isAlreadySelected ? nil : WalletEventsFlowState.Route.showWalletEvent(walletEvent) + send(.walletEvents(.updateRoute(newRoute))) } var selectedTranactionID: String? { - self.transactionHistoryState + self.walletEventsState .route - .flatMap(/TransactionHistoryFlowState.Route.showTransaction) + .flatMap(/WalletEventsFlowState.Route.showWalletEvent) .map(\.id) } @@ -119,7 +119,7 @@ extension SandboxViewStore { extension SandboxState { static var placeholder: Self { .init( - transactionHistoryState: .placeHolder, + walletEventsState: .placeHolder, profileState: .placeholder, route: nil ) @@ -130,7 +130,7 @@ extension SandboxStore { static var placeholder: SandboxStore { SandboxStore( initialState: SandboxState( - transactionHistoryState: .placeHolder, + walletEventsState: .placeHolder, profileState: .placeholder, route: nil ), diff --git a/secant/Features/Sandbox/SandboxView.swift b/secant/Features/Sandbox/SandboxView.swift index 4b2b954..12596b3 100644 --- a/secant/Features/Sandbox/SandboxView.swift +++ b/secant/Features/Sandbox/SandboxView.swift @@ -22,7 +22,7 @@ struct SandboxView: View { @ViewBuilder func view(for route: SandboxState.Route) -> some View { switch route { case .history: - TransactionHistoryFlowView(store: store.historyStore()) + WalletEventsFlowView(store: store.historyStore()) case .send: SendFlowView( store: .init( @@ -94,7 +94,7 @@ struct SandboxView: View { isPresented: viewStore.bindingForRoute(.history), content: { NavigationView { - TransactionHistoryFlowView(store: store.historyStore()) + WalletEventsFlowView(store: store.historyStore()) .toolbar { ToolbarItem { Button("Done") { viewStore.send(.updateRoute(nil)) } diff --git a/secant/Features/TransactionHistoryFlow/TransactionHistoryFlowStore.swift b/secant/Features/TransactionHistoryFlow/TransactionHistoryFlowStore.swift deleted file mode 100644 index f274fe3..0000000 --- a/secant/Features/TransactionHistoryFlow/TransactionHistoryFlowStore.swift +++ /dev/null @@ -1,161 +0,0 @@ -import ComposableArchitecture -import SwiftUI - -typealias TransactionHistoryFlowReducer = Reducer -typealias TransactionHistoryFlowStore = Store -typealias TransactionHistoryFlowViewStore = ViewStore - -// MARK: - State - -struct TransactionHistoryFlowState: Equatable { - enum Route: Equatable { - case latest - case all - case showTransaction(TransactionState) - } - - var route: Route? - - var isScrollable = false - var transactions: IdentifiedArrayOf -} - -// 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 - 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 { - 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 { - return Store( - initialState: .placeHolder, - reducer: .default, - environment: TransactionHistoryFlowEnvironment( - scheduler: DispatchQueue.main.eraseToAnyScheduler(), - SDKSynchronizer: LiveWrappedSDKSynchronizer() - ) - ) - } - - static var demoWithSelectedTransaction: Store { - let transactions = IdentifiedArrayOf.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 { - return .init( - uniqueElements: (0..<30).map { - TransactionState( - date: Date.init(timeIntervalSince1970: 1234567), - id: String($0), - status: .paid(success: true), - subtitle: "", - zecAmount: Zatoshi(amount: 25) - ) - } - ) - } -} diff --git a/secant/Features/TransactionHistoryFlow/Views/TransactionDetailView.swift b/secant/Features/WalletEventsFlow/Views/TransactionDetailView.swift similarity index 100% rename from secant/Features/TransactionHistoryFlow/Views/TransactionDetailView.swift rename to secant/Features/WalletEventsFlow/Views/TransactionDetailView.swift diff --git a/secant/Features/WalletEventsFlow/Views/TransactionRowView.swift b/secant/Features/WalletEventsFlow/Views/TransactionRowView.swift new file mode 100644 index 0000000..317ab5b --- /dev/null +++ b/secant/Features/WalletEventsFlow/Views/TransactionRowView.swift @@ -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)) + } +} diff --git a/secant/Features/WalletEventsFlow/WalletEventsFlowStore.swift b/secant/Features/WalletEventsFlow/WalletEventsFlowStore.swift new file mode 100644 index 0000000..5d38ce8 --- /dev/null +++ b/secant/Features/WalletEventsFlow/WalletEventsFlowStore.swift @@ -0,0 +1,146 @@ +import ComposableArchitecture +import SwiftUI + +typealias WalletEventsFlowReducer = Reducer +typealias WalletEventsFlowStore = Store +typealias WalletEventsFlowViewStore = ViewStore + +// MARK: - State + +struct WalletEventsFlowState: Equatable { + enum Route: Equatable { + case latest + case all + case showWalletEvent(WalletEvent) + } + + var route: Route? + + var isScrollable = false + var walletEvents = IdentifiedArrayOf.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 + 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 { + 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 { + return Store( + initialState: .placeHolder, + reducer: .default, + environment: WalletEventsFlowEnvironment( + scheduler: DispatchQueue.main.eraseToAnyScheduler(), + SDKSynchronizer: LiveWrappedSDKSynchronizer() + ) + ) + } +} + +extension IdentifiedArrayOf where Element == TransactionState { + static var placeholder: IdentifiedArrayOf { + return .init( + uniqueElements: (0..<30).map { + TransactionState( + id: String($0), + status: .paid(success: true), + subtitle: "", + timestamp: 1234567, + zecAmount: Zatoshi(amount: 25) + ) + } + ) + } +} diff --git a/secant/Features/TransactionHistoryFlow/TransactionHistoryFlowView.swift b/secant/Features/WalletEventsFlow/WalletEventsFlowView.swift similarity index 54% rename from secant/Features/TransactionHistoryFlow/TransactionHistoryFlowView.swift rename to secant/Features/WalletEventsFlow/WalletEventsFlowView.swift index 69edd1a..de4f444 100644 --- a/secant/Features/TransactionHistoryFlow/TransactionHistoryFlowView.swift +++ b/secant/Features/WalletEventsFlow/WalletEventsFlowView.swift @@ -1,8 +1,8 @@ import SwiftUI import ComposableArchitecture -struct TransactionHistoryFlowView: View { - let store: TransactionHistoryFlowStore +struct WalletEventsFlowView: View { + let store: WalletEventsFlowStore var body: some View { UITableView.appearance().backgroundColor = .clear @@ -14,11 +14,11 @@ struct TransactionHistoryFlowView: View { if viewStore.isScrollable { List { - transactionsList(with: viewStore) + walletEventsList(with: viewStore) } .listStyle(.sidebar) } else { - transactionsList(with: viewStore) + walletEventsList(with: viewStore) .padding(.horizontal, 32) } } @@ -28,36 +28,16 @@ struct TransactionHistoryFlowView: View { } } -extension TransactionHistoryFlowView { - func transactionsList(with viewStore: TransactionHistoryFlowViewStore) -> some View { - ForEach(viewStore.transactions) { transaction in - WithStateBinding(binding: viewStore.bindingForSelectingTransaction(transaction)) { active in +extension WalletEventsFlowView { + func walletEventsList(with viewStore: WalletEventsFlowViewStore) -> some View { + ForEach(viewStore.walletEvents) { walletEvent in + WithStateBinding(binding: viewStore.bindingForSelectingWalletEvent(walletEvent)) { active in VStack { - HStack { - 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") - } + walletEvent.rowView() } .navigationLink( isActive: active, - destination: { TransactionDetailView(transaction: transaction) } + destination: { walletEvent.detailView() } ) .foregroundColor(Asset.Colors.Text.body.color) .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) { VStack { Button("Latest") { @@ -95,7 +75,7 @@ extension TransactionHistoryFlowView { struct TransactionView_Previews: PreviewProvider { static var previews: some View { NavigationView { - TransactionHistoryFlowView(store: .placeholder) + WalletEventsFlowView(store: .placeholder) .preferredColorScheme(.dark) } } diff --git a/secant/Models/TransactionState.swift b/secant/Models/TransactionState.swift index 67a617b..f2cba7d 100644 --- a/secant/Models/TransactionState.swift +++ b/secant/Models/TransactionState.swift @@ -13,6 +13,7 @@ struct TransactionState: Equatable, Identifiable { enum Status: Equatable { case paid(success: Bool) case received + case failed } var expirationHeight = -1 @@ -21,16 +22,18 @@ struct TransactionState: Equatable, Identifiable { var shielded = true var zAddress: String? - var date: Date var id: String var status: Status var subtitle: String + var timestamp: TimeInterval var zecAmount: Zatoshi + + var address: String { zAddress ?? "" } } extension TransactionState { init(confirmedTransaction: ConfirmedTransactionEntity, sent: Bool = false) { - date = Date(timeIntervalSince1970: confirmedTransaction.blockTimeInSeconds) + timestamp = confirmedTransaction.blockTimeInSeconds id = confirmedTransaction.transactionEntity.transactionId.toHexStringTxId() shielded = true status = sent ? .paid(success: confirmedTransaction.minedHeight > 0) : .received @@ -44,7 +47,7 @@ extension TransactionState { } init(pendingTransaction: PendingTransactionEntity, latestBlockHeight: BlockHeight? = nil) { - date = Date(timeIntervalSince1970: pendingTransaction.createTime) + timestamp = pendingTransaction.createTime id = pendingTransaction.rawTransactionId?.toHexStringTxId() ?? String(pendingTransaction.createTime) shielded = true status = .paid(success: pendingTransaction.isSubmitSuccess) @@ -63,11 +66,11 @@ extension TransactionState { extension TransactionState { static func placeholder( - date: Date, amount: Zatoshi, shielded: Bool = true, status: Status = .received, subtitle: String = "", + timestamp: TimeInterval, uuid: String = UUID().debugDescription ) -> TransactionState { .init( @@ -76,10 +79,10 @@ extension TransactionState { minedHeight: -1, shielded: shielded, zAddress: nil, - date: date, id: uuid, status: status, subtitle: subtitle, + timestamp: timestamp, zecAmount: status == .received ? amount : Zatoshi(amount: -amount.amount) ) } diff --git a/secant/Models/WalletEvent.swift b/secant/Models/WalletEvent.swift new file mode 100644 index 0000000..5c201d5 --- /dev/null +++ b/secant/Models/WalletEvent.swift @@ -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 { + return .init( + uniqueElements: (0..<30).map { + WalletEvent( + id: String($0), + state: WalletEvent.randomWalletEventState(), + timestamp: 1234567 + ) + } + ) + } +} diff --git a/secant/Wrappers/WrappedSDKSynchronizer.swift b/secant/Wrappers/WrappedSDKSynchronizer.swift index b68248c..6193af0 100644 --- a/secant/Wrappers/WrappedSDKSynchronizer.swift +++ b/secant/Wrappers/WrappedSDKSynchronizer.swift @@ -48,9 +48,9 @@ protocol WrappedSDKSynchronizer { func status() -> String func getShieldedBalance() -> Effect - func getAllClearedTransactions() -> Effect<[TransactionState], Never> - func getAllPendingTransactions() -> Effect<[TransactionState], Never> - func getAllTransactions() -> Effect<[TransactionState], Never> + func getAllClearedTransactions() -> Effect<[WalletEvent], Never> + func getAllPendingTransactions() -> Effect<[WalletEvent], Never> + func getAllTransactions() -> Effect<[WalletEvent], Never> func getTransparentAddress(account: Int) -> TransparentAddress? func getShieldedAddress(account: Int) -> SaplingShieldedAddress? @@ -160,37 +160,40 @@ class LiveWrappedSDKSynchronizer: WrappedSDKSynchronizer { return .none } - func getAllClearedTransactions() -> Effect<[TransactionState], Never> { + func getAllClearedTransactions() -> Effect<[WalletEvent], Never> { if let clearedTransactions = try? synchronizer?.allClearedTransactions() { 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 } - func getAllPendingTransactions() -> Effect<[TransactionState], Never> { + func getAllPendingTransactions() -> Effect<[WalletEvent], Never> { if let pendingTransactions = try? synchronizer?.allPendingTransactions(), let syncedBlockHeight = synchronizer?.latestScannedHeight { return Effect(value: pendingTransactions.map { - // TODO: - can we initialize it with latestBlockHeight: = nil? - 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) }) } return .none } - func getAllTransactions() -> Effect<[TransactionState], Never> { + func getAllTransactions() -> Effect<[WalletEvent], Never> { if let pendingTransactions = try? synchronizer?.allPendingTransactions(), let clearedTransactions = try? synchronizer?.allClearedTransactions(), let syncedBlockHeight = synchronizer?.latestScannedHeight { - let clearedTxs = clearedTransactions.map { - TransactionState.init(confirmedTransaction: $0, sent: ($0.toAddress != nil)) + let clearedTxs: [WalletEvent] = clearedTransactions.map { + 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 { - TransactionState.init(pendingTransaction: $0, latestBlockHeight: syncedBlockHeight) + let pendingTxs: [WalletEvent] = pendingTransactions.map { + 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 @@ -290,7 +293,7 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer { return Effect(value: Balance(verified: 12345000, total: 12345000)) } - func getAllClearedTransactions() -> Effect<[TransactionState], Never> { + func getAllClearedTransactions() -> Effect<[WalletEvent], Never> { let mocked: [TransactionStateMockHelper] = [ TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(amount: 1), status: .paid(success: false), uuid: "1"), TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(amount: 2), uuid: "2"), @@ -302,19 +305,20 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer { return Effect( value: mocked.map { - TransactionState.placeholder( - date: Date.init(timeIntervalSince1970: $0.date), + let transaction = TransactionState.placeholder( amount: $0.amount, shielded: $0.shielded, status: $0.status, subtitle: $0.subtitle, + timestamp: $0.date, 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] = [ TransactionStateMockHelper(date: 1651039606, amount: Zatoshi(amount: 6), status: .paid(success: false), subtitle: "pending"), TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(amount: 7), subtitle: "pending"), @@ -325,18 +329,19 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer { return Effect( value: mocked.map { - TransactionState.placeholder( - date: Date.init(timeIntervalSince1970: $0.date), + let transaction = TransactionState.placeholder( amount: $0.amount, shielded: $0.shielded, 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( getAllClearedTransactions(), getAllPendingTransactions() @@ -363,10 +368,10 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer { minedHeight: 50, shielded: true, zAddress: "tteafadlamnelkqe", - date: Date.init(timeIntervalSince1970: 1234567), id: "id", status: .paid(success: true), subtitle: "sub", + timestamp: 1234567, zecAmount: Zatoshi(amount: 10) ) @@ -398,7 +403,7 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer { return .none } - func getAllClearedTransactions() -> Effect<[TransactionState], Never> { + func getAllClearedTransactions() -> Effect<[WalletEvent], Never> { let mocked: [TransactionStateMockHelper] = [ TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(amount: 1), status: .paid(success: false), uuid: "aa11"), TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(amount: 2), uuid: "bb22"), @@ -410,19 +415,20 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer { return Effect( value: mocked.map { - TransactionState.placeholder( - date: Date.init(timeIntervalSince1970: $0.date), + let transaction = TransactionState.placeholder( amount: $0.amount, shielded: $0.shielded, status: $0.status, subtitle: $0.subtitle, + timestamp: $0.date, 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] = [ TransactionStateMockHelper( date: 1651039606, @@ -439,19 +445,20 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer { return Effect( value: mocked.map { - TransactionState.placeholder( - date: Date.init(timeIntervalSince1970: $0.date), + let transaction = TransactionState.placeholder( amount: $0.amount, shielded: $0.shielded, status: $0.status, subtitle: $0.subtitle, + timestamp: $0.date, 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( getAllClearedTransactions(), getAllPendingTransactions() diff --git a/secantTests/HomeTests/HomeTests.swift b/secantTests/HomeTests/HomeTests.swift index 0701ce4..c91de99 100644 --- a/secantTests/HomeTests/HomeTests.swift +++ b/secantTests/HomeTests/HomeTests.swift @@ -74,18 +74,19 @@ class HomeTests: XCTestCase { TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(amount: 4), uuid: "4"), TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(amount: 5), uuid: "5") ] - let transactions = transactionsHelper.map { - TransactionState.placeholder( - date: Date.init(timeIntervalSince1970: $0.date), + let walletEvents: [WalletEvent] = transactionsHelper.map { + let transaction = TransactionState.placeholder( amount: $0.amount, shielded: $0.shielded, status: $0.status, subtitle: $0.subtitle, + timestamp: $0.date, uuid: $0.uuid ) + return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp) } - store.receive(.updateTransactions(transactions)) + store.receive(.updateWalletEvents(walletEvents)) // ad 3. 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 let testScheduler = DispatchQueue.test @@ -118,7 +119,7 @@ class HomeTests: XCTestCase { scanState: .placeholder, synchronizerStatus: "", totalBalance: Zatoshi.zero, - transactionHistoryState: .emptyPlaceHolder, + walletEventsState: .emptyPlaceHolder, verifiedBalance: Zatoshi.zero ) @@ -128,17 +129,17 @@ class HomeTests: XCTestCase { environment: testEnvironment ) - store.send(.transactionHistory(.updateRoute(.all))) { state in - state.transactionHistoryState.route = .all + store.send(.walletEvents(.updateRoute(.all))) { state in + state.walletEventsState.route = .all } store.receive(.updateDrawer(.full)) { state in 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 let testScheduler = DispatchQueue.test @@ -160,7 +161,7 @@ class HomeTests: XCTestCase { scanState: .placeholder, synchronizerStatus: "", totalBalance: Zatoshi.zero, - transactionHistoryState: .emptyPlaceHolder, + walletEventsState: .emptyPlaceHolder, verifiedBalance: Zatoshi.zero ) @@ -170,13 +171,13 @@ class HomeTests: XCTestCase { environment: testEnvironment ) - store.send(.transactionHistory(.updateRoute(.latest))) { state in - state.transactionHistoryState.route = .latest + store.send(.walletEvents(.updateRoute(.latest))) { state in + state.walletEventsState.route = .latest } store.receive(.updateDrawer(.partial)) { state in state.drawerOverlay = .partial - state.transactionHistoryState.isScrollable = false + state.walletEventsState.isScrollable = false } } diff --git a/secantTests/SendTests/SendTests.swift b/secantTests/SendTests/SendTests.swift index 259f0f0..e847cce 100644 --- a/secantTests/SendTests/SendTests.swift +++ b/secantTests/SendTests/SendTests.swift @@ -64,10 +64,10 @@ class SendTests: XCTestCase { minedHeight: 50, shielded: true, zAddress: "tteafadlamnelkqe", - date: Date.init(timeIntervalSince1970: 1234567), id: "id", status: .paid(success: true), subtitle: "sub", + timestamp: 1234567, zecAmount: Zatoshi(amount: 10) ) diff --git a/secantTests/SnapshotTests/HomeSnapshotTests/HomeSnapshotTests.swift b/secantTests/SnapshotTests/HomeSnapshotTests/HomeSnapshotTests.swift index 40b1558..fcb62df 100644 --- a/secantTests/SnapshotTests/HomeSnapshotTests/HomeSnapshotTests.swift +++ b/secantTests/SnapshotTests/HomeSnapshotTests/HomeSnapshotTests.swift @@ -18,15 +18,16 @@ class HomeSnapshotTests: XCTestCase { TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(amount: 4), uuid: "4"), TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(amount: 5), uuid: "5") ] - let transactions = transactionsHelper.map { - TransactionState.placeholder( - date: Date.init(timeIntervalSince1970: $0.date), + let transactions: [WalletEvent] = transactionsHelper.map { + let transaction = TransactionState.placeholder( amount: $0.amount, shielded: $0.shielded, status: $0.status, subtitle: $0.subtitle, + timestamp: $0.date, 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) @@ -40,7 +41,7 @@ class HomeSnapshotTests: XCTestCase { scanState: .placeholder, synchronizerStatus: "", totalBalance: Zatoshi(amount: balance.total), - transactionHistoryState: .init(transactions: IdentifiedArrayOf(uniqueElements: transactions)), + walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: transactions)), verifiedBalance: Zatoshi(amount: balance.verified) ), reducer: .default, @@ -56,7 +57,7 @@ class HomeSnapshotTests: XCTestCase { // all transactions ViewStore(store).send(.updateDrawer(.full)) addAttachments( - name: "\(#function)_fullTransactionHistory", + name: "\(#function)_fullWalletEvents", HomeView(store: store) ) } diff --git a/secantTests/TransactionHistoryTests/TransactionHistoryTests.swift b/secantTests/WalletEventsTests/WalletEventsTests.swift similarity index 73% rename from secantTests/TransactionHistoryTests/TransactionHistoryTests.swift rename to secantTests/WalletEventsTests/WalletEventsTests.swift index 39129b6..ea89ca5 100644 --- a/secantTests/TransactionHistoryTests/TransactionHistoryTests.swift +++ b/secantTests/WalletEventsTests/WalletEventsTests.swift @@ -1,5 +1,5 @@ // -// TransactionHistoryTests.swift +// WalletEventsTests.swift // secantTests // // Created by Lukáš Korba on 27.04.2022. @@ -9,22 +9,22 @@ import XCTest @testable import secant_testnet import ComposableArchitecture -class TransactionHistoryTests: XCTestCase { +class WalletEventsTests: XCTestCase { static let testScheduler = DispatchQueue.test - let testEnvironment = TransactionHistoryFlowEnvironment( + let testEnvironment = WalletEventsFlowEnvironment( scheduler: testScheduler.eraseToAnyScheduler(), SDKSynchronizer: TestWrappedSDKSynchronizer() ) func testSynchronizerSubscription() throws { let store = TestStore( - initialState: TransactionHistoryFlowState( + initialState: WalletEventsFlowState( route: .latest, isScrollable: true, - transactions: [] + walletEvents: [] ), - reducer: TransactionHistoryFlowReducer.default, + reducer: WalletEventsFlowReducer.default, environment: testEnvironment ) @@ -55,26 +55,31 @@ class TransactionHistoryTests: XCTestCase { TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(amount: 9), subtitle: "pending", uuid: "ii99") ] - let transactions = mocked.map { - TransactionState.placeholder( - date: Date.init(timeIntervalSince1970: $0.date), + let walletEvents: [WalletEvent] = mocked.map { + let transaction = TransactionState.placeholder( amount: $0.amount, shielded: $0.shielded, status: $0.status, subtitle: $0.subtitle, + timestamp: $0.date, 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( - initialState: TransactionHistoryFlowState( + initialState: WalletEventsFlowState( route: .latest, isScrollable: true, - transactions: identifiedTransactions + walletEvents: identifiedTransactions ), - reducer: TransactionHistoryFlowReducer.default, + reducer: WalletEventsFlowReducer.default, environment: testEnvironment ) @@ -82,16 +87,16 @@ class TransactionHistoryTests: XCTestCase { Self.testScheduler.advance(by: 0.01) - store.receive(.updateTransactions(transactions)) { state in + store.receive(.updateWalletEvents(walletEvents)) { state in let receivedTransactions = IdentifiedArrayOf( uniqueElements: - transactions + walletEvents .sorted(by: { lhs, rhs in - lhs.date > rhs.date + lhs.timestamp > rhs.timestamp }) ) - state.transactions = receivedTransactions + state.walletEvents = receivedTransactions } } }