From 1668a34380ed14b0d09c2d4278364ff6a3ac5e36 Mon Sep 17 00:00:00 2001
From: Bruno Muniz Azevedo Filho <bruno@elixxir.io>
Date: Sat, 5 Nov 2022 23:57:00 -0300
Subject: [PATCH] refactoring several features

---
 Package.swift                                 |  40 +-
 Sources/App/AppDelegate.swift                 |   6 +-
 Sources/App/DependencyRegistrator.swift       | 145 +++-
 .../Controllers/BackupConfigController.swift  |   3 +-
 .../Controllers/BackupController.swift        |   1 -
 .../BackupPassphraseController.swift          |   2 +-
 .../Controllers/BackupSFTPController.swift    |   4 +-
 .../Controllers/BackupSetupController.swift   |   3 +-
 .../BackupFeature/Service/BackupService.swift |   1 -
 .../ViewModels/BackupConfigViewModel.swift    |   1 -
 .../ViewModels/BackupSetupViewModel.swift     |   1 -
 .../Controllers/GroupChatController.swift     |   3 +-
 .../Controllers/MembersController.swift       |   3 +-
 .../Controllers/RetrySheetController.swift    |   2 +-
 .../Controllers/SheetController.swift         |   2 +-
 .../Controllers/SingleChatController.swift    |  13 +-
 .../Controllers/WebController.swift           | 109 ++-
 .../Coordinator/ChatCoordinator.swift         |   3 +-
 .../ViewModels/GroupChatViewModel.swift       |   1 -
 .../ViewModels/SingleChatViewModel.swift      | 168 +++--
 .../Controller/ChatListController.swift       |  11 +-
 .../ChatListSearchTableController.swift       |   1 -
 .../Controller/ChatListSheetController.swift  |   2 +-
 .../Controller/ChatListTableController.swift  |   1 -
 .../Coordinator/ChatListCoordinator.swift     |   1 -
 .../ViewModel/ChatListViewModel.swift         |   1 -
 .../Controllers/ContactController.swift       |   5 +-
 .../Controllers/NicknameController.swift      |   2 +-
 .../Coordinator/ContactCoordinator.swift      |   1 -
 .../ViewModels/ContactViewModel.swift         |   1 -
 .../Views/ContactInProgressView.swift         |  97 +--
 .../ContactFeature/Views/ContactView.swift    |   1 -
 .../Controllers/ContactListController.swift   |   4 +-
 .../ContactListTableController.swift          |   1 -
 .../Controllers/CreateDrawerController.swift  |   2 +-
 .../Controllers/CreateGroupController.swift   |   7 +-
 .../Coordinator/ContactListCoordinator.swift  |   1 -
 .../ViewModels/ContactListViewModel.swift     |   1 -
 .../ViewModels/CreateGroupViewModel.swift     |   1 -
 Sources/Countries/CountryListController.swift |   2 +-
 Sources/DrawerFeature/DrawerController.swift  |   2 +-
 Sources/LaunchFeature/LaunchController.swift  | 120 +--
 Sources/LaunchFeature/LaunchCoordinator.swift |  84 ---
 Sources/LaunchFeature/LaunchView.swift        |  41 +-
 .../LaunchViewModel+Banned.swift              |  61 ++
 .../LaunchViewModel+Database.swift            |  77 ++
 .../LaunchViewModel+Messenger.swift           | 396 ++++++++++
 .../LaunchViewModel+VersionCheck.swift        |  33 +
 Sources/LaunchFeature/LaunchViewModel.swift   | 698 ++----------------
 .../Controllers/MenuController.swift          |   2 +-
 Sources/Models/AttributeConfirmation.swift    |  15 -
 ...r.swift => OnboardingCodeController.swift} | 105 ++-
 .../OnboardingEmailController.swift           |  93 ++-
 ...nboardingPhoneConfirmationController.swift | 145 ----
 .../OnboardingPhoneController.swift           | 103 ++-
 .../OnboardingStartController.swift           |  89 +--
 .../OnboardingSuccessController.swift         |  67 --
 .../OnboardingUsernameController.swift        |  67 +-
 .../OnboardingWelcomeController.swift         |  21 +-
 .../Coordinator/OnboardingCoordinator.swift   | 153 ----
 .../ViewModels/OnboardingCodeViewModel.swift  |  96 +++
 ...OnboardingEmailConfirmationViewModel.swift |  92 ---
 .../ViewModels/OnboardingEmailViewModel.swift |  64 +-
 ...OnboardingPhoneConfirmationViewModel.swift |  92 ---
 .../ViewModels/OnboardingPhoneViewModel.swift |  69 +-
 .../OnboardingUsernameViewModel.swift         |  59 +-
 .../Views/OnboardingCodeView.swift            | 117 +++
 .../OnboardingEmailConfirmationView.swift     | 121 ---
 .../Views/OnboardingEmailView.swift           | 209 +++---
 .../OnboardingPhoneConfirmationView.swift     | 208 +++---
 .../Views/OnboardingPhoneView.swift           | 208 +++---
 .../Views/OnboardingStartView.swift           |  83 +--
 .../Views/OnboardingSuccessView.swift         |  75 --
 .../Views/OnboardingUsernameRestoreView.swift |  78 +-
 .../Views/OnboardingUsernameView.swift        | 199 +++--
 .../Views/OnboardingWelcomeView.swift         | 150 ++--
 .../RequestPermissionController.swift         |   2 +-
 Sources/Presentation/Presenting.swift         |   2 +-
 .../Controllers/ProfileCodeController.swift   | 209 +++---
 .../Controllers/ProfileController.swift       |   2 +-
 .../Controllers/ProfileEmailController.swift  |  68 +-
 .../Controllers/ProfilePhoneController.swift  |  28 +-
 .../Coordinator/ProfileCoordinator.swift      |  21 +-
 .../ViewModels/ProfileCodeViewModel.swift     |  96 ++-
 .../ViewModels/ProfileEmailViewModel.swift    |  46 +-
 .../ViewModels/ProfilePhoneViewModel.swift    |  52 +-
 .../ViewModels/ProfileViewModel.swift         |   1 -
 Sources/PushFeature/PushHandler.swift         |   1 -
 .../RequestsContainerController.swift         |   2 +-
 .../RequestsFailedController.swift            |   2 +-
 .../RequestsReceivedController.swift          |   3 +-
 .../Controllers/RequestsSentController.swift  |   2 +-
 .../Coordinator/RequestsCoordinator.swift     |   1 -
 Sources/RequestsFeature/Models/Request.swift  |   1 -
 .../ViewModels/RequestsFailedViewModel.swift  |   1 -
 .../RequestsReceivedViewModel.swift           |   1 -
 .../ViewModels/RequestsSentViewModel.swift    |   1 -
 .../Controllers/RestoreController.swift       |   2 +-
 .../Controllers/RestoreListController.swift   |   2 +-
 .../RestorePassphraseController.swift         |   2 +-
 .../Controllers/RestoreSFTPController.swift   |   4 +-
 .../RestoreSuccessController.swift            |   2 +-
 .../ViewModels/RestoreViewModel.swift         |   1 -
 .../Controllers/ScanContainerController.swift |   2 +-
 .../Controllers/ScanController.swift          |   2 +-
 .../Controllers/ScanDisplayController.swift   |   2 +-
 .../Coordinator/ScanCoordinator.swift         |   1 -
 .../ViewModels/ScanDisplayViewModel.swift     |   1 -
 .../ViewModels/ScanViewModel.swift            |   1 -
 .../SearchContainerController.swift           |   2 +-
 .../Controllers/SearchLeftController.swift    |   2 +-
 .../Controllers/SearchRightController.swift   |   2 +-
 .../Coordinator/SearchCoordinator.swift       |   1 -
 .../ViewModels/SearchLeftViewModel.swift      |   1 -
 .../ViewModels/SearchRightViewModel.swift     |   1 -
 .../Controllers/AccountDeleteController.swift |   4 +-
 .../SettingsAdvancedController.swift          |   2 +-
 .../Controllers/SettingsController.swift      |   4 +-
 .../ViewModels/AccountDeleteViewModel.swift   |   1 -
 .../Controllers/RootViewController.swift      |  20 +-
 Sources/{ => Shared}/Models/Payload.swift     |   0
 Sources/{ => Shared}/Models/Reply.swift       |   0
 .../{ => Shared}/Models/pbpayload.pb.swift    |   0
 .../TermsConditionsController.swift           |   2 +-
 Sources/TestHelpers/Dummies.swift             |  37 -
 Sources/TestHelpers/PresenterDouble.swift     |  17 -
 .../XXNavigation/Actions/PresentChat.swift    |  12 +
 .../Actions/PresentChatList.swift             |   9 +
 .../Actions/PresentCountryList.swift          |   9 +
 .../XXNavigation/Actions/PresentDrawer.swift  |   9 +
 .../Actions/PresentGroupChat.swift            |  12 +
 .../Actions/PresentOnboardingCode.swift       |  20 +
 .../Actions/PresentOnboardingEmail.swift      |   9 +
 .../Actions/PresentOnboardingPhone.swift      |   9 +
 .../Actions/PresentOnboardingStart.swift      |   9 +
 .../Actions/PresentOnboardingUsername.swift   |   9 +
 .../Actions/PresentOnboardingWelcome.swift    |   9 +
 .../Actions/PresentRequests.swift             |   9 +
 .../Actions/PresentRestoreList.swift          |   9 +
 .../XXNavigation/Actions/PresentSearch.swift  |  11 +
 .../Actions/PresentTermsAndConditions.swift   |  14 +
 .../Navigators/PresentChatListNavigator.swift |  22 +
 .../Navigators/PresentChatNavigator.swift     |  23 +
 .../PresentCountryListNavigator.swift         |  23 +
 .../Navigators/PresentDrawerNavigator.swift   |   1 +
 .../PresentGroupChatNavigator.swift           |  23 +
 .../PresentOnboardingCodeNavigator.swift      |  23 +
 .../PresentOnboardingEmailNavigator.swift     |  22 +
 .../PresentOnboardingPhoneNavigator.swift     |  22 +
 .../PresentOnboardingStartNavigator.swift     |  22 +
 .../PresentOnboardingUsernameNavigator.swift  |  22 +
 .../PresentOnboardingWelcomeNavigator.swift   |  22 +
 .../Navigators/PresentRequestsNavigator.swift |  22 +
 .../PresentRestoreListNavigator.swift         |  22 +
 .../Navigators/PresentSearchNavigator.swift   |  22 +
 .../PresentTermsAndConditionsNavigator.swift  |  27 +
 156 files changed, 2930 insertions(+), 3153 deletions(-)
 delete mode 100644 Sources/LaunchFeature/LaunchCoordinator.swift
 create mode 100644 Sources/LaunchFeature/LaunchViewModel+Banned.swift
 create mode 100644 Sources/LaunchFeature/LaunchViewModel+Database.swift
 create mode 100644 Sources/LaunchFeature/LaunchViewModel+Messenger.swift
 create mode 100644 Sources/LaunchFeature/LaunchViewModel+VersionCheck.swift
 delete mode 100644 Sources/Models/AttributeConfirmation.swift
 rename Sources/OnboardingFeature/Controllers/{OnboardingEmailConfirmationController.swift => OnboardingCodeController.swift} (58%)
 delete mode 100644 Sources/OnboardingFeature/Controllers/OnboardingPhoneConfirmationController.swift
 delete mode 100644 Sources/OnboardingFeature/Controllers/OnboardingSuccessController.swift
 delete mode 100644 Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift
 create mode 100644 Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift
 delete mode 100644 Sources/OnboardingFeature/ViewModels/OnboardingEmailConfirmationViewModel.swift
 delete mode 100644 Sources/OnboardingFeature/ViewModels/OnboardingPhoneConfirmationViewModel.swift
 create mode 100644 Sources/OnboardingFeature/Views/OnboardingCodeView.swift
 delete mode 100644 Sources/OnboardingFeature/Views/OnboardingEmailConfirmationView.swift
 delete mode 100644 Sources/OnboardingFeature/Views/OnboardingSuccessView.swift
 rename Sources/{ => Shared}/Models/Payload.swift (100%)
 rename Sources/{ => Shared}/Models/Reply.swift (100%)
 rename Sources/{ => Shared}/Models/pbpayload.pb.swift (100%)
 delete mode 100644 Sources/TestHelpers/Dummies.swift
 delete mode 100644 Sources/TestHelpers/PresenterDouble.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentChat.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentChatList.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentCountryList.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentDrawer.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentGroupChat.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentOnboardingCode.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentOnboardingEmail.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentOnboardingPhone.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentOnboardingStart.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentOnboardingUsername.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentOnboardingWelcome.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentRequests.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentRestoreList.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentSearch.swift
 create mode 100644 Sources/XXNavigation/Actions/PresentTermsAndConditions.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentChatListNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentChatNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentCountryListNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentDrawerNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentGroupChatNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentOnboardingCodeNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentOnboardingEmailNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentOnboardingPhoneNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentOnboardingStartNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentOnboardingUsernameNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentOnboardingWelcomeNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentRequestsNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentRestoreListNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentSearchNavigator.swift
 create mode 100644 Sources/XXNavigation/Navigators/PresentTermsAndConditionsNavigator.swift

diff --git a/Package.swift b/Package.swift
index 9f27f5c4..531a2a48 100644
--- a/Package.swift
+++ b/Package.swift
@@ -10,14 +10,12 @@ let package = Package(
   products: [
     .library(name: "App", targets: ["App"]),
     .library(name: "Shared", targets: ["Shared"]),
-    .library(name: "Models", targets: ["Models"]),
     .library(name: "XXLogger", targets: ["XXLogger"]),
     .library(name: "Defaults", targets: ["Defaults"]),
     .library(name: "Keychain", targets: ["Keychain"]),
     .library(name: "Voxophone", targets: ["Voxophone"]),
     .library(name: "Countries", targets: ["Countries"]),
     .library(name: "InputField", targets: ["InputField"]),
-    .library(name: "TestHelpers", targets: ["TestHelpers"]),
     .library(name: "ScanFeature", targets: ["ScanFeature"]),
     .library(name: "Permissions", targets: ["Permissions"]),
     .library(name: "MenuFeature", targets: ["MenuFeature"]),
@@ -25,6 +23,7 @@ let package = Package(
     .library(name: "PushFeature", targets: ["PushFeature"]),
     .library(name: "CrashService", targets: ["CrashService"]),
     .library(name: "TermsFeature", targets: ["TermsFeature"]),
+    .library(name: "XXNavigation", targets: ["XXNavigation"]),
     .library(name: "Presentation", targets: ["Presentation"]),
     .library(name: "BackupFeature", targets: ["BackupFeature"]),
     .library(name: "LaunchFeature", targets: ["LaunchFeature"]),
@@ -153,6 +152,7 @@ let package = Package(
         .target(name: "ReportingFeature"),
         .target(name: "OnboardingFeature"),
         .target(name: "ContactListFeature"),
+        .target(name: "XXNavigation"),
         .product(name: "Navigation", package: "Navigation"),
       ]
     ),
@@ -196,10 +196,17 @@ let package = Package(
         .target(name: "DependencyInjection"),
       ]
     ),
+    .target(
+      name: "XXNavigation",
+      dependencies: [
+        .target(name: "DependencyInjection"),
+        .product(name: "Navigation", package: "Navigation"),
+        .product(name: "XXModels", package: "client-ios-db"),
+      ]
+    ),
     .target(
       name: "PushFeature",
       dependencies: [
-        .target(name: "Models"),
         .target(name: "Defaults"),
         .target(name: "ReportingFeature"),
         .target(name: "DependencyInjection"),
@@ -208,13 +215,6 @@ let package = Package(
         .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
       ]
     ),
-    .target(
-      name: "TestHelpers",
-      dependencies: [
-        .target(name: "Models"),
-        .target(name: "Presentation"),
-      ]
-    ),
     .target(
       name: "Keychain",
       dependencies: [
@@ -227,13 +227,6 @@ let package = Package(
         .target(name: "Shared"),
       ]
     ),
-    .target(
-      name: "Models",
-      dependencies: [
-        .product(name: "DifferenceKit", package: "DifferenceKit"),
-        .product(name: "SwiftProtobuf", package: "swift-protobuf"),
-      ]
-    ),
     .target(
       name: "Defaults",
       dependencies: [
@@ -277,6 +270,7 @@ let package = Package(
         .product(name: "SnapKit", package: "SnapKit"),
         .product(name: "ChatLayout", package: "ChatLayout"),
         .product(name: "DifferenceKit", package: "DifferenceKit"),
+        .product(name: "SwiftProtobuf", package: "swift-protobuf"),
       ],
       exclude: [
         "swiftgen.yml",
@@ -335,7 +329,6 @@ let package = Package(
     .testTarget(
       name: "ContactFeatureTests",
       dependencies: [
-        .target(name: "TestHelpers"),
         .target(name: "ContactFeature"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
@@ -348,7 +341,6 @@ let package = Package(
         .target(name: "Defaults"),
         .target(name: "Keychain"),
         .target(name: "Voxophone"),
-        .target(name: "Models"),
         .target(name: "Permissions"),
         .target(name: "Presentation"),
         .target(name: "DrawerFeature"),
@@ -366,7 +358,6 @@ let package = Package(
       name: "ChatFeatureTests",
       dependencies: [
         .target(name: "ChatFeature"),
-        .target(name: "TestHelpers"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
       ]
@@ -388,7 +379,6 @@ let package = Package(
     .testTarget(
       name: "SearchFeatureTests",
       dependencies: [
-        .target(name: "TestHelpers"),
         .target(name: "SearchFeature"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
@@ -433,7 +423,6 @@ let package = Package(
     .testTarget(
       name: "RequestsFeatureTests",
       dependencies: [
-        .target(name: "TestHelpers"),
         .target(name: "RequestsFeature"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
@@ -462,7 +451,6 @@ let package = Package(
     .testTarget(
       name: "ProfileFeatureTests",
       dependencies: [
-        .target(name: "TestHelpers"),
         .target(name: "ProfileFeature"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
@@ -485,7 +473,6 @@ let package = Package(
     .testTarget(
       name: "ChatListFeatureTests",
       dependencies: [
-        .target(name: "TestHelpers"),
         .target(name: "ChatListFeature"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
@@ -512,7 +499,6 @@ let package = Package(
     .testTarget(
       name: "OnboardingFeatureTests",
       dependencies: [
-        .target(name: "TestHelpers"),
         .target(name: "OnboardingFeature"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
@@ -534,7 +520,6 @@ let package = Package(
       name: "BackupFeature",
       dependencies: [
         .target(name: "Shared"),
-        .target(name: "Models"),
         .target(name: "InputField"),
         .target(name: "Presentation"),
         .target(name: "DrawerFeature"),
@@ -565,7 +550,6 @@ let package = Package(
       name: "ScanFeatureTests",
       dependencies: [
         .target(name: "ScanFeature"),
-        .target(name: "TestHelpers"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
       ]
@@ -583,7 +567,6 @@ let package = Package(
     .testTarget(
       name: "ContactListFeatureTests",
       dependencies: [
-        .target(name: "TestHelpers"),
         .target(name: "ContactListFeature"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
@@ -610,7 +593,6 @@ let package = Package(
     .testTarget(
       name: "SettingsFeatureTests",
       dependencies: [
-        .target(name: "TestHelpers"),
         .target(name: "SettingsFeature"),
         .product(name: "Quick", package: "Quick"),
         .product(name: "Nimble", package: "Nimble"),
diff --git a/Sources/App/AppDelegate.swift b/Sources/App/AppDelegate.swift
index 6ff2efd3..a10b8e67 100644
--- a/Sources/App/AppDelegate.swift
+++ b/Sources/App/AppDelegate.swift
@@ -45,9 +45,13 @@ public class AppDelegate: UIResponder, UIApplicationDelegate {
     setupCrashReporting()
     setupLogging()
 
+    let navController = UINavigationController(rootViewController: LaunchController())
+    let rootViewController = RootViewController(navController)
     window = UIWindow(frame: UIScreen.main.bounds)
-    window?.rootViewController = RootViewController(UINavigationController(rootViewController: LaunchController()))
+    window?.rootViewController = rootViewController
     window?.makeKeyAndVisible()
+
+    DependencyRegistrator.registerNavigators(navController)
     return true
   }
 
diff --git a/Sources/App/DependencyRegistrator.swift b/Sources/App/DependencyRegistrator.swift
index 5f3d0418..211cc7c4 100644
--- a/Sources/App/DependencyRegistrator.swift
+++ b/Sources/App/DependencyRegistrator.swift
@@ -40,10 +40,12 @@ import RequestsFeature
 import OnboardingFeature
 import ContactListFeature
 
+import Shared
 import XXClient
 import Navigation
+import XXNavigation
 import KeychainAccess
-import Shared
+import XXMessengerClient
 
 struct DependencyRegistrator {
   static private let container = DependencyInjection.Container.shared
@@ -99,7 +101,83 @@ struct DependencyRegistrator {
 
   // MARK: COMMON
 
+  static public func registerNavigators(_ navController: UINavigationController) {
+    container.register(CombinedNavigator(
+      PresentModalNavigator(),
+      DismissModalNavigator(),
+      PushNavigator(),
+      PopToRootNavigator(),
+      PopToNavigator(),
+      SetStackNavigator(),
+
+      PresentOnboardingStartNavigator(
+        screen: OnboardingStartController.init,
+        navigationController: { navController }
+      ),
+      PresentChatListNavigator(
+        screen: ChatListController.init,
+        navigationController: { navController }
+      ),
+      PresentTermsAndConditionsNavigator(
+        screen: TermsConditionsController.init,
+        navigationController: { navController }
+      ),
+      PresentSearchNavigator(
+        screen: SearchContainerController.init(_:),
+        navigationController: { navController }
+      ),
+      PresentRequestsNavigator(
+        screen: RequestsContainerController.init,
+        navigationController: { navController }
+      ),
+      PresentChatNavigator(
+        screen: SingleChatController.init(_:),
+        navigationController: { navController }
+      ),
+      PresentGroupChatNavigator(
+        screen: GroupChatController.init(_:),
+        navigationController: { navController }
+      ),
+      PresentOnboardingWelcomeNavigator(
+        screen: OnboardingWelcomeController.init,
+        navigationController: { navController }
+      ),
+      PresentOnboardingUsernameNavigator(
+        screen: OnboardingUsernameController.init,
+        navigationController: { navController }
+      ),
+      PresentRestoreListNavigator(
+        screen: RestoreListController.init,
+        navigationController: { navController }
+      ),
+      PresentOnboardingEmailNavigator(
+        screen: OnboardingEmailController.init,
+        navigationController: { navController }
+      ),
+      PresentOnboardingPhoneNavigator(
+        screen: OnboardingPhoneController.init,
+        navigationController: { navController }
+      ),
+      PresentOnboardingCodeNavigator(
+        screen: OnboardingCodeController.init(_:_:_:),
+        navigationController: { navController }
+      )
+      //        searchFactory: SearchContainerController.init,
+      //        restoreListFactory: RestoreListController.init,
+      //        countriesFactory: CountryListController.init(_:),
+    ) as Navigator)
+  }
+
   static private func registerCommonDependencies() {
+    var environment: MessengerEnvironment = .live()
+    environment.ndfEnvironment = .mainnet
+    environment.udEnvironment = .init(
+      address: AlternativeUDConstants.address,
+      cert: AlternativeUDConstants.cert.data(using: .utf8)!,
+      contact: AlternativeUDConstants.contact.data(using: .utf8)!
+    )
+    container.register(Messenger.live(environment))
+
     container.register(Voxophone())
     container.register(BackupService())
     container.register(MakeAppScreenshot.live)
@@ -113,8 +191,6 @@ struct DependencyRegistrator {
     container.register(ToastController())
     container.register(StatusBarStylist())
 
-    // MARK: Coordinators
-
     container.register(
       TermsCoordinator.live(
         usernameFactory: OnboardingUsernameController.init,
@@ -122,17 +198,6 @@ struct DependencyRegistrator {
       )
     )
 
-    container.register(
-      LaunchCoordinator(
-        termsFactory: TermsConditionsController.init,
-        searchFactory: SearchContainerController.init,
-        requestsFactory: RequestsContainerController.init,
-        chatListFactory: ChatListController.init,
-        onboardingFactory: OnboardingStartController.init,
-        singleChatFactory: SingleChatController.init(_:),
-        groupChatFactory: GroupChatController.init(_:)
-      ) as LaunchCoordinating)
-
     container.register(
       BackupCoordinator(
         sftpFactory: BackupSFTPController.init(_:),
@@ -164,8 +229,8 @@ struct DependencyRegistrator {
         imagePickerFactory: UIImagePickerController.init,
         permissionFactory: RequestPermissionController.init,
         sideMenuFactory: MenuController.init(_:_:),
-        countriesFactory: CountryListController.init(_:),
-        codeFactory: ProfileCodeController.init(_:_:)
+        countriesFactory: CountryListController.init(_:)
+        //codeFactory: ProfileCodeController.init(_:_:)
       ) as ProfileCoordinating)
 
     container.register(
@@ -188,7 +253,7 @@ struct DependencyRegistrator {
     container.register(
       ChatCoordinator(
         retryFactory: RetrySheetController.init,
-        webFactory: WebScreen.init(url:),
+        webFactory: WebScreen.init(_:),
         previewFactory: QLPreviewController.init,
         contactFactory: ContactController.init(_:),
         imagePickerFactory: UIImagePickerController.init,
@@ -213,22 +278,6 @@ struct DependencyRegistrator {
         nicknameFactory: NicknameController.init(_:_:)
       ) as RequestsCoordinating)
 
-    container.register(
-      OnboardingCoordinator(
-        emailFactory: OnboardingEmailController.init,
-        phoneFactory: OnboardingPhoneController.init,
-        searchFactory: SearchContainerController.init,
-        welcomeFactory: OnboardingWelcomeController.init,
-        chatListFactory: ChatListController.init,
-        termsFactory: TermsConditionsController.init,
-        usernameFactory: OnboardingUsernameController.init,
-        restoreListFactory: RestoreListController.init,
-        successFactory: OnboardingSuccessController.init(_:),
-        countriesFactory: CountryListController.init(_:),
-        phoneConfirmationFactory: OnboardingPhoneConfirmationController.init(_:_:),
-        emailConfirmationFactory: OnboardingEmailConfirmationController.init(_:_:)
-      ) as OnboardingCoordinating)
-
     container.register(
       ContactListCoordinator(
         scanFactory: ScanContainerController.init,
@@ -279,3 +328,33 @@ extension PasswordStorage {
     )
   }()
 }
+
+private enum AlternativeUDConstants {
+  static let address = "46.101.98.49:18001"
+  static let cert = """
+            -----BEGIN CERTIFICATE-----
+            MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV
+            BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx
+            GzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJp
+            cDAeFw0xOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVT
+            MRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNV
+            BAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIw
+            DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDh
+            Dwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfs
+            WYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSE
+            tJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uA
+            m3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9
+            bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEA
+            AaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEA
+            neUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIf
+            U/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2
+            qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4
+            cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1R
+            tgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E5
+            6m52PyzMNV+2N21IPppKwA==
+            -----END CERTIFICATE-----
+"""
+  static let contact = """
+<xxc(2)7mbKFLE201WzH4SGxAOpHjjehwztIV+KGifi5L/PYPcDkAZiB9kZo+Dl3Vc7dD2SdZCFMOJVgwqGzfYRDkjc8RGEllBqNxq2sRRX09iQVef0kJQUgJCHNCOcvm6Ki0JJwvjLceyFh36iwK8oLbhLgqEZY86UScdACTyBCzBIab3ob5mBthYc3mheV88yq5PGF2DQ+dEvueUm+QhOSfwzppAJA/rpW9Wq9xzYcQzaqc3ztAGYfm2BBAHS7HVmkCbvZ/K07Xrl4EBPGHJYq12tWAN/C3mcbbBYUOQXyEzbSl/mO7sL3ORr0B4FMuqCi8EdlD6RO52pVhY+Cg6roRH1t5Ng1JxPt8Mv1yyjbifPhZ5fLKwxBz8UiFORfk0/jnhwgm25LRHqtNRRUlYXLvhv0HhqyYTUt17WNtCLATSVbqLrFGdy2EGadn8mP+kQNHp93f27d/uHgBNNe7LpuYCJMdWpoG6bOqmHEftxt0/MIQA8fTtTm3jJzv+7/QjZJDvQIv0SNdp8HFogpuwde+GuS4BcY7v5xz+ArGWcRR63ct2z83MqQEn9ODr1/gAAAgA7szRpDDQIdFUQo9mkWg8xBA==xxc>
+"""
+}
diff --git a/Sources/BackupFeature/Controllers/BackupConfigController.swift b/Sources/BackupFeature/Controllers/BackupConfigController.swift
index f17bdbc8..18848479 100644
--- a/Sources/BackupFeature/Controllers/BackupConfigController.swift
+++ b/Sources/BackupFeature/Controllers/BackupConfigController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import CloudFiles
@@ -9,7 +8,7 @@ import DependencyInjection
 final class BackupConfigController: UIViewController {
     @Dependency private var coordinator: BackupCoordinating
 
-    lazy private var screenView = BackupConfigView()
+    private lazy var screenView = BackupConfigView()
 
     private let viewModel: BackupConfigViewModel
     private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/BackupFeature/Controllers/BackupController.swift b/Sources/BackupFeature/Controllers/BackupController.swift
index 780efb8f..a996d324 100644
--- a/Sources/BackupFeature/Controllers/BackupController.swift
+++ b/Sources/BackupFeature/Controllers/BackupController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Combine
 import DependencyInjection
 
diff --git a/Sources/BackupFeature/Controllers/BackupPassphraseController.swift b/Sources/BackupFeature/Controllers/BackupPassphraseController.swift
index 5021b438..9ec594c8 100644
--- a/Sources/BackupFeature/Controllers/BackupPassphraseController.swift
+++ b/Sources/BackupFeature/Controllers/BackupPassphraseController.swift
@@ -4,7 +4,7 @@ import Combine
 import InputField
 
 public final class BackupPassphraseController: UIViewController {
-  lazy private var screenView = BackupPassphraseView()
+  private lazy var screenView = BackupPassphraseView()
 
   private var passphrase = "" {
     didSet {
diff --git a/Sources/BackupFeature/Controllers/BackupSFTPController.swift b/Sources/BackupFeature/Controllers/BackupSFTPController.swift
index 3fa7f9c3..7b6af4f5 100644
--- a/Sources/BackupFeature/Controllers/BackupSFTPController.swift
+++ b/Sources/BackupFeature/Controllers/BackupSFTPController.swift
@@ -3,8 +3,8 @@ import Combine
 import ScrollViewController
 
 public final class BackupSFTPController: UIViewController {
-  lazy private var screenView = BackupSFTPView()
-  lazy private var scrollViewController = ScrollViewController()
+  private lazy var screenView = BackupSFTPView()
+  private lazy var scrollViewController = ScrollViewController()
 
   private let completion: (String, String, String) -> Void
   private let viewModel = BackupSFTPViewModel()
diff --git a/Sources/BackupFeature/Controllers/BackupSetupController.swift b/Sources/BackupFeature/Controllers/BackupSetupController.swift
index e22de517..a9600531 100644
--- a/Sources/BackupFeature/Controllers/BackupSetupController.swift
+++ b/Sources/BackupFeature/Controllers/BackupSetupController.swift
@@ -1,10 +1,9 @@
 import UIKit
-import Models
 import Combine
 import DependencyInjection
 
 final class BackupSetupController: UIViewController {
-    lazy private var screenView = BackupSetupView()
+    private lazy var screenView = BackupSetupView()
 
     private let viewModel: BackupSetupViewModel
     private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/BackupFeature/Service/BackupService.swift b/Sources/BackupFeature/Service/BackupService.swift
index 8b1b10f7..4c888b88 100644
--- a/Sources/BackupFeature/Service/BackupService.swift
+++ b/Sources/BackupFeature/Service/BackupService.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Combine
 import XXClient
 import Defaults
diff --git a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
index 1057d966..38adaf92 100644
--- a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import XXClient
diff --git a/Sources/BackupFeature/ViewModels/BackupSetupViewModel.swift b/Sources/BackupFeature/ViewModels/BackupSetupViewModel.swift
index 1dc8e612..0d44658b 100644
--- a/Sources/BackupFeature/ViewModels/BackupSetupViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupSetupViewModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import CloudFiles
diff --git a/Sources/ChatFeature/Controllers/GroupChatController.swift b/Sources/ChatFeature/Controllers/GroupChatController.swift
index 9f8b464a..31a65eaf 100644
--- a/Sources/ChatFeature/Controllers/GroupChatController.swift
+++ b/Sources/ChatFeature/Controllers/GroupChatController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import XXModels
@@ -28,7 +27,7 @@ public final class GroupChatController: UIViewController {
 
   private let members: MembersController
   private var collectionView: UICollectionView!
-  lazy private var header = GroupHeaderView()
+  private lazy var header = GroupHeaderView()
   private let inputComponent: ChatInputView
 
   private var animator: ManualAnimator?
diff --git a/Sources/ChatFeature/Controllers/MembersController.swift b/Sources/ChatFeature/Controllers/MembersController.swift
index e7bf2c3e..435ec4df 100644
--- a/Sources/ChatFeature/Controllers/MembersController.swift
+++ b/Sources/ChatFeature/Controllers/MembersController.swift
@@ -1,10 +1,9 @@
 import UIKit
-import Models
 import Shared
 import XXModels
 
 final class MembersController: UIViewController {
-    lazy private var stackView = UIStackView()
+    private lazy var stackView = UIStackView()
 
     private let members: [Contact]
 
diff --git a/Sources/ChatFeature/Controllers/RetrySheetController.swift b/Sources/ChatFeature/Controllers/RetrySheetController.swift
index 48424f43..4605017e 100644
--- a/Sources/ChatFeature/Controllers/RetrySheetController.swift
+++ b/Sources/ChatFeature/Controllers/RetrySheetController.swift
@@ -10,7 +10,7 @@ public final class RetrySheetController: UIViewController {
 
     // MARK: UI
 
-    lazy private var screenView = RetrySheetView()
+    private lazy var screenView = RetrySheetView()
 
     // MARK: Properties
 
diff --git a/Sources/ChatFeature/Controllers/SheetController.swift b/Sources/ChatFeature/Controllers/SheetController.swift
index 974f086d..b0f9ed29 100644
--- a/Sources/ChatFeature/Controllers/SheetController.swift
+++ b/Sources/ChatFeature/Controllers/SheetController.swift
@@ -8,7 +8,7 @@ final class SheetController: UIViewController {
         case report
     }
 
-    lazy private var screenView = SheetView()
+    private lazy var screenView = SheetView()
 
     var actionPublisher: AnyPublisher<Action, Never> {
         actionRelay.eraseToAnyPublisher()
diff --git a/Sources/ChatFeature/Controllers/SingleChatController.swift b/Sources/ChatFeature/Controllers/SingleChatController.swift
index a356dfa2..708b9d50 100644
--- a/Sources/ChatFeature/Controllers/SingleChatController.swift
+++ b/Sources/ChatFeature/Controllers/SingleChatController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import XXLogger
@@ -31,13 +30,13 @@ public final class SingleChatController: UIViewController {
   @Dependency var makeReportDrawer: MakeReportDrawer
   @Dependency var makeAppScreenshot: MakeAppScreenshot
 
-  lazy private var infoView = UIControl()
-  lazy private var nameLabel = UILabel()
-  lazy private var avatarView = AvatarView()
+  private lazy var infoView = UIControl()
+  private lazy var nameLabel = UILabel()
+  private lazy var avatarView = AvatarView()
 
-  lazy private var moreButton = UIButton()
-  lazy private var screenView = ChatView()
-  lazy private var sheet = SheetController()
+  private lazy var moreButton = UIButton()
+  private lazy var screenView = ChatView()
+  private lazy var sheet = SheetController()
 
   private let inputComponent: ChatInputView
   private var collectionView: UICollectionView!
diff --git a/Sources/ChatFeature/Controllers/WebController.swift b/Sources/ChatFeature/Controllers/WebController.swift
index b093af5e..f3099b7a 100644
--- a/Sources/ChatFeature/Controllers/WebController.swift
+++ b/Sources/ChatFeature/Controllers/WebController.swift
@@ -2,68 +2,61 @@ import UIKit
 import WebKit
 
 public final class WebScreen: UIViewController {
-    lazy private(set) var webView = WebView()
-
-    private var url: String!
-
-    public init(url: String) {
-        self.url = url
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    public required init?(coder: NSCoder) { nil }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupScreen()
-    }
-
-    private func setupScreen() {
-        view.addSubview(webView)
-        webView.snp.makeConstraints { $0.edges.equalToSuperview() }
-
-        webView.webView.load(URLRequest(url: URL(string: url)!))
-        webView.closeButton = UIBarButtonItem(title: "Close", style: .done, target: self,
-                                              action: #selector(didTappedClose))
-    }
-
-    @objc private func didTappedClose() {
-        dismiss(animated: true)
-    }
+  private let url: URL
+  private lazy var screenView = WebView()
+
+  public init(_ urlString: String) {
+    self.url = .init(string: urlString)!
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    screenView.webView.load(URLRequest(url: url))
+    screenView.closeButton = UIBarButtonItem(
+      title: "Close",
+      style: .done,
+      target: self,
+      action: #selector(didTappedClose))
+  }
+
+  @objc private func didTappedClose() {
+    dismiss(animated: true)
+  }
 }
 
 final class WebView: UIView {
-
-    let webView = WKWebView()
-    let navBar = UINavigationBar()
-    var closeButton: UIBarButtonItem! {
-        didSet { navBar.topItem?.leftBarButtonItem = closeButton }
+  let webView = WKWebView()
+  let navBar = UINavigationBar()
+  var closeButton: UIBarButtonItem! {
+    didSet { navBar.topItem?.leftBarButtonItem = closeButton }
+  }
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = .white
+    navBar.items = [UINavigationItem(title: "")]
+    addSubview(webView)
+    addSubview(navBar)
+
+    navBar.snp.makeConstraints {
+      $0.top.equalTo(safeAreaLayoutGuide)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
     }
-
-    init() {
-        super.init(frame: .zero)
-        setupLayout()
+    webView.snp.makeConstraints {
+      $0.bottom.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.top.equalTo(navBar.snp.bottom)
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
-
-    private func setupLayout() {
-        backgroundColor = .white
-        navBar.items = [UINavigationItem(title: "")]
-        addSubview(webView)
-        addSubview(navBar)
-
-        navBar.snp.makeConstraints { make -> Void in
-            make.top.equalTo(safeAreaLayoutGuide)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-        }
-
-        webView.snp.makeConstraints { make -> Void in
-            make.bottom.equalToSuperview()
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.top.equalTo(navBar.snp.bottom)
-        }
-    }
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/ChatFeature/Coordinator/ChatCoordinator.swift b/Sources/ChatFeature/Coordinator/ChatCoordinator.swift
index 64a8e46d..5c9045dd 100644
--- a/Sources/ChatFeature/Coordinator/ChatCoordinator.swift
+++ b/Sources/ChatFeature/Coordinator/ChatCoordinator.swift
@@ -1,10 +1,9 @@
 import UIKit
-import Models
 import Shared
+import XXModels
 import QuickLook
 import Permissions
 import Presentation
-import XXModels
 
 public protocol ChatCoordinating {
     func toCamera(from: UIViewController)
diff --git a/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift b/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift
index 4a7c0e9e..324d01dc 100644
--- a/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift
+++ b/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import XXModels
diff --git a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
index cd1a6f4b..4b95f84b 100644
--- a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
+++ b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import XXLogger
@@ -12,7 +11,6 @@ import DifferenceKit
 import ReportingFeature
 import DependencyInjection
 import XXMessengerClient
-import XXClient
 
 import struct XXModels.Message
 import struct XXModels.FileTransfer
@@ -138,33 +136,33 @@ final class SingleChatViewModel: NSObject {
   }
   
   func didSendAudio(url: URL) {
-    do {
-      let _ = try transferManager.send(
-        params: .init(
-          payload: .init(
-            name: "",
-            type: "",
-            preview: Data(),
-            contents: Data()
-          ),
-          recipientId: contact.id,
-          retry: 1,
-          period: 1_000
-        ),
-        callback: .init(handle: {
-          switch $0 {
-          case .success(let progressCallback):
-            print(progressCallback.progress.total)
-          case .failure(let error):
-            print(error.localizedDescription)
-          }
-        })
-      )
-      
-      // transferId
-    } catch {
-      
-    }
+//    do {
+//      let _ = try transferManager.send(
+//        params: .init(
+//          payload: .init(
+//            name: "",
+//            type: "",
+//            preview: Data(),
+//            contents: Data()
+//          ),
+//          recipientId: contact.id,
+//          retry: 1,
+//          period: 1_000
+//        ),
+//        callback: .init(handle: {
+//          switch $0 {
+//          case .success(let progressCallback):
+//            print(progressCallback.progress.total)
+//          case .failure(let error):
+//            print(error.localizedDescription)
+//          }
+//        })
+//      )
+//
+//      // transferId
+//    } catch {
+//
+//    }
   }
   
   func didSend(image: UIImage) {
@@ -174,62 +172,62 @@ final class SingleChatViewModel: NSObject {
     let transferName = UUID().uuidString
     
     do {
-      let tid = try transferManager.send(
-        params: .init(
-          payload: .init(
-            name: transferName,
-            type: "jpeg",
-            preview: Data(),
-            contents: imageData
-          ),
-          recipientId: contact.id,
-          retry: 10,
-          period: 1_000
-        ),
-        callback: .init(handle: {
-          switch $0 {
-          case .success(let progressCallback):
-            
-            if progressCallback.progress.completed {
-              print(">>> Outgoing transfer finished successfully")
-            } else {
-              print(">>> Outgoing transfer. (\(progressCallback.progress.transmitted)/\(progressCallback.progress.total))")
-            }
-            
-            /// THIS IS TOO COMPLEX, NEEDS HELP FROM DARIUSZ
-            
-          case .failure(let error):
-            print(">>> Transfer.error: \(error.localizedDescription)")
-          }
-        })
-      )
-      
-      let transferModel = FileTransfer(
-        id: tid,
-        contactId: contact.id,
-        name: transferName,
-        type: "jpeg",
-        data: imageData,
-        progress: 0.0,
-        isIncoming: false,
-        createdAt: Date()
-      )
-      
-      let transferMessage = Message(
-        senderId: myId,
-        recipientId: contact.id,
-        groupId: nil,
-        date: Date(),
-        status: .sending,
-        isUnread: false,
-        text: "",
-        replyMessageId: nil,
-        roundURL: nil,
-        fileTransferId: tid
-      )
-      
-      try database.saveFileTransfer(transferModel)
-      try database.saveMessage(transferMessage)
+//      let tid = try transferManager.send(
+//        params: .init(
+//          payload: .init(
+//            name: transferName,
+//            type: "jpeg",
+//            preview: Data(),
+//            contents: imageData
+//          ),
+//          recipientId: contact.id,
+//          retry: 10,
+//          period: 1_000
+//        ),
+//        callback: .init(handle: {
+//          switch $0 {
+//          case .success(let progressCallback):
+//
+//            if progressCallback.progress.completed {
+//              print(">>> Outgoing transfer finished successfully")
+//            } else {
+//              print(">>> Outgoing transfer. (\(progressCallback.progress.transmitted)/\(progressCallback.progress.total))")
+//            }
+//
+//            /// THIS IS TOO COMPLEX, NEEDS HELP FROM DARIUSZ
+//
+//          case .failure(let error):
+//            print(">>> Transfer.error: \(error.localizedDescription)")
+//          }
+//        })
+////      )
+//      
+//      let transferModel = FileTransfer(
+//        id: tid,
+//        contactId: contact.id,
+//        name: transferName,
+//        type: "jpeg",
+//        data: imageData,
+//        progress: 0.0,
+//        isIncoming: false,
+//        createdAt: Date()
+//      )
+//      
+//      let transferMessage = Message(
+//        senderId: myId,
+//        recipientId: contact.id,
+//        groupId: nil,
+//        date: Date(),
+//        status: .sending,
+//        isUnread: false,
+//        text: "",
+//        replyMessageId: nil,
+//        roundURL: nil,
+//        fileTransferId: tid
+//      )
+//      
+//      try database.saveFileTransfer(transferModel)
+//      try database.saveMessage(transferMessage)
       
       hudController.dismiss()
     } catch {
diff --git a/Sources/ChatListFeature/Controller/ChatListController.swift b/Sources/ChatListFeature/Controller/ChatListController.swift
index be41db76..34c6fac7 100644
--- a/Sources/ChatListFeature/Controller/ChatListController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import XXModels
@@ -10,11 +9,11 @@ public final class ChatListController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: ChatListCoordinating
 
-  lazy private var screenView = ChatListView()
-  lazy private var topLeftView = ChatListTopLeftNavView()
-  lazy private var topRightView = ChatListTopRightNavView()
-  lazy private var tableController = ChatListTableController(viewModel)
-  lazy private var searchTableController = ChatSearchTableController(viewModel)
+  private lazy var screenView = ChatListView()
+  private lazy var topLeftView = ChatListTopLeftNavView()
+  private lazy var topRightView = ChatListTopRightNavView()
+  private lazy var tableController = ChatListTableController(viewModel)
+  private lazy var searchTableController = ChatSearchTableController(viewModel)
   private var collectionDataSource: UICollectionViewDiffableDataSource<SectionId, Contact>!
 
   private let viewModel = ChatListViewModel()
diff --git a/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift b/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
index 46e9c20b..c1651f26 100644
--- a/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Combine
 import DependencyInjection
 
diff --git a/Sources/ChatListFeature/Controller/ChatListSheetController.swift b/Sources/ChatListFeature/Controller/ChatListSheetController.swift
index cb52ce6a..79ad33eb 100644
--- a/Sources/ChatListFeature/Controller/ChatListSheetController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListSheetController.swift
@@ -7,7 +7,7 @@ public final class ChatListSheetController: UIViewController {
         case deleteAll
     }
 
-    lazy private var screenView = ChatListMenuView()
+    private lazy var screenView = ChatListMenuView()
 
     var didChooseAction: (Action) -> Void
     private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/ChatListFeature/Controller/ChatListTableController.swift b/Sources/ChatListFeature/Controller/ChatListTableController.swift
index 8527195e..b67c29da 100644
--- a/Sources/ChatListFeature/Controller/ChatListTableController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListTableController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Combine
 import XXModels
 import DifferenceKit
diff --git a/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift b/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift
index acd4fbca..57f94bb3 100644
--- a/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift
+++ b/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import XXModels
 import MenuFeature
 import ChatFeature
diff --git a/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift b/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift
index f61aef1e..3792e0c1 100644
--- a/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift
+++ b/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Combine
 import XXModels
 import Defaults
diff --git a/Sources/ContactFeature/Controllers/ContactController.swift b/Sources/ContactFeature/Controllers/ContactController.swift
index 1fa130ce..0fbb22e4 100644
--- a/Sources/ContactFeature/Controllers/ContactController.swift
+++ b/Sources/ContactFeature/Controllers/ContactController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Combine
 import XXModels
 import DrawerFeature
@@ -11,8 +10,8 @@ public final class ContactController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: ContactCoordinating
 
-  lazy private var screenView = ContactView()
-  lazy private var scrollViewController = ScrollViewController()
+  private lazy var screenView = ContactView()
+  private lazy var scrollViewController = ScrollViewController()
 
   private let viewModel: ContactViewModel
   private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/ContactFeature/Controllers/NicknameController.swift b/Sources/ContactFeature/Controllers/NicknameController.swift
index 709a6699..2492083e 100644
--- a/Sources/ContactFeature/Controllers/NicknameController.swift
+++ b/Sources/ContactFeature/Controllers/NicknameController.swift
@@ -5,7 +5,7 @@ import InputField
 import ScrollViewController
 
 public final class NicknameController: UIViewController {
-    lazy private var screenView = NicknameView()
+    private lazy var screenView = NicknameView()
 
     private let prefilled: String
     private let completion: StringClosure
diff --git a/Sources/ContactFeature/Coordinator/ContactCoordinator.swift b/Sources/ContactFeature/Coordinator/ContactCoordinator.swift
index eea7f1ca..2b366da6 100644
--- a/Sources/ContactFeature/Coordinator/ContactCoordinator.swift
+++ b/Sources/ContactFeature/Coordinator/ContactCoordinator.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import XXModels
 import ChatFeature
diff --git a/Sources/ContactFeature/ViewModels/ContactViewModel.swift b/Sources/ContactFeature/ViewModels/ContactViewModel.swift
index ee0e2676..3876c0b9 100644
--- a/Sources/ContactFeature/ViewModels/ContactViewModel.swift
+++ b/Sources/ContactFeature/ViewModels/ContactViewModel.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Combine
 import XXModels
 import Defaults
diff --git a/Sources/ContactFeature/Views/ContactInProgressView.swift b/Sources/ContactFeature/Views/ContactInProgressView.swift
index 165600f9..533b5fe8 100644
--- a/Sources/ContactFeature/Views/ContactInProgressView.swift
+++ b/Sources/ContactFeature/Views/ContactInProgressView.swift
@@ -1,70 +1,53 @@
 import UIKit
 import Shared
-import Models
 import XXModels
 
 final class ContactAlmostView: UIView {
-    // MARK: UI
+  let stack = UIStackView()
+  let feedback = BottomFeedbackComponent()
 
-    let stack = UIStackView()
-    let feedback = BottomFeedbackComponent()
+  init() {
+    super.init(frame: .zero)
+    stack.axis = .vertical
+    stack.spacing = 25
 
-    // MARK: Lifecycle
+    addSubview(stack)
+    addSubview(feedback)
 
-    init() {
-        super.init(frame: .zero)
-        setup()
+    stack.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(24)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    // MARK: Public
-
-    func set(status: Contact.AuthStatus) {
-        switch status {
-        case .requestFailed, .confirmationFailed:
-            feedback.set(
-                icon: Asset.contactRequestExclamation.image,
-                title: Localized.Contact.Inprogress.failed,
-                style: .danger,
-                actionTitle: Localized.Contact.Inprogress.resend
-            )
-
-        case .confirming, .requested, .requesting:
-            feedback.set(
-                icon: Asset.contactRequestExclamation.image,
-                title: Localized.Contact.Inprogress.pending,
-                style: .chill
-            )
-        default:
-            break
-        }
-    }
-
-    // MARK: Properties
-
-    private func setup() {
-        stack.axis = .vertical
-        stack.spacing = 25
-
-        addSubview(stack)
-        addSubview(feedback)
-
-        setupConstraints()
+    feedback.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(stack.snp.bottom).offset(24)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
     }
-
-    private func setupConstraints() {
-        stack.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(24)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-        }
-
-        feedback.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(stack.snp.bottom).offset(24)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func set(status: Contact.AuthStatus) {
+    switch status {
+    case .requestFailed, .confirmationFailed:
+      feedback.set(
+        icon: Asset.contactRequestExclamation.image,
+        title: Localized.Contact.Inprogress.failed,
+        style: .danger,
+        actionTitle: Localized.Contact.Inprogress.resend
+      )
+
+    case .confirming, .requested, .requesting:
+      feedback.set(
+        icon: Asset.contactRequestExclamation.image,
+        title: Localized.Contact.Inprogress.pending,
+        style: .chill
+      )
+    default:
+      break
     }
+  }
 }
diff --git a/Sources/ContactFeature/Views/ContactView.swift b/Sources/ContactFeature/Views/ContactView.swift
index e5fb0392..08b4a4c6 100644
--- a/Sources/ContactFeature/Views/ContactView.swift
+++ b/Sources/ContactFeature/Views/ContactView.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import XXModels
 
 final class ContactView: UIView {
diff --git a/Sources/ContactListFeature/Controllers/ContactListController.swift b/Sources/ContactListFeature/Controllers/ContactListController.swift
index d7f9094b..0b276e5f 100644
--- a/Sources/ContactListFeature/Controllers/ContactListController.swift
+++ b/Sources/ContactListFeature/Controllers/ContactListController.swift
@@ -7,8 +7,8 @@ public final class ContactListController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: ContactListCoordinating
 
-  lazy private var screenView = ContactListView()
-  lazy private var tableController = ContactListTableController(viewModel)
+  private lazy var screenView = ContactListView()
+  private lazy var tableController = ContactListTableController(viewModel)
 
   private let viewModel = ContactListViewModel()
   private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/ContactListFeature/Controllers/ContactListTableController.swift b/Sources/ContactListFeature/Controllers/ContactListTableController.swift
index ac7a0662..0e456781 100644
--- a/Sources/ContactListFeature/Controllers/ContactListTableController.swift
+++ b/Sources/ContactListFeature/Controllers/ContactListTableController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Combine
 import XXModels
 
diff --git a/Sources/ContactListFeature/Controllers/CreateDrawerController.swift b/Sources/ContactListFeature/Controllers/CreateDrawerController.swift
index 543a9722..4ba7213d 100644
--- a/Sources/ContactListFeature/Controllers/CreateDrawerController.swift
+++ b/Sources/ContactListFeature/Controllers/CreateDrawerController.swift
@@ -3,7 +3,7 @@ import Shared
 import Combine
 
 public final class CreateDrawerController: UIViewController {
-    lazy private var screenView = CreateDrawerView()
+    private lazy var screenView = CreateDrawerView()
 
     private let selectedCount: Int
     private let viewModel = CreateDrawerViewModel()
diff --git a/Sources/ContactListFeature/Controllers/CreateGroupController.swift b/Sources/ContactListFeature/Controllers/CreateGroupController.swift
index d6df303a..8f2b2c93 100644
--- a/Sources/ContactListFeature/Controllers/CreateGroupController.swift
+++ b/Sources/ContactListFeature/Controllers/CreateGroupController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import XXModels
@@ -8,9 +7,9 @@ import DependencyInjection
 public final class CreateGroupController: UIViewController {
     @Dependency private var coordinator: ContactListCoordinating
 
-    lazy private var titleLabel = UILabel()
-    lazy private var createButton = UIButton()
-    lazy private var screenView = CreateGroupView()
+    private lazy var titleLabel = UILabel()
+    private lazy var createButton = UIButton()
+    private lazy var screenView = CreateGroupView()
 
     private var selectedElements = [Contact]() {
         didSet { screenView.tableView.reloadData() }
diff --git a/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift b/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift
index eb967cf0..650f031d 100644
--- a/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift
+++ b/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import XXModels
 import MenuFeature
 import ChatFeature
diff --git a/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift b/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift
index 2f1364c5..93de50cd 100644
--- a/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift
+++ b/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift
@@ -1,4 +1,3 @@
-import Models
 import Combine
 import XXModels
 import Defaults
diff --git a/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift b/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift
index 2277d915..724aa19f 100644
--- a/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift
+++ b/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Combine
 import XXModels
 import Defaults
diff --git a/Sources/Countries/CountryListController.swift b/Sources/Countries/CountryListController.swift
index 633633f1..5956946f 100644
--- a/Sources/Countries/CountryListController.swift
+++ b/Sources/Countries/CountryListController.swift
@@ -7,7 +7,7 @@ import DependencyInjection
 public final class CountryListController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
 
-  lazy private var screenView = CountryListView()
+  private lazy var screenView = CountryListView()
 
   private var didChoose: ((Country) -> Void)!
   private let viewModel = CountryListViewModel()
diff --git a/Sources/DrawerFeature/DrawerController.swift b/Sources/DrawerFeature/DrawerController.swift
index d907c26b..de613530 100644
--- a/Sources/DrawerFeature/DrawerController.swift
+++ b/Sources/DrawerFeature/DrawerController.swift
@@ -2,7 +2,7 @@ import UIKit
 import Combine
 
 public final class DrawerController: UIViewController {
-    lazy private var screenView = DrawerView()
+    private lazy var screenView = DrawerView()
     private let content: [DrawerItem]
     public var cancellables = Set<AnyCancellable>()
 
diff --git a/Sources/LaunchFeature/LaunchController.swift b/Sources/LaunchFeature/LaunchController.swift
index 4c533ee1..fbcd6044 100644
--- a/Sources/LaunchFeature/LaunchController.swift
+++ b/Sources/LaunchFeature/LaunchController.swift
@@ -1,19 +1,18 @@
 import UIKit
 import Shared
 import Combine
-import Defaults
+import Navigation
 import PushFeature
 import DependencyInjection
 
 public final class LaunchController: UIViewController {
-  @Dependency var coordinator: LaunchCoordinating
+  @Dependency var navigator: Navigator
 
-  @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
-
-  lazy private var screenView = LaunchView()
+  // TO REMOVE:
+  public var pendingPushRoute: PushRouter.Route?
 
   private let viewModel = LaunchViewModel()
-  public var pendingPushRoute: PushRouter.Route?
+  private lazy var screenView = LaunchView()
   private var cancellables = Set<AnyCancellable>()
 
   public override func viewDidAppear(_ animated: Bool) {
@@ -27,64 +26,23 @@ public final class LaunchController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    navigationController?
-      .navigationBar
-      .customize(translucent: true)
+    navigationController?.navigationBar.customize(translucent: true)
   }
 
   public override func viewDidLayoutSubviews() {
     super.viewDidLayoutSubviews()
-    screenView.setupGradient()
-  }
-
-  public override func viewDidLoad() {
-    super.viewDidLoad()
-  
-    viewModel.routePublisher
-      .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in
-        switch $0 {
-        case .chats:
-          guard didAcceptTerms == true else {
-            coordinator.toTerms(from: self)
-            return
-          }
-
-          if let pushRoute = pendingPushRoute {
-            switch pushRoute {
-            case .requests:
-              coordinator.toRequests(from: self)
-
-            case .search(username: let username):
-              coordinator.toSearch(searching: username, from: self)
-
-            case .groupChat(id: let groupId):
-              if let groupInfo = viewModel.getGroupInfoWith(groupId: groupId) {
-                coordinator.toGroupChat(with: groupInfo, from: self)
-                return
-              }
-              coordinator.toChats(from: self)
-
-            case .contactChat(id: let userId):
-              if let contact = viewModel.getContactWith(userId: userId) {
-                coordinator.toSingleChat(with: contact, from: self)
-                return
-              }
-              coordinator.toChats(from: self)
-            }
-
-            return
-          }
-
-          coordinator.toChats(from: self)
-
-        case .onboarding:
-          coordinator.toOnboarding(from: self)
-
-        case .update(let model):
-          offerUpdate(model: model)
-        }
-      }.store(in: &cancellables)
+    let gradient = CAGradientLayer()
+    gradient.colors = [
+      UIColor(red: 122/255, green: 235/255, blue: 239/255, alpha: 1).cgColor,
+      UIColor(red: 56/255, green: 204/255, blue: 232/255, alpha: 1).cgColor,
+      UIColor(red: 63/255, green: 186/255, blue: 253/255, alpha: 1).cgColor,
+      UIColor(red: 98/255, green: 163/255, blue: 255/255, alpha: 1).cgColor
+    ]
+
+    gradient.frame = screenView.bounds
+    gradient.startPoint = CGPoint(x: 1, y: 0)
+    gradient.endPoint = CGPoint(x: 0, y: 1)
+    screenView.layer.insertSublayer(gradient, at: 0)
   }
 
   private func offerUpdate(model: Update) {
@@ -129,26 +87,26 @@ public final class LaunchController: UIViewController {
       title: model.positiveActionTitle
     )
 
-//    if let negativeTitle = model.negativeActionTitle {
-//      let negativeButton = CapsuleButton()
-//      negativeButton.set(style: .simplestColoredRed, title: negativeTitle)
-//
-//      negativeButton.publisher(for: .touchUpInside)
-//        .sink { [unowned self] in
-//          blocker.hideWindow()
-//          viewModel.continueWithInitialization()
-//        }.store(in: &cancellables)
-//
-//      vStack.addArrangedSubview(negativeButton)
-//    }
-//
-//    blocker.window?.addSubview(drawerView)
-//    drawerView.snp.makeConstraints {
-//      $0.left.equalToSuperview().offset(18)
-//      $0.center.equalToSuperview()
-//      $0.right.equalToSuperview().offset(-18)
-//    }
-//
-//    blocker.showWindow()
+    //    if let negativeTitle = model.negativeActionTitle {
+    //      let negativeButton = CapsuleButton()
+    //      negativeButton.set(style: .simplestColoredRed, title: negativeTitle)
+    //
+    //      negativeButton.publisher(for: .touchUpInside)
+    //        .sink { [unowned self] in
+    //          blocker.hideWindow()
+    //          viewModel.continueWithInitialization()
+    //        }.store(in: &cancellables)
+    //
+    //      vStack.addArrangedSubview(negativeButton)
+    //    }
+    //
+    //    blocker.window?.addSubview(drawerView)
+    //    drawerView.snp.makeConstraints {
+    //      $0.left.equalToSuperview().offset(18)
+    //      $0.center.equalToSuperview()
+    //      $0.right.equalToSuperview().offset(-18)
+    //    }
+    //
+    //    blocker.showWindow()
   }
 }
diff --git a/Sources/LaunchFeature/LaunchCoordinator.swift b/Sources/LaunchFeature/LaunchCoordinator.swift
deleted file mode 100644
index b07a99c7..00000000
--- a/Sources/LaunchFeature/LaunchCoordinator.swift
+++ /dev/null
@@ -1,84 +0,0 @@
-import UIKit
-import Models
-import XXModels
-import Presentation
-
-public protocol LaunchCoordinating {
-    func toChats(from: UIViewController)
-    func toTerms(from: UIViewController)
-    func toRequests(from: UIViewController)
-    func toSearch(searching: String, from: UIViewController)
-    func toOnboarding(from: UIViewController)
-    func toSingleChat(with: Contact, from: UIViewController)
-    func toGroupChat(with: GroupInfo, from: UIViewController)
-}
-
-public struct LaunchCoordinator: LaunchCoordinating {
-    var replacePresenter: Presenting = ReplacePresenter()
-
-    var termsFactory: () -> UIViewController
-    var searchFactory: (String) -> UIViewController
-    var requestsFactory: () -> UIViewController
-    var chatListFactory: () -> UIViewController
-    var onboardingFactory: () -> UIViewController
-    var singleChatFactory: (Contact) -> UIViewController
-    var groupChatFactory: (GroupInfo) -> UIViewController
-
-    public init(
-        termsFactory: @escaping () -> UIViewController,
-        searchFactory: @escaping (String) -> UIViewController,
-        requestsFactory: @escaping () -> UIViewController,
-        chatListFactory: @escaping () -> UIViewController,
-        onboardingFactory: @escaping () -> UIViewController,
-        singleChatFactory: @escaping (Contact) -> UIViewController,
-        groupChatFactory: @escaping (GroupInfo) -> UIViewController
-    ) {
-        self.termsFactory = termsFactory
-        self.searchFactory = searchFactory
-        self.requestsFactory = requestsFactory
-        self.chatListFactory = chatListFactory
-        self.groupChatFactory = groupChatFactory
-        self.onboardingFactory = onboardingFactory
-        self.singleChatFactory = singleChatFactory
-    }
-}
-
-public extension LaunchCoordinator {
-    func toSearch(searching: String, from parent: UIViewController) {
-        let screen = searchFactory(searching)
-        let chatListScreen = chatListFactory()
-        replacePresenter.present(chatListScreen, screen, from: parent)
-    }
-
-    func toTerms(from parent: UIViewController) {
-        let screen = termsFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toChats(from parent: UIViewController) {
-        let screen = chatListFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toRequests(from parent: UIViewController) {
-        let screen = requestsFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toOnboarding(from parent: UIViewController) {
-        let screen = onboardingFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toSingleChat(with contact: Contact, from parent: UIViewController) {
-        let chatListScreen = chatListFactory()
-        let singleChatScreen = singleChatFactory(contact)
-        replacePresenter.present(chatListScreen, singleChatScreen, from: parent)
-    }
-
-    func toGroupChat(with group: GroupInfo, from parent: UIViewController) {
-        let chatListScreen = chatListFactory()
-        let groupChatScreen = groupChatFactory(group)
-        replacePresenter.present(chatListScreen, groupChatScreen, from: parent)
-    }
-}
diff --git a/Sources/LaunchFeature/LaunchView.swift b/Sources/LaunchFeature/LaunchView.swift
index 995c9f8c..8a9fc7a4 100644
--- a/Sources/LaunchFeature/LaunchView.swift
+++ b/Sources/LaunchFeature/LaunchView.swift
@@ -2,36 +2,19 @@ import UIKit
 import Shared
 
 final class LaunchView: UIView {
-    private var imageView = UIImageView()
+  let imageView = UIImageView()
 
-    init() {
-        super.init(frame: .zero)
-        imageView.image = Asset.splash.image
-        imageView.contentMode = .scaleAspectFit
-        backgroundColor = Asset.neutralWhite.color
-
-        addSubview(imageView)
-
-        imageView.snp.makeConstraints {
-            $0.center.equalToSuperview()
-            $0.left.equalToSuperview().offset(100)
-        }
+  init() {
+    super.init(frame: .zero)
+    imageView.image = Asset.splash.image
+    imageView.contentMode = .scaleAspectFit
+    backgroundColor = Asset.neutralWhite.color
+    addSubview(imageView)
+    imageView.snp.makeConstraints {
+      $0.center.equalToSuperview()
+      $0.left.equalToSuperview().offset(100)
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
-
-    func setupGradient() {
-        let gradient = CAGradientLayer()
-        gradient.colors = [
-            UIColor(red: 122/255, green: 235/255, blue: 239/255, alpha: 1).cgColor,
-            UIColor(red: 56/255, green: 204/255, blue: 232/255, alpha: 1).cgColor,
-            UIColor(red: 63/255, green: 186/255, blue: 253/255, alpha: 1).cgColor,
-            UIColor(red: 98/255, green: 163/255, blue: 255/255, alpha: 1).cgColor
-        ]
-
-        gradient.frame = bounds
-        gradient.startPoint = CGPoint(x: 1, y: 0)
-        gradient.endPoint = CGPoint(x: 0, y: 1)
-        layer.insertSublayer(gradient, at: 0)
-    }
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/LaunchFeature/LaunchViewModel+Banned.swift b/Sources/LaunchFeature/LaunchViewModel+Banned.swift
new file mode 100644
index 00000000..d62c2c3d
--- /dev/null
+++ b/Sources/LaunchFeature/LaunchViewModel+Banned.swift
@@ -0,0 +1,61 @@
+import Shared
+import XXModels
+import Foundation
+
+extension LaunchViewModel {
+  func updateBannedList(completion: @escaping () -> Void) {
+    fetchBannedList { result in
+      switch result {
+      case .failure(_):
+        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
+          self.updateBannedList(completion: completion)
+        }
+      case .success(let data):
+        self.processBannedList(data, completion: completion)
+      }
+    }
+  }
+
+  func processBannedList(_ data: Data, completion: @escaping () -> Void) {
+    processBannedList(
+      data: data,
+      forEach: { result in
+        switch result {
+        case .success(let userId):
+          let query = Contact.Query(id: [userId])
+          if var contact = try! database.fetchContacts(query).first {
+            if contact.isBanned == false {
+              contact.isBanned = true
+              try! database.saveContact(contact)
+              self.enqueueBanWarning(contact: contact)
+            }
+          } else {
+            try! database.saveContact(.init(id: userId, isBanned: true))
+          }
+
+        case .failure(_):
+          break
+        }
+      },
+      completion: { result in
+        switch result {
+        case .failure(_):
+          DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
+            self.updateBannedList(completion: completion)
+          }
+
+        case .success(_):
+          completion()
+        }
+      }
+    )
+  }
+
+  func enqueueBanWarning(contact: XXModels.Contact) {
+    let name = (contact.nickname ?? contact.username) ?? "One of your contacts"
+    toastController.enqueueToast(model: .init(
+      title: "\(name) has been banned for offensive content.",
+      leftImage: Asset.requestSentToaster.image
+    ))
+  }
+}
diff --git a/Sources/LaunchFeature/LaunchViewModel+Database.swift b/Sources/LaunchFeature/LaunchViewModel+Database.swift
new file mode 100644
index 00000000..62fa45aa
--- /dev/null
+++ b/Sources/LaunchFeature/LaunchViewModel+Database.swift
@@ -0,0 +1,77 @@
+import XXModels
+import Foundation
+import XXDatabase
+import DependencyInjection
+import XXLegacyDatabaseMigrator
+
+extension LaunchViewModel {
+  func setupDatabase() throws {
+    let legacyOldPath = NSSearchPathForDirectoriesInDomains(
+      .documentDirectory, .userDomainMask, true
+    )[0].appending("/xxmessenger.sqlite")
+
+    let legacyPath = FileManager.default
+      .containerURL(forSecurityApplicationGroupIdentifier: "group.elixxir.messenger")!
+      .appendingPathComponent("database")
+      .appendingPathExtension("sqlite").path
+
+    let dbExistsInLegacyOldPath = FileManager.default.fileExists(atPath: legacyOldPath)
+    let dbExistsInLegacyPath = FileManager.default.fileExists(atPath: legacyPath)
+
+    if dbExistsInLegacyOldPath && !dbExistsInLegacyPath {
+      try? FileManager.default.moveItem(atPath: legacyOldPath, toPath: legacyPath)
+    }
+
+    let dbPath = FileManager.default
+      .containerURL(forSecurityApplicationGroupIdentifier: "group.elixxir.messenger")!
+      .appendingPathComponent("xxm_database")
+      .appendingPathExtension("sqlite").path
+
+    let database = try Database.onDisk(path: dbPath)
+
+    if dbExistsInLegacyPath {
+      try Migrator.live()(
+        try .init(path: legacyPath),
+        to: database,
+        myContactId: Data(), //client.bindings.myId,
+        meMarshaled: Data() //client.bindings.meMarshalled
+      )
+
+      try FileManager.default.moveItem(atPath: legacyPath, toPath: legacyPath.appending("-backup"))
+    }
+
+    DependencyInjection.Container.shared.register(database)
+
+    _ = try? database.bulkUpdateContacts(.init(authStatus: [.requesting]), .init(authStatus: .requestFailed))
+    _ = try? database.bulkUpdateContacts(.init(authStatus: [.confirming]), .init(authStatus: .confirmationFailed))
+    _ = try? database.bulkUpdateContacts(.init(authStatus: [.verificationInProgress]), .init(authStatus: .verificationFailed))
+  }
+
+
+  //  func getContactWith(userId: Data) -> XXModels.Contact? {
+  //    let query = Contact.Query(
+  //      id: [userId],
+  //      isBlocked: reportingStatus.isEnabled() ? false : nil,
+  //      isBanned: reportingStatus.isEnabled() ? false : nil
+  //    )
+  //
+  //    guard let database: Database = try? DependencyInjection.Container.shared.resolve(),
+  //          let contact = try? database.fetchContacts(query).first else {
+  //      return nil
+  //    }
+  //
+  //    return contact
+  //  }
+
+
+  func getGroupInfoWith(groupId: Data) -> GroupInfo? {
+    let query = GroupInfo.Query(groupId: groupId)
+
+    guard let database: Database = try? DependencyInjection.Container.shared.resolve(),
+          let info = try? database.fetchGroupInfos(query).first else {
+      return nil
+    }
+
+    return info
+  }
+}
diff --git a/Sources/LaunchFeature/LaunchViewModel+Messenger.swift b/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
new file mode 100644
index 00000000..f5ed8ee1
--- /dev/null
+++ b/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
@@ -0,0 +1,396 @@
+import XXClient
+import XXModels
+import XXLogger
+import Foundation
+import XXMessengerClient
+import DependencyInjection
+
+extension LaunchViewModel {
+  func setupBackupCallback() {
+    backupCallbackCancellable = messenger.registerBackupCallback(.init(handle: { [weak self] in
+      print(">>> Backup callback from bindings got called")
+      self?.backupService.updateLocalBackup($0)
+    }))
+  }
+
+  func setupMessageCallback() {
+    messageListenerCallbacksCancellable = messenger.registerMessageListener(.init(handle: {
+      guard let payload = try? Payload(with: $0.payload) else {
+        fatalError("Couldn't decode payload: \(String(data: $0.payload, encoding: .utf8) ?? "nil")")
+      }
+
+      try! self.database.saveMessage(.init(
+        networkId: $0.id,
+        senderId: $0.sender,
+        recipientId: self.messenger.e2e.get()!.getContact().getId(),
+        groupId: nil,
+        date: Date.fromTimestamp($0.timestamp),
+        status: .received,
+        isUnread: true,
+        text: payload.text,
+        replyMessageId: payload.reply?.messageId,
+        roundURL: $0.roundURL,
+        fileTransferId: nil
+      ))
+
+      if var contact = try? self.database.fetchContacts(.init(id: [$0.sender])).first {
+        contact.isRecent = false
+        try! self.database.saveContact(contact)
+      }
+    }))
+  }
+
+  func setupAuthCallback() {
+    authCallbacksCancellable = messenger.registerAuthCallbacks(
+      AuthCallbacks(handle: {
+        switch $0 {
+        case .confirm(contact: let contact, receptionId: _, ephemeralId: _, roundId: _):
+          self.handleConfirm(from: contact)
+        case .request(contact: let contact, receptionId: _, ephemeralId: _, roundId: _):
+          self.handleDirectRequest(from: contact)
+        case .reset(contact: let contact, receptionId: _, ephemeralId: _, roundId: _):
+          self.handleReset(from: contact)
+        }
+      })
+    )
+  }
+
+  func handleReset(from user: XXClient.Contact) {
+    if var contact = try? database.fetchContacts(.init(id: [user.getId()])).first {
+      contact.authStatus = .friend
+      _ = try? database.saveContact(contact)
+    }
+  }
+
+  func handleConfirm(from contact: XXClient.Contact) {
+    guard let id = try? contact.getId() else {
+      fatalError("Couldn't extract ID from contact confirmation arrived.")
+    }
+
+    guard var existentContact = try? database.fetchContacts(.init(id: [id])).first else {
+      print(">>> Tried to handle a confirmation from someone that is not a contact yet")
+      return
+    }
+
+    existentContact.isRecent = true
+    existentContact.authStatus = .friend
+    try! database.saveContact(existentContact)
+  }
+
+  func setupLogWriter() {
+    _ = try! SetLogLevel.live(.fatal)
+    RegisterLogWriter.live(.init(handle: { XXLogger.live().debug($0) }))
+  }
+
+  func listenToNetworkUpdates() {
+    networkMonitor.start()
+    networkCallbacksCancellable = messenger.cMix.get()!.addHealthCallback(.init(handle: { [weak self] in
+      guard let self else { return }
+      self.networkMonitor.update($0)
+    }))
+  }
+
+  func handleIncomingTransfer(_ receivedFile: ReceivedFile) {
+    //    if var model = try? database.saveFileTransfer(.init(
+    //      id: receivedFile.transferId,
+    //      contactId: receivedFile.senderId,
+    //      name: receivedFile.name,
+    //      type: receivedFile.type,
+    //      data: nil,
+    //      progress: 0.0,
+    //      isIncoming: true,
+    //      createdAt: Date()
+    //    )) {
+    //      try! database.saveMessage(.init(
+    //        networkId: nil,
+    //        senderId: receivedFile.senderId,
+    //        recipientId: messenger.e2e.get()!.getContact().getId(),
+    //        groupId: nil,
+    //        date: Date(),
+    //        status: .receiving,
+    //        isUnread: false,
+    //        text: "",
+    //        replyMessageId: nil,
+    //        roundURL: nil,
+    //        fileTransferId: model.id
+    //      ))
+    //
+    //      if let manager: XXClient.FileTransfer = try? DependencyInjection.Container.shared.resolve() {
+    //        print(">>> registerReceivedProgressCallback")
+    //
+    //        try! manager.registerReceivedProgressCallback(
+    //          transferId: receivedFile.transferId,
+    //          period: 1_000,
+    //          callback: .init(handle: { [weak self] in
+    //            guard let self else { return }
+    //            switch $0 {
+    //            case .success(let cb):
+    //              if cb.progress.completed {
+    //                model.progress = 100
+    //                model.data = try! manager.receive(transferId: receivedFile.transferId)
+    //              } else {
+    //                model.progress = Float(cb.progress.transmitted/cb.progress.total)
+    //              }
+    //
+    //              model = try! self.database.saveFileTransfer(model)
+    //
+    //            case .failure(let error):
+    //              print(error.localizedDescription)
+    //            }
+    //          })
+    //        )
+    //      } else {
+    //        //print(DependencyInjection.Container.shared.dependencies)
+    //      }
+    //    }
+  }
+
+  func handleDirectRequest(from contact: XXClient.Contact) {
+    guard let id = try? contact.getId() else {
+      fatalError("Couldn't extract ID from contact request arrived.")
+    }
+
+    if let _ = try? database.fetchContacts(.init(id: [id])).first {
+      print(">>> Tried to handle request from pre-existing contact.")
+      return
+    }
+
+    let facts = try? contact.getFacts()
+    let email = facts?.first(where: { $0.type == .email })?.value
+    let phone = facts?.first(where: { $0.type == .phone })?.value
+    let username = facts?.first(where: { $0.type == .username })?.value
+
+    var model = try! database.saveContact(.init(
+      id: id,
+      marshaled: contact.data,
+      username: username,
+      email: email,
+      phone: phone,
+      nickname: nil,
+      photo: nil,
+      authStatus: .verificationInProgress,
+      isRecent: true,
+      createdAt: Date()
+    ))
+
+    do {
+      let messenger: Messenger = try DependencyInjection.Container.shared.resolve()
+      try messenger.waitForNetwork()
+
+      if try messenger.verifyContact(contact) {
+        print(">>> [messenger.verifyContact \(#file):\(#line)]")
+
+        model.authStatus = .verified
+        model = try database.saveContact(model)
+      } else {
+        print(">>> [messenger.verifyContact \(#file):\(#line)]")
+        try database.deleteContact(model)
+      }
+    } catch {
+      print(">>> [messenger.verifyContact] thrown an exception: \(error.localizedDescription)")
+
+      model.authStatus = .verificationFailed
+      model = try! database.saveContact(model)
+    }
+  }
+
+  func handleGroupRequest(from group: XXClient.Group, messenger: Messenger) {
+    if let _ = try? database.fetchGroups(.init(id: [group.getId()])).first {
+      print(">>> Tried to handle a group request that is already handled")
+      return
+    }
+
+    guard var members = try? group.getMembership(), let leader = members.first else {
+      fatalError("Failed to get group membership/leader")
+    }
+
+    try! database.saveGroup(.init(
+      id: group.getId(),
+      name: String(data: group.getName(), encoding: .utf8)!,
+      leaderId: leader.id,
+      createdAt: Date.fromMSTimestamp(group.getCreatedMS()),
+      authStatus: .pending,
+      serialized: group.serialize()
+    ))
+
+    if let initMessageData = group.getInitMessage(),
+       let initMessage = String(data: initMessageData, encoding: .utf8) {
+      try! database.saveMessage(.init(
+        senderId: leader.id,
+        recipientId: nil,
+        groupId: group.getId(),
+        date: Date.fromMSTimestamp(group.getCreatedMS()),
+        status: .received,
+        isUnread: true,
+        text: initMessage
+      ))
+    }
+
+    print(">>> All members in the arrived group request:")
+    members.forEach { print(">>> \($0.id.base64EncodedString().prefix(10))...") }
+    print(">>> My ud.id is: \(try! messenger.ud.get()!.getContact().getId().base64EncodedString().prefix(10))...")
+    print(">>> My e2e.id is: \(try! messenger.e2e.get()!.getContact().getId().base64EncodedString().prefix(10))...")
+
+    let friends = try! database.fetchContacts(.init(
+      id: Set(members.map(\.id)),
+      authStatus: [
+        .friend,
+        .hidden,
+        .requesting,
+        .confirming,
+        .verificationInProgress,
+        .verified,
+        .requested,
+        .requestFailed,
+        .verificationFailed,
+        .confirmationFailed
+      ]
+    ))
+
+    print(">>> These people I already know:")
+    friends.forEach {
+      print(">>> Username: \($0.username), authStatus: \($0.authStatus.rawValue), id: \($0.id.base64EncodedString().prefix(10))...")
+    }
+
+    let strangers = Set(members.map(\.id)).subtracting(Set(friends.map(\.id)))
+
+    strangers.forEach {
+      if let stranger = try? database.fetchContacts(.init(id: [$0])).first {
+        print(">>> This is a stranger, but I already knew about his/her existance: \(stranger.id.base64EncodedString().prefix(10))...")
+      } else {
+        print(">>> This is a complete stranger. Storing on the db: \($0.base64EncodedString().prefix(10))...")
+
+        try! database.saveContact(.init(
+          id: $0,
+          marshaled: nil,
+          username: "Fetching...",
+          email: nil,
+          phone: nil,
+          nickname: nil,
+          photo: nil,
+          authStatus: .stranger,
+          isRecent: false,
+          isBlocked: false,
+          isBanned: false,
+          createdAt: Date.fromMSTimestamp(group.getCreatedMS())
+        ))
+      }
+    }
+
+    members.forEach {
+      let model = XXModels.GroupMember(groupId: group.getId(), contactId: $0.id)
+      _ = try? database.saveGroupMember(model)
+    }
+
+    print(">>> Performing a multi-lookup for group strangers:")
+
+    do {
+      let multiLookup = try messenger.lookupContacts(ids: strangers.map { $0 })
+
+      for user in multiLookup.contacts {
+        print(">>> Found stranger w/ id: \(try! user.getId().base64EncodedString().prefix(10))...")
+
+        if var foo = try? self.database.fetchContacts(.init(id: [user.getId()])).first,
+           let username = try? user.getFact(.username)?.value {
+          foo.username = username
+          print(">>> Set username: \(username) for \(try! user.getId().base64EncodedString().prefix(10))...")
+          _ = try? self.database.saveContact(foo)
+        }
+      }
+
+      for error in multiLookup.errors {
+        print(">>> Failure on Multilookup: \(error.localizedDescription)")
+      }
+
+      for failedId in multiLookup.failedIds {
+        print(">>> Failed id: \(failedId.base64EncodedString().prefix(10))...")
+      }
+    } catch {
+      print(">>> Exception on multilookup: \(error.localizedDescription)")
+    }
+  }
+
+  func generateGroupManager() throws {
+    let manager = try NewGroupChat.live(
+      e2eId: messenger.e2e()!.getId(),
+      groupRequest: .init(handle: { [weak self] group in
+        guard let self else { return }
+        self.handleGroupRequest(from: group, messenger: self.messenger)
+      }),
+      groupChatProcessor: .init(handle: { result in
+        switch result {
+        case .success(let cb):
+
+          print("Incoming GroupMessage:")
+          print("- groupId: \(cb.decryptedMessage.groupId.base64EncodedString().prefix(10))...")
+          print("- senderId: \(cb.decryptedMessage.senderId.base64EncodedString().prefix(10))...")
+          print("- messageId: \(cb.decryptedMessage.messageId.base64EncodedString().prefix(10))...")
+
+          if let payload = try? Payload(with: cb.decryptedMessage.payload) {
+            print("- payload.text: \(payload.text)")
+
+            if let reply = payload.reply {
+              print("- payload.reply.senderId: \(reply.senderId.base64EncodedString().prefix(10))...")
+              print("- payload.reply.messageId: \(reply.messageId.base64EncodedString().prefix(10))...")
+            } else {
+              print("- payload.reply: ∅")
+            }
+          }
+          print("")
+
+          guard let payload = try? Payload(with: cb.decryptedMessage.payload) else {
+            fatalError("Couldn't decode payload: \(String(data: cb.decryptedMessage.payload, encoding: .utf8) ?? "nil")")
+          }
+
+          let msg = Message(
+            networkId: cb.decryptedMessage.messageId,
+            senderId: cb.decryptedMessage.senderId,
+            recipientId: nil,
+            groupId: cb.decryptedMessage.groupId,
+            date: Date.fromTimestamp(Int(cb.decryptedMessage.timestamp)),
+            status: .received,
+            isUnread: true,
+            text: payload.text,
+            replyMessageId: payload.reply?.messageId,
+            roundURL: "https://google.com.br",
+            fileTransferId: nil
+          )
+
+          _ = try? self.database.saveMessage(msg)
+
+        case .failure(let error):
+          break
+        }
+      })
+    )
+
+    DependencyInjection.Container.shared.register(manager)
+  }
+
+  func generateTransferManager() throws {
+    //    let manager = try InitFileTransfer.live(
+    //      e2eId: messenger.e2e()!.getId(),
+    //      callback: .init(handle: { [weak self] in
+    //        guard let self else { return }
+    //
+    //        switch $0 {
+    //        case .success(let receivedFile):
+    //          self.handleIncomingTransfer(receivedFile, messenger: messenger)
+    //        case .failure(let error):
+    //          print(error.localizedDescription)
+    //        }
+    //      })
+    //    )
+    //
+    //    DependencyInjection.Container.shared.register(manager)
+  }
+
+  func generateTrafficManager() throws {
+    let manager = try NewDummyTrafficManager.live(
+      cMixId: messenger.e2e()!.getId()
+    )
+
+    DependencyInjection.Container.shared.register(manager)
+    try! manager.setStatus(dummyTrafficOn)
+  }
+}
diff --git a/Sources/LaunchFeature/LaunchViewModel+VersionCheck.swift b/Sources/LaunchFeature/LaunchViewModel+VersionCheck.swift
new file mode 100644
index 00000000..4496c75f
--- /dev/null
+++ b/Sources/LaunchFeature/LaunchViewModel+VersionCheck.swift
@@ -0,0 +1,33 @@
+import Shared
+import VersionChecking
+
+extension LaunchViewModel {
+  func versionFailed(error: Error) {
+    hudController.show(.init(
+      title: Localized.Launch.Version.failed,
+      content: error.localizedDescription
+    ))
+  }
+
+  func versionUpdateRequired(_ info: DappVersionInformation) {
+    hudController.dismiss()
+    routeSubject.send(.update(Update(
+      content: info.minimumMessage,
+      urlString: info.appUrl,
+      positiveActionTitle: Localized.Launch.Version.Required.positive,
+      negativeActionTitle: nil,
+      actionStyle: .brandColored
+    )))
+  }
+
+  func versionUpdateRecommended(_ info: DappVersionInformation) {
+    hudController.dismiss()
+    routeSubject.send(.update(Update(
+      content: Localized.Launch.Version.Recommended.title,
+      urlString: info.appUrl,
+      positiveActionTitle: Localized.Launch.Version.Recommended.positive,
+      negativeActionTitle: Localized.Launch.Version.Recommended.negative,
+      actionStyle: .simplestColoredRed
+    )))
+  }
+}
diff --git a/Sources/LaunchFeature/LaunchViewModel.swift b/Sources/LaunchFeature/LaunchViewModel.swift
index 92f46f14..3639e1d1 100644
--- a/Sources/LaunchFeature/LaunchViewModel.swift
+++ b/Sources/LaunchFeature/LaunchViewModel.swift
@@ -1,5 +1,4 @@
 import Shared
-import Models
 import Combine
 import Defaults
 import XXModels
@@ -42,6 +41,7 @@ enum LaunchRoute {
 
 final class LaunchViewModel {
   @Dependency var database: Database
+  @Dependency var messenger: Messenger
   @Dependency var hudController: HUDController
   @Dependency var backupService: BackupService
   @Dependency var versionChecker: VersionChecker
@@ -55,6 +55,7 @@ final class LaunchViewModel {
 
   @KeyObject(.username, defaultValue: nil) var username: String?
   @KeyObject(.biometrics, defaultValue: false) var isBiometricsOn: Bool
+  @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
   @KeyObject(.dummyTrafficOn, defaultValue: false) var dummyTrafficOn: Bool
 
   var authCallbacksCancellable: Cancellable?
@@ -66,7 +67,7 @@ final class LaunchViewModel {
     routeSubject.eraseToAnyPublisher()
   }
 
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = {
+  private var scheduler: AnySchedulerOf<DispatchQueue> = {
     DispatchQueue.global().eraseToAnyScheduler()
   }()
 
@@ -82,31 +83,30 @@ final class LaunchViewModel {
     fileName: ""
   )
 
-  private var cancellables = Set<AnyCancellable>()
-  private let routeSubject = PassthroughSubject<LaunchRoute, Never>()
+  var cancellables = Set<AnyCancellable>()
+  let routeSubject = PassthroughSubject<LaunchRoute, Never>()
 
   func viewDidAppear() {
-    backgroundScheduler.schedule(after: .init(.now() + 1)) { [weak self] in
-      guard let self = self else { return }
-
+    scheduler.schedule(after: .init(.now() + 1)) { [weak self] in
+      guard let self else { return }
       self.hudController.show()
-
-      self.versionChecker().sink { [unowned self] in
-        switch $0 {
-        case .upToDate:
-          self.updateBannedList {
-            self.updateErrors {
-              self.continueWithInitialization()
+      self.versionChecker()
+        .sink { [unowned self] in
+          switch $0 {
+          case .upToDate:
+            self.updateBannedList {
+              self.updateErrors {
+                self.continueWithInitialization()
+              }
             }
+          case .failure(let error):
+            self.versionFailed(error: error)
+          case .updateRequired(let info):
+            self.versionUpdateRequired(info)
+          case .updateRecommended(let info):
+            self.versionUpdateRecommended(info)
           }
-        case .failure(let error):
-          self.versionFailed(error: error)
-        case .updateRequired(let info):
-          self.versionUpdateRequired(info)
-        case .updateRecommended(let info):
-          self.versionUpdateRecommended(info)
-        }
-      }.store(in: &self.cancellables)
+        }.store(in: &self.cancellables)
     }
   }
 
@@ -114,13 +114,10 @@ final class LaunchViewModel {
     do {
       try self.setupDatabase()
 
-      let messenger = makeMessenger()
-      DependencyInjection.Container.shared.register(messenger)
-
       setupLogWriter()
-      setupAuthCallback(messenger)
-      setupBackupCallback(messenger)
-      setupMessageCallback(messenger)
+      setupAuthCallback()
+      setupBackupCallback()
+      setupMessageCallback()
 
       if messenger.isLoaded() == false {
         if messenger.isCreated() == false {
@@ -137,10 +134,10 @@ final class LaunchViewModel {
         try messenger.listenForMessages()
       }
 
-      try generateGroupManager(messenger)
-      try generateTrafficManager(messenger)
-      try generateTransferManager(messenger)
-      listenToNetworkUpdates(messenger)
+      try generateGroupManager()
+      try generateTrafficManager()
+      try generateTransferManager()
+      listenToNetworkUpdates()
 
       if messenger.isLoggedIn() == false {
         if try messenger.isRegistered() {
@@ -157,11 +154,9 @@ final class LaunchViewModel {
         hudController.dismiss()
         routeSubject.send(.chats)
       }
-
       if !messenger.isBackupRunning() {
         try? messenger.resumeBackup()
       }
-
       // TODO: Biometric auth
 
     } catch {
@@ -180,109 +175,6 @@ final class LaunchViewModel {
     routeSubject.send(.onboarding)
   }
 
-  private func setupDatabase() throws {
-    let legacyOldPath = NSSearchPathForDirectoriesInDomains(
-      .documentDirectory, .userDomainMask, true
-    )[0].appending("/xxmessenger.sqlite")
-
-    let legacyPath = FileManager.default
-      .containerURL(forSecurityApplicationGroupIdentifier: "group.elixxir.messenger")!
-      .appendingPathComponent("database")
-      .appendingPathExtension("sqlite").path
-
-    let dbExistsInLegacyOldPath = FileManager.default.fileExists(atPath: legacyOldPath)
-    let dbExistsInLegacyPath = FileManager.default.fileExists(atPath: legacyPath)
-
-    if dbExistsInLegacyOldPath && !dbExistsInLegacyPath {
-      try? FileManager.default.moveItem(atPath: legacyOldPath, toPath: legacyPath)
-    }
-
-    let dbPath = FileManager.default
-      .containerURL(forSecurityApplicationGroupIdentifier: "group.elixxir.messenger")!
-      .appendingPathComponent("xxm_database")
-      .appendingPathExtension("sqlite").path
-
-    let database = try Database.onDisk(path: dbPath)
-
-    if dbExistsInLegacyPath {
-      try Migrator.live()(
-        try .init(path: legacyPath),
-        to: database,
-        myContactId: Data(), //client.bindings.myId,
-        meMarshaled: Data() //client.bindings.meMarshalled
-      )
-
-      try FileManager.default.moveItem(atPath: legacyPath, toPath: legacyPath.appending("-backup"))
-    }
-
-    DependencyInjection.Container.shared.register(database)
-
-    _ = try? database.bulkUpdateContacts(.init(authStatus: [.requesting]), .init(authStatus: .requestFailed))
-    _ = try? database.bulkUpdateContacts(.init(authStatus: [.confirming]), .init(authStatus: .confirmationFailed))
-    _ = try? database.bulkUpdateContacts(.init(authStatus: [.verificationInProgress]), .init(authStatus: .verificationFailed))
-  }
-
-  func getContactWith(userId: Data) -> XXModels.Contact? {
-    let query = Contact.Query(
-      id: [userId],
-      isBlocked: reportingStatus.isEnabled() ? false : nil,
-      isBanned: reportingStatus.isEnabled() ? false : nil
-    )
-
-    guard let database: Database = try? DependencyInjection.Container.shared.resolve(),
-          let contact = try? database.fetchContacts(query).first else {
-      return nil
-    }
-
-    return contact
-  }
-
-  func getGroupInfoWith(groupId: Data) -> GroupInfo? {
-    let query = GroupInfo.Query(groupId: groupId)
-
-    guard let database: Database = try? DependencyInjection.Container.shared.resolve(),
-          let info = try? database.fetchGroupInfos(query).first else {
-      return nil
-    }
-
-    return info
-  }
-
-  private func versionFailed(error: Error) {
-    hudController.show(.init(
-      title: Localized.Launch.Version.failed,
-      content: error.localizedDescription
-    ))
-  }
-
-  private func versionUpdateRequired(_ info: DappVersionInformation) {
-    hudController.dismiss()
-
-    let model = Update(
-      content: info.minimumMessage,
-      urlString: info.appUrl,
-      positiveActionTitle: Localized.Launch.Version.Required.positive,
-      negativeActionTitle: nil,
-      actionStyle: .brandColored
-    )
-
-    routeSubject.send(.update(model))
-  }
-
-  private func versionUpdateRecommended(_ info: DappVersionInformation) {
-    hudController.dismiss()
-
-    let model = Update(
-      content: Localized.Launch.Version.Recommended.title,
-      urlString: info.appUrl,
-      positiveActionTitle: Localized.Launch.Version.Recommended.positive,
-      negativeActionTitle: Localized.Launch.Version.Recommended.negative,
-      actionStyle: .simplestColoredRed
-    )
-
-    routeSubject.send(.update(model))
-  }
-
   private func checkBiometrics(completion: @escaping (Result<Bool, Error>) -> Void) {
     if permissionHandler.isBiometricsAvailable && isBiometricsOn {
       permissionHandler.requestBiometrics {
@@ -303,7 +195,7 @@ final class LaunchViewModel {
     let errorsURLString = "https://git.xx.network/elixxir/client-error-database/-/raw/main/clientErrors.json"
 
     URLSession.shared.dataTask(with: URL(string: errorsURLString)!) { [weak self] data, _, error in
-      guard let self = self else { return }
+      guard let self else { return }
 
       guard error == nil else {
         print(">>> Issue when trying to download errors json: \(error!.localizedDescription)")
@@ -324,490 +216,50 @@ final class LaunchViewModel {
       }
     }.resume()
   }
-
-  private func updateBannedList(completion: @escaping () -> Void) {
-    fetchBannedList { result in
-      switch result {
-      case .failure(_):
-        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
-          self.updateBannedList(completion: completion)
-        }
-      case .success(let data):
-        self.processBannedList(data, completion: completion)
-      }
-    }
-  }
-
-  private func processBannedList(_ data: Data, completion: @escaping () -> Void) {
-    processBannedList(
-      data: data,
-      forEach: { result in
-        switch result {
-        case .success(let userId):
-          let query = Contact.Query(id: [userId])
-          if var contact = try! database.fetchContacts(query).first {
-            if contact.isBanned == false {
-              contact.isBanned = true
-              try! database.saveContact(contact)
-              self.enqueueBanWarning(contact: contact)
-            }
-          } else {
-            try! database.saveContact(.init(id: userId, isBanned: true))
-          }
-
-        case .failure(_):
-          break
-        }
-      },
-      completion: { result in
-        switch result {
-        case .failure(_):
-          DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
-            self.updateBannedList(completion: completion)
-          }
-
-        case .success(_):
-          completion()
-        }
-      }
-    )
-  }
-
-  private func enqueueBanWarning(contact: XXModels.Contact) {
-    let name = (contact.nickname ?? contact.username) ?? "One of your contacts"
-    toastController.enqueueToast(model: .init(
-      title: "\(name) has been banned for offensive content.",
-      leftImage: Asset.requestSentToaster.image
-    ))
-  }
-}
-
-extension LaunchViewModel {
-  private func generateGroupManager(_ messenger: Messenger) throws {
-    let manager = try NewGroupChat.live(
-      e2eId: messenger.e2e()!.getId(),
-      groupRequest: .init(handle: { [weak self] group in
-        guard let self = self else { return }
-        self.handleGroupRequest(from: group, messenger: messenger)
-      }),
-      groupChatProcessor: .init(handle: { result in
-        switch result {
-        case .success(let cb):
-
-          print("Incoming GroupMessage:")
-          print("- groupId: \(cb.decryptedMessage.groupId.base64EncodedString().prefix(10))...")
-          print("- senderId: \(cb.decryptedMessage.senderId.base64EncodedString().prefix(10))...")
-          print("- messageId: \(cb.decryptedMessage.messageId.base64EncodedString().prefix(10))...")
-
-          if let payload = try? Payload(with: cb.decryptedMessage.payload) {
-            print("- payload.text: \(payload.text)")
-
-            if let reply = payload.reply {
-              print("- payload.reply.senderId: \(reply.senderId.base64EncodedString().prefix(10))...")
-              print("- payload.reply.messageId: \(reply.messageId.base64EncodedString().prefix(10))...")
-            } else {
-              print("- payload.reply: ∅")
-            }
-          }
-          print("")
-
-          guard let payload = try? Payload(with: cb.decryptedMessage.payload) else {
-            fatalError("Couldn't decode payload: \(String(data: cb.decryptedMessage.payload, encoding: .utf8) ?? "nil")")
-          }
-
-          let msg = Message(
-            networkId: cb.decryptedMessage.messageId,
-            senderId: cb.decryptedMessage.senderId,
-            recipientId: nil,
-            groupId: cb.decryptedMessage.groupId,
-            date: Date.fromTimestamp(Int(cb.decryptedMessage.timestamp)),
-            status: .received,
-            isUnread: true,
-            text: payload.text,
-            replyMessageId: payload.reply?.messageId,
-            roundURL: "https://google.com.br",
-            fileTransferId: nil
-          )
-
-          _ = try? self.database.saveMessage(msg)
-
-        case .failure(let error):
-          break
-        }
-      })
-    )
-
-    DependencyInjection.Container.shared.register(manager)
-  }
-
-  private func generateTransferManager(_ messenger: Messenger) throws {
-    //    let manager = try InitFileTransfer.live(
-    //      e2eId: messenger.e2e()!.getId(),
-    //      callback: .init(handle: { [weak self] in
-    //        guard let self = self else { return }
-    //
-    //        switch $0 {
-    //        case .success(let receivedFile):
-    //          self.handleIncomingTransfer(receivedFile, messenger: messenger)
-    //        case .failure(let error):
-    //          print(error.localizedDescription)
-    //        }
-    //      })
-    //    )
-    //
-    //    DependencyInjection.Container.shared.register(manager)
-  }
-
-  private func generateTrafficManager(_ messenger: Messenger) throws {
-    let manager = try NewDummyTrafficManager.live(
-      cMixId: messenger.e2e()!.getId()
-    )
-
-    DependencyInjection.Container.shared.register(manager)
-    try! manager.setStatus(dummyTrafficOn)
-  }
-}
-
-extension LaunchViewModel {
-  private func handleDirectRequest(from contact: XXClient.Contact) {
-    guard let id = try? contact.getId() else {
-      fatalError("Couldn't extract ID from contact request arrived.")
-    }
-
-    if let _ = try? database.fetchContacts(.init(id: [id])).first {
-      print(">>> Tried to handle request from pre-existing contact.")
-      return
-    }
-
-    let facts = try? contact.getFacts()
-    let email = facts?.first(where: { $0.type == .email })?.value
-    let phone = facts?.first(where: { $0.type == .phone })?.value
-    let username = facts?.first(where: { $0.type == .username })?.value
-
-    var model = try! database.saveContact(.init(
-      id: id,
-      marshaled: contact.data,
-      username: username,
-      email: email,
-      phone: phone,
-      nickname: nil,
-      photo: nil,
-      authStatus: .verificationInProgress,
-      isRecent: true,
-      createdAt: Date()
-    ))
-
-    do {
-      let messenger: Messenger = try DependencyInjection.Container.shared.resolve()
-      try messenger.waitForNetwork()
-
-      if try messenger.verifyContact(contact) {
-        print(">>> [messenger.verifyContact \(#file):\(#line)]")
-
-        model.authStatus = .verified
-        model = try database.saveContact(model)
-      } else {
-        print(">>> [messenger.verifyContact \(#file):\(#line)]")
-        try database.deleteContact(model)
-      }
-    } catch {
-      print(">>> [messenger.verifyContact] thrown an exception: \(error.localizedDescription)")
-
-      model.authStatus = .verificationFailed
-      model = try! database.saveContact(model)
-    }
-  }
-
-  private func handleConfirm(from contact: XXClient.Contact) {
-    guard let id = try? contact.getId() else {
-      fatalError("Couldn't extract ID from contact confirmation arrived.")
-    }
-
-    guard var existentContact = try? database.fetchContacts(.init(id: [id])).first else {
-      print(">>> Tried to handle a confirmation from someone that is not a contact yet")
-      return
-    }
-
-    existentContact.isRecent = true
-    existentContact.authStatus = .friend
-    try! database.saveContact(existentContact)
-  }
-
-  private func handleReset(from user: XXClient.Contact) {
-    if var contact = try? database.fetchContacts(.init(id: [user.getId()])).first {
-      contact.authStatus = .friend
-      _ = try? database.saveContact(contact)
-    }
-  }
-
-  private func handleGroupRequest(from group: XXClient.Group, messenger: Messenger) {
-    if let _ = try? database.fetchGroups(.init(id: [group.getId()])).first {
-      print(">>> Tried to handle a group request that is already handled")
-      return
-    }
-
-    guard var members = try? group.getMembership(), let leader = members.first else {
-      fatalError("Failed to get group membership/leader")
-    }
-
-    try! database.saveGroup(.init(
-      id: group.getId(),
-      name: String(data: group.getName(), encoding: .utf8)!,
-      leaderId: leader.id,
-      createdAt: Date.fromMSTimestamp(group.getCreatedMS()),
-      authStatus: .pending,
-      serialized: group.serialize()
-    ))
-
-    if let initMessageData = group.getInitMessage(),
-       let initMessage = String(data: initMessageData, encoding: .utf8) {
-      try! database.saveMessage(.init(
-        senderId: leader.id,
-        recipientId: nil,
-        groupId: group.getId(),
-        date: Date.fromMSTimestamp(group.getCreatedMS()),
-        status: .received,
-        isUnread: true,
-        text: initMessage
-      ))
-    }
-
-    print(">>> All members in the arrived group request:")
-    members.forEach { print(">>> \($0.id.base64EncodedString().prefix(10))...") }
-    print(">>> My ud.id is: \(try! messenger.ud.get()!.getContact().getId().base64EncodedString().prefix(10))...")
-    print(">>> My e2e.id is: \(try! messenger.e2e.get()!.getContact().getId().base64EncodedString().prefix(10))...")
-
-    let friends = try! database.fetchContacts(.init(
-      id: Set(members.map(\.id)),
-      authStatus: [
-        .friend,
-        .hidden,
-        .requesting,
-        .confirming,
-        .verificationInProgress,
-        .verified,
-        .requested,
-        .requestFailed,
-        .verificationFailed,
-        .confirmationFailed
-      ]
-    ))
-
-    print(">>> These people I already know:")
-    friends.forEach {
-      print(">>> Username: \($0.username), authStatus: \($0.authStatus.rawValue), id: \($0.id.base64EncodedString().prefix(10))...")
-    }
-
-    let strangers = Set(members.map(\.id)).subtracting(Set(friends.map(\.id)))
-
-    strangers.forEach {
-      if let stranger = try? database.fetchContacts(.init(id: [$0])).first {
-        print(">>> This is a stranger, but I already knew about his/her existance: \(stranger.id.base64EncodedString().prefix(10))...")
-      } else {
-        print(">>> This is a complete stranger. Storing on the db: \($0.base64EncodedString().prefix(10))...")
-
-        try! database.saveContact(.init(
-          id: $0,
-          marshaled: nil,
-          username: "Fetching...",
-          email: nil,
-          phone: nil,
-          nickname: nil,
-          photo: nil,
-          authStatus: .stranger,
-          isRecent: false,
-          isBlocked: false,
-          isBanned: false,
-          createdAt: Date.fromMSTimestamp(group.getCreatedMS())
-        ))
-      }
-    }
-
-    members.forEach {
-      let model = XXModels.GroupMember(groupId: group.getId(), contactId: $0.id)
-      _ = try? database.saveGroupMember(model)
-    }
-
-    print(">>> Performing a multi-lookup for group strangers:")
-
-    do {
-      let multiLookup = try messenger.lookupContacts(ids: strangers.map { $0 })
-
-      for user in multiLookup.contacts {
-        print(">>> Found stranger w/ id: \(try! user.getId().base64EncodedString().prefix(10))...")
-
-        if var foo = try? self.database.fetchContacts(.init(id: [user.getId()])).first,
-           let username = try? user.getFact(.username)?.value {
-          foo.username = username
-          print(">>> Set username: \(username) for \(try! user.getId().base64EncodedString().prefix(10))...")
-          _ = try? self.database.saveContact(foo)
-        }
-      }
-
-      for error in multiLookup.errors {
-        print(">>> Failure on Multilookup: \(error.localizedDescription)")
-      }
-
-      for failedId in multiLookup.failedIds {
-        print(">>> Failed id: \(failedId.base64EncodedString().prefix(10))...")
-      }
-    } catch {
-      print(">>> Exception on multilookup: \(error.localizedDescription)")
-    }
-  }
 }
 
-extension LaunchViewModel {
-  private func handleIncomingTransfer(_ receivedFile: ReceivedFile, messenger: Messenger) {
-    if var model = try? database.saveFileTransfer(.init(
-      id: receivedFile.transferId,
-      contactId: receivedFile.senderId,
-      name: receivedFile.name,
-      type: receivedFile.type,
-      data: nil,
-      progress: 0.0,
-      isIncoming: true,
-      createdAt: Date()
-    )) {
-      try! database.saveMessage(.init(
-        networkId: nil,
-        senderId: receivedFile.senderId,
-        recipientId: messenger.e2e.get()!.getContact().getId(),
-        groupId: nil,
-        date: Date(),
-        status: .receiving,
-        isUnread: false,
-        text: "",
-        replyMessageId: nil,
-        roundURL: nil,
-        fileTransferId: model.id
-      ))
-
-      if let manager: XXClient.FileTransfer = try? DependencyInjection.Container.shared.resolve() {
-        print(">>> registerReceivedProgressCallback")
-
-        try! manager.registerReceivedProgressCallback(
-          transferId: receivedFile.transferId,
-          period: 1_000,
-          callback: .init(handle: { [weak self] in
-            guard let self = self else { return }
-            switch $0 {
-            case .success(let cb):
-              if cb.progress.completed {
-                model.progress = 100
-                model.data = try! manager.receive(transferId: receivedFile.transferId)
-              } else {
-                model.progress = Float(cb.progress.transmitted/cb.progress.total)
-              }
-
-              model = try! self.database.saveFileTransfer(model)
-
-            case .failure(let error):
-              print(error.localizedDescription)
-            }
-          })
-        )
-      } else {
-        //print(DependencyInjection.Container.shared.dependencies)
-      }
-    }
-  }
-
-  private func setupLogWriter() {
-    _ = try! SetLogLevel.live(.fatal)
-    RegisterLogWriter.live(.init(handle: { XXLogger.live().debug($0) }))
-  }
-
-  private func makeMessenger() -> Messenger {
-    var environment: MessengerEnvironment = .live()
-    environment.ndfEnvironment = .mainnet
-    environment.udEnvironment = .init(
-      address: "46.101.98.49:18001",
-      cert: """
-            -----BEGIN CERTIFICATE-----
-            MIIDbDCCAlSgAwIBAgIJAOUNtZneIYECMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV
-            BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQx
-            GzAZBgNVBAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJp
-            cDAeFw0xOTAzMDUxODM1NDNaFw0yOTAzMDIxODM1NDNaMGgxCzAJBgNVBAYTAlVT
-            MRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlDbGFyZW1vbnQxGzAZBgNV
-            BAoMElByaXZhdGVncml0eSBDb3JwLjETMBEGA1UEAwwKKi5jbWl4LnJpcDCCASIw
-            DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPP0WyVkfZA/CEd2DgKpcudn0oDh
-            Dwsjmx8LBDWsUgQzyLrFiVigfUmUefknUH3dTJjmiJtGqLsayCnWdqWLHPJYvFfs
-            WYW0IGF93UG/4N5UAWO4okC3CYgKSi4ekpfw2zgZq0gmbzTnXcHF9gfmQ7jJUKSE
-            tJPSNzXq+PZeJTC9zJAb4Lj8QzH18rDM8DaL2y1ns0Y2Hu0edBFn/OqavBJKb/uA
-            m3AEjqeOhC7EQUjVamWlTBPt40+B/6aFJX5BYm2JFkRsGBIyBVL46MvC02MgzTT9
-            bJIJfwqmBaTruwemNgzGu7Jk03hqqS1TUEvSI6/x8bVoba3orcKkf9HsDjECAwEA
-            AaMZMBcwFQYDVR0RBA4wDIIKKi5jbWl4LnJpcDANBgkqhkiG9w0BAQUFAAOCAQEA
-            neUocN4AbcQAC1+b3To8u5UGdaGxhcGyZBlAoenRVdjXK3lTjsMdMWb4QctgNfIf
-            U/zuUn2mxTmF/ekP0gCCgtleZr9+DYKU5hlXk8K10uKxGD6EvoiXZzlfeUuotgp2
-            qvI3ysOm/hvCfyEkqhfHtbxjV7j7v7eQFPbvNaXbLa0yr4C4vMK/Z09Ui9JrZ/Z4
-            cyIkxfC6/rOqAirSdIp09EGiw7GM8guHyggE4IiZrDslT8V3xIl985cbCxSxeW1R
-            tgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E5
-            6m52PyzMNV+2N21IPppKwA==
-            -----END CERTIFICATE-----
-            """.data(using: .utf8)!,
-      contact: """
-      <xxc(2)7mbKFLE201WzH4SGxAOpHjjehwztIV+KGifi5L/PYPcDkAZiB9kZo+Dl3Vc7dD2SdZCFMOJVgwqGzfYRDkjc8RGEllBqNxq2sRRX09iQVef0kJQUgJCHNCOcvm6Ki0JJwvjLceyFh36iwK8oLbhLgqEZY86UScdACTyBCzBIab3ob5mBthYc3mheV88yq5PGF2DQ+dEvueUm+QhOSfwzppAJA/rpW9Wq9xzYcQzaqc3ztAGYfm2BBAHS7HVmkCbvZ/K07Xrl4EBPGHJYq12tWAN/C3mcbbBYUOQXyEzbSl/mO7sL3ORr0B4FMuqCi8EdlD6RO52pVhY+Cg6roRH1t5Ng1JxPt8Mv1yyjbifPhZ5fLKwxBz8UiFORfk0/jnhwgm25LRHqtNRRUlYXLvhv0HhqyYTUt17WNtCLATSVbqLrFGdy2EGadn8mP+kQNHp93f27d/uHgBNNe7LpuYCJMdWpoG6bOqmHEftxt0/MIQA8fTtTm3jJzv+7/QjZJDvQIv0SNdp8HFogpuwde+GuS4BcY7v5xz+ArGWcRR63ct2z83MqQEn9ODr1/gAAAgA7szRpDDQIdFUQo9mkWg8xBA==xxc>
-      """.data(using: .utf8)!
-    )
-
-    return Messenger.live(environment)
-  }
-
-  private func setupAuthCallback(_ messenger: Messenger) {
-    authCallbacksCancellable = messenger.registerAuthCallbacks(
-      AuthCallbacks(handle: {
-        switch $0 {
-        case .confirm(contact: let contact, receptionId: _, ephemeralId: _, roundId: _):
-          self.handleConfirm(from: contact)
-        case .request(contact: let contact, receptionId: _, ephemeralId: _, roundId: _):
-          self.handleDirectRequest(from: contact)
-        case .reset(contact: let contact, receptionId: _, ephemeralId: _, roundId: _):
-          self.handleReset(from: contact)
-        }
-      })
-    )
-  }
-
-  private func setupBackupCallback(_ messenger: Messenger) {
-    backupCallbackCancellable = messenger.registerBackupCallback(.init(handle: { [weak self] in
-      print(">>> Backup callback from bindings got called")
-      self?.backupService.updateLocalBackup($0)
-    }))
-  }
-
-  private func setupMessageCallback(_ messenger: Messenger) {
-    messageListenerCallbacksCancellable = messenger.registerMessageListener(.init(handle: {
-      guard let payload = try? Payload(with: $0.payload) else {
-        fatalError("Couldn't decode payload: \(String(data: $0.payload, encoding: .utf8) ?? "nil")")
-      }
-
-      try! self.database.saveMessage(.init(
-        networkId: $0.id,
-        senderId: $0.sender,
-        recipientId: messenger.e2e.get()!.getContact().getId(),
-        groupId: nil,
-        date: Date.fromTimestamp($0.timestamp),
-        status: .received,
-        isUnread: true,
-        text: payload.text,
-        replyMessageId: payload.reply?.messageId,
-        roundURL: $0.roundURL,
-        fileTransferId: nil
-      ))
-
-      if var contact = try? self.database.fetchContacts(.init(id: [$0.sender])).first {
-        contact.isRecent = false
-        try! self.database.saveContact(contact)
-      }
-    }))
-  }
-
-  private func listenToNetworkUpdates(_ messenger: Messenger) {
-    networkMonitor.start()
-    networkCallbacksCancellable = messenger.cMix.get()!.addHealthCallback(.init(handle: { [weak self] in
-      guard let self = self else { return }
-      self.networkMonitor.update($0)
-    }))
-  }
-}
+//    viewModel.routePublisher
+//      .receive(on: DispatchQueue.main)
+//      .sink { [unowned self] in
+//        switch $0 {
+//        case .chats:
+//          guard didAcceptTerms == true else {
+//            navigator.perform(PresentTermsAndConditions(popAllowed: false))
+//            return
+//          }
+//
+//          if let pushRoute = pendingPushRoute {
+//            switch pushRoute {
+//            case .requests:
+//              navigator.perform(PresentRequests())
+//
+//            case .search(username: let username):
+//              navigator.perform(PresentSearch(searching: username))
+//
+//            case .groupChat(id: let groupId):
+//              if let info = viewModel.getGroupInfoWith(groupId: groupId) {
+//                navigator.perform(PresentGroupChat(model: info))
+//                return
+//              }
+//              navigator.perform(PresentChatList())
+//
+//            case .contactChat(id: let userId):
+//              if let model = viewModel.getContactWith(userId: userId) {
+//                navigator.perform(PresentChat(contact: model))
+//                return
+//              }
+//              navigator.perform(PresentChatList())
+//            }
+//
+//            return
+//          }
+//
+//          navigator.perform(PresentChatList())
+//
+//        case .onboarding:
+//          navigator.perform(PresentOnboardingStart())
+//
+//        case .update(let model):
+//          offerUpdate(model: model)
+//        }
+//      }.store(in: &cancellables)
diff --git a/Sources/MenuFeature/Controllers/MenuController.swift b/Sources/MenuFeature/Controllers/MenuController.swift
index 49b86d3a..22cee488 100644
--- a/Sources/MenuFeature/Controllers/MenuController.swift
+++ b/Sources/MenuFeature/Controllers/MenuController.swift
@@ -20,7 +20,7 @@ public final class MenuController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: MenuCoordinating
 
-  lazy private var screenView = MenuView()
+  private lazy var screenView = MenuView()
 
   private let previousItem: MenuItem
   private let viewModel = MenuViewModel()
diff --git a/Sources/Models/AttributeConfirmation.swift b/Sources/Models/AttributeConfirmation.swift
deleted file mode 100644
index 2f8b99ea..00000000
--- a/Sources/Models/AttributeConfirmation.swift
+++ /dev/null
@@ -1,15 +0,0 @@
-public struct AttributeConfirmation: Equatable {
-    public var content: String
-    public var isEmail: Bool = false
-    public var confirmationId: String?
-
-    public init(
-        content: String,
-        isEmail: Bool = false,
-        confirmationId: String? = nil
-    ) {
-        self.content = content
-        self.isEmail = isEmail
-        self.confirmationId = confirmationId
-    }
-}
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingEmailConfirmationController.swift b/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
similarity index 58%
rename from Sources/OnboardingFeature/Controllers/OnboardingEmailConfirmationController.swift
rename to Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
index 4ae996ad..b8fe915a 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingEmailConfirmationController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
@@ -1,29 +1,37 @@
 import UIKit
 import Shared
-import Models
 import Combine
+import Navigation
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 import ScrollViewController
 
-public final class OnboardingEmailConfirmationController: UIViewController {
+public final class OnboardingCodeController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: OnboardingCoordinating
 
-  lazy private var screenView = OnboardingEmailConfirmationView()
-  lazy private var scrollViewController = ScrollViewController()
+  private lazy var screenView = OnboardingCodeView()
+  private lazy var scrollViewController = ScrollViewController()
 
+  private let isEmail: Bool
+  private let content: String
+  private let viewModel: OnboardingCodeViewModel
   private var cancellables = Set<AnyCancellable>()
-  private let completion: (UIViewController) -> Void
   private var drawerCancellables = Set<AnyCancellable>()
-  private let viewModel: OnboardingEmailConfirmationViewModel
 
   public init(
-    _ confirmation: AttributeConfirmation,
-    _ completion: @escaping (UIViewController) -> Void
+    _ isEmail: Bool,
+    _ content: String,
+    _ confirmationId: String
   ) {
-    self.completion = completion
-    self.viewModel = OnboardingEmailConfirmationViewModel(confirmation)
+    self.viewModel = .init(
+      isEmail: isEmail,
+      content: content,
+      confirmationId: confirmationId
+    )
+    self.isEmail = isEmail
+    self.content = content
     super.init(nibName: nil, bundle: nil)
   }
 
@@ -42,14 +50,24 @@ public final class OnboardingEmailConfirmationController: UIViewController {
     setupBindings()
 
     screenView.setupSubtitle(
-      Localized.Onboarding.EmailConfirmation.subtitle(viewModel.confirmation.content)
+      isEmail ?
+      Localized.Onboarding.EmailConfirmation.subtitle(content) :
+      Localized.Onboarding.PhoneConfirmation.subtitle(content)
     )
 
     screenView.didTapInfo = { [weak self] in
-      self?.presentInfo(
-        title: Localized.Onboarding.EmailConfirmation.Info.title,
-        subtitle: Localized.Onboarding.EmailConfirmation.Info.subtitle
-      )
+      guard let self else { return }
+      if self.isEmail {
+        self.presentInfo(
+          title: Localized.Onboarding.EmailConfirmation.Info.title,
+          subtitle: Localized.Onboarding.EmailConfirmation.Info.subtitle
+        )
+      } else {
+        self.presentInfo(
+          title: Localized.Onboarding.PhoneConfirmation.Info.title,
+          subtitle: Localized.Onboarding.PhoneConfirmation.Info.subtitle
+        )
+      }
     }
   }
 
@@ -63,40 +81,57 @@ public final class OnboardingEmailConfirmationController: UIViewController {
   }
 
   private func setupBindings() {
-    screenView.inputField.textPublisher
-      .sink { [unowned self] in viewModel.didInput($0) }
-      .store(in: &cancellables)
+    screenView
+      .inputField
+      .textPublisher
+      .sink { [unowned self] in
+        viewModel.didInput($0)
+      }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel
+      .statePublisher
       .map(\.status)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.update(status: $0) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.update(status: $0)
+      }.store(in: &cancellables)
 
-    screenView.nextButton
-      .publisher(for: .touchUpInside)
+    viewModel
+      .statePublisher
+      .map(\.didConfirm)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in viewModel.didTapNext() }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        guard $0 == true else { return }
+        if isEmail {
+          navigator.perform(PresentOnboardingPhone())
+        } else {
+          navigator.perform(PresentChatList())
+        }
+      }.store(in: &cancellables)
 
-    viewModel.completionPublisher
+    screenView
+      .nextButton
+      .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] _ in completion(self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        viewModel.didTapNext()
+      }.store(in: &cancellables)
 
-    screenView.resendButton
+    screenView
+      .resendButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in viewModel.didTapResend() }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        viewModel.didTapResend()
+      }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel
+      .statePublisher
       .map(\.resendDebouncer)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
         screenView.resendButton.isEnabled = $0 == 0
-
         if $0 == 0 {
           screenView.resendButton.setTitle(Localized.Profile.Code.resend(""), for: .normal)
         } else {
@@ -140,6 +175,6 @@ public final class OnboardingEmailConfirmationController: UIViewController {
         }
       }.store(in: &drawerCancellables)
 
-    coordinator.toDrawer(drawer, from: self)
+    navigator.perform(PresentDrawer())
   }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
index 2f65daf7..b6554d3d 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
@@ -1,16 +1,18 @@
 import UIKit
 import Shared
 import Combine
+import Navigation
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 import ScrollViewController
 
 public final class OnboardingEmailController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: OnboardingCoordinating
 
-  lazy private var screenView = OnboardingEmailView()
-  lazy private var scrollViewController = ScrollViewController()
+  private lazy var screenView = OnboardingEmailView()
+  private lazy var scrollViewController = ScrollViewController()
 
   private var cancellables = Set<AnyCancellable>()
   private let viewModel = OnboardingEmailViewModel()
@@ -25,12 +27,11 @@ public final class OnboardingEmailController: UIViewController {
   public override func viewDidLoad() {
     super.viewDidLoad()
     navigationItem.backButtonTitle = " "
-
     setupScrollView()
     setupBindings()
-
     screenView.didTapInfo = { [weak self] in
-      self?.presentInfo(
+      guard let self else { return }
+      self.presentInfo(
         title: Localized.Onboarding.Email.Info.title,
         subtitle: Localized.Onboarding.Email.Info.subtitle,
         urlString: "https://links.xx.network/ud"
@@ -41,52 +42,66 @@ public final class OnboardingEmailController: UIViewController {
   private func setupScrollView() {
     addChild(scrollViewController)
     view.addSubview(scrollViewController.view)
-    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.view.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
     scrollViewController.didMove(toParent: self)
     scrollViewController.contentView = screenView
     scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
   }
 
   private func setupBindings() {
-    screenView.inputField.textPublisher
-      .sink { [unowned self] in viewModel.didInput($0) }
-      .store(in: &cancellables)
+    screenView
+      .inputField
+      .textPublisher
+      .sink { [unowned self] in
+        viewModel.didInput($0)
+      }.store(in: &cancellables)
 
-    screenView.inputField.returnPublisher
-      .sink { [unowned self] in screenView.inputField.endEditing(true) }
-      .store(in: &cancellables)
+    screenView
+      .inputField
+      .returnPublisher
+      .sink { [unowned self] in
+        screenView.inputField.endEditing(true)
+      }.store(in: &cancellables)
 
-    viewModel.state
-      .map(\.confirmation)
+    viewModel
+      .statePublisher
       .receive(on: DispatchQueue.main)
-      .compactMap { $0 }
       .sink { [unowned self] in
+        guard let id = $0.confirmationId else { return }
         viewModel.clearUp()
-        coordinator.toEmailConfirmation(with: $0, from: self) { controller in
-          let successModel = OnboardingSuccessModel(
-            title: Localized.Onboarding.Success.Email.title,
-            subtitle: nil,
-            nextController: self.coordinator.toPhone(from:)
+        navigator.perform(
+          PresentOnboardingCode(
+            isEmail: true,
+            content: $0.input,
+            confirmationId: id
           )
-
-          self.coordinator.toSuccess(with: successModel, from: controller)
-        }
+        )
       }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel
+      .statePublisher
       .map(\.status)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.update(status: $0) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.update(status: $0)
+      }.store(in: &cancellables)
 
-    screenView.nextButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in viewModel.didTapNext() }
-      .store(in: &cancellables)
+    screenView
+      .nextButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        viewModel.didTapNext()
+      }.store(in: &cancellables)
 
-    screenView.skipButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in coordinator.toPhone(from: self) }
-      .store(in: &cancellables)
+    screenView
+      .skipButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        navigator.perform(PresentOnboardingPhone())
+      }.store(in: &cancellables)
   }
 
   private func presentInfo(
@@ -128,6 +143,16 @@ public final class OnboardingEmailController: UIViewController {
         }
       }.store(in: &drawerCancellables)
 
-    coordinator.toDrawer(drawer, from: self)
+    navigator.perform(PresentDrawer())
   }
 }
+
+//        coordinator.toEmailConfirmation(with: $0, from: self) { controller in
+//          let successModel = OnboardingSuccessModel(
+//            title: Localized.Onboarding.Success.Email.title,
+//            subtitle: nil,
+//            nextController: self.coordinator.toPhone(from:)
+//          )
+//
+//          self.coordinator.toSuccess(with: successModel, from: controller)
+//        }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingPhoneConfirmationController.swift b/Sources/OnboardingFeature/Controllers/OnboardingPhoneConfirmationController.swift
deleted file mode 100644
index ab9cbca2..00000000
--- a/Sources/OnboardingFeature/Controllers/OnboardingPhoneConfirmationController.swift
+++ /dev/null
@@ -1,145 +0,0 @@
-import UIKit
-import Shared
-import Models
-import Combine
-import DrawerFeature
-import DependencyInjection
-import ScrollViewController
-
-public final class OnboardingPhoneConfirmationController: UIViewController {
-  @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: OnboardingCoordinating
-
-  lazy private var screenView = OnboardingPhoneConfirmationView()
-  lazy private var scrollViewController = ScrollViewController()
-
-  private var cancellables = Set<AnyCancellable>()
-  private let completion: (UIViewController) -> Void
-  private var drawerCancellables = Set<AnyCancellable>()
-  private let viewModel: OnboardingPhoneConfirmationViewModel
-
-  public init(
-    _ confirmation: AttributeConfirmation,
-    _ completion: @escaping (UIViewController) -> Void
-  ) {
-    self.completion = completion
-    self.viewModel = OnboardingPhoneConfirmationViewModel(confirmation)
-    super.init(nibName: nil, bundle: nil)
-  }
-
-  required init?(coder: NSCoder) { nil }
-
-  public override func viewWillAppear(_ animated: Bool) {
-    super.viewWillAppear(animated)
-    navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.darkContent)
-    navigationController?.navigationBar.customize(translucent: true)
-  }
-
-  public override func viewDidLoad() {
-    super.viewDidLoad()
-    setupScrollView()
-    setupBindings()
-
-    screenView.setupSubtitle(
-      Localized.Onboarding.PhoneConfirmation.subtitle(viewModel.confirmation.content)
-    )
-
-    screenView.didTapInfo = { [weak self] in
-      self?.presentInfo(
-        title: Localized.Onboarding.PhoneConfirmation.Info.title,
-        subtitle: Localized.Onboarding.PhoneConfirmation.Info.subtitle
-      )
-    }
-  }
-
-  private func setupScrollView() {
-    addChild(scrollViewController)
-    view.addSubview(scrollViewController.view)
-    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-    scrollViewController.didMove(toParent: self)
-    scrollViewController.contentView = screenView
-    scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
-  }
-
-  private func setupBindings() {
-    screenView.inputField.textPublisher
-      .sink { [unowned self] in viewModel.didInput($0) }
-      .store(in: &cancellables)
-
-    viewModel.state
-      .map(\.status)
-      .removeDuplicates()
-      .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.update(status: $0) }
-      .store(in: &cancellables)
-
-    screenView.nextButton
-      .publisher(for: .touchUpInside)
-      .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in viewModel.didTapNext() }
-      .store(in: &cancellables)
-
-    viewModel.completionPublisher
-      .receive(on: DispatchQueue.main)
-      .sink { [unowned self] _ in completion(self) }
-      .store(in: &cancellables)
-
-    screenView.resendButton
-      .publisher(for: .touchUpInside)
-      .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in viewModel.didTapResend() }
-      .store(in: &cancellables)
-
-    viewModel.state
-      .map(\.resendDebouncer)
-      .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in
-        screenView.resendButton.isEnabled = $0 == 0
-
-        if $0 == 0 {
-          screenView.resendButton.setTitle(Localized.Profile.Code.resend(""), for: .normal)
-        } else {
-          screenView.resendButton.setTitle(Localized.Profile.Code.resend("(\($0))"), for: .disabled)
-        }
-      }.store(in: &cancellables)
-  }
-
-  private func presentInfo(title: String, subtitle: String) {
-    let actionButton = CapsuleButton()
-    actionButton.set(style: .seeThrough, title: Localized.Settings.InfoDrawer.action)
-
-    let drawer = DrawerController(with: [
-      DrawerText(
-        font: Fonts.Mulish.bold.font(size: 26.0),
-        text: title,
-        color: Asset.neutralActive.color,
-        alignment: .left,
-        spacingAfter: 19
-      ),
-      DrawerText(
-        font: Fonts.Mulish.regular.font(size: 16.0),
-        text: subtitle,
-        color: Asset.neutralBody.color,
-        alignment: .left,
-        lineHeightMultiple: 1.1,
-        spacingAfter: 37
-      ),
-      DrawerStack(views: [
-        actionButton,
-        FlexibleSpace()
-      ])
-    ])
-
-    actionButton.publisher(for: .touchUpInside)
-      .receive(on: DispatchQueue.main)
-      .sink {
-        drawer.dismiss(animated: true) { [weak self] in
-          guard let self = self else { return }
-          self.drawerCancellables.removeAll()
-        }
-      }.store(in: &drawerCancellables)
-
-    coordinator.toDrawer(drawer, from: self)
-  }
-}
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
index e593fbd2..dc9df4ea 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
@@ -1,16 +1,18 @@
 import UIKit
 import Shared
 import Combine
+import Navigation
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 import ScrollViewController
 
 public final class OnboardingPhoneController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: OnboardingCoordinating
 
-  lazy private var screenView = OnboardingPhoneView()
-  lazy private var scrollViewController = ScrollViewController()
+  private lazy var screenView = OnboardingPhoneView()
+  private lazy var scrollViewController = ScrollViewController()
 
   private var cancellables = Set<AnyCancellable>()
   private let viewModel = OnboardingPhoneViewModel()
@@ -25,12 +27,11 @@ public final class OnboardingPhoneController: UIViewController {
   public override func viewDidLoad() {
     super.viewDidLoad()
     navigationItem.backButtonTitle = " "
-
     setupScrollView()
     setupBindings()
-
     screenView.didTapInfo = { [weak self] in
-      self?.presentInfo(
+      guard let self else { return }
+      self.presentInfo(
         title: Localized.Onboarding.Phone.Info.title,
         subtitle: Localized.Onboarding.Phone.Info.subtitle,
         urlString: "https://links.xx.network/ud"
@@ -41,58 +42,78 @@ public final class OnboardingPhoneController: UIViewController {
   private func setupScrollView() {
     addChild(scrollViewController)
     view.addSubview(scrollViewController.view)
-    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.view.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
     scrollViewController.didMove(toParent: self)
     scrollViewController.contentView = screenView
     scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
   }
 
   private func setupBindings() {
-    screenView.inputField.textPublisher
-      .sink { [unowned self] in viewModel.didInput($0) }
-      .store(in: &cancellables)
+    screenView
+      .inputField
+      .textPublisher
+      .sink { [unowned self] in
+        viewModel.didInput($0)
+      }.store(in: &cancellables)
 
-    screenView.inputField.returnPublisher
-      .sink { [unowned self] in screenView.inputField.endEditing(true) }
-      .store(in: &cancellables)
+    screenView
+      .inputField
+      .returnPublisher
+      .sink { [unowned self] in
+        screenView.inputField.endEditing(true)
+      }.store(in: &cancellables)
 
-    viewModel.state.map(\.status)
+    viewModel
+      .statePublisher
+      .map(\.status)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.update(status: $0) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.update(status: $0)
+      }.store(in: &cancellables)
 
-    screenView.nextButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in viewModel.didTapNext() }
-      .store(in: &cancellables)
+    screenView
+      .nextButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        viewModel.didTapNext()
+      }.store(in: &cancellables)
 
-    screenView.skipButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in coordinator.toChats(from: self) }
-      .store(in: &cancellables)
+    screenView
+      .skipButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        navigator.perform(PresentChatList())
+      }.store(in: &cancellables)
 
-    screenView.inputField.codePublisher
+    screenView
+      .inputField
+      .codePublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        coordinator.toCountries(from: self) { self.viewModel.didChooseCountry($0) }
+        navigator.perform(PresentCountryList())
       }.store(in: &cancellables)
 
-    viewModel.state.map(\.confirmation)
+    viewModel
+      .statePublisher
       .receive(on: DispatchQueue.main)
-      .compactMap { $0 }
       .sink { [unowned self] in
+        guard let id = $0.confirmationId, let content = $0.content else { return }
         viewModel.clearUp()
-        coordinator.toPhoneConfirmation(with: $0, from: self) { controller in
-          let successModel = OnboardingSuccessModel(
-            title: Localized.Onboarding.Success.Phone.title,
-            subtitle: nil,
-            nextController: self.coordinator.toChats(from:)
+        navigator.perform(
+          PresentOnboardingCode(
+            isEmail: false,
+            content: content,
+            confirmationId: id
           )
-
-          self.coordinator.toSuccess(with: successModel, from: controller)
-        }
+        )
       }.store(in: &cancellables)
 
-    viewModel.state.map(\.country)
+    viewModel
+      .statePublisher
+      .map(\.country)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
@@ -140,6 +161,16 @@ public final class OnboardingPhoneController: UIViewController {
         }
       }.store(in: &drawerCancellables)
 
-    coordinator.toDrawer(drawer, from: self)
+    navigator.perform(PresentDrawer())
   }
 }
+
+//        coordinator.toPhoneConfirmation(with: $0, from: self) { controller in
+//          let successModel = OnboardingSuccessModel(
+//            title: Localized.Onboarding.Success.Phone.title,
+//            subtitle: nil,
+//            nextController: self.coordinator.toChats(from:)
+//          )
+//
+//          self.coordinator.toSuccess(with: successModel, from: controller)
+//        }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
index 23ff5f77..ac5df16e 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
@@ -1,49 +1,52 @@
 import UIKit
 import Combine
+import Navigation
+import XXNavigation
 import DependencyInjection
 
 public final class OnboardingStartController: UIViewController {
-    @Dependency private var coordinator: OnboardingCoordinating
-
-    lazy private var screenView = OnboardingStartView()
-
-    private var cancellables = Set<AnyCancellable>()
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        navigationController?.navigationBar.customize(translucent: true)
-    }
-
-    public override func viewDidLayoutSubviews() {
-        super.viewDidLayoutSubviews()
-
-        let gradient = CAGradientLayer()
-        gradient.colors = [
-            UIColor(red: 122/255, green: 235/255, blue: 239/255, alpha: 1).cgColor,
-            UIColor(red: 56/255, green: 204/255, blue: 232/255, alpha: 1).cgColor,
-            UIColor(red: 63/255, green: 186/255, blue: 253/255, alpha: 1).cgColor,
-            UIColor(red: 98/255, green: 163/255, blue: 255/255, alpha: 1).cgColor
-        ]
-
-        gradient.startPoint = CGPoint(x: 0, y: 0)
-        gradient.endPoint = CGPoint(x: 1, y: 1)
-
-        gradient.frame = screenView.bounds
-        screenView.layer.insertSublayer(gradient, at: 0)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        screenView
-        .startButton
-        .publisher(for: .touchUpInside)
-            .sink { [unowned self] in coordinator.toTerms(from: self) }
-            .store(in: &cancellables)
-    }
+  @Dependency var navigator: Navigator
+
+  private lazy var screenView = OnboardingStartView()
+
+  private var cancellables = Set<AnyCancellable>()
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    navigationController?.navigationBar.customize(translucent: true)
+  }
+
+  public override func viewDidLayoutSubviews() {
+    super.viewDidLayoutSubviews()
+
+    let gradient = CAGradientLayer()
+    gradient.colors = [
+      UIColor(red: 122/255, green: 235/255, blue: 239/255, alpha: 1).cgColor,
+      UIColor(red: 56/255, green: 204/255, blue: 232/255, alpha: 1).cgColor,
+      UIColor(red: 63/255, green: 186/255, blue: 253/255, alpha: 1).cgColor,
+      UIColor(red: 98/255, green: 163/255, blue: 255/255, alpha: 1).cgColor
+    ]
+
+    gradient.startPoint = CGPoint(x: 0, y: 0)
+    gradient.endPoint = CGPoint(x: 1, y: 1)
+
+    gradient.frame = screenView.bounds
+    screenView.layer.insertSublayer(gradient, at: 0)
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+
+    screenView
+      .startButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        navigator.perform(PresentTermsAndConditions())
+      }.store(in: &cancellables)
+  }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingSuccessController.swift b/Sources/OnboardingFeature/Controllers/OnboardingSuccessController.swift
deleted file mode 100644
index d072efad..00000000
--- a/Sources/OnboardingFeature/Controllers/OnboardingSuccessController.swift
+++ /dev/null
@@ -1,67 +0,0 @@
-import UIKit
-import Models
-import Shared
-import Combine
-import Countries
-import DependencyInjection
-
-public struct OnboardingSuccessModel {
-    var title: String
-    var subtitle: String?
-    var nextController: (UIViewController) -> Void
-}
-
-public final class OnboardingSuccessController: UIViewController {
-    @Dependency private var coordinator: OnboardingCoordinating
-
-    lazy private var screenView = OnboardingSuccessView()
-    private var cancellables = Set<AnyCancellable>()
-
-    private var model: OnboardingSuccessModel
-
-    public override func loadView() {
-        view = screenView
-    }
-
-    public init(_ model: OnboardingSuccessModel) {
-        self.model = model
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationController?.navigationBar.customize(translucent: true)
-    }
-
-    public override func viewDidLayoutSubviews() {
-        super.viewDidLayoutSubviews()
-
-        let gradient = CAGradientLayer()
-        gradient.colors = [
-            UIColor(red: 122/255, green: 235/255, blue: 239/255, alpha: 1).cgColor,
-            UIColor(red: 56/255, green: 204/255, blue: 232/255, alpha: 1).cgColor,
-            UIColor(red: 63/255, green: 186/255, blue: 253/255, alpha: 1).cgColor,
-            UIColor(red: 98/255, green: 163/255, blue: 255/255, alpha: 1).cgColor
-        ]
-
-        gradient.startPoint = CGPoint(x: 0, y: 0)
-        gradient.endPoint = CGPoint(x: 1, y: 1)
-
-        gradient.frame = screenView.bounds
-        screenView.layer.insertSublayer(gradient, at: 0)
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        screenView.setTitle(model.title)
-        screenView.setSubtitle(model.subtitle)
-
-        screenView.nextButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in model.nextController(self) }
-            .store(in: &cancellables)
-    }
-}
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
index 566cc2ed..5939dab8 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
@@ -1,16 +1,18 @@
 import UIKit
 import Shared
 import Combine
+import Navigation
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 import ScrollViewController
 
 public final class OnboardingUsernameController: UIViewController {
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: OnboardingCoordinating
 
-  lazy private var screenView = OnboardingUsernameView()
-  lazy private var scrollViewController = ScrollViewController()
+  private lazy var screenView = OnboardingUsernameView()
+  private lazy var scrollViewController = ScrollViewController()
 
   private var cancellables = Set<AnyCancellable>()
   private let viewModel = OnboardingUsernameViewModel()
@@ -27,9 +29,9 @@ public final class OnboardingUsernameController: UIViewController {
     super.viewDidLoad()
     setupScrollView()
     setupBindings()
-
     screenView.didTapInfo = { [weak self] in
-      self?.presentInfo(
+      guard let self else { return }
+      self.presentInfo(
         title: Localized.Onboarding.Username.Info.title,
         subtitle: Localized.Onboarding.Username.Info.subtitle,
         urlString: "https://links.xx.network/ud"
@@ -39,28 +41,37 @@ public final class OnboardingUsernameController: UIViewController {
 
   private func setupScrollView() {
     scrollViewController.scrollView.backgroundColor = .white
-
     addChild(scrollViewController)
     view.addSubview(scrollViewController.view)
-    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.view.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
     scrollViewController.didMove(toParent: self)
     scrollViewController.contentView = screenView
   }
 
   private func setupBindings() {
-    screenView.inputField.textPublisher
+    screenView
+      .inputField
+      .textPublisher
       .removeDuplicates()
       .compactMap { $0 }
-      .sink { [unowned self] in viewModel.didInput($0) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        viewModel.didInput($0)
+      }.store(in: &cancellables)
 
-    screenView.restoreView.restoreButton
+    screenView
+      .restoreView
+      .restoreButton
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toRestoreList(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentRestoreList())
+      }.store(in: &cancellables)
 
-    screenView.inputField.returnPublisher
+    screenView
+      .inputField
+      .returnPublisher
       .sink { [unowned self] in
         if screenView.nextButton.isEnabled {
           viewModel.didTapRegister()
@@ -69,21 +80,29 @@ public final class OnboardingUsernameController: UIViewController {
         }
       }.store(in: &cancellables)
 
-    screenView.nextButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in viewModel.didTapRegister() }
-      .store(in: &cancellables)
+    screenView
+      .nextButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        viewModel.didTapRegister()
+      }.store(in: &cancellables)
 
-    viewModel.greenPublisher
+    viewModel
+      .statePublisher
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in coordinator.toWelcome(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        guard $0.didConfirm == true else { return }
+        navigator.perform(PresentOnboardingWelcome())
+      }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel
+      .statePublisher
       .map(\.status)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.update(status: $0) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.update(status: $0)
+      }.store(in: &cancellables)
   }
 
   private func presentInfo(
@@ -125,6 +144,6 @@ public final class OnboardingUsernameController: UIViewController {
         }
       }.store(in: &drawerCancellables)
 
-    coordinator.toDrawer(drawer, from: self)
+    navigator.perform(PresentDrawer())
   }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
index 9bed33d2..c979f812 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
@@ -2,16 +2,17 @@ import UIKit
 import Shared
 import Combine
 import Defaults
+import Navigation
+import XXNavigation
 import DrawerFeature
 import DependencyInjection
 
 public final class OnboardingWelcomeController: UIViewController {
-  @KeyObject(.username, defaultValue: "") var username: String
-
+  @Dependency var navigator: Navigator
   @Dependency var barStylist: StatusBarStylist
-  @Dependency var coordinator: OnboardingCoordinating
+  @KeyObject(.username, defaultValue: "") var username: String
 
-  lazy private var screenView = OnboardingWelcomeView()
+  private lazy var screenView = OnboardingWelcomeView()
 
   private var cancellables = Set<AnyCancellable>()
   private var drawerCancellables = Set<AnyCancellable>()
@@ -43,12 +44,14 @@ public final class OnboardingWelcomeController: UIViewController {
 
   private func setupBindings() {
     screenView.continueButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in coordinator.toEmail(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentOnboardingEmail())
+      }.store(in: &cancellables)
 
     screenView.skipButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in coordinator.toChats(from: self) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        navigator.perform(PresentChatList())
+      }.store(in: &cancellables)
   }
 
   private func presentInfo(
@@ -90,6 +93,6 @@ public final class OnboardingWelcomeController: UIViewController {
         }
       }.store(in: &drawerCancellables)
 
-    coordinator.toDrawer(drawer, from: self)
+    navigator.perform(PresentDrawer())
   }
 }
diff --git a/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift b/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift
deleted file mode 100644
index dd26a3f6..00000000
--- a/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift
+++ /dev/null
@@ -1,153 +0,0 @@
-import UIKit
-import Shared
-import Models
-import Countries
-import Presentation
-
-public typealias AttributeControllerClosure = (UIViewController) -> Void
-
-public protocol OnboardingCoordinating {
-    func toChats(from: UIViewController)
-    func toEmail(from: UIViewController)
-    func toPhone(from: UIViewController)
-    func toTerms(from: UIViewController)
-    func toWelcome(from: UIViewController)
-    func toUsername(from: UIViewController)
-    func toRestoreList(from: UIViewController)
-    func toDrawer(_: UIViewController, from: UIViewController)
-    func toSuccess(with: OnboardingSuccessModel, from: UIViewController)
-
-    func toEmailConfirmation(
-        with: AttributeConfirmation,
-        from: UIViewController,
-        completion: @escaping (UIViewController) -> Void
-    )
-
-    func toPhoneConfirmation(
-        with: AttributeConfirmation,
-        from: UIViewController,
-        completion: @escaping (UIViewController) -> Void
-    )
-
-    func toCountries(
-        from: UIViewController,
-        _ onChoose: @escaping (Country) -> Void
-    )
-}
-
-public struct OnboardingCoordinator: OnboardingCoordinating {
-    var pushPresenter: Presenting = PushPresenter()
-    var bottomPresenter: Presenting = BottomPresenter()
-    var replacePresenter: Presenting = ReplacePresenter()
-
-    var emailFactory: () -> UIViewController
-    var phoneFactory: () -> UIViewController
-    var searchFactory: (String?) -> UIViewController
-    var welcomeFactory: () -> UIViewController
-    var chatListFactory: () -> UIViewController
-    var termsFactory: () -> UIViewController
-    var usernameFactory: () -> UIViewController
-    var restoreListFactory: () -> UIViewController
-    var successFactory: (OnboardingSuccessModel) -> UIViewController
-    var countriesFactory: (@escaping (Country) -> Void) -> UIViewController
-    var phoneConfirmationFactory: (AttributeConfirmation, @escaping AttributeControllerClosure) -> UIViewController
-    var emailConfirmationFactory: (AttributeConfirmation, @escaping AttributeControllerClosure) -> UIViewController
-
-    public init(
-        emailFactory: @escaping () -> UIViewController,
-        phoneFactory: @escaping () -> UIViewController,
-        searchFactory: @escaping (String?) -> UIViewController,
-        welcomeFactory: @escaping () -> UIViewController,
-        chatListFactory: @escaping () -> UIViewController,
-        termsFactory: @escaping () -> UIViewController,
-        usernameFactory: @escaping () -> UIViewController,
-        restoreListFactory: @escaping () -> UIViewController,
-        successFactory: @escaping (OnboardingSuccessModel) -> UIViewController,
-        countriesFactory: @escaping (@escaping (Country) -> Void) -> UIViewController,
-        phoneConfirmationFactory: @escaping (AttributeConfirmation, @escaping AttributeControllerClosure) -> UIViewController,
-        emailConfirmationFactory: @escaping (AttributeConfirmation, @escaping AttributeControllerClosure) -> UIViewController
-    ) {
-        self.emailFactory = emailFactory
-        self.termsFactory = termsFactory
-        self.phoneFactory = phoneFactory
-        self.searchFactory = searchFactory
-        self.welcomeFactory = welcomeFactory
-        self.successFactory = successFactory
-        self.usernameFactory = usernameFactory
-        self.chatListFactory = chatListFactory
-        self.countriesFactory = countriesFactory
-        self.restoreListFactory = restoreListFactory
-        self.phoneConfirmationFactory = phoneConfirmationFactory
-        self.emailConfirmationFactory = emailConfirmationFactory
-    }
-}
-
-public extension OnboardingCoordinator {
-    func toTerms(from parent: UIViewController) {
-        let screen = termsFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toEmail(from parent: UIViewController) {
-        let screen = emailFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toPhone(from parent: UIViewController) {
-        let screen = phoneFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toWelcome(from parent: UIViewController) {
-        let screen = welcomeFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toRestoreList(from parent: UIViewController) {
-        let screen = restoreListFactory()
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toSuccess(with model: OnboardingSuccessModel, from parent: UIViewController) {
-        let screen = successFactory(model)
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toUsername(from parent: UIViewController) {
-        let screen = usernameFactory()
-        replacePresenter.present(screen, from: parent)
-    }
-
-    func toDrawer(_ drawer: UIViewController, from parent: UIViewController) {
-        bottomPresenter.present(drawer, from: parent)
-    }
-
-    func toChats(from parent: UIViewController) {
-        let searchScreen = searchFactory(nil)
-        let chatListScreen = chatListFactory()
-        replacePresenter.present(chatListScreen, searchScreen, from: parent)
-    }
-
-    func toCountries(from parent: UIViewController, _ onChoose: @escaping (Country) -> Void) {
-        let screen = countriesFactory(onChoose)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toEmailConfirmation(
-        with confirmation: AttributeConfirmation,
-        from parent: UIViewController,
-        completion: @escaping (UIViewController) -> Void
-    ) {
-        let screen = emailConfirmationFactory(confirmation, completion)
-        pushPresenter.present(screen, from: parent)
-    }
-
-    func toPhoneConfirmation(
-        with confirmation: AttributeConfirmation,
-        from parent: UIViewController,
-        completion: @escaping (UIViewController) -> Void
-    ) {
-        let screen = phoneConfirmationFactory(confirmation, completion)
-        pushPresenter.present(screen, from: parent)
-    }
-}
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift
new file mode 100644
index 00000000..47fde15f
--- /dev/null
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift
@@ -0,0 +1,96 @@
+import Shared
+import Combine
+import Defaults
+import XXClient
+import InputField
+import Foundation
+import CombineSchedulers
+import XXMessengerClient
+import DependencyInjection
+
+final class OnboardingCodeViewModel {
+  struct ViewState: Equatable {
+    var input: String = ""
+    var status: InputField.ValidationStatus = .unknown(nil)
+    var resendDebouncer: Int = 0
+    var didConfirm: Bool = false
+  }
+
+  var statePublisher: AnyPublisher<ViewState, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
+
+  @Dependency var messenger: Messenger
+  @Dependency var hudController: HUDController
+  @KeyObject(.email, defaultValue: nil) var email: String?
+  @KeyObject(.phone, defaultValue: nil) var phone: String?
+
+  private var timer: Timer?
+  private let isEmail: Bool
+  private let content: String
+  private let confirmationId: String
+  private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
+  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
+
+  init(
+    isEmail: Bool,
+    content: String,
+    confirmationId: String
+  ) {
+    self.isEmail = isEmail
+    self.content = content
+    self.confirmationId = confirmationId
+    didTapResend()
+  }
+
+  func didInput(_ string: String) {
+    stateSubject.value.input = string
+    validate()
+  }
+
+  func didTapResend() {
+    guard stateSubject.value.resendDebouncer == 0 else { return }
+    stateSubject.value.resendDebouncer = 60
+    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {  [weak self] in
+      guard let self = self, self.stateSubject.value.resendDebouncer > 0 else {
+        $0.invalidate()
+        return
+      }
+      self.stateSubject.value.resendDebouncer -= 1
+    }
+  }
+
+  func didTapNext() {
+    hudController.show()
+    scheduler.schedule { [weak self] in
+      guard let self else { return }
+      do {
+        try self.messenger.ud.get()!.confirmFact(
+          confirmationId: self.confirmationId,
+          code: self.stateSubject.value.input
+        )
+        if self.isEmail {
+          self.email = self.content
+        } else {
+          self.phone = self.content
+        }
+        self.timer?.invalidate()
+        self.hudController.dismiss()
+        self.stateSubject.value.didConfirm = true
+      } catch {
+        self.hudController.dismiss()
+        let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+        self.stateSubject.value.status = .invalid(xxError)
+      }
+    }
+  }
+
+  private func validate() {
+    switch Validator.code.validate(stateSubject.value.input) {
+    case .success:
+      stateSubject.value.status = .valid(nil)
+    case .failure(let error):
+      stateSubject.value.status = .invalid(error)
+    }
+  }
+}
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingEmailConfirmationViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingEmailConfirmationViewModel.swift
deleted file mode 100644
index d008997d..00000000
--- a/Sources/OnboardingFeature/ViewModels/OnboardingEmailConfirmationViewModel.swift
+++ /dev/null
@@ -1,92 +0,0 @@
-import UIKit
-import Models
-import Shared
-import Combine
-import Defaults
-import InputField
-import XXClient
-import CombineSchedulers
-import DependencyInjection
-import XXMessengerClient
-
-struct OnboardingEmailConfirmationViewState: Equatable {
-  var input: String = ""
-  var status: InputField.ValidationStatus = .unknown(nil)
-  var resendDebouncer: Int = 0
-}
-
-final class OnboardingEmailConfirmationViewModel {
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
-  
-  @KeyObject(.email, defaultValue: nil) var email: String?
-  
-  var completionPublisher: AnyPublisher<AttributeConfirmation, Never> { completionRelay.eraseToAnyPublisher() }
-  private let completionRelay = PassthroughSubject<AttributeConfirmation, Never>()
-  
-  var timer: Timer?
-  let confirmation: AttributeConfirmation
-  
-  var state: AnyPublisher<OnboardingEmailConfirmationViewState, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<OnboardingEmailConfirmationViewState, Never>(.init())
-  
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
-  
-  init(_ confirmation: AttributeConfirmation) {
-    self.confirmation = confirmation
-    didTapResend()
-  }
-  
-  func didInput(_ string: String) {
-    stateRelay.value.input = string
-    validate()
-  }
-  
-  func didTapResend() {
-    guard stateRelay.value.resendDebouncer == 0 else { return }
-    
-    stateRelay.value.resendDebouncer = 60
-    
-    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {  [weak self] in
-      guard let self = self, self.stateRelay.value.resendDebouncer > 0 else {
-        $0.invalidate()
-        return
-      }
-      
-      self.stateRelay.value.resendDebouncer -= 1
-    }
-  }
-  
-  func didTapNext() {
-    hudController.show()
-    
-    backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
-      
-      do {
-        try self.messenger.ud.get()!.confirmFact(
-          confirmationId: self.confirmation.confirmationId!,
-          code: self.stateRelay.value.input
-        )
-        
-        self.email = self.confirmation.content
-        
-        self.timer?.invalidate()
-        self.hudController.dismiss()
-        self.completionRelay.send(self.confirmation)
-      } catch {
-        let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
-      }
-    }
-  }
-  
-  private func validate() {
-    switch Validator.code.validate(stateRelay.value.input) {
-    case .success:
-      stateRelay.value.status = .valid(nil)
-    case .failure(let error):
-      stateRelay.value.status = .invalid(error)
-    }
-  }
-}
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
index 6e1159ae..ad07d4a7 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
@@ -1,70 +1,62 @@
-import UIKit
-import Models
 import Shared
 import Combine
-import Defaults
 import XXClient
 import InputField
+import Foundation
 import CombineSchedulers
 import XXMessengerClient
 import DependencyInjection
 
-struct OnboardingEmailViewState: Equatable {
-  var input: String = ""
-  var confirmation: AttributeConfirmation? = nil
-  var status: InputField.ValidationStatus = .unknown(nil)
-}
-
 final class OnboardingEmailViewModel {
+  struct ViewState: Equatable {
+    var input: String = ""
+    var confirmationId: String?
+    var status: InputField.ValidationStatus = .unknown(nil)
+  }
+
   @Dependency var messenger: Messenger
   @Dependency var hudController: HUDController
-  
-  @KeyObject(.pushNotifications, defaultValue: false) private var pushNotifications
-  
-  var state: AnyPublisher<OnboardingEmailViewState, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<OnboardingEmailViewState, Never>(.init())
-  
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
-  
+
+  var statePublisher: AnyPublisher<ViewState, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
+
+  private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
+  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
+
   func clearUp() {
-    stateRelay.value.confirmation = nil
+    stateSubject.value.confirmationId = nil
   }
-  
+
   func didInput(_ string: String) {
-    stateRelay.value.input = string
+    stateSubject.value.input = string
     validate()
   }
-  
+
   func didTapNext() {
     hudController.show()
-    
-    backgroundScheduler.schedule { [weak self] in
+    scheduler.schedule { [weak self] in
       guard let self = self else { return }
-      
       do {
         let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
-          .init(type: .email, value: self.stateRelay.value.input)
+          .init(type: .email, value: self.stateSubject.value.input)
         )
-        
         self.hudController.dismiss()
-        self.stateRelay.value.confirmation = .init(
-          content: self.stateRelay.value.input,
-          isEmail: true,
-          confirmationId: confirmationId
-        )
+        self.stateSubject.value.confirmationId = confirmationId
       } catch {
+        self.hudController.dismiss()
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
+        self.stateSubject.value.status = .invalid(xxError)
       }
     }
   }
-  
+
   private func validate() {
-    switch Validator.email.validate(stateRelay.value.input) {
+    switch Validator.email.validate(stateSubject.value.input) {
     case .success:
-      stateRelay.value.status = .valid(nil)
+      stateSubject.value.status = .valid(nil)
     case .failure(let error):
-      stateRelay.value.status = .invalid(error)
+      stateSubject.value.status = .invalid(error)
     }
   }
 }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneConfirmationViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneConfirmationViewModel.swift
deleted file mode 100644
index 387993d5..00000000
--- a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneConfirmationViewModel.swift
+++ /dev/null
@@ -1,92 +0,0 @@
-import UIKit
-import Models
-import Shared
-import Combine
-import Defaults
-import InputField
-import XXClient
-import CombineSchedulers
-import XXMessengerClient
-import DependencyInjection
-
-struct OnboardingPhoneConfirmationViewState: Equatable {
-  var input: String = ""
-  var status: InputField.ValidationStatus = .unknown(nil)
-  var resendDebouncer: Int = 0
-}
-
-final class OnboardingPhoneConfirmationViewModel {
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
-  
-  @KeyObject(.phone, defaultValue: nil) var phone: String?
-  
-  var completionPublisher: AnyPublisher<AttributeConfirmation, Never> { completionRelay.eraseToAnyPublisher() }
-  private let completionRelay = PassthroughSubject<AttributeConfirmation, Never>()
-  
-  var timer: Timer?
-  let confirmation: AttributeConfirmation
-  
-  var state: AnyPublisher<OnboardingPhoneConfirmationViewState, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<OnboardingPhoneConfirmationViewState, Never>(.init())
-  
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
-  
-  init(_ confirmation: AttributeConfirmation) {
-    self.confirmation = confirmation
-    didTapResend()
-  }
-  
-  func didInput(_ string: String) {
-    stateRelay.value.input = string
-    validate()
-  }
-  
-  func didTapResend() {
-    guard stateRelay.value.resendDebouncer == 0 else { return }
-    
-    stateRelay.value.resendDebouncer = 60
-    
-    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {  [weak self] in
-      guard let self = self, self.stateRelay.value.resendDebouncer > 0 else {
-        $0.invalidate()
-        return
-      }
-      
-      self.stateRelay.value.resendDebouncer -= 1
-    }
-  }
-  
-  func didTapNext() {
-    hudController.show()
-    
-    backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
-      
-      do {
-        try self.messenger.ud.get()!.confirmFact(
-          confirmationId: self.confirmation.confirmationId!,
-          code: self.stateRelay.value.input
-        )
-        
-        self.phone = self.confirmation.content
-        
-        self.timer?.invalidate()
-        self.hudController.dismiss()
-        self.completionRelay.send(self.confirmation)
-      } catch {
-        let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
-      }
-    }
-  }
-  
-  private func validate() {
-    switch Validator.code.validate(stateRelay.value.input) {
-    case .success:
-      stateRelay.value.status = .valid(nil)
-    case .failure(let error):
-      stateRelay.value.status = .invalid(error)
-    }
-  }
-}
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
index 346a7bf1..435d12a9 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
@@ -1,5 +1,4 @@
 import Shared
-import Models
 import Combine
 import XXClient
 import Countries
@@ -9,71 +8,65 @@ import CombineSchedulers
 import XXMessengerClient
 import DependencyInjection
 
-struct OnboardingPhoneViewState: Equatable {
-  var input: String = ""
-  var confirmation: AttributeConfirmation?
-  var status: InputField.ValidationStatus = .unknown(nil)
-  var country: Country = .fromMyPhone()
-}
-
 final class OnboardingPhoneViewModel {
+  struct ViewState: Equatable {
+    var input: String = ""
+    var content: String?
+    var confirmationId: String?
+    var status: InputField.ValidationStatus = .unknown(nil)
+    var country: Country = .fromMyPhone()
+  }
+
   @Dependency var messenger: Messenger
   @Dependency var hudController: HUDController
-  
-  var state: AnyPublisher<OnboardingPhoneViewState, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<OnboardingPhoneViewState, Never>(.init())
-  
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
+
+  var statePublisher: AnyPublisher<ViewState, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
+
+  private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
+  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
   func clearUp() {
-    stateRelay.value.confirmation = nil
+    stateSubject.value.confirmationId = nil
   }
-  
+
   func didInput(_ string: String) {
-    stateRelay.value.input = string
+    stateSubject.value.input = string
     validate()
   }
-  
+
   func didChooseCountry(_ country: Country) {
-    stateRelay.value.country = country
+    stateSubject.value.country = country
     validate()
   }
-  
-  func didGoForward() {
-    stateRelay.value.confirmation = nil
-  }
-  
+
   func didTapNext() {
     hudController.show()
-    
-    backgroundScheduler.schedule { [weak self] in
+    scheduler.schedule { [weak self] in
       guard let self = self else { return }
-      
-      let content = "\(self.stateRelay.value.input)\(self.stateRelay.value.country.code)"
-      
+      let content = "\(self.stateSubject.value.input)\(self.stateSubject.value.country.code)"
       do {
         let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
           .init(type: .phone, value: content)
         )
-        
         self.hudController.dismiss()
-        self.stateRelay.value.confirmation = .init(
-          content: content,
-          confirmationId: confirmationId
-        )
+        self.stateSubject.value.content = content
+        self.stateSubject.value.confirmationId = confirmationId
       } catch {
+        self.hudController.dismiss()
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
+        self.stateSubject.value.status = .invalid(xxError)
       }
     }
   }
-  
+
   private func validate() {
-    switch Validator.phone.validate((stateRelay.value.country.regex, stateRelay.value.input)) {
+    switch Validator.phone.validate((stateSubject.value.country.regex, stateSubject.value.input)) {
     case .success:
-      stateRelay.value.status = .valid(nil)
+      stateSubject.value.status = .valid(nil)
     case .failure(let error):
-      stateRelay.value.status = .invalid(error)
+      stateSubject.value.status = .invalid(error)
     }
   }
 }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift
index 1483525b..06a5f5fa 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift
@@ -1,5 +1,4 @@
 import Shared
-import Models
 import Combine
 import Defaults
 import XXModels
@@ -10,53 +9,47 @@ import XXMessengerClient
 import CombineSchedulers
 import DependencyInjection
 
-struct OnboardingUsernameViewState: Equatable {
-  var input: String = ""
-  var status: InputField.ValidationStatus = .unknown(nil)
-}
-
 final class OnboardingUsernameViewModel {
+  struct ViewState: Equatable {
+    var input: String = ""
+    var status: InputField.ValidationStatus = .unknown(nil)
+    var didConfirm: Bool = false
+  }
+
   @Dependency var database: Database
   @Dependency var messenger: Messenger
   @Dependency var hudController: HUDController
-  
   @KeyObject(.username, defaultValue: "") var username: String
-  
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue>
-  = DispatchQueue.global().eraseToAnyScheduler()
-  
-  var greenPublisher: AnyPublisher<Void, Never> { greenRelay.eraseToAnyPublisher() }
-  private let greenRelay = PassthroughSubject<Void, Never>()
 
-  var state: AnyPublisher<OnboardingUsernameViewState, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<OnboardingUsernameViewState, Never>(.init())
-  
+  var statePublisher: AnyPublisher<ViewState, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
+
+  private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
+  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
+
   func didInput(_ string: String) {
-    stateRelay.value.input = string.trimmingCharacters(in: .whitespacesAndNewlines)
-    
-    switch Validator.username.validate(stateRelay.value.input) {
+    stateSubject.value.input = string.trimmingCharacters(in: .whitespacesAndNewlines)
+    switch Validator.username.validate(stateSubject.value.input) {
     case .success(let text):
-      stateRelay.value.status = .valid(text)
+      stateSubject.value.status = .valid(text)
     case .failure(let error):
-      stateRelay.value.status = .invalid(error)
+      stateSubject.value.status = .invalid(error)
     }
   }
-  
+
   func didTapRegister() {
     hudController.show()
-    
-    backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
-      
+    scheduler.schedule { [weak self] in
+      guard let self else { return }
       do {
         try self.messenger.register(
-          username: self.stateRelay.value.input
+          username: self.stateSubject.value.input
         )
-        
         try self.database.saveContact(.init(
           id: self.messenger.e2e.get()!.getContact().getId(),
           marshaled: self.messenger.e2e.get()!.getContact().data,
-          username: self.stateRelay.value.input,
+          username: self.stateSubject.value.input,
           email: nil,
           phone: nil,
           nickname: nil,
@@ -67,13 +60,13 @@ final class OnboardingUsernameViewModel {
           isBanned: false,
           createdAt: Date()
         ))
-        
-        self.username = self.stateRelay.value.input
+        self.username = self.stateSubject.value.input
         self.hudController.dismiss()
-        self.greenRelay.send()
+        self.stateSubject.value.didConfirm = true
       } catch {
         self.hudController.dismiss()
-        self.stateRelay.value.status = .invalid(CreateUserFriendlyErrorMessage.live(error.localizedDescription))
+        let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+        self.stateSubject.value.status = .invalid(xxError)
       }
     }
   }
diff --git a/Sources/OnboardingFeature/Views/OnboardingCodeView.swift b/Sources/OnboardingFeature/Views/OnboardingCodeView.swift
new file mode 100644
index 00000000..9f4b48d5
--- /dev/null
+++ b/Sources/OnboardingFeature/Views/OnboardingCodeView.swift
@@ -0,0 +1,117 @@
+import UIKit
+import Shared
+import InputField
+
+final class OnboardingCodeView: UIView {
+  let titleLabel = UILabel()
+  let subtitleView = TextWithInfoView()
+  let inputField = InputField()
+  let nextButton = CapsuleButton()
+  let resendButton = UIButton()
+  let stackView = UIStackView()
+  var didTapInfo: (() -> Void)?
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    setupTitle(Localized.Onboarding.EmailConfirmation.title)
+
+    inputField.setup(
+      placeholder: Localized.Onboarding.EmailConfirmation.input,
+      subtitleColor: Asset.neutralWeak.color,
+      allowsEmptySpace: false,
+      keyboardType: .numberPad,
+      autocapitalization: .none,
+      contentType: .oneTimeCode
+    )
+
+    resendButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
+    resendButton.setTitleColor(Asset.neutralWeak.color, for: .disabled)
+    resendButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    resendButton.setTitle(Localized.Onboarding.EmailConfirmation.resend(""), for: .normal)
+
+    nextButton.set(style: .brandColored, title: Localized.Onboarding.EmailConfirmation.next)
+    nextButton.isEnabled = false
+
+    stackView.spacing = 15
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(nextButton)
+    stackView.addArrangedSubview(resendButton)
+
+    addSubview(titleLabel)
+    addSubview(subtitleView)
+    addSubview(inputField)
+    addSubview(stackView)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(30)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
+    }
+    subtitleView.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
+    }
+    inputField.snp.makeConstraints {
+      $0.top.equalTo(subtitleView.snp.bottom).offset(24)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-38)
+    }
+    stackView.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func update(status: InputField.ValidationStatus) {
+    inputField.update(status: status)
+
+    switch status {
+    case .valid:
+      nextButton.isEnabled = true
+    case .invalid, .unknown:
+      nextButton.isEnabled = false
+    }
+  }
+
+  private func setupTitle(_ title: String) {
+    let attString = NSMutableAttributedString(string: title)
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.0
+
+    attString.addAttribute(.paragraphStyle, value: paragraph)
+    attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
+    attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
+
+    attString.addAttributes(attributes: [
+      .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
+      .foregroundColor: Asset.brandPrimary.color
+    ], betweenCharacters: "#")
+
+    titleLabel.numberOfLines = 0
+    titleLabel.attributedText = attString
+  }
+
+  public func setupSubtitle(_ subtitle: String) {
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+
+    subtitleView.setup(
+      text: subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraph
+      ],
+      didTapInfo: { [weak self] in self?.didTapInfo?() }
+    )
+  }
+}
diff --git a/Sources/OnboardingFeature/Views/OnboardingEmailConfirmationView.swift b/Sources/OnboardingFeature/Views/OnboardingEmailConfirmationView.swift
deleted file mode 100644
index 8d412274..00000000
--- a/Sources/OnboardingFeature/Views/OnboardingEmailConfirmationView.swift
+++ /dev/null
@@ -1,121 +0,0 @@
-import UIKit
-import Shared
-import InputField
-
-final class OnboardingEmailConfirmationView: UIView {
-    let titleLabel = UILabel()
-    let subtitleView = TextWithInfoView()
-    let inputField = InputField()
-    let nextButton = CapsuleButton()
-    let resendButton = UIButton()
-    let stackView = UIStackView()
-
-    var didTapInfo: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        setupTitle(Localized.Onboarding.EmailConfirmation.title)
-
-        inputField.setup(
-            placeholder: Localized.Onboarding.EmailConfirmation.input,
-            subtitleColor: Asset.neutralWeak.color,
-            allowsEmptySpace: false,
-            keyboardType: .numberPad,
-            autocapitalization: .none,
-            contentType: .oneTimeCode
-        )
-
-        resendButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
-        resendButton.setTitleColor(Asset.neutralWeak.color, for: .disabled)
-        resendButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        resendButton.setTitle(Localized.Onboarding.EmailConfirmation.resend(""), for: .normal)
-
-        nextButton.set(style: .brandColored, title: Localized.Onboarding.EmailConfirmation.next)
-        nextButton.isEnabled = false
-
-        stackView.spacing = 15
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(nextButton)
-        stackView.addArrangedSubview(resendButton)
-
-        addSubview(titleLabel)
-        addSubview(subtitleView)
-        addSubview(inputField)
-        addSubview(stackView)
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(30)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        subtitleView.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(8)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        inputField.snp.makeConstraints { make in
-            make.top.equalTo(subtitleView.snp.bottom).offset(24)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-38)
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-40)
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
-        }
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    func update(status: InputField.ValidationStatus) {
-        inputField.update(status: status)
-
-        switch status {
-        case .valid:
-            nextButton.isEnabled = true
-        case .invalid, .unknown:
-            nextButton.isEnabled = false
-        }
-    }
-
-    private func setupTitle(_ title: String) {
-        let attString = NSMutableAttributedString(string: title)
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.0
-
-        attString.addAttribute(.paragraphStyle, value: paragraph)
-        attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
-        attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
-
-        attString.addAttributes(attributes: [
-            .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
-            .foregroundColor: Asset.brandPrimary.color
-        ], betweenCharacters: "#")
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attString
-    }
-
-    public func setupSubtitle(_ subtitle: String) {
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
-
-        subtitleView.setup(
-            text: subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraph
-            ],
-            didTapInfo: { [weak self] in self?.didTapInfo?() }
-        )
-    }
-}
diff --git a/Sources/OnboardingFeature/Views/OnboardingEmailView.swift b/Sources/OnboardingFeature/Views/OnboardingEmailView.swift
index 760996ab..c681215e 100644
--- a/Sources/OnboardingFeature/Views/OnboardingEmailView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingEmailView.swift
@@ -3,118 +3,111 @@ import Shared
 import InputField
 
 final class OnboardingEmailView: UIView {
-    let titleLabel = UILabel()
-    let subtitleView = TextWithInfoView()
-    let inputField = InputField()
-    let nextButton = CapsuleButton()
-    let skipButton = UIButton()
-    let stackView = UIStackView()
-
-    var didTapInfo: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        setupTitle(Localized.Onboarding.Email.title)
-        setupSubtitle(Localized.Onboarding.Email.subtitle)
-
-        inputField.setup(
-            placeholder: Localized.Onboarding.Email.input,
-            subtitleColor: Asset.neutralWeak.color,
-            allowsEmptySpace: false,
-            keyboardType: .emailAddress,
-            autocapitalization: .none,
-            contentType: .emailAddress
-        )
-
-        skipButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 14.0)
-        skipButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
-        skipButton.setTitle(Localized.Onboarding.Email.skip, for: .normal)
-        nextButton.set(style: .brandColored, title: Localized.Onboarding.Email.action)
-        nextButton.isEnabled = false
-
-        stackView.spacing = 20
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(nextButton)
-        stackView.addArrangedSubview(skipButton)
-
-        addSubview(titleLabel)
-        addSubview(subtitleView)
-        addSubview(inputField)
-        addSubview(stackView)
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(30)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        subtitleView.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(8)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        inputField.snp.makeConstraints { make in
-            make.top.equalTo(subtitleView.snp.bottom).offset(24)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-38)
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-40)
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
-        }
+  let titleLabel = UILabel()
+  let subtitleView = TextWithInfoView()
+  let inputField = InputField()
+  let nextButton = CapsuleButton()
+  let skipButton = UIButton()
+  let stackView = UIStackView()
+  var didTapInfo: (() -> Void)?
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    setupTitle(Localized.Onboarding.Email.title)
+    setupSubtitle(Localized.Onboarding.Email.subtitle)
+
+    inputField.setup(
+      placeholder: Localized.Onboarding.Email.input,
+      subtitleColor: Asset.neutralWeak.color,
+      allowsEmptySpace: false,
+      keyboardType: .emailAddress,
+      autocapitalization: .none,
+      contentType: .emailAddress
+    )
+
+    skipButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 14.0)
+    skipButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
+    skipButton.setTitle(Localized.Onboarding.Email.skip, for: .normal)
+    nextButton.set(style: .brandColored, title: Localized.Onboarding.Email.action)
+    nextButton.isEnabled = false
+
+    stackView.spacing = 20
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(nextButton)
+    stackView.addArrangedSubview(skipButton)
+
+    addSubview(titleLabel)
+    addSubview(subtitleView)
+    addSubview(inputField)
+    addSubview(stackView)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(30)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    func update(status: InputField.ValidationStatus) {
-        inputField.update(status: status)
-
-        switch status {
-        case .valid:
-            nextButton.isEnabled = true
-        case .invalid, .unknown:
-            nextButton.isEnabled = false
-        }
+    subtitleView.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    private func setupTitle(_ title: String) {
-        let attString = NSMutableAttributedString(string: title)
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
-
-        attString.addAttribute(.paragraphStyle, value: paragraph)
-        attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
-        attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
-
-        attString.addAttributes(attributes: [
-            .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
-            .foregroundColor: Asset.brandPrimary.color
-        ], betweenCharacters: "#")
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attString
+    inputField.snp.makeConstraints {
+      $0.top.equalTo(subtitleView.snp.bottom).offset(24)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-38)
+    }
+    stackView.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
     }
+  }
 
-    private func setupSubtitle(_ subtitle: String) {
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
+  required init?(coder: NSCoder) { nil }
 
-        subtitleView.setup(
-            text: subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraph
-            ],
-            didTapInfo: { [weak self] in self?.didTapInfo?() }
-        )
+  func update(status: InputField.ValidationStatus) {
+    inputField.update(status: status)
+    switch status {
+    case .valid:
+      nextButton.isEnabled = true
+    case .invalid, .unknown:
+      nextButton.isEnabled = false
     }
+  }
+
+  private func setupTitle(_ title: String) {
+    let attString = NSMutableAttributedString(string: title)
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+    attString.addAttribute(.paragraphStyle, value: paragraph)
+    attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
+    attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
+    attString.addAttributes(attributes: [
+      .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
+      .foregroundColor: Asset.brandPrimary.color
+    ], betweenCharacters: "#")
+
+    titleLabel.numberOfLines = 0
+    titleLabel.attributedText = attString
+  }
+
+  private func setupSubtitle(_ subtitle: String) {
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+
+    subtitleView.setup(
+      text: subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraph
+      ],
+      didTapInfo: { [weak self] in self?.didTapInfo?() }
+    )
+  }
 }
diff --git a/Sources/OnboardingFeature/Views/OnboardingPhoneConfirmationView.swift b/Sources/OnboardingFeature/Views/OnboardingPhoneConfirmationView.swift
index 0509f5d5..8caa2767 100644
--- a/Sources/OnboardingFeature/Views/OnboardingPhoneConfirmationView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingPhoneConfirmationView.swift
@@ -3,119 +3,109 @@ import Shared
 import InputField
 
 final class OnboardingPhoneConfirmationView: UIView {
-    let titleLabel = UILabel()
-    let subtitleView = TextWithInfoView()
-    let inputField = InputField()
-    let nextButton = CapsuleButton()
-    let resendButton = UIButton()
-    let stackView = UIStackView()
-
-    var didTapInfo: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        setupTitle(Localized.Onboarding.PhoneConfirmation.title)
-
-        inputField.setup(
-            placeholder: Localized.Onboarding.PhoneConfirmation.input,
-            subtitleColor: Asset.neutralWeak.color,
-            allowsEmptySpace: false,
-            keyboardType: .numberPad,
-            autocapitalization: .none,
-            contentType: .oneTimeCode
-        )
-
-        resendButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
-        resendButton.setTitleColor(Asset.neutralWeak.color, for: .disabled)
-        resendButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        resendButton.setTitle(Localized.Onboarding.PhoneConfirmation.resend(""), for: .normal)
-
-        nextButton.set(style: .brandColored, title: Localized.Onboarding.PhoneConfirmation.next)
-        nextButton.isEnabled = false
-
-        stackView.spacing = 15
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(nextButton)
-        stackView.addArrangedSubview(resendButton)
-
-        addSubview(titleLabel)
-        addSubview(subtitleView)
-        addSubview(inputField)
-        addSubview(stackView)
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(30)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        subtitleView.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(8)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        inputField.snp.makeConstraints { make in
-            make.top.equalTo(subtitleView.snp.bottom).offset(24)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-38)
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-40)
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
-        }
+  let titleLabel = UILabel()
+  let subtitleView = TextWithInfoView()
+  let inputField = InputField()
+  let nextButton = CapsuleButton()
+  let resendButton = UIButton()
+  let stackView = UIStackView()
+  var didTapInfo: (() -> Void)?
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+    setupTitle(Localized.Onboarding.PhoneConfirmation.title)
+
+    inputField.setup(
+      placeholder: Localized.Onboarding.PhoneConfirmation.input,
+      subtitleColor: Asset.neutralWeak.color,
+      allowsEmptySpace: false,
+      keyboardType: .numberPad,
+      autocapitalization: .none,
+      contentType: .oneTimeCode
+    )
+
+    resendButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
+    resendButton.setTitleColor(Asset.neutralWeak.color, for: .disabled)
+    resendButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    resendButton.setTitle(Localized.Onboarding.PhoneConfirmation.resend(""), for: .normal)
+    nextButton.set(style: .brandColored, title: Localized.Onboarding.PhoneConfirmation.next)
+    nextButton.isEnabled = false
+
+    stackView.spacing = 15
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(nextButton)
+    stackView.addArrangedSubview(resendButton)
+
+    addSubview(titleLabel)
+    addSubview(subtitleView)
+    addSubview(inputField)
+    addSubview(stackView)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(30)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    func update(status: InputField.ValidationStatus) {
-        inputField.update(status: status)
-
-        switch status {
-        case .valid:
-            nextButton.isEnabled = true
-        case .invalid, .unknown:
-            nextButton.isEnabled = false
-        }
+    subtitleView.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    private func setupTitle(_ title: String) {
-        let attString = NSMutableAttributedString(string: title)
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.0
-
-        attString.addAttribute(.paragraphStyle, value: paragraph)
-        attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
-        attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
-
-        attString.addAttributes(attributes: [
-            .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
-            .foregroundColor: Asset.brandPrimary.color
-        ], betweenCharacters: "#")
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attString
+    inputField.snp.makeConstraints {
+      $0.top.equalTo(subtitleView.snp.bottom).offset(24)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-38)
+    }
+    stackView.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
     }
+  }
 
-    public func setupSubtitle(_ subtitle: String) {
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
+  required init?(coder: NSCoder) { nil }
 
-        subtitleView.setup(
-            text: subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraph
-            ],
-            didTapInfo: { [weak self] in self?.didTapInfo?() }
-        )
+  func update(status: InputField.ValidationStatus) {
+    inputField.update(status: status)
+    switch status {
+    case .valid:
+      nextButton.isEnabled = true
+    case .invalid, .unknown:
+      nextButton.isEnabled = false
     }
+  }
+
+  private func setupTitle(_ title: String) {
+    let attString = NSMutableAttributedString(string: title)
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.0
+    attString.addAttribute(.paragraphStyle, value: paragraph)
+    attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
+    attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
+    attString.addAttributes(attributes: [
+      .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
+      .foregroundColor: Asset.brandPrimary.color
+    ], betweenCharacters: "#")
+
+    titleLabel.numberOfLines = 0
+    titleLabel.attributedText = attString
+  }
+  
+  public func setupSubtitle(_ subtitle: String) {
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+    subtitleView.setup(
+      text: subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraph
+      ],
+      didTapInfo: { [weak self] in self?.didTapInfo?() }
+    )
+  }
 }
diff --git a/Sources/OnboardingFeature/Views/OnboardingPhoneView.swift b/Sources/OnboardingFeature/Views/OnboardingPhoneView.swift
index caec887d..a8df7c86 100644
--- a/Sources/OnboardingFeature/Views/OnboardingPhoneView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingPhoneView.swift
@@ -3,118 +3,110 @@ import Shared
 import InputField
 
 final class OnboardingPhoneView: UIView {
-    let titleLabel = UILabel()
-    let subtitleView = TextWithInfoView()
-    let inputField = InputField()
-    let nextButton = CapsuleButton()
-    let skipButton = UIButton()
-    let stackView = UIStackView()
-
-    var didTapInfo: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        setupTitle(Localized.Onboarding.Phone.title)
-        setupSubtitle(Localized.Onboarding.Phone.subtitle)
-
-        inputField.setup(
-            style: .phone,
-            placeholder: Localized.Onboarding.Phone.input,
-            subtitleColor: Asset.neutralWeak.color,
-            keyboardType: .phonePad,
-            contentType: .telephoneNumber,
-            codeAccessibility: Localized.Accessibility.Onboarding.Phone.code
-        )
-
-        skipButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 14.0)
-        skipButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
-        skipButton.setTitle(Localized.Onboarding.Phone.skip, for: .normal)
-        nextButton.set(style: .brandColored, title: Localized.Onboarding.Phone.action)
-        nextButton.isEnabled = false
-
-        stackView.spacing = 20
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(nextButton)
-        stackView.addArrangedSubview(skipButton)
-
-        addSubview(titleLabel)
-        addSubview(subtitleView)
-        addSubview(inputField)
-        addSubview(stackView)
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(30)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        subtitleView.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(8)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        inputField.snp.makeConstraints { make in
-            make.top.equalTo(subtitleView.snp.bottom).offset(24)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-38)
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-40)
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
-        }
+  let titleLabel = UILabel()
+  let subtitleView = TextWithInfoView()
+  let inputField = InputField()
+  let nextButton = CapsuleButton()
+  let skipButton = UIButton()
+  let stackView = UIStackView()
+  var didTapInfo: (() -> Void)?
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    setupTitle(Localized.Onboarding.Phone.title)
+    setupSubtitle(Localized.Onboarding.Phone.subtitle)
+
+    inputField.setup(
+      style: .phone,
+      placeholder: Localized.Onboarding.Phone.input,
+      subtitleColor: Asset.neutralWeak.color,
+      keyboardType: .phonePad,
+      contentType: .telephoneNumber,
+      codeAccessibility: Localized.Accessibility.Onboarding.Phone.code
+    )
+
+    skipButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 14.0)
+    skipButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
+    skipButton.setTitle(Localized.Onboarding.Phone.skip, for: .normal)
+    nextButton.set(style: .brandColored, title: Localized.Onboarding.Phone.action)
+    nextButton.isEnabled = false
+
+    stackView.spacing = 20
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(nextButton)
+    stackView.addArrangedSubview(skipButton)
+
+    addSubview(titleLabel)
+    addSubview(subtitleView)
+    addSubview(inputField)
+    addSubview(stackView)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(30)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    func update(status: InputField.ValidationStatus) {
-        inputField.update(status: status)
-
-        switch status {
-        case .valid:
-            nextButton.isEnabled = true
-        case .invalid, .unknown:
-            nextButton.isEnabled = false
-        }
+    subtitleView.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    private func setupTitle(_ title: String) {
-        let attString = NSMutableAttributedString(string: title)
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
-
-        attString.addAttribute(.paragraphStyle, value: paragraph)
-        attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
-        attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
-
-        attString.addAttributes(attributes: [
-            .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
-            .foregroundColor: Asset.brandPrimary.color
-        ], betweenCharacters: "#")
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attString
+    inputField.snp.makeConstraints {
+      $0.top.equalTo(subtitleView.snp.bottom).offset(24)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-38)
+    }
+    stackView.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
     }
+  }
 
-    private func setupSubtitle(_ subtitle: String) {
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
+  required init?(coder: NSCoder) { nil }
 
-        subtitleView.setup(
-            text: subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraph
-            ],
-            didTapInfo: { [weak self] in self?.didTapInfo?() }
-        )
+  func update(status: InputField.ValidationStatus) {
+    inputField.update(status: status)
+    switch status {
+    case .valid:
+      nextButton.isEnabled = true
+    case .invalid, .unknown:
+      nextButton.isEnabled = false
     }
+  }
+
+  private func setupTitle(_ title: String) {
+    let attString = NSMutableAttributedString(string: title)
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+    attString.addAttribute(.paragraphStyle, value: paragraph)
+    attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
+    attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
+    attString.addAttributes(attributes: [
+      .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
+      .foregroundColor: Asset.brandPrimary.color
+    ], betweenCharacters: "#")
+
+    titleLabel.numberOfLines = 0
+    titleLabel.attributedText = attString
+  }
+
+  private func setupSubtitle(_ subtitle: String) {
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+    subtitleView.setup(
+      text: subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraph
+      ],
+      didTapInfo: { [weak self] in self?.didTapInfo?() }
+    )
+  }
 }
diff --git a/Sources/OnboardingFeature/Views/OnboardingStartView.swift b/Sources/OnboardingFeature/Views/OnboardingStartView.swift
index a3e953aa..2a83c1b6 100644
--- a/Sources/OnboardingFeature/Views/OnboardingStartView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingStartView.swift
@@ -2,48 +2,47 @@ import UIKit
 import Shared
 
 final class OnboardingStartView: UIView {
-    let titleLabel = UILabel()
-    let stackView = UIStackView()
-    let logoImageView = UIImageView()
-    let startButton = CapsuleButton()
-    let bottomImageView = UIImageView()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-        logoImageView.image = Asset.onboardingLogoStart.image
-        bottomImageView.image = Asset.onboardingBottomLogoStart.image
-
-        titleLabel.textAlignment = .center
-        titleLabel.textColor = Asset.neutralWhite.color
-        titleLabel.font = Fonts.Mulish.bold.font(size: 18.0)
-        titleLabel.text = Localized.Onboarding.Start.title
-        startButton.set(style: .white, title: Localized.Onboarding.Start.action)
-
-        logoImageView.contentMode = .center
-        bottomImageView.contentMode = .center
-
-        stackView.spacing = 40
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(titleLabel)
-        stackView.addArrangedSubview(startButton)
-        stackView.addArrangedSubview(bottomImageView)
-        stackView.setCustomSpacing(70, after: startButton)
-
-        addSubview(logoImageView)
-        addSubview(stackView)
-
-        logoImageView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(130)
-            make.centerX.equalToSuperview()
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-40)
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-40)
-        }
+  let titleLabel = UILabel()
+  let stackView = UIStackView()
+  let logoImageView = UIImageView()
+  let startButton = CapsuleButton()
+  let bottomImageView = UIImageView()
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+    logoImageView.image = Asset.onboardingLogoStart.image
+    bottomImageView.image = Asset.onboardingBottomLogoStart.image
+
+    titleLabel.textAlignment = .center
+    titleLabel.textColor = Asset.neutralWhite.color
+    titleLabel.font = Fonts.Mulish.bold.font(size: 18.0)
+    titleLabel.text = Localized.Onboarding.Start.title
+    startButton.set(style: .white, title: Localized.Onboarding.Start.action)
+
+    logoImageView.contentMode = .center
+    bottomImageView.contentMode = .center
+
+    stackView.spacing = 40
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(titleLabel)
+    stackView.addArrangedSubview(startButton)
+    stackView.addArrangedSubview(bottomImageView)
+    stackView.setCustomSpacing(70, after: startButton)
+
+    addSubview(logoImageView)
+    addSubview(stackView)
+
+    logoImageView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(130)
+      $0.centerX.equalToSuperview()
     }
+    stackView.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-40)
+    }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/OnboardingFeature/Views/OnboardingSuccessView.swift b/Sources/OnboardingFeature/Views/OnboardingSuccessView.swift
deleted file mode 100644
index 7e02167c..00000000
--- a/Sources/OnboardingFeature/Views/OnboardingSuccessView.swift
+++ /dev/null
@@ -1,75 +0,0 @@
-import UIKit
-import Shared
-
-final class OnboardingSuccessView: UIView {
-    let iconImageView = UIImageView()
-    let titleLabel = UILabel()
-    let subtitleLabel = UILabel()
-    let nextButton = CapsuleButton()
-
-    init() {
-        super.init(frame: .zero)
-
-        iconImageView.contentMode = .center
-        iconImageView.image = Asset.onboardingSuccess.image
-        nextButton.set(style: .white, title: Localized.Onboarding.Success.action)
-
-        subtitleLabel.numberOfLines = 0
-        subtitleLabel.textColor = Asset.neutralWhite.color
-        subtitleLabel.font = Fonts.Mulish.regular.font(size: 16.0)
-
-        addSubview(iconImageView)
-        addSubview(titleLabel)
-        addSubview(subtitleLabel)
-        addSubview(nextButton)
-
-        iconImageView.snp.makeConstraints { make in
-            make.top.equalTo(safeAreaLayoutGuide).offset(40)
-            make.left.equalToSuperview().offset(40)
-        }
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalTo(iconImageView.snp.bottom).offset(40)
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-90)
-        }
-
-        subtitleLabel.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(30)
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-90)
-        }
-
-        nextButton.snp.makeConstraints { make in
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.equalToSuperview().offset(-60)
-        }
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    func setTitle(_ title: String) {
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.1
-
-        let attrString = NSMutableAttributedString(string: title)
-
-        attrString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 39.0))
-        attrString.addAttribute(.foregroundColor, value: Asset.neutralWhite.color)
-
-        attrString.addAttribute(
-            name: .foregroundColor,
-            value: Asset.neutralBody.color,
-            betweenCharacters: "#"
-        )
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attrString
-    }
-
-    func setSubtitle(_ subtitle: String?) {
-        subtitleLabel.text = subtitle
-    }
-}
diff --git a/Sources/OnboardingFeature/Views/OnboardingUsernameRestoreView.swift b/Sources/OnboardingFeature/Views/OnboardingUsernameRestoreView.swift
index f0343755..170d0a63 100644
--- a/Sources/OnboardingFeature/Views/OnboardingUsernameRestoreView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingUsernameRestoreView.swift
@@ -2,46 +2,44 @@ import UIKit
 import Shared
 
 final class OnboardingUsernameRestoreView: UIView {
-    let titleLabel = UILabel()
-    let restoreButton = CapsuleButton()
-    let separatorView = UIView()
-
-    init() {
-        super.init(frame: .zero)
-
-        titleLabel.text = Localized.Onboarding.Username.Restore.title
-        restoreButton.set(style: .seeThrough, title: Localized.Onboarding.Username.Restore.action)
-
-        titleLabel.numberOfLines = 0
-        titleLabel.textAlignment = .center
-        titleLabel.font = Fonts.Mulish.bold.font(size: 24)
-
-        addSubview(titleLabel)
-        addSubview(restoreButton)
-        addSubview(separatorView)
-
-        separatorView.backgroundColor = Asset.neutralLine.color
-
-        separatorView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.height.equalTo(1)
-        }
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalTo(separatorView.snp.bottom).offset(40)
-            make.left.equalToSuperview().offset(20)
-            make.right.equalToSuperview().offset(-20)
-        }
-
-        restoreButton.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(34)
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-40)
-            make.bottom.equalToSuperview()
-        }
+  let titleLabel = UILabel()
+  let restoreButton = CapsuleButton()
+  let separatorView = UIView()
+
+  init() {
+    super.init(frame: .zero)
+
+    titleLabel.text = Localized.Onboarding.Username.Restore.title
+    restoreButton.set(style: .seeThrough, title: Localized.Onboarding.Username.Restore.action)
+
+    titleLabel.numberOfLines = 0
+    titleLabel.textAlignment = .center
+    titleLabel.font = Fonts.Mulish.bold.font(size: 24)
+
+    addSubview(titleLabel)
+    addSubview(restoreButton)
+    addSubview(separatorView)
+
+    separatorView.backgroundColor = Asset.neutralLine.color
+
+    separatorView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.height.equalTo(1)
+    }
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(separatorView.snp.bottom).offset(40)
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
+    }
+    restoreButton.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(34)
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/OnboardingFeature/Views/OnboardingUsernameView.swift b/Sources/OnboardingFeature/Views/OnboardingUsernameView.swift
index 32ec1e43..7bd6e102 100644
--- a/Sources/OnboardingFeature/Views/OnboardingUsernameView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingUsernameView.swift
@@ -3,114 +3,105 @@ import Shared
 import InputField
 
 final class OnboardingUsernameView: UIView {
-    let titleLabel = UILabel()
-    let subtitleView = TextWithInfoView()
-    let inputField = InputField()
-    let nextButton = CapsuleButton()
-    let restoreView = OnboardingUsernameRestoreView()
-
-    var didTapInfo: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        setupTitle(Localized.Onboarding.Username.title)
-        setupSubtitle(Localized.Onboarding.Username.subtitle)
-
-        inputField.setup(
-            placeholder: Localized.Onboarding.Username.input,
-            subtitleColor: Asset.neutralWeak.color,
-            allowsEmptySpace: false,
-            autocapitalization: .none
-        )
-
-        nextButton.set(style: .brandColored, title: Localized.Onboarding.Username.next)
-        nextButton.isEnabled = false
-
-        addSubview(titleLabel)
-        addSubview(subtitleView)
-        addSubview(inputField)
-        addSubview(nextButton)
-        addSubview(restoreView)
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(30)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        subtitleView.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(8)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        inputField.snp.makeConstraints { make in
-            make.top.equalTo(subtitleView.snp.bottom).offset(24)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-38)
-        }
-
-        nextButton.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-40)
-        }
-
-        restoreView.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(nextButton.snp.bottom).offset(30)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
-        }
+  let titleLabel = UILabel()
+  let subtitleView = TextWithInfoView()
+  let inputField = InputField()
+  let nextButton = CapsuleButton()
+  let restoreView = OnboardingUsernameRestoreView()
+  var didTapInfo: (() -> Void)?
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    setupTitle(Localized.Onboarding.Username.title)
+    setupSubtitle(Localized.Onboarding.Username.subtitle)
+
+    inputField.setup(
+      placeholder: Localized.Onboarding.Username.input,
+      subtitleColor: Asset.neutralWeak.color,
+      allowsEmptySpace: false,
+      autocapitalization: .none
+    )
+
+    nextButton.set(style: .brandColored, title: Localized.Onboarding.Username.next)
+    nextButton.isEnabled = false
+
+    addSubview(titleLabel)
+    addSubview(subtitleView)
+    addSubview(inputField)
+    addSubview(nextButton)
+    addSubview(restoreView)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(30)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    func update(status: InputField.ValidationStatus) {
-        inputField.update(status: status)
-
-        switch status {
-        case .valid:
-            nextButton.isEnabled = true
-        case .invalid, .unknown:
-            nextButton.isEnabled = false
-        }
+    subtitleView.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    private func setupTitle(_ title: String) {
-        let attString = NSMutableAttributedString(string: title)
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
-
-        attString.addAttribute(.paragraphStyle, value: paragraph)
-        attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
-        attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
-
-        attString.addAttributes(attributes: [
-            .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
-            .foregroundColor: Asset.brandPrimary.color
-        ], betweenCharacters: "#")
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attString
+    inputField.snp.makeConstraints {
+      $0.top.equalTo(subtitleView.snp.bottom).offset(24)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-38)
+    }
+    nextButton.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(20)
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+    }
+    restoreView.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(nextButton.snp.bottom).offset(30)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
     }
+  }
 
-    private func setupSubtitle(_ subtitle: String) {
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
+  required init?(coder: NSCoder) { nil }
 
-        subtitleView.setup(
-            text: subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraph
-            ],
-            didTapInfo: { [weak self] in self?.didTapInfo?() }
-        )
+  func update(status: InputField.ValidationStatus) {
+    inputField.update(status: status)
+    switch status {
+    case .valid:
+      nextButton.isEnabled = true
+    case .invalid, .unknown:
+      nextButton.isEnabled = false
     }
+  }
+
+  private func setupTitle(_ title: String) {
+    let attString = NSMutableAttributedString(string: title)
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+    attString.addAttribute(.paragraphStyle, value: paragraph)
+    attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
+    attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
+    attString.addAttributes(attributes: [
+      .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
+      .foregroundColor: Asset.brandPrimary.color
+    ], betweenCharacters: "#")
+
+    titleLabel.numberOfLines = 0
+    titleLabel.attributedText = attString
+  }
+
+  private func setupSubtitle(_ subtitle: String) {
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+    subtitleView.setup(
+      text: subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraph
+      ],
+      didTapInfo: { [weak self] in self?.didTapInfo?() }
+    )
+  }
 }
diff --git a/Sources/OnboardingFeature/Views/OnboardingWelcomeView.swift b/Sources/OnboardingFeature/Views/OnboardingWelcomeView.swift
index d3581a4d..ae4b5a60 100644
--- a/Sources/OnboardingFeature/Views/OnboardingWelcomeView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingWelcomeView.swift
@@ -2,85 +2,79 @@ import UIKit
 import Shared
 
 final class OnboardingWelcomeView: UIView {
-    let titleLabel = UILabel()
-    let subtitleView = TextWithInfoView()
-    let stackView = UIStackView()
-    let continueButton = CapsuleButton()
-    let skipButton = CapsuleButton()
-
-    var didTapInfo: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        setupSubtitle(Localized.Onboarding.Welcome.subtitle)
-
-        skipButton.set(style: .brandColored, title: Localized.Onboarding.Welcome.skip)
-        continueButton.set(style: .brandColored, title: Localized.Onboarding.Welcome.continue)
-
-        stackView.spacing = 15
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(continueButton)
-        stackView.addArrangedSubview(skipButton)
-
-        addSubview(titleLabel)
-        addSubview(subtitleView)
-        addSubview(stackView)
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalTo(safeAreaLayoutGuide).offset(30)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        subtitleView.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(8)
-            make.left.equalToSuperview().offset(38)
-            make.right.equalToSuperview().offset(-41)
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.left.equalToSuperview().offset(40)
-            make.right.equalToSuperview().offset(-40)
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
-        }
+  let titleLabel = UILabel()
+  let subtitleView = TextWithInfoView()
+  let stackView = UIStackView()
+  let continueButton = CapsuleButton()
+  let skipButton = CapsuleButton()
+  var didTapInfo: (() -> Void)?
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    setupSubtitle(Localized.Onboarding.Welcome.subtitle)
+
+    skipButton.set(style: .brandColored, title: Localized.Onboarding.Welcome.skip)
+    continueButton.set(style: .brandColored, title: Localized.Onboarding.Welcome.continue)
+
+    stackView.spacing = 15
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(continueButton)
+    stackView.addArrangedSubview(skipButton)
+
+    addSubview(titleLabel)
+    addSubview(subtitleView)
+    addSubview(stackView)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(safeAreaLayoutGuide).offset(30)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    func setupTitle(_ title: String) {
-        let attString = NSMutableAttributedString(string: title)
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.1
-
-        attString.addAttribute(.paragraphStyle, value: paragraph)
-        attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
-        attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
-
-        attString.addAttributes(attributes: [
-            .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
-            .foregroundColor: Asset.brandPrimary.color
-        ], betweenCharacters: "#")
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attString
+    subtitleView.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
-
-    private func setupSubtitle(_ subtitle: String) {
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
-
-        subtitleView.setup(
-            text: subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraph
-            ],
-            didTapInfo: { [weak self] in self?.didTapInfo?() }
-        )
+    stackView.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
     }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func setupTitle(_ title: String) {
+    let attString = NSMutableAttributedString(string: title)
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.1
+    attString.addAttribute(.paragraphStyle, value: paragraph)
+    attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
+    attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
+    attString.addAttributes(attributes: [
+      .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
+      .foregroundColor: Asset.brandPrimary.color
+    ], betweenCharacters: "#")
+
+    titleLabel.numberOfLines = 0
+    titleLabel.attributedText = attString
+  }
+
+  private func setupSubtitle(_ subtitle: String) {
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+    subtitleView.setup(
+      text: subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraph
+      ],
+      didTapInfo: { [weak self] in self?.didTapInfo?() }
+    )
+  }
 }
diff --git a/Sources/Permissions/RequestPermissionController.swift b/Sources/Permissions/RequestPermissionController.swift
index 6aa33347..d424df15 100644
--- a/Sources/Permissions/RequestPermissionController.swift
+++ b/Sources/Permissions/RequestPermissionController.swift
@@ -13,7 +13,7 @@ public final class RequestPermissionController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var permissions: PermissionHandling
 
-  lazy private var screenView = RequestPermissionView()
+  private lazy var screenView = RequestPermissionView()
 
   private var type: PermissionType!
   private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/Presentation/Presenting.swift b/Sources/Presentation/Presenting.swift
index 7de99327..b79da38e 100644
--- a/Sources/Presentation/Presenting.swift
+++ b/Sources/Presentation/Presenting.swift
@@ -24,7 +24,7 @@ public struct ModalPresenter: Presenting {
     public init() {}
 
     public func present(_ target: UIViewController..., from parent: UIViewController) {
-        let statusBarVC = RootViewController(target.first!)
+      let statusBarVC = RootViewController(UINavigationController(rootViewController: target.first!))
         statusBarVC.modalPresentationStyle = .fullScreen
         parent.present(statusBarVC, animated: true)
     }
diff --git a/Sources/ProfileFeature/Controllers/ProfileCodeController.swift b/Sources/ProfileFeature/Controllers/ProfileCodeController.swift
index 037ac041..60036d37 100644
--- a/Sources/ProfileFeature/Controllers/ProfileCodeController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileCodeController.swift
@@ -1,115 +1,114 @@
 import UIKit
-import Models
 import Shared
 import Combine
-import Countries
+import Navigation
+import XXNavigation
 import DependencyInjection
 import ScrollViewController
 
-public typealias ControllerClosure = (UIViewController, AttributeConfirmation) -> Void
-
 public final class ProfileCodeController: UIViewController {
-    lazy private var screenView = ProfileCodeView()
-    lazy private var scrollViewController = ScrollViewController()
-
-    private let completion: ControllerClosure
-    private let confirmation: AttributeConfirmation
-    private var cancellables = Set<AnyCancellable>()
-    lazy private var viewModel = ProfileCodeViewModel(confirmation)
-
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralWhite.color)
-    }
-
-    public init(
-        _ confirmation: AttributeConfirmation,
-        _ completion: @escaping ControllerClosure
-    ) {
-        self.completion = completion
-        self.confirmation = confirmation
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupScrollView()
-        setupBindings()
-        setupDetail()
-    }
-
-    private func setupScrollView() {
-        addChild(scrollViewController)
-        view.addSubview(scrollViewController.view)
-        scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-        scrollViewController.didMove(toParent: self)
-        scrollViewController.contentView = screenView
-        scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
-    }
-
-    private func setupBindings() {
-        screenView.inputField.textPublisher
-            .sink { [unowned self] in viewModel.didInput($0) }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.status)
-            .removeDuplicates()
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                switch $0 {
-                case .valid:
-                    screenView.saveButton.isEnabled = true
-                case .invalid, .unknown:
-                    screenView.saveButton.isEnabled = false
-                }
-            }.store(in: &cancellables)
-
-        screenView.saveButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in viewModel.didTapNext() }
-            .store(in: &cancellables)
-
-        viewModel.state
-            .map(\.resendDebouncer)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                screenView.resendButton.isEnabled = $0 == 0
-
-                if $0 == 0 {
-                    screenView.resendButton.setTitle(Localized.Profile.Code.resend(""), for: .normal)
-                } else {
-                    screenView.resendButton.setTitle(Localized.Profile.Code.resend("(\($0))"), for: .disabled)
-                }
-            }.store(in: &cancellables)
-
-        screenView.resendButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in viewModel.didTapResend() }
-            .store(in: &cancellables)
-
-        viewModel.completionPublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in completion(self, $0) }
-            .store(in: &cancellables)
-    }
-
-    private func setupDetail() {
-        var content: String!
-
-        if confirmation.isEmail {
-            content = confirmation.content
+  @Dependency var navigator: Navigator
+  @Dependency var barStylist: StatusBarStylist
+
+  private lazy var screenView = ProfileCodeView()
+  private lazy var scrollViewController = ScrollViewController()
+
+  private let isEmail: Bool
+  private let content: String
+  private let viewModel: ProfileCodeViewModel
+  private var cancellables = Set<AnyCancellable>()
+
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
+
+  public init(
+    _ isEmail: Bool,
+    _ content: String,
+    _ confirmationId: String
+  ) {
+    self.viewModel = .init(
+      isEmail: isEmail,
+      content: content,
+      confirmationId: confirmationId
+    )
+    self.isEmail = isEmail
+    self.content = content
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupScrollView()
+    setupBindings()
+
+//    var content: String!
+//
+//    if confirmation.isEmail {
+//      content = confirmation.content
+//    } else {
+//      let country = Country.findFrom(confirmation.content)
+//      content = "\(country.prefix)\(confirmation.content.dropLast(2))"
+//    }
+//
+//    screenView.set(content, isEmail: confirmation.isEmail)
+  }
+
+  private func setupScrollView() {
+    addChild(scrollViewController)
+    view.addSubview(scrollViewController.view)
+    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.didMove(toParent: self)
+    scrollViewController.contentView = screenView
+    scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
+  }
+
+  private func setupBindings() {
+    screenView.inputField.textPublisher
+      .sink { [unowned self] in viewModel.didInput($0) }
+      .store(in: &cancellables)
+
+    viewModel.statePublisher
+      .map(\.status)
+      .removeDuplicates()
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        switch $0 {
+        case .valid:
+          screenView.saveButton.isEnabled = true
+        case .invalid, .unknown:
+          screenView.saveButton.isEnabled = false
+        }
+      }.store(in: &cancellables)
+
+    screenView.saveButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in viewModel.didTapNext() }
+      .store(in: &cancellables)
+
+    viewModel.statePublisher
+      .map(\.resendDebouncer)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.resendButton.isEnabled = $0 == 0
+
+        if $0 == 0 {
+          screenView.resendButton.setTitle(Localized.Profile.Code.resend(""), for: .normal)
         } else {
-            let country = Country.findFrom(confirmation.content)
-            content = "\(country.prefix)\(confirmation.content.dropLast(2))"
+          screenView.resendButton.setTitle(Localized.Profile.Code.resend("(\($0))"), for: .disabled)
         }
-
-        screenView.set(content, isEmail: confirmation.isEmail)
-    }
+      }.store(in: &cancellables)
+
+    screenView.resendButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in viewModel.didTapResend() }
+      .store(in: &cancellables)
+  }
 }
diff --git a/Sources/ProfileFeature/Controllers/ProfileController.swift b/Sources/ProfileFeature/Controllers/ProfileController.swift
index 15499606..787f83f6 100644
--- a/Sources/ProfileFeature/Controllers/ProfileController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileController.swift
@@ -8,7 +8,7 @@ public final class ProfileController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: ProfileCoordinating
 
-  lazy private var screenView = ProfileView()
+  private lazy var screenView = ProfileView()
 
   private let viewModel = ProfileViewModel()
   private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
index 39396d0a..46077336 100644
--- a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
@@ -8,8 +8,8 @@ public final class ProfileEmailController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: ProfileCoordinating
 
-  lazy private var screenView = ProfileEmailView()
-  lazy private var scrollViewController = ScrollViewController()
+  private lazy var screenView = ProfileEmailView()
+  private lazy var scrollViewController = ScrollViewController()
 
   private let viewModel = ProfileEmailViewModel()
   private var cancellables = Set<AnyCancellable>()
@@ -31,46 +31,60 @@ public final class ProfileEmailController: UIViewController {
   private func setupScrollView() {
     addChild(scrollViewController)
     view.addSubview(scrollViewController.view)
-    scrollViewController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+    scrollViewController.view.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
     scrollViewController.didMove(toParent: self)
     scrollViewController.contentView = screenView
     scrollViewController.scrollView.backgroundColor = Asset.neutralWhite.color
   }
 
   private func setupBindings() {
-    screenView.inputField.textPublisher
-      .sink { [unowned self] in viewModel.didInput($0) }
-      .store(in: &cancellables)
+    screenView
+      .inputField
+      .textPublisher
+      .sink { [unowned self] in
+        viewModel.didInput($0)
+      }.store(in: &cancellables)
 
-    screenView.inputField.returnPublisher
-      .sink { [unowned self] in screenView.inputField.endEditing(true) }
-      .store(in: &cancellables)
+    screenView
+      .inputField
+      .returnPublisher
+      .sink { [unowned self] in
+        screenView.inputField.endEditing(true)
+      }.store(in: &cancellables)
 
-    viewModel.state
-      .map(\.confirmation)
+    viewModel
+      .statePublisher
+      .map(\.confirmationId)
       .receive(on: DispatchQueue.main)
       .compactMap { $0 }
       .sink { [unowned self] in
         viewModel.clearUp()
-        coordinator.toCode(with: $0, from: self) { _, _ in
-          if let viewControllers = self.navigationController?.viewControllers {
-            self.navigationController?.popToViewController(
-              viewControllers[viewControllers.count - 3],
-              animated: true
-            )
-          }
-        }
-      }
-      .store(in: &cancellables)
+//        coordinator.toCode(with: $0, from: self) { _, _ in
+//          if let viewControllers = self.navigationController?.viewControllers {
+//            self.navigationController?.popToViewController(
+//              viewControllers[viewControllers.count - 3],
+//              animated: true
+//            )
+//          }
+//        }
+      }.store(in: &cancellables)
 
-    viewModel.state.map(\.status)
+    viewModel
+      .statePublisher
+      .map(\.status)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in screenView.update(status: $0) }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        screenView.update(status: $0)
+      }.store(in: &cancellables)
 
-    screenView.saveButton.publisher(for: .touchUpInside)
-      .sink { [unowned self] in viewModel.didTapNext() }
-      .store(in: &cancellables)
+    screenView
+      .saveButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        viewModel.didTapNext()
+      }.store(in: &cancellables)
   }
 }
diff --git a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
index 6b220c37..1708fc9e 100644
--- a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
@@ -8,8 +8,8 @@ public final class ProfilePhoneController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: ProfileCoordinating
 
-  lazy private var screenView = ProfilePhoneView()
-  lazy private var scrollViewController = ScrollViewController()
+  private lazy var screenView = ProfilePhoneView()
+  private lazy var scrollViewController = ScrollViewController()
 
   private let viewModel = ProfilePhoneViewModel()
   private var cancellables = Set<AnyCancellable>()
@@ -52,23 +52,23 @@ public final class ProfilePhoneController: UIViewController {
         coordinator.toCountries(from: self) { self.viewModel.didChooseCountry($0) }
       }.store(in: &cancellables)
 
-    viewModel.state
-      .map(\.confirmation)
+    viewModel.statePublisher
+      .map(\.confirmationId)
       .receive(on: DispatchQueue.main)
       .compactMap { $0 }
       .sink { [unowned self] in
         viewModel.clearUp()
-        coordinator.toCode(with: $0, from: self) { _, _ in
-          if let viewControllers = self.navigationController?.viewControllers {
-            self.navigationController?.popToViewController(
-              viewControllers[viewControllers.count - 3],
-              animated: true
-            )
-          }
-        }
+//        coordinator.toCode(with: $0, from: self) { _, _ in
+//          if let viewControllers = self.navigationController?.viewControllers {
+//            self.navigationController?.popToViewController(
+//              viewControllers[viewControllers.count - 3],
+//              animated: true
+//            )
+//          }
+//        }
       }.store(in: &cancellables)
 
-    viewModel.state
+    viewModel.statePublisher
       .map(\.country)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
@@ -78,7 +78,7 @@ public final class ProfilePhoneController: UIViewController {
       }
       .store(in: &cancellables)
 
-    viewModel.state
+    viewModel.statePublisher
       .map(\.status)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
diff --git a/Sources/ProfileFeature/Coordinator/ProfileCoordinator.swift b/Sources/ProfileFeature/Coordinator/ProfileCoordinator.swift
index 947937b4..59b569ef 100644
--- a/Sources/ProfileFeature/Coordinator/ProfileCoordinator.swift
+++ b/Sources/ProfileFeature/Coordinator/ProfileCoordinator.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Countries
 import Permissions
 import MenuFeature
@@ -14,12 +13,6 @@ public protocol ProfileCoordinating {
     func toDrawer(_: UIViewController, from: UIViewController)
     func toPermission(type: PermissionType, from: UIViewController)
 
-    func toCode(
-        with: AttributeConfirmation,
-        from: UIViewController,
-        _: @escaping ControllerClosure
-    )
-
     func toCountries(
         from: UIViewController,
         _: @escaping (Country) -> Void
@@ -38,7 +31,6 @@ public struct ProfileCoordinator: ProfileCoordinating {
     var permissionFactory: () -> RequestPermissionController
     var sideMenuFactory: (MenuItem, UIViewController) -> UIViewController
     var countriesFactory: (@escaping (Country) -> Void) -> UIViewController
-    var codeFactory: (AttributeConfirmation, @escaping ControllerClosure) -> UIViewController
 
     public init(
         emailFactory: @escaping () -> UIViewController,
@@ -46,10 +38,8 @@ public struct ProfileCoordinator: ProfileCoordinating {
         imagePickerFactory: @escaping () -> UIImagePickerController,
         permissionFactory: @escaping () -> RequestPermissionController, // ⚠️
         sideMenuFactory: @escaping (MenuItem, UIViewController) -> UIViewController,
-        countriesFactory: @escaping (@escaping (Country) -> Void) -> UIViewController,
-        codeFactory: @escaping (AttributeConfirmation, @escaping ControllerClosure) -> UIViewController
+        countriesFactory: @escaping (@escaping (Country) -> Void) -> UIViewController
     ) {
-        self.codeFactory = codeFactory
         self.emailFactory = emailFactory
         self.phoneFactory = phoneFactory
         self.sideMenuFactory = sideMenuFactory
@@ -70,15 +60,6 @@ public extension ProfileCoordinator {
         pushPresenter.present(screen, from: parent)
     }
 
-    func toCode(
-        with confirmation: AttributeConfirmation,
-        from parent: UIViewController,
-        _ completion: @escaping ControllerClosure
-    ) {
-        let screen = codeFactory(confirmation, completion)
-        pushPresenter.present(screen, from: parent)
-    }
-
     func toPermission(type: PermissionType, from parent: UIViewController) {
         let screen = permissionFactory()
         screen.setup(type: type)
diff --git a/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift
index 926c6d49..173c8e19 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift
@@ -1,101 +1,95 @@
 import Shared
-import Models
 import Combine
 import Defaults
 import XXClient
-import Foundation
 import InputField
-import BackupFeature
+import Foundation
 import CombineSchedulers
 import XXMessengerClient
 import DependencyInjection
 
-struct ProfileCodeViewState: Equatable {
-  var input: String = ""
-  var status: InputField.ValidationStatus = .unknown(nil)
-  var resendDebouncer: Int = 0
-}
-
 final class ProfileCodeViewModel {
+  struct ViewState: Equatable {
+    var input: String = ""
+    var status: InputField.ValidationStatus = .unknown(nil)
+    var resendDebouncer: Int = 0
+    var didConfirm: Bool = false
+  }
+
+  var statePublisher: AnyPublisher<ViewState, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
+
   @Dependency var messenger: Messenger
   @Dependency var hudController: HUDController
-  @Dependency var backupService: BackupService
-
   @KeyObject(.email, defaultValue: nil) var email: String?
   @KeyObject(.phone, defaultValue: nil) var phone: String?
 
-  let confirmation: AttributeConfirmation
-
-  var timer: Timer?
-
-  var completionPublisher: AnyPublisher<AttributeConfirmation, Never> { completionRelay.eraseToAnyPublisher() }
-  private let completionRelay = PassthroughSubject<AttributeConfirmation, Never>()
-
-  var state: AnyPublisher<ProfileCodeViewState, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<ProfileCodeViewState, Never>(.init())
-
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
-
-  init(_ confirmation: AttributeConfirmation) {
-    self.confirmation = confirmation
+  private var timer: Timer?
+  private let isEmail: Bool
+  private let content: String
+  private let confirmationId: String
+  private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
+  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
+
+  init(
+    isEmail: Bool,
+    content: String,
+    confirmationId: String
+  ) {
+    self.isEmail = isEmail
+    self.content = content
+    self.confirmationId = confirmationId
     didTapResend()
   }
 
   func didInput(_ string: String) {
-    stateRelay.value.input = string
+    stateSubject.value.input = string
     validate()
   }
 
   func didTapResend() {
-    guard stateRelay.value.resendDebouncer == 0 else { return }
-
-    stateRelay.value.resendDebouncer = 60
-
+    guard stateSubject.value.resendDebouncer == 0 else { return }
+    stateSubject.value.resendDebouncer = 60
     timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {  [weak self] in
-      guard let self = self, self.stateRelay.value.resendDebouncer > 0 else {
+      guard let self = self, self.stateSubject.value.resendDebouncer > 0 else {
         $0.invalidate()
         return
       }
-
-      self.stateRelay.value.resendDebouncer -= 1
+      self.stateSubject.value.resendDebouncer -= 1
     }
   }
 
   func didTapNext() {
     hudController.show()
-
-    backgroundScheduler.schedule { [weak self] in
-      guard let self = self else { return }
-
+    scheduler.schedule { [weak self] in
+      guard let self else { return }
       do {
         try self.messenger.ud.get()!.confirmFact(
-          confirmationId: self.confirmation.confirmationId!,
-          code: self.stateRelay.value.input
+          confirmationId: self.confirmationId,
+          code: self.stateSubject.value.input
         )
-
-        if self.confirmation.isEmail {
-          self.email = self.confirmation.content
+        if self.isEmail {
+          self.email = self.content
         } else {
-          self.phone = self.confirmation.content
+          self.phone = self.content
         }
-
         self.timer?.invalidate()
         self.hudController.dismiss()
-        self.completionRelay.send(self.confirmation)
-
-        self.backupService.didUpdateFacts()
+        self.stateSubject.value.didConfirm = true
       } catch {
-        self.hudController.show(.init(error: error))
+        let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+        self.hudController.show(.init(content: xxError))
       }
     }
   }
 
   private func validate() {
-    switch Validator.code.validate(stateRelay.value.input) {
+    switch Validator.code.validate(stateSubject.value.input) {
     case .success:
-      stateRelay.value.status = .valid(nil)
+      stateSubject.value.status = .valid(nil)
     case .failure(let error):
-      stateRelay.value.status = .invalid(error)
+      stateSubject.value.status = .invalid(error)
     }
   }
 }
diff --git a/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
index 79b36b2f..6e0f17fe 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
@@ -1,4 +1,3 @@
-import Models
 import Shared
 import Combine
 import XXClient
@@ -8,47 +7,44 @@ import CombineSchedulers
 import XXMessengerClient
 import DependencyInjection
 
-struct ProfileEmailViewState: Equatable {
-  var input: String = ""
-  var confirmation: AttributeConfirmation? = nil
-  var status: InputField.ValidationStatus = .unknown(nil)
-}
-
 final class ProfileEmailViewModel {
+  struct ViewState: Equatable {
+    var input: String = ""
+    var content: String?
+    var confirmationId: String?
+    var status: InputField.ValidationStatus = .unknown(nil)
+  }
+  
   @Dependency var messenger: Messenger
   @Dependency var hudController: HUDController
 
-  var state: AnyPublisher<ProfileEmailViewState, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<ProfileEmailViewState, Never>(.init())
+  var statePublisher: AnyPublisher<ViewState, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
 
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
+  private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
+  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
   func didInput(_ string: String) {
-    stateRelay.value.input = string
+    stateSubject.value.input = string
     validate()
   }
 
   func clearUp() {
-    stateRelay.value.confirmation = nil
+    stateSubject.value.confirmationId = nil
   }
 
   func didTapNext() {
     hudController.show()
-
-    backgroundScheduler.schedule { [weak self] in
+    scheduler.schedule { [weak self] in
       guard let self = self else { return }
-
       do {
         let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
-          .init(type: .email, value: self.stateRelay.value.input)
+          .init(type: .email, value: self.stateSubject.value.input)
         )
-
         self.hudController.dismiss()
-        self.stateRelay.value.confirmation = .init(
-          content: self.stateRelay.value.input,
-          isEmail: true,
-          confirmationId: confirmationId
-        )
+        self.stateSubject.value.confirmationId = confirmationId
+        self.stateSubject.value.content = self.stateSubject.value.input
       } catch {
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
         self.hudController.show(.init(content: xxError))
@@ -57,11 +53,11 @@ final class ProfileEmailViewModel {
   }
 
   private func validate() {
-    switch Validator.email.validate(stateRelay.value.input) {
+    switch Validator.email.validate(stateSubject.value.input) {
     case .success:
-      stateRelay.value.status = .valid(nil)
+      stateSubject.value.status = .valid(nil)
     case .failure(let error):
-      stateRelay.value.status = .invalid(error)
+      stateSubject.value.status = .invalid(error)
     }
   }
 }
diff --git a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
index b2b3e34d..8adc37cc 100644
--- a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
@@ -1,63 +1,59 @@
 import Shared
-import Models
 import Combine
 import XXClient
 import Countries
 import InputField
 import Foundation
 import CombineSchedulers
-import DependencyInjection
 import XXMessengerClient
-
-struct ProfilePhoneViewState: Equatable {
-  var input: String = ""
-  var confirmation: AttributeConfirmation? = nil
-  var status: InputField.ValidationStatus = .unknown(nil)
-  var country: Country = .fromMyPhone()
-}
+import DependencyInjection
 
 final class ProfilePhoneViewModel {
+  struct ViewState: Equatable {
+    var input: String = ""
+    var content: String?
+    var confirmationId: String?
+    var status: InputField.ValidationStatus = .unknown(nil)
+    var country: Country = .fromMyPhone()
+  }
+
   @Dependency var messenger: Messenger
   @Dependency var hudController: HUDController
 
-  var state: AnyPublisher<ProfilePhoneViewState, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<ProfilePhoneViewState, Never>(.init())
+  var statePublisher: AnyPublisher<ViewState, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
 
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
+  private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
+  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
   func didInput(_ string: String) {
-    stateRelay.value.input = string
+    stateSubject.value.input = string
     validate()
   }
 
   func clearUp() {
-    stateRelay.value.confirmation = nil
+    stateSubject.value.confirmationId = nil
   }
 
   func didChooseCountry(_ country: Country) {
-    stateRelay.value.country = country
+    stateSubject.value.country = country
     validate()
   }
 
   func didTapNext() {
     hudController.show()
-
-    backgroundScheduler.schedule { [weak self] in
+    scheduler.schedule { [weak self] in
       guard let self = self else { return }
-
-      let content = "\(self.stateRelay.value.input)\(self.stateRelay.value.country.code)"
-
+      let content = "\(self.stateSubject.value.input)\(self.stateSubject.value.country.code)"
       do {
         let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
           .init(type: .phone, value: content)
         )
 
         self.hudController.dismiss()
-        self.stateRelay.value.confirmation = .init(
-          content: content,
-          confirmationId: confirmationId
-        )
-
+        self.stateSubject.value.content = content
+        self.stateSubject.value.confirmationId = confirmationId
       } catch {
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
         self.hudController.show(.init(content: xxError))
@@ -66,11 +62,11 @@ final class ProfilePhoneViewModel {
   }
 
   private func validate() {
-    switch Validator.phone.validate((stateRelay.value.country.regex, stateRelay.value.input)) {
+    switch Validator.phone.validate((stateSubject.value.country.regex, stateSubject.value.input)) {
     case .success:
-      stateRelay.value.status = .valid(nil)
+      stateSubject.value.status = .valid(nil)
     case .failure(let error):
-      stateRelay.value.status = .invalid(error)
+      stateSubject.value.status = .invalid(error)
     }
   }
 }
diff --git a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
index d8aa7752..996af851 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import Combine
 import Defaults
 import XXClient
diff --git a/Sources/PushFeature/PushHandler.swift b/Sources/PushFeature/PushHandler.swift
index e6407316..b43a575d 100644
--- a/Sources/PushFeature/PushHandler.swift
+++ b/Sources/PushFeature/PushHandler.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Defaults
 import XXClient
 import XXModels
diff --git a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
index ef723bcb..7a878ab3 100644
--- a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
@@ -8,7 +8,7 @@ public final class RequestsContainerController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: RequestsCoordinating
 
-  lazy private var screenView = RequestsContainerView()
+  private lazy var screenView = RequestsContainerView()
   private var cancellables = Set<AnyCancellable>()
 
   public override func loadView() {
diff --git a/Sources/RequestsFeature/Controllers/RequestsFailedController.swift b/Sources/RequestsFeature/Controllers/RequestsFailedController.swift
index 40d6b4cd..bb62744b 100644
--- a/Sources/RequestsFeature/Controllers/RequestsFailedController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsFailedController.swift
@@ -3,7 +3,7 @@ import Combine
 import DependencyInjection
 
 final class RequestsFailedController: UIViewController {
-    lazy private var screenView = RequestsFailedView()
+    private lazy var screenView = RequestsFailedView()
     private var cancellables = Set<AnyCancellable>()
     private let viewModel = RequestsFailedViewModel()
     private var dataSource: UICollectionViewDiffableDataSource<Section, Request>?
diff --git a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
index b6fc65c1..feec2f28 100644
--- a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import XXModels
@@ -11,7 +10,7 @@ final class RequestsReceivedController: UIViewController {
     @Dependency var toaster: ToastController
     @Dependency var coordinator: RequestsCoordinating
 
-    lazy private var screenView = RequestsReceivedView()
+    private lazy var screenView = RequestsReceivedView()
     private var cancellables = Set<AnyCancellable>()
     private let viewModel = RequestsReceivedViewModel()
     private var drawerCancellables = Set<AnyCancellable>()
diff --git a/Sources/RequestsFeature/Controllers/RequestsSentController.swift b/Sources/RequestsFeature/Controllers/RequestsSentController.swift
index b632e821..7edec938 100644
--- a/Sources/RequestsFeature/Controllers/RequestsSentController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsSentController.swift
@@ -7,7 +7,7 @@ final class RequestsSentController: UIViewController {
         connectionSubject.eraseToAnyPublisher()
     }
 
-    lazy private var screenView = RequestsSentView()
+    private lazy var screenView = RequestsSentView()
     private let viewModel = RequestsSentViewModel()
     private var cancellables = Set<AnyCancellable>()
     private let tapSubject = PassthroughSubject<Request, Never>()
diff --git a/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift b/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift
index 571bf625..9e8297c0 100644
--- a/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift
+++ b/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Shared
-import Models
 import XXModels
 import MenuFeature
 import Presentation
diff --git a/Sources/RequestsFeature/Models/Request.swift b/Sources/RequestsFeature/Models/Request.swift
index 595410d4..aac0fd8c 100644
--- a/Sources/RequestsFeature/Models/Request.swift
+++ b/Sources/RequestsFeature/Models/Request.swift
@@ -1,4 +1,3 @@
-import Models
 import XXModels
 import Foundation
 
diff --git a/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift
index 97159b02..351d3b37 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import XXModels
diff --git a/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift
index c459bf79..055b7236 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import Defaults
diff --git a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
index 9faa4954..4936e676 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import Defaults
diff --git a/Sources/RestoreFeature/Controllers/RestoreController.swift b/Sources/RestoreFeature/Controllers/RestoreController.swift
index 27031b75..12bc3a7d 100644
--- a/Sources/RestoreFeature/Controllers/RestoreController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreController.swift
@@ -7,7 +7,7 @@ import DependencyInjection
 public final class RestoreController: UIViewController {
     @Dependency private var coordinator: RestoreCoordinating
 
-    lazy private var screenView = RestoreView()
+    private lazy var screenView = RestoreView()
 
     private let viewModel: RestoreViewModel
     private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/RestoreFeature/Controllers/RestoreListController.swift b/Sources/RestoreFeature/Controllers/RestoreListController.swift
index bfea5df3..026bdbd0 100644
--- a/Sources/RestoreFeature/Controllers/RestoreListController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreListController.swift
@@ -7,7 +7,7 @@ import DependencyInjection
 public final class RestoreListController: UIViewController {
   @Dependency var coordinator: RestoreCoordinating
 
-  lazy private var screenView = RestoreListView()
+  private lazy var screenView = RestoreListView()
 
   private let viewModel = RestoreListViewModel()
   private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/RestoreFeature/Controllers/RestorePassphraseController.swift b/Sources/RestoreFeature/Controllers/RestorePassphraseController.swift
index 67dd450b..45bd32d7 100644
--- a/Sources/RestoreFeature/Controllers/RestorePassphraseController.swift
+++ b/Sources/RestoreFeature/Controllers/RestorePassphraseController.swift
@@ -4,7 +4,7 @@ import Combine
 import InputField
 
 public final class RestorePassphraseController: UIViewController {
-  lazy private var screenView = RestorePassphraseView()
+  private lazy var screenView = RestorePassphraseView()
 
   private var passphrase = "" {
     didSet {
diff --git a/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift b/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift
index 2ddf4ab1..3486ea10 100644
--- a/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift
@@ -4,8 +4,8 @@ import DependencyInjection
 import ScrollViewController
 
 public final class RestoreSFTPController: UIViewController {
-  lazy private var screenView = RestoreSFTPView()
-  lazy private var scrollViewController = ScrollViewController()
+  private lazy var screenView = RestoreSFTPView()
+  private lazy var scrollViewController = ScrollViewController()
 
   private let completion: (String, String, String) -> Void
   private let viewModel = RestoreSFTPViewModel()
diff --git a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
index 4f6f1d9b..13c31363 100644
--- a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
@@ -7,7 +7,7 @@ public final class RestoreSuccessController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: RestoreCoordinating
 
-  lazy private var screenView = RestoreSuccessView()
+  private lazy var screenView = RestoreSuccessView()
   private var cancellables = Set<AnyCancellable>()
 
   public override func loadView() {
diff --git a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
index 98b68d83..14fe7a35 100644
--- a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
+++ b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Shared
 import Combine
 import Defaults
diff --git a/Sources/ScanFeature/Controllers/ScanContainerController.swift b/Sources/ScanFeature/Controllers/ScanContainerController.swift
index 9105e132..883f95fd 100644
--- a/Sources/ScanFeature/Controllers/ScanContainerController.swift
+++ b/Sources/ScanFeature/Controllers/ScanContainerController.swift
@@ -8,7 +8,7 @@ public final class ScanContainerController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: ScanCoordinating
 
-  lazy private var screenView = ScanContainerView()
+  private lazy var screenView = ScanContainerView()
 
   private let scanController = ScanController()
   private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/ScanFeature/Controllers/ScanController.swift b/Sources/ScanFeature/Controllers/ScanController.swift
index 52055ac4..8f05a944 100644
--- a/Sources/ScanFeature/Controllers/ScanController.swift
+++ b/Sources/ScanFeature/Controllers/ScanController.swift
@@ -9,7 +9,7 @@ final class ScanController: UIViewController {
     @Dependency private var coordinator: ScanCoordinating
     @Dependency private var permissions: PermissionHandling
 
-    lazy private var screenView = ScanView()
+    private lazy var screenView = ScanView()
 
     var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
diff --git a/Sources/ScanFeature/Controllers/ScanDisplayController.swift b/Sources/ScanFeature/Controllers/ScanDisplayController.swift
index e373d4de..c439855c 100644
--- a/Sources/ScanFeature/Controllers/ScanDisplayController.swift
+++ b/Sources/ScanFeature/Controllers/ScanDisplayController.swift
@@ -2,7 +2,7 @@ import UIKit
 import Combine
 
 final class ScanDisplayController: UIViewController {
-    lazy private var screenView = ScanDisplayView()
+    private lazy var screenView = ScanDisplayView()
 
     private let viewModel = ScanDisplayViewModel()
     private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/ScanFeature/Coordinator/ScanCoordinator.swift b/Sources/ScanFeature/Coordinator/ScanCoordinator.swift
index 98e60577..cfdc386a 100644
--- a/Sources/ScanFeature/Coordinator/ScanCoordinator.swift
+++ b/Sources/ScanFeature/Coordinator/ScanCoordinator.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import XXModels
 import MenuFeature
 import Presentation
diff --git a/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift b/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
index fb03482a..00be78ca 100644
--- a/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
+++ b/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import Combine
 import Defaults
 import Countries
diff --git a/Sources/ScanFeature/ViewModels/ScanViewModel.swift b/Sources/ScanFeature/ViewModels/ScanViewModel.swift
index 48e2ed29..c46965ca 100644
--- a/Sources/ScanFeature/ViewModels/ScanViewModel.swift
+++ b/Sources/ScanFeature/ViewModels/ScanViewModel.swift
@@ -1,5 +1,4 @@
 import Shared
-import Models
 import Combine
 import XXModels
 import XXClient
diff --git a/Sources/SearchFeature/Controllers/SearchContainerController.swift b/Sources/SearchFeature/Controllers/SearchContainerController.swift
index 69665f8c..77f2a535 100644
--- a/Sources/SearchFeature/Controllers/SearchContainerController.swift
+++ b/Sources/SearchFeature/Controllers/SearchContainerController.swift
@@ -9,7 +9,7 @@ public final class SearchContainerController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: SearchCoordinating
 
-  lazy private var screenView = SearchContainerView()
+  private lazy var screenView = SearchContainerView()
 
   private var contentOffset: CGPoint?
   private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/SearchFeature/Controllers/SearchLeftController.swift b/Sources/SearchFeature/Controllers/SearchLeftController.swift
index e850dfde..7eb72535 100644
--- a/Sources/SearchFeature/Controllers/SearchLeftController.swift
+++ b/Sources/SearchFeature/Controllers/SearchLeftController.swift
@@ -15,7 +15,7 @@ final class SearchLeftController: UIViewController {
     @KeyObject(.sharingEmail, defaultValue: false) var isSharingEmail: Bool
     @KeyObject(.sharingPhone, defaultValue: false) var isSharingPhone: Bool
 
-    lazy private var screenView = SearchLeftView()
+    private lazy var screenView = SearchLeftView()
 
     let viewModel: SearchLeftViewModel
     private var dataSource: SearchDiffableDataSource!
diff --git a/Sources/SearchFeature/Controllers/SearchRightController.swift b/Sources/SearchFeature/Controllers/SearchRightController.swift
index 35240054..4541af0f 100644
--- a/Sources/SearchFeature/Controllers/SearchRightController.swift
+++ b/Sources/SearchFeature/Controllers/SearchRightController.swift
@@ -5,7 +5,7 @@ import DependencyInjection
 final class SearchRightController: UIViewController {
     @Dependency var coordinator: SearchCoordinating
 
-    lazy private var screenView = SearchRightView()
+    private lazy var screenView = SearchRightView()
 
     private var cancellables = Set<AnyCancellable>()
     private let cameraController = CameraController()
diff --git a/Sources/SearchFeature/Coordinator/SearchCoordinator.swift b/Sources/SearchFeature/Coordinator/SearchCoordinator.swift
index 21a9d7b3..053e5b65 100644
--- a/Sources/SearchFeature/Coordinator/SearchCoordinator.swift
+++ b/Sources/SearchFeature/Coordinator/SearchCoordinator.swift
@@ -1,5 +1,4 @@
 import UIKit
-import Models
 import XXModels
 import Countries
 import Presentation
diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
index 5fd6243a..969152bd 100644
--- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
@@ -1,6 +1,5 @@
 import Retry
 import UIKit
-import Models
 import Shared
 import Combine
 import XXModels
diff --git a/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift b/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift
index c238960c..de6a06ea 100644
--- a/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift
@@ -1,5 +1,4 @@
 import Shared
-import Models
 import Combine
 import XXModels
 import Defaults
diff --git a/Sources/SettingsFeature/Controllers/AccountDeleteController.swift b/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
index 7b23ea80..01ad5ad5 100644
--- a/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
+++ b/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
@@ -11,8 +11,8 @@ public final class AccountDeleteController: UIViewController {
 
     @Dependency var coordinator: SettingsCoordinating
 
-    lazy private var screenView = AccountDeleteView()
-    lazy private var scrollViewController = ScrollViewController()
+    private lazy var screenView = AccountDeleteView()
+    private lazy var scrollViewController = ScrollViewController()
 
     private let viewModel = AccountDeleteViewModel()
     private var cancellables = Set<AnyCancellable>()
diff --git a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
index efe25a00..62dcd629 100644
--- a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
@@ -6,7 +6,7 @@ import DependencyInjection
 public final class SettingsAdvancedController: UIViewController {
     @Dependency private var coordinator: SettingsCoordinating
 
-    lazy private var screenView = SettingsAdvancedView()
+    private lazy var screenView = SettingsAdvancedView()
 
     private var cancellables = Set<AnyCancellable>()
     private let viewModel = SettingsAdvancedViewModel()
diff --git a/Sources/SettingsFeature/Controllers/SettingsController.swift b/Sources/SettingsFeature/Controllers/SettingsController.swift
index de85af7c..74ca0b94 100644
--- a/Sources/SettingsFeature/Controllers/SettingsController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsController.swift
@@ -9,8 +9,8 @@ public final class SettingsController: UIViewController {
   @Dependency var barStylist: StatusBarStylist
   @Dependency var coordinator: SettingsCoordinating
 
-  lazy private var scrollViewController = ScrollViewController()
-  lazy private var screenView = SettingsView {
+  private lazy var scrollViewController = ScrollViewController()
+  private lazy var screenView = SettingsView {
     switch $0 {
     case .icognitoKeyboard:
       self.presentInfo(
diff --git a/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift b/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift
index d03db85a..bb1b4cb3 100644
--- a/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift
+++ b/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift
@@ -1,6 +1,5 @@
 import Shared
 import Retry
-import Models
 import Combine
 import Defaults
 import Keychain
diff --git a/Sources/Shared/Controllers/RootViewController.swift b/Sources/Shared/Controllers/RootViewController.swift
index 909af5d6..86f20217 100644
--- a/Sources/Shared/Controllers/RootViewController.swift
+++ b/Sources/Shared/Controllers/RootViewController.swift
@@ -8,15 +8,15 @@ public final class RootViewController: UIViewController {
   @Dependency var toastDispatcher: ToastController
 
   var hud: HUDView?
-  let content: UIViewController?
   var cancellables = Set<AnyCancellable>()
+  public let navController: UINavigationController
 
   var toastTimer: Timer?
   let toastTopPadding: CGFloat = 10
   var topToastConstraint: NSLayoutConstraint?
 
-  public init(_ content: UIViewController?) {
-    self.content = content
+  public init(_ content: UINavigationController) {
+    self.navController = content
     super.init(nibName: nil, bundle: nil)
   }
 
@@ -29,15 +29,11 @@ public final class RootViewController: UIViewController {
   public override func viewDidLoad() {
     super.viewDidLoad()
 
-    if let content {
-      addChild(content)
-      view.addSubview(content.view)
-      content.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-      content.view.frame = view.bounds
-      content.didMove(toParent: self)
-    } else {
-      view.isUserInteractionEnabled = false
-    }
+    addChild(navController)
+    view.addSubview(navController.view)
+    navController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+    navController.view.frame = view.bounds
+    navController.didMove(toParent: self)
 
     barStylist
       .styleSubject
diff --git a/Sources/Models/Payload.swift b/Sources/Shared/Models/Payload.swift
similarity index 100%
rename from Sources/Models/Payload.swift
rename to Sources/Shared/Models/Payload.swift
diff --git a/Sources/Models/Reply.swift b/Sources/Shared/Models/Reply.swift
similarity index 100%
rename from Sources/Models/Reply.swift
rename to Sources/Shared/Models/Reply.swift
diff --git a/Sources/Models/pbpayload.pb.swift b/Sources/Shared/Models/pbpayload.pb.swift
similarity index 100%
rename from Sources/Models/pbpayload.pb.swift
rename to Sources/Shared/Models/pbpayload.pb.swift
diff --git a/Sources/TermsFeature/TermsConditionsController.swift b/Sources/TermsFeature/TermsConditionsController.swift
index 08a6081f..d426489d 100644
--- a/Sources/TermsFeature/TermsConditionsController.swift
+++ b/Sources/TermsFeature/TermsConditionsController.swift
@@ -11,7 +11,7 @@ public final class TermsConditionsController: UIViewController {
   @KeyObject(.username, defaultValue: nil) var username: String?
   @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
 
-  lazy private var screenView = TermsConditionsView()
+  private lazy var screenView = TermsConditionsView()
 
   private var cancellables = Set<AnyCancellable>()
 
diff --git a/Sources/TestHelpers/Dummies.swift b/Sources/TestHelpers/Dummies.swift
deleted file mode 100644
index e29064cd..00000000
--- a/Sources/TestHelpers/Dummies.swift
+++ /dev/null
@@ -1,37 +0,0 @@
-import Models
-import Foundation
-
-public extension Contact {
-    static let dummy = Contact(
-        photo: nil,
-        userId: Data(),
-        email: nil,
-        phone: nil,
-        status: .friend,
-        marshaled: Data(),
-        username: "username",
-        nickname: nil,
-        createdAt: Date()
-    )
-}
-
-public extension GroupChatInfo {
-    static let dummy = GroupChatInfo(
-        group: .dummy,
-        members: []
-    )
-}
-
-public extension Group {
-    static let dummy = Group(
-        leader: Data(),
-        name: "name",
-        groupId: Data(),
-        accepted: true,
-        serialize: Data()
-    )
-}
-
-public extension SingleChatInfo {
-    static let dummy = SingleChatInfo(contact: .dummy, lastMessage: nil)
-}
diff --git a/Sources/TestHelpers/PresenterDouble.swift b/Sources/TestHelpers/PresenterDouble.swift
deleted file mode 100644
index 603c6a46..00000000
--- a/Sources/TestHelpers/PresenterDouble.swift
+++ /dev/null
@@ -1,17 +0,0 @@
-import UIKit
-import Presentation
-
-public final class PresenterDouble: Presenting {
-    public var didPresentFrom: UIViewController?
-    public var didPresentTarget: UIViewController?
-
-    public init() {}
-
-    public func present(
-        _ target: UIViewController,
-        from parent: UIViewController
-    ) {
-        didPresentFrom = parent
-        didPresentTarget = target
-    }
-}
diff --git a/Sources/XXNavigation/Actions/PresentChat.swift b/Sources/XXNavigation/Actions/PresentChat.swift
new file mode 100644
index 00000000..db7e63b6
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentChat.swift
@@ -0,0 +1,12 @@
+import XXModels
+import Navigation
+
+public struct PresentChat: Navigation.Action {
+  public var contact: Contact
+  public var animated: Bool = true
+
+  public init(contact: Contact, animated: Bool = true) {
+    self.contact = contact
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentChatList.swift b/Sources/XXNavigation/Actions/PresentChatList.swift
new file mode 100644
index 00000000..69f3f942
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentChatList.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentChatList: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentCountryList.swift b/Sources/XXNavigation/Actions/PresentCountryList.swift
new file mode 100644
index 00000000..adb7ee1d
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentCountryList.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentCountryList: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentDrawer.swift b/Sources/XXNavigation/Actions/PresentDrawer.swift
new file mode 100644
index 00000000..44e85b95
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentDrawer.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentDrawer: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentGroupChat.swift b/Sources/XXNavigation/Actions/PresentGroupChat.swift
new file mode 100644
index 00000000..39219036
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentGroupChat.swift
@@ -0,0 +1,12 @@
+import XXModels
+import Navigation
+
+public struct PresentGroupChat: Navigation.Action {
+  public var model: GroupInfo
+  public var animated: Bool = true
+
+  public init(model: GroupInfo, animated: Bool = true) {
+    self.model = model
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingCode.swift b/Sources/XXNavigation/Actions/PresentOnboardingCode.swift
new file mode 100644
index 00000000..59f0926f
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentOnboardingCode.swift
@@ -0,0 +1,20 @@
+import Navigation
+
+public struct PresentOnboardingCode: Navigation.Action {
+  public var isEmail: Bool
+  public var content: String
+  public var animated: Bool = true
+  public var confirmationId: String
+
+  public init(
+    isEmail: Bool,
+    content: String,
+    confirmationId: String,
+    animated: Bool = true
+  ) {
+    self.animated = animated
+    self.isEmail = isEmail
+    self.content = content
+    self.confirmationId = confirmationId
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingEmail.swift b/Sources/XXNavigation/Actions/PresentOnboardingEmail.swift
new file mode 100644
index 00000000..6d418378
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentOnboardingEmail.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentOnboardingEmail: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingPhone.swift b/Sources/XXNavigation/Actions/PresentOnboardingPhone.swift
new file mode 100644
index 00000000..6a104049
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentOnboardingPhone.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentOnboardingPhone: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingStart.swift b/Sources/XXNavigation/Actions/PresentOnboardingStart.swift
new file mode 100644
index 00000000..fc0bf229
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentOnboardingStart.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentOnboardingStart: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingUsername.swift b/Sources/XXNavigation/Actions/PresentOnboardingUsername.swift
new file mode 100644
index 00000000..5a828dc4
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentOnboardingUsername.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentOnboardingUsername: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentOnboardingWelcome.swift b/Sources/XXNavigation/Actions/PresentOnboardingWelcome.swift
new file mode 100644
index 00000000..1c412089
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentOnboardingWelcome.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentOnboardingWelcome: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentRequests.swift b/Sources/XXNavigation/Actions/PresentRequests.swift
new file mode 100644
index 00000000..0f9718f0
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentRequests.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentRequests: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentRestoreList.swift b/Sources/XXNavigation/Actions/PresentRestoreList.swift
new file mode 100644
index 00000000..8a7fbb5a
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentRestoreList.swift
@@ -0,0 +1,9 @@
+import Navigation
+
+public struct PresentRestoreList: Navigation.Action {
+  public var animated: Bool = true
+
+  public init(animated: Bool = true) {
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentSearch.swift b/Sources/XXNavigation/Actions/PresentSearch.swift
new file mode 100644
index 00000000..7cb33ba2
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentSearch.swift
@@ -0,0 +1,11 @@
+import Navigation
+
+public struct PresentSearch: Navigation.Action {
+  public var searching: String?
+  public var animated: Bool = true
+
+  public init(searching: String? = nil, animated: Bool = true) {
+    self.searching = searching
+    self.animated = animated
+  }
+}
diff --git a/Sources/XXNavigation/Actions/PresentTermsAndConditions.swift b/Sources/XXNavigation/Actions/PresentTermsAndConditions.swift
new file mode 100644
index 00000000..2df2ad38
--- /dev/null
+++ b/Sources/XXNavigation/Actions/PresentTermsAndConditions.swift
@@ -0,0 +1,14 @@
+import Navigation
+
+public struct PresentTermsAndConditions: Navigation.Action {
+  public var animated: Bool = true
+  public var popAllowed: Bool = true
+
+  public init(
+    animated: Bool = true,
+    popAllowed: Bool = true
+  ) {
+    self.animated = animated
+    self.popAllowed = popAllowed
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentChatListNavigator.swift b/Sources/XXNavigation/Navigators/PresentChatListNavigator.swift
new file mode 100644
index 00000000..0d83657f
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentChatListNavigator.swift
@@ -0,0 +1,22 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentChatListNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentChatList, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentChatNavigator.swift b/Sources/XXNavigation/Navigators/PresentChatNavigator.swift
new file mode 100644
index 00000000..2714bc55
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentChatNavigator.swift
@@ -0,0 +1,23 @@
+import UIKit
+import XXModels
+import Navigation
+import DependencyInjection
+
+public struct PresentChatNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: (Contact) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentChat, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(action.contact), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping (Contact) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentCountryListNavigator.swift b/Sources/XXNavigation/Navigators/PresentCountryListNavigator.swift
new file mode 100644
index 00000000..a5842927
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentCountryListNavigator.swift
@@ -0,0 +1,23 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentCountryListNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentCountryList, completion: @escaping () -> Void) {
+    if let topViewController = navigationController().topViewController {
+      let modalAction = PresentModal(screen(), from: topViewController)
+    }
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentDrawerNavigator.swift b/Sources/XXNavigation/Navigators/PresentDrawerNavigator.swift
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentDrawerNavigator.swift
@@ -0,0 +1 @@
+
diff --git a/Sources/XXNavigation/Navigators/PresentGroupChatNavigator.swift b/Sources/XXNavigation/Navigators/PresentGroupChatNavigator.swift
new file mode 100644
index 00000000..a44485bc
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentGroupChatNavigator.swift
@@ -0,0 +1,23 @@
+import UIKit
+import XXModels
+import Navigation
+import DependencyInjection
+
+public struct PresentGroupChatNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: (GroupInfo) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentGroupChat, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(action.model), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping (GroupInfo) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingCodeNavigator.swift b/Sources/XXNavigation/Navigators/PresentOnboardingCodeNavigator.swift
new file mode 100644
index 00000000..359dc109
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentOnboardingCodeNavigator.swift
@@ -0,0 +1,23 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentOnboardingCodeNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: (Bool, String, String) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentOnboardingCode, completion: @escaping () -> Void) {
+    let controller = screen(action.isEmail, action.content, action.confirmationId)
+    let pushAction = Push(controller, on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping (Bool, String, String) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingEmailNavigator.swift b/Sources/XXNavigation/Navigators/PresentOnboardingEmailNavigator.swift
new file mode 100644
index 00000000..190941d8
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentOnboardingEmailNavigator.swift
@@ -0,0 +1,22 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentOnboardingEmailNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentOnboardingEmail, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingPhoneNavigator.swift b/Sources/XXNavigation/Navigators/PresentOnboardingPhoneNavigator.swift
new file mode 100644
index 00000000..674a2ad3
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentOnboardingPhoneNavigator.swift
@@ -0,0 +1,22 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentOnboardingPhoneNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentOnboardingPhone, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingStartNavigator.swift b/Sources/XXNavigation/Navigators/PresentOnboardingStartNavigator.swift
new file mode 100644
index 00000000..050b6790
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentOnboardingStartNavigator.swift
@@ -0,0 +1,22 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentOnboardingStartNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentOnboardingStart, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingUsernameNavigator.swift b/Sources/XXNavigation/Navigators/PresentOnboardingUsernameNavigator.swift
new file mode 100644
index 00000000..964ee100
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentOnboardingUsernameNavigator.swift
@@ -0,0 +1,22 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentOnboardingUsernameNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentOnboardingUsername, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentOnboardingWelcomeNavigator.swift b/Sources/XXNavigation/Navigators/PresentOnboardingWelcomeNavigator.swift
new file mode 100644
index 00000000..e5fc1ed4
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentOnboardingWelcomeNavigator.swift
@@ -0,0 +1,22 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentOnboardingWelcomeNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentOnboardingWelcome, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentRequestsNavigator.swift b/Sources/XXNavigation/Navigators/PresentRequestsNavigator.swift
new file mode 100644
index 00000000..c39d439b
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentRequestsNavigator.swift
@@ -0,0 +1,22 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentRequestsNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentRequests, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentRestoreListNavigator.swift b/Sources/XXNavigation/Navigators/PresentRestoreListNavigator.swift
new file mode 100644
index 00000000..0e9a783a
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentRestoreListNavigator.swift
@@ -0,0 +1,22 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentRestoreListNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentRestoreList, completion: @escaping () -> Void) {
+    let pushAction = Push(screen(), on: navigationController(), animated: action.animated)
+    navigator.perform(pushAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentSearchNavigator.swift b/Sources/XXNavigation/Navigators/PresentSearchNavigator.swift
new file mode 100644
index 00000000..d4ce74c1
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentSearchNavigator.swift
@@ -0,0 +1,22 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentSearchNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: (String?) -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentSearch, completion: @escaping () -> Void) {
+    let setStackAction = SetStack([screen(action.searching)], on: navigationController(), animated: action.animated)
+    navigator.perform(setStackAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping (String?) -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
diff --git a/Sources/XXNavigation/Navigators/PresentTermsAndConditionsNavigator.swift b/Sources/XXNavigation/Navigators/PresentTermsAndConditionsNavigator.swift
new file mode 100644
index 00000000..61ad413e
--- /dev/null
+++ b/Sources/XXNavigation/Navigators/PresentTermsAndConditionsNavigator.swift
@@ -0,0 +1,27 @@
+import UIKit
+import Navigation
+import DependencyInjection
+
+public struct PresentTermsAndConditionsNavigator: TypedNavigator {
+  @Dependency var navigator: Navigator
+  var screen: () -> UIViewController
+  var navigationController: () -> UINavigationController
+
+  public func perform(_ action: PresentTermsAndConditions, completion: @escaping () -> Void) {
+    let navAction: Action
+    if action.popAllowed {
+      navAction = Push(screen(), on: navigationController(), animated: action.animated)
+    } else {
+      navAction = SetStack([screen()], on: navigationController(), animated: action.animated)
+    }
+    navigator.perform(navAction, completion: completion)
+  }
+
+  public init(
+    screen: @escaping () -> UIViewController,
+    navigationController: @escaping () -> UINavigationController
+  ) {
+    self.screen = screen
+    self.navigationController = navigationController
+  }
+}
-- 
GitLab